package org.andengine.util.system;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Scanner;
import java.util.regex.MatchResult;
import org.andengine.util.StreamUtils;
import org.andengine.util.adt.data.constants.DataConstants;
import org.andengine.util.exception.AndEngineException;
import org.andengine.util.exception.MethodNotFoundException;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
import android.os.Debug.MemoryInfo;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 15:50:31 - 14.07.2010
*/
public final class SystemUtils {
// ===========================================================
// Constants
// ===========================================================
public static final boolean SDK_VERSION_ECLAIR_OR_LATER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR;
public static final boolean SDK_VERSION_FROYO_OR_LATER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO;
public static final boolean SDK_VERSION_GINGERBREAD_OR_LATER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD;
public static final boolean SDK_VERSION_HONEYCOMB_OR_LATER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
public static final boolean SDK_VERSION_ICE_CREAM_SANDWICH_OR_LATER = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
private static final String BOGOMIPS_PATTERN = "BogoMIPS[\\s]*:[\\s]*(\\d+\\.\\d+)[\\s]*\n";
private static final String MEMTOTAL_PATTERN = "MemTotal[\\s]*:[\\s]*(\\d+)[\\s]*kB\n";
private static final String MEMFREE_PATTERN = "MemFree[\\s]*:[\\s]*(\\d+)[\\s]*kB\n";
// ===========================================================
// Fields
// ===========================================================
private static MemoryInfo sMemoryInfo;
// ===========================================================
// Constructors
// ===========================================================
private SystemUtils() {
}
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public static boolean isEmulator() {
if (Build.PRODUCT != null && Build.PRODUCT.equals("google_sdk")) {
return true;
} else if (Build.MODEL != null && Build.MODEL.equals("google_sdk")) {
return true;
} else if (Build.BRAND != null && Build.BRAND.startsWith("generic")){
return true;
} else if (Build.DEVICE != null && Build.DEVICE.startsWith("generic")) {
return true;
} else {
return false;
}
}
public static MemoryInfo getMemoryInfo() {
/* Lazy allocation. */
if (SystemUtils.sMemoryInfo == null) {
SystemUtils.sMemoryInfo = new MemoryInfo();
}
Debug.getMemoryInfo(SystemUtils.sMemoryInfo);
return SystemUtils.sMemoryInfo;
}
public static boolean isGoogleTV(final Context pContext) throws SystemUtilsException {
return SystemUtils.hasSystemFeature(pContext, "com.google.android.tv");
}
public static boolean isGoogleTV(final Context pContext, final boolean pDefault) {
try {
return SystemUtils.isGoogleTV(pContext);
} catch (final SystemUtilsException e) {
return pDefault;
}
}
public static boolean hasCamera(final Context pContext) throws SystemUtilsException {
return SystemUtils.hasSystemFeature(pContext, PackageManager.FEATURE_CAMERA);
}
public static boolean hasCamera(final Context pContext, final boolean pDefault) {
try {
return SystemUtils.hasCamera(pContext);
} catch (final SystemUtilsException e) {
return pDefault;
}
}
public static boolean isNDKSupported(final Context pContext, final boolean pDefault) {
try {
if (SystemUtils.isGoogleTV(pContext)) {
if (SystemUtils.isAndroidVersionOrHigher(Build.VERSION_CODES.JELLY_BEAN_MR1)) {
return true;
} else {
return false;
}
} else {
return true;
}
} catch (final SystemUtilsException e) {
return pDefault;
}
}
public static String getApplicationLabel(final Context pContext) throws SystemUtilsException {
final int labelResID = SystemUtils.getApplicationInfo(pContext).labelRes;
return pContext.getString(labelResID);
}
public static int getPackageVersionCode(final Context pContext) throws SystemUtilsException {
return SystemUtils.getPackageInfo(pContext).versionCode;
}
public static String getPackageVersionName(final Context pContext) throws SystemUtilsException {
return SystemUtils.getPackageInfo(pContext).versionName;
}
public static String getPackageName(final Context pContext) {
return pContext.getPackageName();
}
public static String getApkFilePath(final Context pContext) throws SystemUtilsException {
return SystemUtils.getApplicationInfo(pContext, 0).sourceDir;
}
public static ApplicationInfo getApplicationInfo(final Context pContext) throws SystemUtilsException {
return SystemUtils.getApplicationInfo(pContext, 0);
}
public static ApplicationInfo getApplicationInfo(final Context pContext, final int pFlags) throws SystemUtilsException {
try {
return pContext.getPackageManager().getApplicationInfo(pContext.getPackageName(), pFlags);
} catch (final NameNotFoundException e) {
throw new SystemUtilsException(e);
}
}
public static PackageInfo getPackageInfo(final Context pContext) throws SystemUtilsException {
return SystemUtils.getPackageInfo(pContext, 0);
}
public static PackageInfo getPackageInfo(final Context pContext, final int pFlags) throws SystemUtilsException {
try {
return pContext.getPackageManager().getPackageInfo(pContext.getPackageName(), pFlags);
} catch (final NameNotFoundException e) {
throw new SystemUtilsException(e);
}
}
public static int getTargetSDKVersion(final Context pContext) throws SystemUtilsException {
return SystemUtils.getApplicationInfo(pContext).targetSdkVersion;
}
public static boolean hasSystemFeature(final Context pContext, final String pFeature) throws SystemUtilsException {
final PackageManager packageManager = pContext.getPackageManager();
try {
try {
return packageManager.hasSystemFeature(pFeature);
} catch (final Throwable t) {
final Method PackageManager_hasSystemFeatures = PackageManager.class.getMethod("hasSystemFeature", String.class);
if (PackageManager_hasSystemFeatures == null) {
throw new SystemUtilsException(new MethodNotFoundException(PackageManager.class.getSimpleName() + ".hasSystemFeature(String)"));
} else {
final boolean result = (Boolean) PackageManager_hasSystemFeatures.invoke(packageManager, pFeature);
return result;
}
}
} catch (final Throwable t) {
throw new SystemUtilsException(t);
}
}
public static boolean hasSystemFeature(final Context pContext, final String pFeature, final boolean pDefault) {
try {
return SystemUtils.hasSystemFeature(pContext, pFeature);
} catch (final SystemUtilsException e) {
return pDefault;
}
}
public static boolean optMetaDataBoolean(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return bundle.getBoolean(pKey);
}
public static boolean optMetaDataBoolean(final Context pContext, final String pKey, final boolean pDefaultValue) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return bundle.getBoolean(pKey, pDefaultValue);
}
public static int optMetaDataInt(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return bundle.getInt(pKey);
}
public static int optMetaDataInt(final Context pContext, final String pKey, final int pDefaultValue) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return bundle.getInt(pKey, pDefaultValue);
}
public static float optMetaDataFloat(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return bundle.getFloat(pKey);
}
public static float optMetaDataFloat(final Context pContext, final String pKey, final float pDefaultValue) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return bundle.getFloat(pKey, pDefaultValue);
}
public static String optMetaDataString(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return bundle.getString(pKey);
}
public static String optMetaDataString(final Context pContext, final String pKey, final String pDefaultValue) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
if (bundle.containsKey(pKey)) {
return bundle.getString(pKey);
} else {
return pDefaultValue;
}
}
public static int optMetaDataColor(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
return Color.parseColor(bundle.getString(pKey));
}
public static int optMetaDataColor(final Context pContext, final String pKey, final int pDefaultValue) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
if (bundle.containsKey(pKey)) {
return Color.parseColor(bundle.getString(pKey));
} else {
return pDefaultValue;
}
}
public static boolean getMetaDataBoolean(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
if (bundle.containsKey(pKey)) {
return bundle.getBoolean(pKey);
} else {
throw new SystemUtilsException(new IllegalArgumentException("Could not find meta data with key: '" + pKey + "'."));
}
}
public static int getMetaDataInt(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
if (bundle.containsKey(pKey)) {
return bundle.getInt(pKey);
} else {
throw new SystemUtilsException(new IllegalArgumentException("Could not find meta data with key: '" + pKey + "'."));
}
}
public static float getMetaDataFloat(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
if (bundle.containsKey(pKey)) {
return bundle.getFloat(pKey);
} else {
throw new SystemUtilsException(new IllegalArgumentException("Could not find meta data with key: '" + pKey + "'."));
}
}
public static String getMetaDataString(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
if (bundle.containsKey(pKey)) {
return bundle.getString(pKey);
} else {
throw new SystemUtilsException(new IllegalArgumentException("Could not find meta data with key: '" + pKey + "'."));
}
}
public static int getMetaDataColor(final Context pContext, final String pKey) throws SystemUtilsException {
final Bundle bundle = SystemUtils.getMetaData(pContext);
if (bundle.containsKey(pKey)) {
return Color.parseColor(bundle.getString(pKey));
} else {
throw new SystemUtilsException(new IllegalArgumentException("Could not find meta data with key: '" + pKey + "'."));
}
}
public static Bundle getMetaData(final Context pContext) throws SystemUtilsException {
try {
final ApplicationInfo applicationInfo = SystemUtils.getApplicationInfo(pContext, PackageManager.GET_META_DATA);
return applicationInfo.metaData;
} catch (final Throwable t) {
throw new SystemUtilsException(t);
}
}
/**
* @param pBuildVersionCode taken from {@link Build.VERSION_CODES}.
*/
public static boolean isAndroidVersionOrLower(final int pBuildVersionCode) {
return Build.VERSION.SDK_INT <= pBuildVersionCode;
}
/**
* @param pBuildVersionCode taken from {@link Build.VERSION_CODES}.
*/
public static boolean isAndroidVersionOrHigher(final int pBuildVersionCode) {
return Build.VERSION.SDK_INT >= pBuildVersionCode;
}
/**
* @param pBuildVersionCodeMin taken from {@link Build.VERSION_CODES}.
* @param pBuildVersionCodeMax taken from {@link Build.VERSION_CODES}.
*/
public static boolean isAndroidVersion(final int pBuildVersionCodeMin, final int pBuildVersionCodeMax) {
return (Build.VERSION.SDK_INT >= pBuildVersionCodeMin) && (Build.VERSION.SDK_INT <= pBuildVersionCodeMax);
}
public static float getCPUBogoMips() throws SystemUtilsException {
final MatchResult matchResult = SystemUtils.matchSystemFile("/proc/cpuinfo", SystemUtils.BOGOMIPS_PATTERN, 1000);
try {
if (matchResult.groupCount() > 0) {
return Float.parseFloat(matchResult.group(1));
} else {
throw new SystemUtilsException();
}
} catch (final NumberFormatException e) {
throw new SystemUtilsException(e);
}
}
/**
* @return in kiloBytes.
* @throws SystemUtilsException
*/
public static long getSystemMemorySize() throws SystemUtilsException {
final MatchResult matchResult = SystemUtils.matchSystemFile("/proc/meminfo", SystemUtils.MEMTOTAL_PATTERN, 1000);
try {
if (matchResult.groupCount() > 0) {
return Long.parseLong(matchResult.group(1));
} else {
throw new SystemUtilsException();
}
} catch (final NumberFormatException e) {
throw new SystemUtilsException(e);
}
}
/**
* @return in kiloBytes.
* @throws SystemUtilsException
*/
public static long getSystemMemoryFreeSize() throws SystemUtilsException {
final MatchResult matchResult = SystemUtils.matchSystemFile("/proc/meminfo", SystemUtils.MEMFREE_PATTERN, 1000);
try {
if (matchResult.groupCount() > 0) {
return Long.parseLong(matchResult.group(1));
} else {
throw new SystemUtilsException();
}
} catch (final NumberFormatException e) {
throw new SystemUtilsException(e);
}
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static long getCPUFrequencyCurrent() throws SystemUtilsException {
return SystemUtils.readSystemFileAsLong("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static long getCPUFrequencyMin() throws SystemUtilsException {
return SystemUtils.readSystemFileAsLong("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static long getCPUFrequencyMax() throws SystemUtilsException {
return SystemUtils.readSystemFileAsLong("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static long getCPUFrequencyMinScaling() throws SystemUtilsException {
return SystemUtils.readSystemFileAsLong("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static long getCPUFrequencyMaxScaling() throws SystemUtilsException {
return SystemUtils.readSystemFileAsLong("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq");
}
private static MatchResult matchSystemFile(final String pSystemFile, final String pPattern, final int pHorizon) throws SystemUtilsException {
InputStream in = null;
try {
final Process process = new ProcessBuilder(new String[] {"/system/bin/cat", pSystemFile}).start();
in = process.getInputStream();
final Scanner scanner = new Scanner(in);
final boolean matchFound = scanner.findWithinHorizon(pPattern, pHorizon) != null;
if (matchFound) {
return scanner.match();
} else {
throw new SystemUtilsException();
}
} catch (final IOException e) {
throw new SystemUtilsException(e);
} finally {
StreamUtils.close(in);
}
}
private static long readSystemFileAsLong(final String pSystemFile) throws SystemUtilsException {
InputStream in = null;
try {
final Process process = new ProcessBuilder(new String[] {"/system/bin/cat", pSystemFile}).start();
in = process.getInputStream();
final String content = StreamUtils.readFully(in);
return Long.parseLong(content);
} catch (final IOException e) {
throw new SystemUtilsException(e);
} catch (final NumberFormatException e) {
throw new SystemUtilsException(e);
} finally {
StreamUtils.close(in);
}
}
public static long getNativeHeapSize() {
return Debug.getNativeHeapSize() / DataConstants.BYTES_PER_KILOBYTE;
}
public static long getNativeHeapFreeSize() {
return Debug.getNativeHeapFreeSize() / DataConstants.BYTES_PER_KILOBYTE;
}
public static long getNativeHeapAllocatedSize() {
return Debug.getNativeHeapAllocatedSize() / DataConstants.BYTES_PER_KILOBYTE;
}
public static long getDalvikHeapSize() {
return Runtime.getRuntime().totalMemory() / DataConstants.BYTES_PER_KILOBYTE;
}
public static long getDalvikHeapFreeSize() {
return Runtime.getRuntime().freeMemory() / DataConstants.BYTES_PER_KILOBYTE;
}
public static long getDalvikHeapAllocatedSize() {
return SystemUtils.getDalvikHeapSize() - SystemUtils.getDalvikHeapFreeSize();
}
public static long getNativeProportionalSetSize() {
return SystemUtils.getMemoryInfo().nativePss;
}
public static long getNativePrivateDirtyPages() {
return SystemUtils.getMemoryInfo().nativePrivateDirty;
}
public static long getNativeSharedDirtyPages() {
return SystemUtils.getMemoryInfo().nativeSharedDirty;
}
public static long getDalvikProportionalSetSize() {
return SystemUtils.getMemoryInfo().dalvikPss;
}
public static long getDalvikPrivateDirtyPages() {
return SystemUtils.getMemoryInfo().dalvikPrivateDirty;
}
public static long getDalvikSharedDirtyPages() {
return SystemUtils.getMemoryInfo().dalvikSharedDirty;
}
public static long getOtherProportionalSetSize() {
return SystemUtils.getMemoryInfo().otherPss;
}
public static long getOtherPrivateDirtyPages() {
return SystemUtils.getMemoryInfo().otherPrivateDirty;
}
public static long getOtherSharedDirtyPages() {
return SystemUtils.getMemoryInfo().otherSharedDirty;
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static class SystemUtilsException extends AndEngineException {
// ===========================================================
// Constants
// ===========================================================
private static final long serialVersionUID = -7256483361095147596L;
// ===========================================================
// Constructors
// ===========================================================
public SystemUtilsException() {
}
public SystemUtilsException(final Throwable pThrowable) {
super(pThrowable);
}
}
}