#filter substitution /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.gecko; import android.os.StrictMode; import android.util.Log; import java.io.File; import java.io.FileFilter; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * A collection of system info values, broadly mirroring a subset of * nsSystemInfo. See also the constants in AppConstants, which reflect * much of nsIXULAppInfo. */ public final class SysInfo { private static final String LOG_TAG = "GeckoSysInfo"; // We don't mind an instant of possible duplicate work, we only wish to // avoid inconsistency, so we don't bother with synchronization for // these. private static volatile int cpuCount = -1; private static volatile int totalRAM = -1; /** * Get the number of cores on the device. * * We can't use a nice tidy API call, because they're all wrong: * * * * This method is based on that code. * * @return the number of CPU cores, or 1 if the number could not be * determined. */ public static int getCPUCount() { if (cpuCount > 0) { return cpuCount; } if (android.os.Build.VERSION.SDK_INT < 9) { return readCPUCount(); } // Avoid a strict mode warning... but only on devices that have StrictMode. StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads(); try { return readCPUCount(); } finally { StrictMode.setThreadPolicy(savedPolicy); } } private static int readCPUCount() { class CpuFilter implements FileFilter { @Override public boolean accept(File pathname) { return Pattern.matches("cpu[0-9]+", pathname.getName()); } } try { final File dir = new File("/sys/devices/system/cpu/"); return cpuCount = dir.listFiles(new CpuFilter()).length; } catch (Exception e) { Log.w(LOG_TAG, "Assuming 1 CPU; got exception.", e); return cpuCount = 1; } } /** * Fetch the total memory of the device in MB by parsing /proc/meminfo. * * Of course, Android doesn't have a neat and tidy way to find total * RAM, so we do it by parsing /proc/meminfo. * * @return 0 if a problem occurred, or memory size in MB. */ public static int getMemSize() { if (totalRAM >= 0) { return totalRAM; } try { RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r"); try { // MemTotal will be one of the first three lines. int i = 0; String memTotal = null; while (i++ < 3) { memTotal = reader.readLine(); if (memTotal == null || memTotal.startsWith("MemTotal: ")) { break; } memTotal = null; } if (memTotal == null) { return totalRAM = 0; } // Parse a line like this: // MemTotal: 1605324 kB Matcher m = Pattern.compile("^MemTotal:\\s+([0-9]+) kB\\s*$") .matcher(memTotal); if (m.matches()) { String kb = m.group(1); if (kb != null) { return totalRAM = (Integer.parseInt(kb) / 1024); } } Log.w(LOG_TAG, "Got unexpected MemTotal line: " + memTotal); return totalRAM = 0; } finally { reader.close(); } } catch (FileNotFoundException f) { return totalRAM = 0; } catch (IOException e) { return totalRAM = 0; } } /** * @return the SDK version supported by this device, such as '16'. */ public static int getVersion() { return android.os.Build.VERSION.SDK_INT; } /** * @return the release version string, such as "4.1.2". */ public static String getReleaseVersion() { return android.os.Build.VERSION.RELEASE; } /** * @return the device manufacturer, such as "HTC". */ public static String getManufacturer() { return android.os.Build.MANUFACTURER; } /** * @return the device name, such as "HTC One". */ public static String getDevice() { // No, not android.os.Build.DEVICE. return android.os.Build.MODEL; } /** * @return the Android "hardware" identifier, such as "m7". */ public static String getHardware() { return android.os.Build.HARDWARE; } /** * @return the system OS name. Hardcoded to "Android". */ public static String getName() { // We deliberately differ from PR_SI_SYSNAME, which is "Linux". return "Android"; } /** * @return the architecture string, excluding ABI. */ public static String getArch() { return "@CPU_ARCH@"; // "arm" } /** * @return the Android architecture string, including ABI. */ public static String getArchABI() { // Android likes to include the ABI, too ("armeabiv7"), so we // differ to add value. return android.os.Build.CPU_ABI; } }