| Index: base/sys_info_android.cc
|
| diff --git a/base/sys_info_android.cc b/base/sys_info_android.cc
|
| index 53801703845c972ff6449fea1da152427af674e5..5d4eff0135fde9f2a274cbec58c58907677edc6b 100644
|
| --- a/base/sys_info_android.cc
|
| +++ b/base/sys_info_android.cc
|
| @@ -44,39 +44,68 @@ void ParseOSVersionNumbers(const char* os_version_str,
|
| *bugfix_version = kDefaultAndroidBugfixVersion;
|
| }
|
|
|
| -int ParseHeapSize(const base::StringPiece& str) {
|
| +// Parses a system property (specified with unit 'k','m' or 'g').
|
| +// Returns a value in bytes.
|
| +// Returns -1 if the string could not be parsed.
|
| +int64 ParseSystemPropertyBytes(const base::StringPiece& str) {
|
| const int64 KB = 1024;
|
| const int64 MB = 1024 * KB;
|
| const int64 GB = 1024 * MB;
|
| - CHECK_GT(str.size(), 0u);
|
| - int64 factor = 1;
|
| + if (str.size() == 0u)
|
| + return -1;
|
| + int64 unit_multiplier = 1;
|
| size_t length = str.size();
|
| if (str[length - 1] == 'k') {
|
| - factor = KB;
|
| + unit_multiplier = KB;
|
| length--;
|
| } else if (str[length - 1] == 'm') {
|
| - factor = MB;
|
| + unit_multiplier = MB;
|
| length--;
|
| } else if (str[length - 1] == 'g') {
|
| - factor = GB;
|
| + unit_multiplier = GB;
|
| length--;
|
| - } else {
|
| - CHECK('0' <= str[length - 1] && str[length - 1] <= '9');
|
| }
|
| int64 result = 0;
|
| bool parsed = base::StringToInt64(str.substr(0, length), &result);
|
| - CHECK(parsed);
|
| - result = result * factor / MB;
|
| - // dalvik.vm.heapsize property is writable by user,
|
| - // truncate it to reasonable value to avoid overflows later.
|
| - result = std::min<int64>(std::max<int64>(32, result), 1024);
|
| - return static_cast<int>(result);
|
| + bool negative = result <= 0;
|
| + bool overflow = result >= std::numeric_limits<int64>::max() / unit_multiplier;
|
| + if (!parsed || negative || overflow)
|
| + return -1;
|
| + return result * unit_multiplier;
|
| }
|
|
|
| int GetDalvikHeapSizeMB() {
|
| char heap_size_str[PROP_VALUE_MAX];
|
| __system_property_get("dalvik.vm.heapsize", heap_size_str);
|
| - return ParseHeapSize(heap_size_str);
|
| + // dalvik.vm.heapsize property is writable by a root user.
|
| + // Clamp it to reasonable range as a sanity check,
|
| + // a typical android device will never have less than 48MB.
|
| + const int64 MB = 1024 * 1024;
|
| + int64 result = ParseSystemPropertyBytes(heap_size_str);
|
| + if (result == -1) {
|
| + // We should consider not exposing these values if they are not reliable.
|
| + LOG(ERROR) << "Can't parse dalvik.vm.heapsize: " << heap_size_str;
|
| + result = base::SysInfo::AmountOfPhysicalMemoryMB() / 3;
|
| + }
|
| + result = std::min<int64>(std::max<int64>(32 * MB, result), 1024 * MB) / MB;
|
| + return static_cast<int>(result);
|
| +}
|
| +
|
| +int GetDalvikHeapGrowthLimitMB() {
|
| + char heap_size_str[PROP_VALUE_MAX];
|
| + __system_property_get("dalvik.vm.heapgrowthlimit", heap_size_str);
|
| + // dalvik.vm.heapgrowthlimit property is writable by a root user.
|
| + // Clamp it to reasonable range as a sanity check,
|
| + // a typical android device will never have less than 24MB.
|
| + const int64 MB = 1024 * 1024;
|
| + int64 result = ParseSystemPropertyBytes(heap_size_str);
|
| + if (result == -1) {
|
| + // We should consider not exposing these values if they are not reliable.
|
| + LOG(ERROR) << "Can't parse dalvik.vm.heapgrowthlimit: " << heap_size_str;
|
| + result = base::SysInfo::AmountOfPhysicalMemoryMB() / 6;
|
| + }
|
| + result = std::min<int64>(std::max<int64>(16 * MB, result), 512 * MB) / MB;
|
| + return static_cast<int>(result);
|
| }
|
|
|
| } // anonymous namespace
|
| @@ -122,4 +151,10 @@ int SysInfo::DalvikHeapSizeMB() {
|
| return heap_size;
|
| }
|
|
|
| +int SysInfo::DalvikHeapGrowthLimitMB() {
|
| + static int heap_growth_limit = GetDalvikHeapGrowthLimitMB();
|
| + return heap_growth_limit;
|
| +}
|
| +
|
| +
|
| } // namespace base
|
|
|