OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/sys_info.h" | 5 #include "base/sys_info.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include "base/android/build_info.h" |
8 #include <sys/system_properties.h> | |
9 | |
10 #include "base/android/sys_utils.h" | 8 #include "base/android/sys_utils.h" |
11 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 10 #include "base/logging.h" |
13 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
14 #include "base/strings/string_piece.h" | |
15 #include "base/strings/stringprintf.h" | |
16 #include "base/sys_info_internal.h" | 12 #include "base/sys_info_internal.h" |
17 | 13 |
18 #if (__ANDROID_API__ >= 21 /* 5.0 - Lollipop */) | |
19 | |
20 namespace { | |
21 | |
22 typedef int (SystemPropertyGetFunction)(const char*, char*); | |
23 | |
24 SystemPropertyGetFunction* DynamicallyLoadRealSystemPropertyGet() { | |
25 // libc.so should already be open, get a handle to it. | |
26 void* handle = dlopen("libc.so", RTLD_NOLOAD); | |
27 if (!handle) { | |
28 LOG(FATAL) << "Cannot dlopen libc.so: " << dlerror(); | |
29 } | |
30 SystemPropertyGetFunction* real_system_property_get = | |
31 reinterpret_cast<SystemPropertyGetFunction*>( | |
32 dlsym(handle, "__system_property_get")); | |
33 if (!real_system_property_get) { | |
34 LOG(FATAL) << "Cannot resolve __system_property_get(): " << dlerror(); | |
35 } | |
36 return real_system_property_get; | |
37 } | |
38 | |
39 static base::LazyInstance<base::internal::LazySysInfoValue< | |
40 SystemPropertyGetFunction*, DynamicallyLoadRealSystemPropertyGet> >::Leaky | |
41 g_lazy_real_system_property_get = LAZY_INSTANCE_INITIALIZER; | |
42 | |
43 } // namespace | |
44 | |
45 // Android 'L' removes __system_property_get from the NDK, however it is still | |
46 // a hidden symbol in libc. Until we remove all calls of __system_property_get | |
47 // from Chrome we work around this by defining a weak stub here, which uses | |
48 // dlsym to but ensures that Chrome uses the real system | |
49 // implementatation when loaded. http://crbug.com/392191. | |
50 BASE_EXPORT int __system_property_get(const char* name, char* value) { | |
51 return g_lazy_real_system_property_get.Get().value()(name, value); | |
52 } | |
53 | |
54 #endif | |
55 | |
56 namespace { | 14 namespace { |
57 | 15 |
58 // Default version of Android to fall back to when actual version numbers | 16 // Default version of Android to fall back to when actual version numbers |
59 // cannot be acquired. Use the latest Android release with a higher bug fix | 17 // cannot be acquired. Use the latest Android release with a higher bug fix |
60 // version to avoid unnecessarily comparison errors with the latest release. | 18 // version to avoid unnecessarily comparison errors with the latest release. |
61 // This should be manually kept up-to-date on each Android release. | 19 // This should be manually kept up-to-date on each Android release. |
62 const int kDefaultAndroidMajorVersion = 5; | 20 const int kDefaultAndroidMajorVersion = 5; |
63 const int kDefaultAndroidMinorVersion = 1; | 21 const int kDefaultAndroidMinorVersion = 1; |
64 const int kDefaultAndroidBugfixVersion = 99; | 22 const int kDefaultAndroidBugfixVersion = 99; |
65 | 23 |
(...skipping 14 matching lines...) Expand all Loading... |
80 return; | 38 return; |
81 } | 39 } |
82 } | 40 } |
83 | 41 |
84 // For some reason, we couldn't parse the version number string. | 42 // For some reason, we couldn't parse the version number string. |
85 *major_version = kDefaultAndroidMajorVersion; | 43 *major_version = kDefaultAndroidMajorVersion; |
86 *minor_version = kDefaultAndroidMinorVersion; | 44 *minor_version = kDefaultAndroidMinorVersion; |
87 *bugfix_version = kDefaultAndroidBugfixVersion; | 45 *bugfix_version = kDefaultAndroidBugfixVersion; |
88 } | 46 } |
89 | 47 |
90 // Parses a system property (specified with unit 'k','m' or 'g'). | |
91 // Returns a value in bytes. | |
92 // Returns -1 if the string could not be parsed. | |
93 int64 ParseSystemPropertyBytes(const base::StringPiece& str) { | |
94 const int64 KB = 1024; | |
95 const int64 MB = 1024 * KB; | |
96 const int64 GB = 1024 * MB; | |
97 if (str.size() == 0u) | |
98 return -1; | |
99 int64 unit_multiplier = 1; | |
100 size_t length = str.size(); | |
101 if (str[length - 1] == 'k') { | |
102 unit_multiplier = KB; | |
103 length--; | |
104 } else if (str[length - 1] == 'm') { | |
105 unit_multiplier = MB; | |
106 length--; | |
107 } else if (str[length - 1] == 'g') { | |
108 unit_multiplier = GB; | |
109 length--; | |
110 } | |
111 int64 result = 0; | |
112 bool parsed = base::StringToInt64(str.substr(0, length), &result); | |
113 bool negative = result <= 0; | |
114 bool overflow = result >= std::numeric_limits<int64>::max() / unit_multiplier; | |
115 if (!parsed || negative || overflow) | |
116 return -1; | |
117 return result * unit_multiplier; | |
118 } | |
119 | |
120 int GetDalvikHeapSizeMB() { | 48 int GetDalvikHeapSizeMB() { |
121 char heap_size_str[PROP_VALUE_MAX]; | 49 // See developer.android.com/reference/android/app/ActivityManager.html for |
122 __system_property_get("dalvik.vm.heapsize", heap_size_str); | 50 // how "large memory class" relates to the Dalvik heap size. |
123 // dalvik.vm.heapsize property is writable by a root user. | 51 int result = base::android::BuildInfo::GetInstance()->large_memory_class(); |
124 // Clamp it to reasonable range as a sanity check, | |
125 // a typical android device will never have less than 48MB. | |
126 const int64 MB = 1024 * 1024; | |
127 int64 result = ParseSystemPropertyBytes(heap_size_str); | |
128 if (result == -1) { | 52 if (result == -1) { |
129 // We should consider not exposing these values if they are not reliable. | 53 // We should consider not exposing these values if they are not reliable. |
130 LOG(ERROR) << "Can't parse dalvik.vm.heapsize: " << heap_size_str; | 54 LOG(ERROR) << "Invalid large memory class"; |
131 result = base::SysInfo::AmountOfPhysicalMemoryMB() / 3; | 55 result = base::SysInfo::AmountOfPhysicalMemoryMB() / 3; |
132 } | 56 } |
133 result = std::min<int64>(std::max<int64>(32 * MB, result), 1024 * MB) / MB; | 57 return std::min(std::max(32, result), 1024); |
134 return static_cast<int>(result); | |
135 } | |
136 | |
137 int GetDalvikHeapGrowthLimitMB() { | |
138 char heap_size_str[PROP_VALUE_MAX]; | |
139 __system_property_get("dalvik.vm.heapgrowthlimit", heap_size_str); | |
140 // dalvik.vm.heapgrowthlimit property is writable by a root user. | |
141 // Clamp it to reasonable range as a sanity check, | |
142 // a typical android device will never have less than 24MB. | |
143 const int64 MB = 1024 * 1024; | |
144 int64 result = ParseSystemPropertyBytes(heap_size_str); | |
145 if (result == -1) { | |
146 // We should consider not exposing these values if they are not reliable. | |
147 LOG(ERROR) << "Can't parse dalvik.vm.heapgrowthlimit: " << heap_size_str; | |
148 result = base::SysInfo::AmountOfPhysicalMemoryMB() / 6; | |
149 } | |
150 result = std::min<int64>(std::max<int64>(16 * MB, result), 512 * MB) / MB; | |
151 return static_cast<int>(result); | |
152 } | 58 } |
153 | 59 |
154 } // anonymous namespace | 60 } // anonymous namespace |
155 | 61 |
156 namespace base { | 62 namespace base { |
157 | 63 |
158 std::string SysInfo::HardwareModelName() { | 64 std::string SysInfo::HardwareModelName() { |
159 char device_model_str[PROP_VALUE_MAX]; | 65 return android::BuildInfo::GetInstance()->model(); |
160 __system_property_get("ro.product.model", device_model_str); | |
161 return std::string(device_model_str); | |
162 } | 66 } |
163 | 67 |
164 std::string SysInfo::OperatingSystemName() { | 68 std::string SysInfo::OperatingSystemName() { |
165 return "Android"; | 69 return "Android"; |
166 } | 70 } |
167 | 71 |
168 std::string SysInfo::OperatingSystemVersion() { | 72 std::string SysInfo::OperatingSystemVersion() { |
169 int32 major, minor, bugfix; | 73 return android::BuildInfo::GetInstance()->build_version_release(); |
170 OperatingSystemVersionNumbers(&major, &minor, &bugfix); | |
171 return StringPrintf("%d.%d.%d", major, minor, bugfix); | |
172 } | 74 } |
173 | 75 |
174 void SysInfo::OperatingSystemVersionNumbers(int32* major_version, | 76 void SysInfo::OperatingSystemVersionNumbers(int32* major_version, |
175 int32* minor_version, | 77 int32* minor_version, |
176 int32* bugfix_version) { | 78 int32* bugfix_version) { |
177 // Read the version number string out from the properties. | 79 const char* os_version_str = |
178 char os_version_str[PROP_VALUE_MAX]; | 80 android::BuildInfo::GetInstance()->build_version_release(); |
179 __system_property_get("ro.build.version.release", os_version_str); | |
180 | 81 |
181 // Parse out the numbers. | 82 // Parse out the numbers. |
182 ParseOSVersionNumbers(os_version_str, major_version, minor_version, | 83 ParseOSVersionNumbers(os_version_str, major_version, minor_version, |
183 bugfix_version); | 84 bugfix_version); |
184 } | 85 } |
185 | 86 |
186 std::string SysInfo::GetAndroidBuildCodename() { | 87 std::string SysInfo::GetAndroidBuildCodename() { |
187 char os_version_codename_str[PROP_VALUE_MAX]; | 88 return android::BuildInfo::GetInstance()->build_version_codename(); |
188 __system_property_get("ro.build.version.codename", os_version_codename_str); | |
189 return std::string(os_version_codename_str); | |
190 } | 89 } |
191 | 90 |
192 std::string SysInfo::GetAndroidBuildID() { | 91 std::string SysInfo::GetAndroidBuildID() { |
193 char os_build_id_str[PROP_VALUE_MAX]; | 92 return android::BuildInfo::GetInstance()->build_id(); |
194 __system_property_get("ro.build.id", os_build_id_str); | |
195 return std::string(os_build_id_str); | |
196 } | 93 } |
197 | 94 |
198 int SysInfo::DalvikHeapSizeMB() { | 95 int SysInfo::DalvikHeapSizeMB() { |
199 static int heap_size = GetDalvikHeapSizeMB(); | 96 static int heap_size = GetDalvikHeapSizeMB(); |
200 return heap_size; | 97 return heap_size; |
201 } | 98 } |
202 | 99 |
203 int SysInfo::DalvikHeapGrowthLimitMB() { | |
204 static int heap_growth_limit = GetDalvikHeapGrowthLimitMB(); | |
205 return heap_growth_limit; | |
206 } | |
207 | |
208 static base::LazyInstance< | 100 static base::LazyInstance< |
209 base::internal::LazySysInfoValue<bool, | 101 base::internal::LazySysInfoValue<bool, |
210 android::SysUtils::IsLowEndDeviceFromJni> >::Leaky | 102 android::SysUtils::IsLowEndDeviceFromJni> >::Leaky |
211 g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER; | 103 g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER; |
212 | 104 |
213 bool SysInfo::IsLowEndDevice() { | 105 bool SysInfo::IsLowEndDevice() { |
214 return g_lazy_low_end_device.Get().value(); | 106 return g_lazy_low_end_device.Get().value(); |
215 } | 107 } |
216 | 108 |
217 | 109 |
218 } // namespace base | 110 } // namespace base |
OLD | NEW |