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
3// found in the LICENSE file.
4
5#include "base/sys_info.h"
6
7#include <sys/system_properties.h>
8
9#include "base/logging.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_piece.h"
12#include "base/strings/stringprintf.h"
13
14namespace {
15
16// Default version of Android to fall back to when actual version numbers
17// cannot be acquired.
18// TODO(dfalcantara): Keep this reasonably up to date with the latest publicly
19//                    available version of Android.
20const int kDefaultAndroidMajorVersion = 4;
21const int kDefaultAndroidMinorVersion = 3;
22const int kDefaultAndroidBugfixVersion = 0;
23
24// Parse out the OS version numbers from the system properties.
25void ParseOSVersionNumbers(const char* os_version_str,
26                           int32 *major_version,
27                           int32 *minor_version,
28                           int32 *bugfix_version) {
29  if (os_version_str[0]) {
30    // Try to parse out the version numbers from the string.
31    int num_read = sscanf(os_version_str, "%d.%d.%d", major_version,
32                          minor_version, bugfix_version);
33
34    if (num_read > 0) {
35      // If we don't have a full set of version numbers, make the extras 0.
36      if (num_read < 2) *minor_version = 0;
37      if (num_read < 3) *bugfix_version = 0;
38      return;
39    }
40  }
41
42  // For some reason, we couldn't parse the version number string.
43  *major_version = kDefaultAndroidMajorVersion;
44  *minor_version = kDefaultAndroidMinorVersion;
45  *bugfix_version = kDefaultAndroidBugfixVersion;
46}
47
48// Parses a system property (specified with unit 'k','m' or 'g').
49// Returns a value in bytes.
50// Returns -1 if the string could not be parsed.
51int64 ParseSystemPropertyBytes(const base::StringPiece& str) {
52  const int64 KB = 1024;
53  const int64 MB = 1024 * KB;
54  const int64 GB = 1024 * MB;
55  if (str.size() == 0u)
56    return -1;
57  int64 unit_multiplier = 1;
58  size_t length = str.size();
59  if (str[length - 1] == 'k') {
60    unit_multiplier = KB;
61    length--;
62  } else if (str[length - 1] == 'm') {
63    unit_multiplier = MB;
64    length--;
65  } else if (str[length - 1] == 'g') {
66    unit_multiplier = GB;
67    length--;
68  }
69  int64 result = 0;
70  bool parsed = base::StringToInt64(str.substr(0, length), &result);
71  bool negative = result <= 0;
72  bool overflow = result >= std::numeric_limits<int64>::max() / unit_multiplier;
73  if (!parsed || negative || overflow)
74    return -1;
75  return result * unit_multiplier;
76}
77
78int GetDalvikHeapSizeMB() {
79  char heap_size_str[PROP_VALUE_MAX];
80  __system_property_get("dalvik.vm.heapsize", heap_size_str);
81  // dalvik.vm.heapsize property is writable by a root user.
82  // Clamp it to reasonable range as a sanity check,
83  // a typical android device will never have less than 48MB.
84  const int64 MB = 1024 * 1024;
85  int64 result = ParseSystemPropertyBytes(heap_size_str);
86  if (result == -1) {
87     // We should consider not exposing these values if they are not reliable.
88     LOG(ERROR) << "Can't parse dalvik.vm.heapsize: " << heap_size_str;
89     result = base::SysInfo::AmountOfPhysicalMemoryMB() / 3;
90  }
91  result = std::min<int64>(std::max<int64>(32 * MB, result), 1024 * MB) / MB;
92  return static_cast<int>(result);
93}
94
95int GetDalvikHeapGrowthLimitMB() {
96  char heap_size_str[PROP_VALUE_MAX];
97  __system_property_get("dalvik.vm.heapgrowthlimit", heap_size_str);
98  // dalvik.vm.heapgrowthlimit property is writable by a root user.
99  // Clamp it to reasonable range as a sanity check,
100  // a typical android device will never have less than 24MB.
101  const int64 MB = 1024 * 1024;
102  int64 result = ParseSystemPropertyBytes(heap_size_str);
103  if (result == -1) {
104     // We should consider not exposing these values if they are not reliable.
105     LOG(ERROR) << "Can't parse dalvik.vm.heapgrowthlimit: " << heap_size_str;
106     result = base::SysInfo::AmountOfPhysicalMemoryMB() / 6;
107  }
108  result = std::min<int64>(std::max<int64>(16 * MB, result), 512 * MB) / MB;
109  return static_cast<int>(result);
110}
111
112}  // anonymous namespace
113
114namespace base {
115
116std::string SysInfo::OperatingSystemName() {
117  return "Android";
118}
119
120std::string SysInfo::GetAndroidBuildCodename() {
121  char os_version_codename_str[PROP_VALUE_MAX];
122  __system_property_get("ro.build.version.codename", os_version_codename_str);
123  return std::string(os_version_codename_str);
124}
125
126std::string SysInfo::GetAndroidBuildID() {
127  char os_build_id_str[PROP_VALUE_MAX];
128  __system_property_get("ro.build.id", os_build_id_str);
129  return std::string(os_build_id_str);
130}
131
132std::string SysInfo::GetDeviceName() {
133  char device_model_str[PROP_VALUE_MAX];
134  __system_property_get("ro.product.model", device_model_str);
135  return std::string(device_model_str);
136}
137
138std::string SysInfo::OperatingSystemVersion() {
139  int32 major, minor, bugfix;
140  OperatingSystemVersionNumbers(&major, &minor, &bugfix);
141  return StringPrintf("%d.%d.%d", major, minor, bugfix);
142}
143
144void SysInfo::OperatingSystemVersionNumbers(int32* major_version,
145                                            int32* minor_version,
146                                            int32* bugfix_version) {
147  // Read the version number string out from the properties.
148  char os_version_str[PROP_VALUE_MAX];
149  __system_property_get("ro.build.version.release", os_version_str);
150
151  // Parse out the numbers.
152  ParseOSVersionNumbers(os_version_str, major_version, minor_version,
153                        bugfix_version);
154}
155
156int SysInfo::DalvikHeapSizeMB() {
157  static int heap_size = GetDalvikHeapSizeMB();
158  return heap_size;
159}
160
161int SysInfo::DalvikHeapGrowthLimitMB() {
162  static int heap_growth_limit = GetDalvikHeapGrowthLimitMB();
163  return heap_growth_limit;
164}
165
166
167}  // namespace base
168