| 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 |