blob: f60f024fdb29c1c8e4e9d4079c5cb378d2fb1756 [file] [log] [blame]
[email protected]5702108f2012-05-25 15:31:371// 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
3// found in the LICENSE file.
4
5#include "base/sys_info.h"
6
[email protected]2e4045d2014-07-18 05:41:547#include <dlfcn.h>
avi9b6f42932015-12-26 22:15:148#include <stddef.h>
9#include <stdint.h>
[email protected]5702108f2012-05-25 15:31:3710#include <sys/system_properties.h>
11
svaisanen2e4bd662016-04-11 07:34:2112#include "base/android/jni_android.h"
[email protected]35b4f0c2014-06-26 16:55:2713#include "base/android/sys_utils.h"
14#include "base/lazy_instance.h"
[email protected]5702108f2012-05-25 15:31:3715#include "base/logging.h"
[email protected]dfa049e2013-02-07 02:57:2216#include "base/strings/string_number_conversions.h"
[email protected]eb62f7262013-03-30 14:29:0017#include "base/strings/string_piece.h"
Guido Urdaneta84618ee2018-08-30 10:32:3718#include "base/strings/string_util.h"
[email protected]c851cfd2013-06-10 20:11:1419#include "base/strings/stringprintf.h"
[email protected]35b4f0c2014-06-26 16:55:2720#include "base/sys_info_internal.h"
[email protected]5702108f2012-05-25 15:31:3721
fdegans27660a32014-10-24 13:00:1822#if (__ANDROID_API__ >= 21 /* 5.0 - Lollipop */)
[email protected]2e4045d2014-07-18 05:41:5423
24namespace {
25
26typedef int (SystemPropertyGetFunction)(const char*, char*);
27
28SystemPropertyGetFunction* DynamicallyLoadRealSystemPropertyGet() {
29 // libc.so should already be open, get a handle to it.
30 void* handle = dlopen("libc.so", RTLD_NOLOAD);
31 if (!handle) {
32 LOG(FATAL) << "Cannot dlopen libc.so: " << dlerror();
33 }
34 SystemPropertyGetFunction* real_system_property_get =
35 reinterpret_cast<SystemPropertyGetFunction*>(
36 dlsym(handle, "__system_property_get"));
37 if (!real_system_property_get) {
38 LOG(FATAL) << "Cannot resolve __system_property_get(): " << dlerror();
39 }
40 return real_system_property_get;
41}
42
43static base::LazyInstance<base::internal::LazySysInfoValue<
44 SystemPropertyGetFunction*, DynamicallyLoadRealSystemPropertyGet> >::Leaky
45 g_lazy_real_system_property_get = LAZY_INSTANCE_INITIALIZER;
46
47} // namespace
48
49// Android 'L' removes __system_property_get from the NDK, however it is still
50// a hidden symbol in libc. Until we remove all calls of __system_property_get
51// from Chrome we work around this by defining a weak stub here, which uses
52// dlsym to but ensures that Chrome uses the real system
53// implementatation when loaded. http://crbug.com/392191.
fdegans3c7624d62015-01-07 16:17:4754BASE_EXPORT int __system_property_get(const char* name, char* value) {
[email protected]2e4045d2014-07-18 05:41:5455 return g_lazy_real_system_property_get.Get().value()(name, value);
56}
57
58#endif
59
[email protected]5702108f2012-05-25 15:31:3760namespace {
61
[email protected]abef4b332012-08-21 23:55:5262// Default version of Android to fall back to when actual version numbers
[email protected]de874b42014-07-10 08:05:2163// cannot be acquired. Use the latest Android release with a higher bug fix
64// version to avoid unnecessarily comparison errors with the latest release.
thakis3e861de2016-06-14 14:24:0165// This should be manually kept up to date on each Android release.
Bo Liu447e316f2017-10-26 19:08:4466const int kDefaultAndroidMajorVersion = 8;
67const int kDefaultAndroidMinorVersion = 1;
[email protected]de874b42014-07-10 08:05:2168const int kDefaultAndroidBugfixVersion = 99;
[email protected]abef4b332012-08-21 23:55:5269
Bo Liu4f2b4e142017-05-26 21:41:5170// Get and parse out the OS version numbers from the system properties.
71// Note if parse fails, the "default" version is returned as fallback.
72void GetOsVersionStringAndNumbers(std::string* version_string,
73 int32_t* major_version,
74 int32_t* minor_version,
75 int32_t* bugfix_version) {
76 // Read the version number string out from the properties.
77 char os_version_str[PROP_VALUE_MAX];
78 __system_property_get("ro.build.version.release", os_version_str);
79
[email protected]abef4b332012-08-21 23:55:5280 if (os_version_str[0]) {
81 // Try to parse out the version numbers from the string.
82 int num_read = sscanf(os_version_str, "%d.%d.%d", major_version,
83 minor_version, bugfix_version);
84
85 if (num_read > 0) {
86 // If we don't have a full set of version numbers, make the extras 0.
Bo Liu4f2b4e142017-05-26 21:41:5187 if (num_read < 2)
88 *minor_version = 0;
89 if (num_read < 3)
90 *bugfix_version = 0;
91 *version_string = std::string(os_version_str);
[email protected]abef4b332012-08-21 23:55:5292 return;
93 }
94 }
95
96 // For some reason, we couldn't parse the version number string.
97 *major_version = kDefaultAndroidMajorVersion;
98 *minor_version = kDefaultAndroidMinorVersion;
99 *bugfix_version = kDefaultAndroidBugfixVersion;
Bo Liu4f2b4e142017-05-26 21:41:51100 *version_string = ::base::StringPrintf("%d.%d.%d", *major_version,
101 *minor_version, *bugfix_version);
[email protected]abef4b332012-08-21 23:55:52102}
103
[email protected]0cea3552013-02-16 18:15:50104// Parses a system property (specified with unit 'k','m' or 'g').
105// Returns a value in bytes.
106// Returns -1 if the string could not be parsed.
avidd4e614352015-12-09 00:44:49107int64_t ParseSystemPropertyBytes(const base::StringPiece& str) {
108 const int64_t KB = 1024;
109 const int64_t MB = 1024 * KB;
110 const int64_t GB = 1024 * MB;
[email protected]0cea3552013-02-16 18:15:50111 if (str.size() == 0u)
112 return -1;
avidd4e614352015-12-09 00:44:49113 int64_t unit_multiplier = 1;
[email protected]5702108f2012-05-25 15:31:37114 size_t length = str.size();
115 if (str[length - 1] == 'k') {
[email protected]0cea3552013-02-16 18:15:50116 unit_multiplier = KB;
[email protected]5702108f2012-05-25 15:31:37117 length--;
118 } else if (str[length - 1] == 'm') {
[email protected]0cea3552013-02-16 18:15:50119 unit_multiplier = MB;
[email protected]5702108f2012-05-25 15:31:37120 length--;
121 } else if (str[length - 1] == 'g') {
[email protected]0cea3552013-02-16 18:15:50122 unit_multiplier = GB;
[email protected]5702108f2012-05-25 15:31:37123 length--;
[email protected]5702108f2012-05-25 15:31:37124 }
avidd4e614352015-12-09 00:44:49125 int64_t result = 0;
[email protected]5702108f2012-05-25 15:31:37126 bool parsed = base::StringToInt64(str.substr(0, length), &result);
[email protected]0cea3552013-02-16 18:15:50127 bool negative = result <= 0;
avidd4e614352015-12-09 00:44:49128 bool overflow =
129 result >= std::numeric_limits<int64_t>::max() / unit_multiplier;
[email protected]0cea3552013-02-16 18:15:50130 if (!parsed || negative || overflow)
131 return -1;
132 return result * unit_multiplier;
[email protected]5702108f2012-05-25 15:31:37133}
134
135int GetDalvikHeapSizeMB() {
136 char heap_size_str[PROP_VALUE_MAX];
137 __system_property_get("dalvik.vm.heapsize", heap_size_str);
[email protected]0cea3552013-02-16 18:15:50138 // dalvik.vm.heapsize property is writable by a root user.
139 // Clamp it to reasonable range as a sanity check,
140 // a typical android device will never have less than 48MB.
avidd4e614352015-12-09 00:44:49141 const int64_t MB = 1024 * 1024;
142 int64_t result = ParseSystemPropertyBytes(heap_size_str);
[email protected]0cea3552013-02-16 18:15:50143 if (result == -1) {
144 // We should consider not exposing these values if they are not reliable.
145 LOG(ERROR) << "Can't parse dalvik.vm.heapsize: " << heap_size_str;
146 result = base::SysInfo::AmountOfPhysicalMemoryMB() / 3;
147 }
avidd4e614352015-12-09 00:44:49148 result =
149 std::min<int64_t>(std::max<int64_t>(32 * MB, result), 1024 * MB) / MB;
[email protected]0cea3552013-02-16 18:15:50150 return static_cast<int>(result);
151}
152
153int GetDalvikHeapGrowthLimitMB() {
154 char heap_size_str[PROP_VALUE_MAX];
155 __system_property_get("dalvik.vm.heapgrowthlimit", heap_size_str);
156 // dalvik.vm.heapgrowthlimit property is writable by a root user.
157 // Clamp it to reasonable range as a sanity check,
158 // a typical android device will never have less than 24MB.
avidd4e614352015-12-09 00:44:49159 const int64_t MB = 1024 * 1024;
160 int64_t result = ParseSystemPropertyBytes(heap_size_str);
[email protected]0cea3552013-02-16 18:15:50161 if (result == -1) {
162 // We should consider not exposing these values if they are not reliable.
163 LOG(ERROR) << "Can't parse dalvik.vm.heapgrowthlimit: " << heap_size_str;
164 result = base::SysInfo::AmountOfPhysicalMemoryMB() / 6;
165 }
avidd4e614352015-12-09 00:44:49166 result = std::min<int64_t>(std::max<int64_t>(16 * MB, result), 512 * MB) / MB;
[email protected]0cea3552013-02-16 18:15:50167 return static_cast<int>(result);
[email protected]5702108f2012-05-25 15:31:37168}
169
Guido Urdaneta84618ee2018-08-30 10:32:37170std::string HardwareManufacturerName() {
171 char device_model_str[PROP_VALUE_MAX];
172 __system_property_get("ro.product.manufacturer", device_model_str);
173 return std::string(device_model_str);
174}
175
[email protected]5702108f2012-05-25 15:31:37176} // anonymous namespace
177
178namespace base {
179
tdresserae4166952015-07-16 15:41:04180std::string SysInfo::HardwareModelName() {
[email protected]abef4b332012-08-21 23:55:52181 char device_model_str[PROP_VALUE_MAX];
182 __system_property_get("ro.product.model", device_model_str);
183 return std::string(device_model_str);
184}
185
tdresserae4166952015-07-16 15:41:04186std::string SysInfo::OperatingSystemName() {
187 return "Android";
188}
189
[email protected]82aeeaa2013-05-07 04:52:45190std::string SysInfo::OperatingSystemVersion() {
Bo Liu4f2b4e142017-05-26 21:41:51191 std::string version_string;
avidd4e614352015-12-09 00:44:49192 int32_t major, minor, bugfix;
Bo Liu4f2b4e142017-05-26 21:41:51193 GetOsVersionStringAndNumbers(&version_string, &major, &minor, &bugfix);
194 return version_string;
[email protected]82aeeaa2013-05-07 04:52:45195}
196
avidd4e614352015-12-09 00:44:49197void SysInfo::OperatingSystemVersionNumbers(int32_t* major_version,
198 int32_t* minor_version,
199 int32_t* bugfix_version) {
Bo Liu4f2b4e142017-05-26 21:41:51200 std::string version_string;
201 GetOsVersionStringAndNumbers(&version_string, major_version, minor_version,
202 bugfix_version);
[email protected]abef4b332012-08-21 23:55:52203}
204
tdresserae4166952015-07-16 15:41:04205std::string SysInfo::GetAndroidBuildCodename() {
206 char os_version_codename_str[PROP_VALUE_MAX];
207 __system_property_get("ro.build.version.codename", os_version_codename_str);
208 return std::string(os_version_codename_str);
209}
210
211std::string SysInfo::GetAndroidBuildID() {
212 char os_build_id_str[PROP_VALUE_MAX];
213 __system_property_get("ro.build.id", os_build_id_str);
214 return std::string(os_build_id_str);
215}
216
[email protected]5702108f2012-05-25 15:31:37217int SysInfo::DalvikHeapSizeMB() {
218 static int heap_size = GetDalvikHeapSizeMB();
219 return heap_size;
220}
221
[email protected]0cea3552013-02-16 18:15:50222int SysInfo::DalvikHeapGrowthLimitMB() {
223 static int heap_growth_limit = GetDalvikHeapGrowthLimitMB();
224 return heap_growth_limit;
225}
226
[email protected]35b4f0c2014-06-26 16:55:27227static base::LazyInstance<
228 base::internal::LazySysInfoValue<bool,
229 android::SysUtils::IsLowEndDeviceFromJni> >::Leaky
230 g_lazy_low_end_device = LAZY_INSTANCE_INITIALIZER;
231
Eric Karl6c24049a2018-03-13 16:34:03232bool SysInfo::IsLowEndDeviceImpl() {
svaisanen2e4bd662016-04-11 07:34:21233 // This code might be used in some environments
234 // which might not have a Java environment.
235 // Note that we need to call the Java version here.
236 // There exists a complete native implementation in
237 // sys_info.cc but calling that here would mean that
238 // the Java code and the native code would call different
239 // implementations which could give different results.
240 // Also the Java code cannot depend on the native code
241 // since it might not be loaded yet.
242 if (!base::android::IsVMInitialized())
243 return false;
[email protected]35b4f0c2014-06-26 16:55:27244 return g_lazy_low_end_device.Get().value();
245}
246
Guido Urdaneta84618ee2018-08-30 10:32:37247// static
248SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
249 HardwareInfo info;
250 info.manufacturer = HardwareManufacturerName();
251 info.model = HardwareModelName();
252 DCHECK(IsStringUTF8(info.manufacturer));
253 DCHECK(IsStringUTF8(info.model));
254 return info;
255}
[email protected]0cea3552013-02-16 18:15:50256
[email protected]5702108f2012-05-25 15:31:37257} // namespace base