Chromium Code Reviews| Index: base/android/java/src/org/chromium/base/SysUtils.java |
| diff --git a/base/android/java/src/org/chromium/base/SysUtils.java b/base/android/java/src/org/chromium/base/SysUtils.java |
| index 7af5a40069af8aaf09f499f2a2849aa73cc1576b..ea33438e843c2d20b39193592e38ed60dc45e7e9 100644 |
| --- a/base/android/java/src/org/chromium/base/SysUtils.java |
| +++ b/base/android/java/src/org/chromium/base/SysUtils.java |
| @@ -4,15 +4,30 @@ |
| package org.chromium.base; |
| +import java.io.BufferedReader; |
| +import java.io.FileReader; |
| +import java.util.regex.Matcher; |
| +import java.util.regex.Pattern; |
| + |
| import android.app.ActivityManager; |
| import android.app.ActivityManager.MemoryInfo; |
| import android.content.Context; |
| import android.os.Build; |
| +import android.util.Log; |
| /** |
| * Exposes system related information about the current device. |
| */ |
| public class SysUtils { |
| + // Any device that runs this or an older version of the system cannot be considered 'low-end' |
| + private static final int ANDROID_LOW_MEMORY_ANDROID_SDK_THRESHOLD = |
| + Build.VERSION_CODES.JELLY_BEAN_MR2; |
| + |
| + // A device reporting strictly more total memory in megabytes cannot be considered 'low-end'. |
| + private static final long ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB = 512; |
| + |
| + private static final String TAG = "SysUtils"; |
| + |
| private static Boolean sLowEndDevice; |
| private SysUtils() { } |
| @@ -20,11 +35,63 @@ public class SysUtils { |
| /** |
| * @return Whether or not this device should be considered a low end device. |
| */ |
| + @CalledByNative |
| public static boolean isLowEndDevice() { |
| - if (sLowEndDevice == null) sLowEndDevice = nativeIsLowEndDevice(); |
| + if (Build.VERSION.SDK_INT <= ANDROID_LOW_MEMORY_ANDROID_SDK_THRESHOLD) |
| + return false; |
| + |
| + if (sLowEndDevice == null) { |
| + boolean isLowEnd = false; |
| + |
| + // Extract total memory RAM size by parsing /proc/meminfo, note that |
|
bulach
2013/11/06 12:16:39
is /proc/meminfo always world readable?
an idea f
|
| + // this is exactly what the implementation of sysconf(_SC_PHYS_PAGES) |
| + // does. However, it can't be called because this method must be |
| + // usable before any native code is loaded. |
| + |
| + // An alternative is to use ActivityManager.getMemoryInfo(), but this |
| + // requires a valid ActivityManager handle, which can only come from |
| + // a valid Context object, which itself cannot be retrieved |
| + // during early startup, where this method is called. And making it |
| + // an explicit parameter here makes all call paths _much_ more |
| + // complicated. |
| + |
| + Pattern pattern = Pattern.compile("^MemTotal:\\s+([0-9]+) kB$"); |
| + try { |
| + FileReader fileReader = new FileReader("/proc/meminfo"); |
| + try { |
| + BufferedReader reader = new BufferedReader(fileReader); |
| + String line; |
| + for (;;) { |
| + line = reader.readLine(); |
| + if (line == null) |
| + break; |
| + |
| + Matcher m = pattern.matcher(line); |
| + if (!m.find()) |
| + continue; |
| + |
| + long totalMemoryKiloBytes = Long.parseLong(m.group(1)); |
| + |
| + // Sanity check. |
| + if (totalMemoryKiloBytes <= 1024) { |
| + Log.w(TAG, "Invalid /proc/meminfo total size in kB: " + m.group(1)); |
| + break; |
| + } |
| + long totalMemoryMegaBytes = totalMemoryKiloBytes * 1024; |
| + isLowEnd = (totalMemoryMegaBytes < ANDROID_LOW_MEMORY_DEVICE_THRESHOLD_MB); |
| + break; |
| + } |
| + } finally { |
| + fileReader.close(); |
| + } |
| + } catch (Exception e) { |
| + // In case of error, assume this is _not_ a low-end device. |
| + Log.w(TAG, "Cannot get total physical size from /proc/meminfo", e); |
| + } |
| + |
| + sLowEndDevice = isLowEnd; |
| + } |
| return sLowEndDevice.booleanValue(); |
| } |
| - |
| - private static native boolean nativeIsLowEndDevice(); |
| } |