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