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.debug.Debug;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
/**
* (c) 2010 Nicolas Gramlich
* (c) 2011 Zynga Inc.
*
* @author Nicolas Gramlich
* @since 15:50:31 - 14.07.2010
*/
public 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
// ===========================================================
// ===========================================================
// Constructors
// ===========================================================
// ===========================================================
// Getter & Setter
// ===========================================================
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public static boolean isGoogleTV(final Context pContext) {
return SystemUtils.hasSystemFeature(pContext, "com.google.android.tv");
}
public static int getPackageVersionCode(final Context pContext) {
return SystemUtils.getPackageInfo(pContext).versionCode;
}
public static String getPackageVersionName(final Context pContext) {
return SystemUtils.getPackageInfo(pContext).versionName;
}
public static String getPackageName(final Context pContext) {
return pContext.getPackageName();
}
public static String getApkFilePath(final Context pContext) throws NameNotFoundException {
final PackageManager packMgmr = pContext.getPackageManager();
return packMgmr.getApplicationInfo(SystemUtils.getPackageName(pContext), 0).sourceDir;
}
private static PackageInfo getPackageInfo(final Context pContext) {
try {
return pContext.getPackageManager().getPackageInfo(pContext.getPackageName(), 0);
} catch (final NameNotFoundException e) {
Debug.e(e);
return null;
}
}
public static boolean hasSystemFeature(final Context pContext, final String pFeature) {
try {
final Method PackageManager_hasSystemFeatures = PackageManager.class.getMethod("hasSystemFeature", new Class[] { String.class });
return (PackageManager_hasSystemFeatures == null) ? false : (Boolean) PackageManager_hasSystemFeatures.invoke(pContext.getPackageManager(), pFeature);
} catch (final Throwable t) {
return false;
}
}
/**
* @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 int getMemoryTotal() throws SystemUtilsException {
final MatchResult matchResult = SystemUtils.matchSystemFile("/proc/meminfo", SystemUtils.MEMTOTAL_PATTERN, 1000);
try {
if(matchResult.groupCount() > 0) {
return Integer.parseInt(matchResult.group(1));
} else {
throw new SystemUtilsException();
}
} catch (final NumberFormatException e) {
throw new SystemUtilsException(e);
}
}
/**
* @return in kiloBytes.
* @throws SystemUtilsException
*/
public static int getMemoryFree() throws SystemUtilsException {
final MatchResult matchResult = SystemUtils.matchSystemFile("/proc/meminfo", SystemUtils.MEMFREE_PATTERN, 1000);
try {
if(matchResult.groupCount() > 0) {
return Integer.parseInt(matchResult.group(1));
} else {
throw new SystemUtilsException();
}
} catch (final NumberFormatException e) {
throw new SystemUtilsException(e);
}
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static int getCPUFrequencyCurrent() throws SystemUtilsException {
return SystemUtils.readSystemFileAsInt("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static int getCPUFrequencyMin() throws SystemUtilsException {
return SystemUtils.readSystemFileAsInt("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static int getCPUFrequencyMax() throws SystemUtilsException {
return SystemUtils.readSystemFileAsInt("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static int getCPUFrequencyMinScaling() throws SystemUtilsException {
return SystemUtils.readSystemFileAsInt("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq");
}
/**
* @return in kiloHertz.
* @throws SystemUtilsException
*/
public static int getCPUFrequencyMaxScaling() throws SystemUtilsException {
return SystemUtils.readSystemFileAsInt("/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 int readSystemFileAsInt(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 Integer.parseInt(content);
} catch (final IOException e) {
throw new SystemUtilsException(e);
} catch (final NumberFormatException e) {
throw new SystemUtilsException(e);
} finally {
StreamUtils.close(in);
}
}
// ===========================================================
// Inner and Anonymous Classes
// ===========================================================
public static class SystemUtilsException extends Exception {
// ===========================================================
// Constants
// ===========================================================
private static final long serialVersionUID = -7256483361095147596L;
// ===========================================================
// Methods
// ===========================================================
public SystemUtilsException() {
}
public SystemUtilsException(final Throwable pThrowable) {
super(pThrowable);
}
}
}