/*
* Copyright (C) 2011 asksven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.asksven.android.common.privateapiproxies;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import com.asksven.android.common.CommonLogSettings;
import com.asksven.android.common.nameutils.UidInfo;
import com.asksven.android.common.nameutils.UidNameResolver;
import com.asksven.android.common.utils.DateUtils;
import com.asksven.android.system.AndroidVersion;
/**
* A proxy to the non-public API BatteryStats
* http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.3.3_r1/android/os/BatteryStats.java/?v=source
* @author sven
*
*/
public class BatteryStatsProxy
{
/*
* Instance of the BatteryStatsImpl
*/
private Object m_Instance = null;
@SuppressWarnings("rawtypes")
private Class m_ClassDefinition = null;
private static final String TAG = "BatteryStatsProxy";
/*
* The UID stats are kept here as their methods / data can not be accessed
* outside of this class due to non-public types (Uid, Proc, etc.)
*/
private SparseArray<? extends Object> m_uidStats = null;
/**
* An instance to the UidNameResolver
*/
private UidNameResolver m_nameResolver;
private static BatteryStatsProxy m_proxy = null;
synchronized public static BatteryStatsProxy getInstance(Context ctx)
{
if (m_proxy == null)
{
m_proxy = new BatteryStatsProxy(ctx);
}
return m_proxy;
}
public void invalidate()
{
m_proxy = null;
}
/**
* Default cctor
*/
private BatteryStatsProxy(Context context)
{
/*
* As BatteryStats is a service we need to get a binding using the IBatteryStats.Stub.getStatistics()
* method (using reflection).
* If we would be using a public API the code would look like:
* @see com.android.settings.fuelgauge.PowerUsageSummary.java
* protected void onCreate(Bundle icicle) {
* super.onCreate(icicle);
*
* mStats = (BatteryStatsImpl)getLastNonConfigurationInstance();
*
* addPreferencesFromResource(R.xml.power_usage_summary);
* mBatteryInfo = IBatteryStats.Stub.asInterface(
* ServiceManager.getService("batteryinfo"));
* mAppListGroup = (PreferenceGroup) findPreference("app_list");
* mPowerProfile = new PowerProfile(this);
* }
*
* followed by
* private void load() {
* try {
* byte[] data = mBatteryInfo.getStatistics();
* Parcel parcel = Parcel.obtain();
* parcel.unmarshall(data, 0, data.length);
* parcel.setDataPosition(0);
* mStats = com.android.internal.os.BatteryStatsImpl.CREATOR
* .createFromParcel(parcel);
* mStats.distributeWorkLocked(BatteryStats.STATS_SINCE_CHARGED);
* } catch (RemoteException e) {
* Log.e(TAG, "RemoteException:", e);
* }
* }
*/
m_nameResolver = new UidNameResolver();
try
{
ClassLoader cl = context.getClassLoader();
m_ClassDefinition = cl.loadClass("com.android.internal.os.BatteryStatsImpl");
// get the IBinder to the "batteryinfo" service
@SuppressWarnings("rawtypes")
Class serviceManagerClass = cl.loadClass("android.os.ServiceManager");
// parameter types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetService= new Class[1];
paramTypesGetService[0]= String.class;
@SuppressWarnings("unchecked")
Method methodGetService = serviceManagerClass.getMethod("getService", paramTypesGetService);
// parameters
Object[] paramsGetService= new Object[1];
paramsGetService[0] = "batteryinfo";
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "invoking android.os.ServiceManager.getService(\"batteryinfo\")");
}
IBinder serviceBinder = (IBinder) methodGetService.invoke(serviceManagerClass, paramsGetService);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "android.os.ServiceManager.getService(\"batteryinfo\") returned a service binder");
}
// now we have a binder. Let's us that on IBatteryStats.Stub.asInterface
// to get an IBatteryStats
// Note the $-syntax here as Stub is a nested class
@SuppressWarnings("rawtypes")
Class iBatteryStatsStub = cl.loadClass("com.android.internal.app.IBatteryStats$Stub");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesAsInterface= new Class[1];
paramTypesAsInterface[0]= IBinder.class;
@SuppressWarnings("unchecked")
Method methodAsInterface = iBatteryStatsStub.getMethod("asInterface", paramTypesAsInterface);
// Parameters
Object[] paramsAsInterface= new Object[1];
paramsAsInterface[0] = serviceBinder;
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "invoking com.android.internal.app.IBatteryStats$Stub.asInterface");
}
Object iBatteryStatsInstance = methodAsInterface.invoke(iBatteryStatsStub, paramsAsInterface);
// and finally we call getStatistics from that IBatteryStats to obtain a Parcel
@SuppressWarnings("rawtypes")
Class iBatteryStats = cl.loadClass("com.android.internal.app.IBatteryStats");
@SuppressWarnings("unchecked")
Method methodGetStatistics = iBatteryStats.getMethod("getStatistics");
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "invoking getStatistics");
}
byte[] data = (byte[]) methodGetStatistics.invoke(iBatteryStatsInstance);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "retrieving parcel");
}
Parcel parcel = Parcel.obtain();
parcel.unmarshall(data, 0, data.length);
parcel.setDataPosition(0);
@SuppressWarnings("rawtypes")
Class batteryStatsImpl = cl.loadClass("com.android.internal.os.BatteryStatsImpl");
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "reading CREATOR field");
}
Field creatorField = batteryStatsImpl.getField("CREATOR");
// From here on we don't need reflection anymore
@SuppressWarnings("rawtypes")
Parcelable.Creator batteryStatsImpl_CREATOR = (Parcelable.Creator) creatorField.get(batteryStatsImpl);
m_Instance = batteryStatsImpl_CREATOR.createFromParcel(parcel);
}
catch( Exception e )
{
if (e instanceof InvocationTargetException && e.getCause() != null) {
Log.e(TAG, "An exception occured in BatteryStatsProxy(). Message: " + e.getCause().getMessage());
} else {
Log.e(TAG, "An exception occured in BatteryStatsProxy(). Message: " + e.getMessage());
}
m_Instance = null;
}
}
/**
* Returns true if the proxy could not be initialized properly
* @return true if the proxy wasn't initialized
*/
public boolean initFailed()
{
return m_Instance == null;
}
/**
* Returns the total, last, or current battery realtime in microseconds.
*
* @param curTime the current elapsed realtime in microseconds.
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long computeBatteryRealtime(long curTime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("computeBatteryRealtime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(curTime);
params[1]= new Integer(iStatsType);
ret = (Long) method.invoke(m_Instance, params);
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current battery realtime in microseconds.
*
* @param curTime the current elapsed realtime in microseconds.
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getBatteryRealtime(long curTime) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[1];
paramTypes[0]= long.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getBatteryRealtime", paramTypes);
//Parameters
Object[] params= new Object[1];
params[0]= new Long(curTime);
ret= (Long) method.invoke(m_Instance, params);
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current battery uptime in microseconds.
*
* @param curTime the current elapsed realtime in microseconds.
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long computeBatteryUptime(long curTime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("computeBatteryUptime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(curTime);
params[1]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current screen on time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getScreenOnTime(long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getScreenOnTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns if phone is on battery.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public boolean getIsOnBattery() throws BatteryInfoUnavailableException
{
boolean ret = true;
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getIsOnBattery", paramTypes);
ret= (Boolean) method.invoke(m_Instance);
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = true;
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current phone on time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getPhoneOnTime(long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getPhoneOnTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current wifi on time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getWifiOnTime(long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getWifiOnTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "getWifiOnTime with params " + params[0] + " and " + params[1] + " returned " + ret);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current wifi on time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getGlobalWifiRunningTime(long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getGlobalWifiRunningTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "getGlobalWifiRunningTime with params " + params[0] + " and " + params[1] + " returned " + ret);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current wifi running time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getWifiRunningTime(Context context, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = iBatteryStatsUid.getMethod("getWifiRunningTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret += (Long) method.invoke(myUid, params);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "getWifiRunningTime with params " + params[0] + " and " + params[1] + " returned " + ret);
}
}
}
catch( IllegalArgumentException e )
{
Log.e(TAG, "getWifiRunning threw an IllegalArgumentException: " + e.getMessage());
throw e;
}
catch( Exception e )
{
Log.e(TAG, "getWifiRunning threw an Exception: " + e.getMessage());
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
}
return ret;
}
/**
* Returns the total, last, or current wifi lock time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getFullWifiLockTime(Context context, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = iBatteryStatsUid.getMethod("getFullWifiLockTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret += (Long) method.invoke(myUid, params);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
}
return ret;
}
/**
* Returns the total, last, or current wifi scanning time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getScanWifiLockTime(Context context, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = iBatteryStatsUid.getMethod("getScanWifiLockTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret += (Long) method.invoke(myUid, params);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
}
return ret;
}
/**
* Returns the total, last, or current wifi multicast time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getWifiMulticastTime(Context context, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = iBatteryStatsUid.getMethod("getWifiMulticastTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret += (Long) method.invoke(myUid, params);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
}
return ret;
}
/**
* Returns the time in microseconds the phone has been running with the given data connection type.
*
* @params dataType the given data connection type (@see http://www.netmite.com/android/mydroid/donut/frameworks/base/core/java/android/os/BatteryStats.java)
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getPhoneDataConnectionTime(int dataType, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[3];
paramTypes[0]= int.class;
paramTypes[1]= long.class;
paramTypes[2]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getPhoneDataConnectionTime", paramTypes);
//Parameters
Object[] params= new Object[3];
params[0]= new Integer(dataType);
params[1]= new Long(batteryRealtime);
params[2]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "getPhoneDataConnectionTime with params " + params[0] + ", " + params[1] + "and " + params[2] + " returned " + ret);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the time in microseconds the phone has been running with the given signal strength.
*
* @params signalStrength the given data connection type (@see http://www.netmite.com/android/mydroid/donut/frameworks/base/core/java/android/os/BatteryStats.java)
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getPhoneSignalStrengthTime(int signalStrength, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[3];
paramTypes[0]= int.class;
paramTypes[1]= long.class;
paramTypes[2]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getPhoneDataConnectionTime", paramTypes);
//Parameters
Object[] params= new Object[3];
params[0]= new Integer(signalStrength);
params[1]= new Long(batteryRealtime);
params[2]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "getPhoneSignalStrengthTime with params " + params[0] + ", " + params[1] + "and " + params[2] + " returned " + ret);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the time in microseconds the screen has been running with the given brightness
*/
public Long getScreenBrightnessTime(int brightness, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[3];
paramTypes[0]= int.class;
paramTypes[1]= long.class;
paramTypes[2]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getScreenBrightnessTime", paramTypes);
//Parameters
Object[] params= new Object[3];
params[0]= new Integer(brightness);
params[1]= new Long(batteryRealtime);
params[2]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
if (CommonLogSettings.DEBUG)
{
Log.i(TAG, "getScreenBrightnessTime with params " + params[0] + ", " + params[1] + "and " + params[2] + " returned " + ret);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the total, last, or current audio on time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getAudioTurnedOnTime(Context context, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = iBatteryStatsUid.getMethod("getAudioTurnedOnTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret += (Long) method.invoke(myUid, params);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
}
return ret;
}
/**
* Returns the total, last, or current video on time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getVideoTurnedOnTime(Context context, long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = iBatteryStatsUid.getMethod("getVideoTurnedTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret += (Long) method.invoke(myUid, params);
}
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
}
return ret;
}
/**
* Returns the total, last, or current bluetooth on time in microseconds.
*
* @param batteryRealtime the battery realtime in microseconds (@see computeBatteryRealtime).
* @param iStatsType one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
*/
public Long getBluetoothOnTime(long batteryRealtime, int iStatsType) throws BatteryInfoUnavailableException
{
Long ret = new Long(0);
try
{
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[2];
paramTypes[0]= long.class;
paramTypes[1]= int.class;
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getBluetoothOnTime", paramTypes);
//Parameters
Object[] params= new Object[2];
params[0]= new Long(batteryRealtime);
params[1]= new Integer(iStatsType);
ret= (Long) method.invoke(m_Instance, params);
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = new Long(0);
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Return whether we are currently running on battery.
*/
public boolean getIsOnBattery(Context context) throws BatteryInfoUnavailableException
{
boolean ret = false;
try
{
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getIsOnBattery");
Boolean oRet = (Boolean) method.invoke(m_Instance);
ret = oRet.booleanValue();
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = false;
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Returns the current battery percentage level if we are in a discharge cycle, otherwise
* returns the level at the last plug event.
*/
public int getDischargeCurrentLevel() throws BatteryInfoUnavailableException
{
int ret = 0;
try
{
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("getDischargeCurrentLevel");
Integer oRet = (Integer) method.invoke(m_Instance);
ret = oRet.intValue();
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Exception e )
{
ret = 0;
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Initalizes the collection of history items
*/
public boolean startIteratingHistoryLocked() throws BatteryInfoUnavailableException
{
Boolean ret = false;
try
{
@SuppressWarnings("unchecked")
Method method = m_ClassDefinition.getMethod("startIteratingHistoryLocked");
ret= (Boolean) method.invoke(m_Instance);
}
catch( IllegalArgumentException e )
{
Log.e(TAG, "An exception occured in startIteratingHistoryLocked(). Message: " + e.getMessage() + ", cause: " + e.getCause().getMessage());
throw e;
}
catch( Exception e )
{
ret = false;
throw new BatteryInfoUnavailableException();
}
return ret;
}
/**
* Collect the UidStats using reflection and store them
*/
@SuppressWarnings("unchecked")
private void collectUidStats()
{
try
{
Method method = m_ClassDefinition.getMethod("getUidStats");
m_uidStats = (SparseArray<? extends Object>) method.invoke(m_Instance);
}
catch( IllegalArgumentException e )
{
Log.e(TAG, "An exception occured in collectUidStats(). Message: " + e.getMessage() + ", cause: " + e.getCause().getMessage());
throw e;
}
catch( Exception e )
{
m_uidStats = null;
}
}
/**
* Obtain the wakelock stats as a list of Wakelocks (@see com.asksven.android.common.privateapiproxies.Wakelock}
* @param context a Context
* @param iWakeType a type of wakelock @see com.asksven.android.common.privateapiproxies.BatteryStatsTypes
* @param iStatType a type of stat @see com.asksven.android.common.privateapiproxies.BatteryStatsTypes
* @return a List of Wakelock s
* @throws Exception
*/
@SuppressWarnings("unchecked")
public ArrayList<StatElement> getWakelockStats(Context context, int iWakeType, int iStatType, int iWlPctRef) throws Exception
{
// type checks
boolean validTypes = (BatteryStatsTypes.assertValidWakeType(iWakeType)
&& BatteryStatsTypes.assertValidStatType(iStatType)
&& BatteryStatsTypes.assertValidWakelockPctRef(iWlPctRef));
if (!validTypes)
{
Log.e(TAG, "Invalid WakeType or StatType");
throw new Exception("Invalid WakeType of StatType");
}
ArrayList<StatElement> myStats = new ArrayList<StatElement>();
this.collectUidStats();
if (m_uidStats != null)
{
long uSecBatteryTime = this.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, iStatType);
long uSecAwakeTime = this.computeBatteryUptime(SystemClock.elapsedRealtime() * 1000, iStatType);
long uSecScreenOnTime =this.getScreenOnTime(uSecBatteryTime, iStatType);
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
// Process wake lock usage
Method methodGetWakelockStats = iBatteryStatsUid.getMethod("getWakelockStats");
// Map of String, BatteryStats.Uid.Wakelock
Map<String, ? extends Object> wakelockStats = (Map<String, ? extends Object>) methodGetWakelockStats.invoke(myUid);
Method methodGetUid = iBatteryStatsUid.getMethod("getUid");
Integer uid = (Integer) methodGetUid.invoke(myUid);
long wakelockTime = 0;
int wakelockCount = 0;
// Map of String, BatteryStats.Uid.Wakelock
for (Map.Entry<String, ? extends Object> wakelockEntry : wakelockStats.entrySet())
{
// BatteryStats.Uid.Wakelock
Object wakelock = wakelockEntry.getValue();
@SuppressWarnings("rawtypes")
Class batteryStatsUidWakelock = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid$Wakelock");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetWakeTime= new Class[1];
paramTypesGetWakeTime[0]= int.class;
Method methodGetWakeTime = batteryStatsUidWakelock.getMethod("getWakeTime", paramTypesGetWakeTime);
//Parameters
Object[] paramsGetWakeTime= new Object[1];
// Partial wake locks BatteryStatsTypes.WAKE_TYPE_PARTIAL
// are the ones that should normally be of interest but
// WAKE_TYPE_PARTIAL, WAKE_TYPE_FULL, WAKE_TYPE_WINDOW
// are possible
paramsGetWakeTime[0]= Integer.valueOf(iWakeType);
// BatteryStats.Timer
Object wakeTimer = methodGetWakeTime.invoke(wakelock, paramsGetWakeTime);
if (wakeTimer != null)
{
@SuppressWarnings("rawtypes")
Class iBatteryStatsTimer = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Timer");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetTotalTimeLocked= new Class[2];
paramTypesGetTotalTimeLocked[0]= long.class;
paramTypesGetTotalTimeLocked[1]= int.class;
Method methodGetTotalTimeLocked = iBatteryStatsTimer.getMethod("getTotalTimeLocked", paramTypesGetTotalTimeLocked);
//Parameters
Object[] paramsGetTotalTimeLocked= new Object[2];
paramsGetTotalTimeLocked[0]= new Long(uSecBatteryTime);
paramsGetTotalTimeLocked[1]= Integer.valueOf(iStatType);
Long wake = (Long) methodGetTotalTimeLocked.invoke(wakeTimer, paramsGetTotalTimeLocked);
// Log.d(TAG, "Wakelocks inner: Process = " + wakelockEntry.getKey() + " wakelock [s] " + wake);
wakelockTime += wake;
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetCountLocked= new Class[1];
paramTypesGetCountLocked[0]= int.class;
Method methodGetCountLocked = iBatteryStatsTimer.getMethod("getCountLocked", paramTypesGetCountLocked);
//Parameters
Object[] paramsGetCountLocked= new Object[1];
paramsGetCountLocked[0]= new Integer(iStatType);
Integer count = (Integer) methodGetCountLocked.invoke(wakeTimer, paramsGetCountLocked);
// Log.d(TAG, "Wakelocks inner: Process = " + wakelockEntry.getKey() + " count " + count);
wakelockCount += count;
}
// else
// {
// Log.d(TAG, "Wakelocks: Process = " + wakelockEntry.getKey() + " with no Timer spotted");
// }
// convert so milliseconds
wakelockTime /= 1000;
long uSec = 0;
switch (iWlPctRef)
{
case 0:
uSec = uSecBatteryTime;
break;
case 1:
uSec = uSecAwakeTime;
break;
case 2:
uSec = (uSecAwakeTime - uSecScreenOnTime);
break;
}
Wakelock myWl = new Wakelock(iWakeType, wakelockEntry.getKey(), wakelockTime, uSec / 1000, wakelockCount);
// opt for lazy loading: do no populate UidInfo, just uid. UidInfo will be fetched on demand
myWl.setUid(uid);
myStats.add(myWl);
// Log.d(TAG, "Wakelocks: Process = " + wakelockEntry.getKey() + " wakelock [s] " + wakelockTime + ", count " + wakelockCount);
}
}
}
catch( Exception e )
{
Log.e(TAG, "An exception occured in getWakelockStats(). Message: " + e.getMessage() + ", cause: " + e.getCause().getMessage());
throw e;
}
}
return myStats;
}
/**
* Obtain the wakelock stats as a list of Wakelocks (@see com.asksven.android.common.privateapiproxies.Wakelock}
* @param context a Context
* @param iWakeType a type of wakelock @see com.asksven.android.common.privateapiproxies.BatteryStatsTypes
* @param iStatType a type of stat @see com.asksven.android.common.privateapiproxies.BatteryStatsTypes
* @return a List of Wakelock s
* @throws Exception
*/
@SuppressWarnings("unchecked")
public ArrayList<KernelWakelock> getKernelWakelockStats(Context context, int iStatType, int iWlPctRef, boolean bAlternate) throws Exception
{
// type checks
boolean validTypes = (BatteryStatsTypes.assertValidStatType(iStatType)
&& BatteryStatsTypes.assertValidWakelockPctRef(iWlPctRef));
if (!validTypes)
{
Log.e(TAG, "Invalid WakeType or StatType");
throw new Exception("Invalid WakeType or StatType");
}
Log.d(TAG, "getWakelockStats was called with params "
+"[iStatType] = " + iStatType
+ "[iWlPctRef] = " + iWlPctRef);
ArrayList<KernelWakelock> myStats = new ArrayList<KernelWakelock>();
long uSecBatteryTime = this.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, iStatType);
long msSinceBoot = SystemClock.elapsedRealtime();
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStats = cl.loadClass("com.android.internal.os.BatteryStatsImpl");
// Process wake lock usage
Method methodGetKernelWakelockStats = iBatteryStats.getMethod("getKernelWakelockStats");
Class classSamplingTimer = cl.loadClass("com.android.internal.os.BatteryStatsImpl$SamplingTimer");
Field currentReportedCount = classSamplingTimer.getDeclaredField("mCurrentReportedCount");
Field currentReportedTotalTime = classSamplingTimer.getDeclaredField("mCurrentReportedTotalTime");
Field unpluggedReportedCount = classSamplingTimer.getDeclaredField("mUnpluggedReportedCount");
Field unpluggedReportedTotalTime = classSamplingTimer.getDeclaredField("mUnpluggedReportedTotalTime");
Field inDischarge = classSamplingTimer.getDeclaredField("mInDischarge");
Field trackingReportedValues = classSamplingTimer.getDeclaredField("mTrackingReportedValues");
currentReportedCount.setAccessible(true);
currentReportedTotalTime.setAccessible(true);
unpluggedReportedCount.setAccessible(true);
unpluggedReportedTotalTime.setAccessible(true);
inDischarge.setAccessible(true);
trackingReportedValues.setAccessible(true);
//Parameters
Object[] params= new Object[1];
// Map of String, BatteryStatsImpl.SamplingTimer
Map<String, ? extends Object> kernelWakelockStats = (Map<String, ? extends Object>) methodGetKernelWakelockStats.invoke(m_Instance);
// Map of String, BatteryStats.Uid.Wakelock
for (Map.Entry<String, ? extends Object> wakelockEntry : kernelWakelockStats.entrySet())
{
// BatteryStats.SamplingTimer
String wakelockName = wakelockEntry.getKey();
Object samplingTimer = wakelockEntry.getValue();
params[0]= samplingTimer;
// read private fields
Integer currentReportedCountVal = (Integer) currentReportedCount.get(params[0]);
Long currentReportedTotalTimeVal = (Long) currentReportedTotalTime.get(params[0]);
Integer unpluggedReportedCountVal = (Integer) unpluggedReportedCount.get(params[0]);
Long unpluggedReportedTotalTimeVal = (Long) unpluggedReportedTotalTime.get(params[0]);
Boolean inDischargeVal = (Boolean) inDischarge.get(params[0]);
Boolean trackingReportedValuesVal = (Boolean) trackingReportedValues.get(params[0]);
if (CommonLogSettings.DEBUG)
{
Log.d(TAG, "Kernel wakelock '" + wakelockEntry.getKey() + "'"
+ " : reading fields from SampleTimer: "
+ " [currentReportedCountVal] = " + currentReportedCountVal
+ " [currentReportedTotalTimeVal] = " + currentReportedTotalTimeVal
+ " [unpluggedReportedCountVal] = " + unpluggedReportedCountVal
+ " [mUnpluggedReportedTotalTimeVal] = " + unpluggedReportedTotalTimeVal
+ " [mInDischarge] = " + inDischargeVal
+ " [mTrackingReportedValues] = " + trackingReportedValuesVal);
}
//
// @SuppressWarnings("rawtypes")
// Class batteryStatsSamplingTimerClass = cl.loadClass("com.android.internal.os.BatteryStatsImpl$SamplingTimer");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetTotalTimeLocked= new Class[2];
paramTypesGetTotalTimeLocked[0]= long.class;
paramTypesGetTotalTimeLocked[1]= int.class;
//Parameters
Object[] paramGetTotalTimeLocked= new Object[2];
paramGetTotalTimeLocked[0]= new Long(uSecBatteryTime);
paramGetTotalTimeLocked[1]= new Integer(iStatType);
Method methodGetTotalTimeLocked = classSamplingTimer
.getMethod("getTotalTimeLocked", paramTypesGetTotalTimeLocked);
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetCountLocked= new Class[1];
paramTypesGetCountLocked[0]= int.class;
//Parameters
Object[] paramGetCountLocked= new Object[1];
paramGetCountLocked[0]= new Integer(iStatType);
Method methodGetCountLocked = classSamplingTimer
.getMethod("getCountLocked", paramTypesGetCountLocked);
Long wake = (Long) methodGetTotalTimeLocked.invoke(samplingTimer, paramGetTotalTimeLocked);
Integer count = (Integer) methodGetCountLocked.invoke(samplingTimer, paramGetCountLocked);
if (CommonLogSettings.DEBUG)
{
Log.d(TAG, "Kernel wakelock: " + wakelockEntry.getKey() + " wakelock [s] " + wake / 1000
+ " count " + count);
}
// return the data depending on the method
if (!bAlternate)
{
KernelWakelock myWl = new KernelWakelock(wakelockEntry.getKey(), wake / 1000, uSecBatteryTime / 1000, count);
myStats.add(myWl);
}
else
{
KernelWakelock myWl = new KernelWakelock(
wakelockEntry.getKey(),
unpluggedReportedTotalTimeVal / 1000,
msSinceBoot,
unpluggedReportedCountVal);
myStats.add(myWl);
}
}
}
catch( Exception e )
{
Log.e(TAG, "An exception occured in getKernelWakelockStats(). Message: " + e.getMessage() + ", cause: " + e.getCause().getMessage());
throw e;
}
return myStats;
}
/**
* Obtain the process stats as a list of Processes (@see com.asksven.android.common.privateapiproxies.Process}
* @param context a Context
* @param iStatType a type of stat @see com.asksven.android.common.privateapiproxies.BatteryStatsTypes
* @return a List of Process es
* @throws Exception
*/
@SuppressWarnings("unchecked")
public ArrayList<StatElement> getProcessStats(Context context, int iStatType) throws Exception
{
// type checks
boolean validTypes = BatteryStatsTypes.assertValidStatType(iStatType);
if (!validTypes)
{
Log.e(TAG, "Invalid WakeType or StatType");
throw new Exception("Invalid StatType");
}
ArrayList<StatElement> myStats = new ArrayList<StatElement>();
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
Method methodGetProcessStats = iBatteryStatsUid.getMethod("getProcessStats");
Method methodGetUid = iBatteryStatsUid.getMethod("getUid");
Integer uid = (Integer) methodGetUid.invoke(myUid);
// Map of String, BatteryStats.Uid.Proc
Map<String, ? extends Object> processStats = (Map<String, ? extends Object>) methodGetProcessStats.invoke(myUid);
if (processStats.size() > 0)
{
for (Map.Entry<String, ? extends Object> ent : processStats.entrySet())
{
if (CommonLogSettings.TRACE)
{
Log.d(TAG, "Process name = " + ent.getKey());
}
// Object is a BatteryStatsTypes.Uid.Proc
Object ps = ent.getValue();
@SuppressWarnings("rawtypes")
Class batteryStatsUidProc = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid$Proc");
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetXxxTime= new Class[1];
paramTypesGetXxxTime[0]= int.class;
Method methodGetUserTime = batteryStatsUidProc.getMethod("getUserTime", paramTypesGetXxxTime);
Method methodGetSystemTime = batteryStatsUidProc.getMethod("getSystemTime", paramTypesGetXxxTime);
Method methodGetStarts = batteryStatsUidProc.getMethod("getStarts", paramTypesGetXxxTime);
//Parameters
Object[] paramsGetXxxTime= new Object[1];
paramsGetXxxTime[0]= new Integer(iStatType);
Long userTime = (Long) methodGetUserTime.invoke(ps, paramsGetXxxTime);
Long systemTime = (Long) methodGetSystemTime.invoke(ps, paramsGetXxxTime);
Integer starts = (Integer) methodGetStarts.invoke(ps, paramsGetXxxTime);
if (CommonLogSettings.TRACE)
{
Log.d(TAG, "UserTime = " + userTime);
Log.d(TAG, "SystemTime = " + systemTime);
Log.d(TAG, "Starts = " + starts);
}
// take only the processes with CPU time
if ((userTime + systemTime) > 1000)
{
Process myPs = new Process(ent.getKey(), userTime, systemTime, starts);
// opt for lazy loading: do no populate UidInfo, just uid. UidInfo will be fetched on demand
myPs.setUid(uid);
// try resolving names
// String myName = m_nameResolver.getLabel(context, ent.getKey());
myStats.add(myPs);
}
else
{
if (CommonLogSettings.TRACE)
{
Log.d(TAG, "Process " + ent.getKey() + " was discarded (CPU time =0)");
}
}
}
}
}
}
catch( Exception e )
{
Log.e(TAG, "An exception occured in getProcessStats(). Message: " + e.getMessage() + ", cause: " + e.getCause().getMessage());
throw e;
}
}
return myStats;
}
/**
* Obtain the network usage stats as a list of NetworkUsages (@see com.asksven.android.common.privateapiproxies.NetworkUsage}
* @param context a Context
* @param iStatType a type of stat @see com.asksven.android.common.privateapiproxies.BatteryStatsTypes
* @return a List of NetworkUsage s
* @throws Exception
*/
@SuppressWarnings("unchecked")
public ArrayList<NetworkUsage> getNetworkUsageStats(Context context, int iStatType) throws Exception
{
// type checks
boolean validTypes = BatteryStatsTypes.assertValidStatType(iStatType);
if (!validTypes)
{
Log.e(TAG, "Invalid WakeType or StatType");
throw new Exception("Invalid StatType");
}
ArrayList<NetworkUsage> myStats = new ArrayList<NetworkUsage>();
this.collectUidStats();
if (m_uidStats != null)
{
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class iBatteryStatsUid = cl.loadClass("com.android.internal.os.BatteryStatsImpl$Uid");
int NU = m_uidStats.size();
for (int iu = 0; iu < NU; iu++)
{
// Object is an instance of BatteryStats.Uid
Object myUid = m_uidStats.valueAt(iu);
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypesGetTcpBytesXxx= new Class[1];
paramTypesGetTcpBytesXxx[0]= int.class;
Method methodGetTcpBytesReceived = iBatteryStatsUid.getMethod("getTcpBytesReceived", paramTypesGetTcpBytesXxx);
Method methodGetTcpBytesSent = iBatteryStatsUid.getMethod("getTcpBytesSent", paramTypesGetTcpBytesXxx);
//Parameters
Object[] paramGetTcpBytesXxx = new Object[1];
paramGetTcpBytesXxx[0]= new Integer(iStatType);
Long tcpBytesReceived = (Long) methodGetTcpBytesReceived.invoke(myUid, paramGetTcpBytesXxx);
Long tcpBytesSent = (Long) methodGetTcpBytesSent.invoke(myUid, paramGetTcpBytesXxx);
Method methodGetUid = iBatteryStatsUid.getMethod("getUid");
Integer uid = (Integer) methodGetUid.invoke(myUid);
if (CommonLogSettings.DEBUG)
{
Log.d(TAG, "Uid = " + uid + ": received:" + tcpBytesReceived + ", sent: " + tcpBytesSent);
}
NetworkUsage myData = new NetworkUsage(uid, tcpBytesReceived, tcpBytesSent);
// try resolving names
UidInfo myInfo = m_nameResolver.getNameForUid(context, uid);
myData.setUidInfo(myInfo);
myStats.add(myData);
}
}
catch( Exception e )
{
throw e;
}
}
return myStats;
}
/**
* Obtain the network usage stats as a list of NetworkUsages (@see com.asksven.android.common.privateapiproxies.NetworkUsage}
* @param context a Context
* @param iStatType a type of stat @see com.asksven.android.common.privateapiproxies.BatteryStatsTypes
* @return a List of NetworkUsage s
* @throws Exception
*/
public ArrayList<NetworkUsage> getKernelNetworkStats(int iStatsType)
{
ArrayList<NetworkUsage> myRet = new ArrayList<NetworkUsage>();
try
{
@SuppressWarnings("unchecked")
// we must use getDeclaredMethod as that method is private
Method method = m_ClassDefinition.getDeclaredMethod("getNetworkStatsDetailGroupedByUid");
method.setAccessible(true);
Object networkStats = method.invoke(m_Instance);
String myRes = "tada";
}
catch (Exception e)
{
myRet = null;
}
return myRet;
}
@SuppressWarnings("unchecked")
public ArrayList<HistoryItem> getHistory(Context context) throws Exception
{
ArrayList<HistoryItem> myStats = new ArrayList<HistoryItem>();
try
{
ClassLoader cl = context.getClassLoader();
@SuppressWarnings("rawtypes")
Class classHistoryItem = cl.loadClass("android.os.BatteryStats$HistoryItem");
// get constructor
Constructor cctor = classHistoryItem.getConstructor();
Object myHistoryItem = cctor.newInstance();
// prepare the method call for getNextHistoryItem
//Parameters Types
@SuppressWarnings("rawtypes")
Class[] paramTypes= new Class[1];
paramTypes[0]= classHistoryItem;
@SuppressWarnings("unchecked")
Method methodNext = m_ClassDefinition.getMethod("getNextHistoryLocked", paramTypes);
//Parameters
Object[] params= new Object[1];
// initalize hist and iterate like this
// if (stats.startIteratingHistoryLocked()) {
// final HistoryItem rec = new HistoryItem();
// while (stats.getNextHistoryLocked(rec)) {
// read the time of query for history
Long statTimeRef = Long.valueOf(this.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000,
BatteryStatsTypes.STATS_SINCE_CHARGED));
statTimeRef = System.currentTimeMillis();
if (CommonLogSettings.DEBUG)
{
Log.d(TAG, "Reference time (" + statTimeRef + ": " + DateUtils.format(DateUtils.DATE_FORMAT_NOW, statTimeRef));
}
// statTimeLast stores the timestamp of the last sample
Long statTimeLast = Long.valueOf(0);
if (this.startIteratingHistoryLocked())
{
params[0]= myHistoryItem;
Boolean bNext = (Boolean) methodNext.invoke(m_Instance, params);
while (bNext)
{
// process stats: create HistoryItems from params
Field timeField = classHistoryItem.getField("time"); // long
Field cmdField = classHistoryItem.getField("cmd"); // byte
Byte cmdValue = (Byte) cmdField.get(params[0]);
// process only valid items
byte updateCmd = 0;
// ICS has a different implementation of HistoryItems constants
if (AndroidVersion.isIcs())
{
updateCmd = HistoryItemIcs.CMD_UPDATE;
}
else
{
updateCmd = HistoryItem.CMD_UPDATE;
}
if (cmdValue == updateCmd)
{
Field batteryLevelField = classHistoryItem.getField("batteryLevel"); // byte
Field batteryStatusField = classHistoryItem.getField("batteryStatus"); // byte
Field batteryHealthField = classHistoryItem.getField("batteryHealth"); // byte
Field batteryPlugTypeField = classHistoryItem.getField("batteryPlugType"); // byte
Field batteryTemperatureField = classHistoryItem.getField("batteryTemperature"); // char
Field batteryVoltageField = classHistoryItem.getField("batteryVoltage"); // char
Field statesField = classHistoryItem.getField("states"); // int
// retrieve all values
@SuppressWarnings("rawtypes")
Long timeValue = (Long) timeField.get(params[0]);
// store values only once
if (!statTimeLast.equals(timeValue))
{
Byte batteryLevelValue = (Byte) batteryLevelField.get(params[0]);
Byte batteryStatusValue = (Byte) batteryStatusField.get(params[0]);
Byte batteryHealthValue = (Byte) batteryHealthField.get(params[0]);
Byte batteryPlugTypeValue = (Byte) batteryPlugTypeField.get(params[0]);
String batteryTemperatureValue = String.valueOf(batteryTemperatureField.get(params[0]));
String batteryVoltageValue = String.valueOf(batteryVoltageField.get(params[0]));
Integer statesValue = (Integer) statesField.get(params[0]);
HistoryItem myItem = null;
// ICS has a different implementation of HistoryItems constants
if (AndroidVersion.isIcs())
{
myItem = new HistoryItemIcs(timeValue, cmdValue, batteryLevelValue,
batteryStatusValue, batteryHealthValue, batteryPlugTypeValue,
batteryTemperatureValue, batteryVoltageValue, statesValue);
}
else
{
myItem = new HistoryItem(timeValue, cmdValue, batteryLevelValue,
batteryStatusValue, batteryHealthValue, batteryPlugTypeValue,
batteryTemperatureValue, batteryVoltageValue, statesValue);
}
myStats.add(myItem);
}
// overwrite the time of the last sample
statTimeLast = timeValue;
}
else
{
Log.d(TAG, "Skipped item");
}
bNext = (Boolean) methodNext.invoke(m_Instance, params);
}
// norm the time of each sample
// stat time last is the number of millis since
// the stats is being collected
// the ref time is a full plain time (with date)
Long offset = statTimeRef - statTimeLast;
if (CommonLogSettings.DEBUG)
{
Log.d(TAG, "Reference time (" + statTimeRef + ")" + DateUtils.format(DateUtils.DATE_FORMAT_NOW, statTimeRef));
Log.d(TAG, "Last sample (" + statTimeLast + ")" + DateUtils.format(DateUtils.DATE_FORMAT_NOW, statTimeLast));
Log.d(TAG, "Correcting all HistoryItem times by an offset of (" + offset + ")" + DateUtils.formatDuration(offset * 1000));
}
for (int i=0; i < myStats.size(); i++)
{
myStats.get(i).setOffset(offset);
}
}
}
catch( Exception e )
{
Log.e(TAG, "An exception occured in getHistory(). Message: " + e.getMessage() + ", cause: " + e.getCause().getMessage());
throw e;
}
return myStats;
}
}