Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 package org.mozilla.gecko.util;
8 import android.content.Context;
9 import android.content.pm.PackageManager;
10 import android.content.res.Configuration;
11 import android.os.Build;
12 import android.util.Log;
13 import android.view.ViewConfiguration;
15 import java.io.FileInputStream;
16 import java.io.FileNotFoundException;
17 import java.io.IOException;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
21 public final class HardwareUtils {
22 private static final String LOGTAG = "GeckoHardwareUtils";
24 // Minimum memory threshold for a device to be considered
25 // a low memory platform (see isLowMemoryPlatform). This value
26 // has be in sync with Gecko's equivalent threshold (defined in
27 // xpcom/base/nsMemoryImpl.cpp) and should only be used in cases
28 // where we can't depend on Gecko to be up and running e.g. show/hide
29 // reading list capabilities in HomePager.
30 private static final int LOW_MEMORY_THRESHOLD_MB = 384;
32 // Number of bytes of /proc/meminfo to read in one go.
33 private static final int MEMINFO_BUFFER_SIZE_BYTES = 256;
35 private static volatile int sTotalRAM = -1;
37 private static Context sContext;
39 private static Boolean sIsLargeTablet;
40 private static Boolean sIsSmallTablet;
41 private static Boolean sIsTelevision;
42 private static Boolean sHasMenuButton;
44 private HardwareUtils() {
45 }
47 public static void init(Context context) {
48 if (sContext != null) {
49 Log.w(LOGTAG, "HardwareUtils.init called twice!");
50 }
51 sContext = context;
52 }
54 public static boolean isTablet() {
55 return isLargeTablet() || isSmallTablet();
56 }
58 public static boolean isLargeTablet() {
59 if (sIsLargeTablet == null) {
60 int screenLayout = sContext.getResources().getConfiguration().screenLayout;
61 sIsLargeTablet = (Build.VERSION.SDK_INT >= 11 &&
62 ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE));
63 }
64 return sIsLargeTablet;
65 }
67 public static boolean isSmallTablet() {
68 if (sIsSmallTablet == null) {
69 int screenLayout = sContext.getResources().getConfiguration().screenLayout;
70 sIsSmallTablet = (Build.VERSION.SDK_INT >= 11 &&
71 ((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE));
72 }
73 return sIsSmallTablet;
74 }
76 public static boolean isTelevision() {
77 if (sIsTelevision == null) {
78 sIsTelevision = sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION);
79 }
80 return sIsTelevision;
81 }
83 public static boolean hasMenuButton() {
84 if (sHasMenuButton == null) {
85 sHasMenuButton = Boolean.TRUE;
86 if (Build.VERSION.SDK_INT >= 11) {
87 sHasMenuButton = Boolean.FALSE;
88 }
89 if (Build.VERSION.SDK_INT >= 14) {
90 sHasMenuButton = ViewConfiguration.get(sContext).hasPermanentMenuKey();
91 }
92 }
93 return sHasMenuButton;
94 }
96 /**
97 * Helper functions used to extract key/value data from /proc/meminfo
98 * Pulled from:
99 * http://androidxref.com/4.2_r1/xref/frameworks/base/core/java/com/android/internal/util/MemInfoReader.java
100 */
102 private static boolean matchMemText(byte[] buffer, int index, int bufferLength, byte[] text) {
103 final int N = text.length;
104 if ((index + N) >= bufferLength) {
105 return false;
106 }
107 for (int i = 0; i < N; i++) {
108 if (buffer[index + i] != text[i]) {
109 return false;
110 }
111 }
112 return true;
113 }
115 /**
116 * Parses a line like:
117 *
118 * MemTotal: 1605324 kB
119 *
120 * into 1605324.
121 *
122 * @return the first uninterrupted sequence of digits following the
123 * specified index, parsed as an integer value in KB.
124 */
125 private static int extractMemValue(byte[] buffer, int offset, int length) {
126 if (offset >= length) {
127 return 0;
128 }
130 while (offset < length && buffer[offset] != '\n') {
131 if (buffer[offset] >= '0' && buffer[offset] <= '9') {
132 int start = offset++;
133 while (offset < length &&
134 buffer[offset] >= '0' &&
135 buffer[offset] <= '9') {
136 ++offset;
137 }
138 return Integer.parseInt(new String(buffer, start, offset - start), 10);
139 }
140 ++offset;
141 }
142 return 0;
143 }
145 /**
146 * Fetch the total memory of the device in MB by parsing /proc/meminfo.
147 *
148 * Of course, Android doesn't have a neat and tidy way to find total
149 * RAM, so we do it by parsing /proc/meminfo.
150 *
151 * @return 0 if a problem occurred, or memory size in MB.
152 */
153 public static int getMemSize() {
154 if (sTotalRAM >= 0) {
155 return sTotalRAM;
156 }
158 // This is the string "MemTotal" that we're searching for in the buffer.
159 final byte[] MEMTOTAL = {'M', 'e', 'm', 'T', 'o', 't', 'a', 'l'};
160 try {
161 final byte[] buffer = new byte[MEMINFO_BUFFER_SIZE_BYTES];
162 final FileInputStream is = new FileInputStream("/proc/meminfo");
163 try {
164 final int length = is.read(buffer);
166 for (int i = 0; i < length; i++) {
167 if (matchMemText(buffer, i, length, MEMTOTAL)) {
168 i += 8;
169 sTotalRAM = extractMemValue(buffer, i, length) / 1024;
170 Log.d(LOGTAG, "System memory: " + sTotalRAM + "MB.");
171 return sTotalRAM;
172 }
173 }
174 } finally {
175 is.close();
176 }
178 Log.w(LOGTAG, "Did not find MemTotal line in /proc/meminfo.");
179 return sTotalRAM = 0;
180 } catch (FileNotFoundException f) {
181 return sTotalRAM = 0;
182 } catch (IOException e) {
183 return sTotalRAM = 0;
184 }
185 }
187 public static boolean isLowMemoryPlatform() {
188 final int memSize = getMemSize();
190 // Fallback to false if we fail to read meminfo
191 // for some reason.
192 if (memSize == 0) {
193 Log.w(LOGTAG, "Could not compute system memory. Falling back to isLowMemoryPlatform = false.");
194 return false;
195 }
197 return memSize < LOW_MEMORY_THRESHOLD_MB;
198 }
199 }