--- /dev/null
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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.android.settings.fuelgauge;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.graphics.drawable.Drawable;
+import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.UserManager;
+import com.android.internal.os.BatterySipper;
+import com.android.settings.R;
+import com.android.settings.users.UserUtils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * Wraps the power usage data of a BatterySipper with information about package name
+ * and icon image.
+ */
+public class BatteryEntry {
+ public static final int MSG_UPDATE_NAME_ICON = 1;
+ public static final int MSG_REPORT_FULLY_DRAWN = 2;
+
+ static final HashMap<String,UidToDetail> sUidCache = new HashMap<String,UidToDetail>();
+
+ static final ArrayList<BatteryEntry> mRequestQueue = new ArrayList<BatteryEntry>();
+ static Handler mHandler;
+
+ static private class NameAndIconLoader extends Thread {
+ private boolean mAbort = false;
+
+ public NameAndIconLoader() {
+ super("BatteryUsage Icon Loader");
+ }
+
+ public void abort() {
+ mAbort = true;
+ }
+
+ @Override
+ public void run() {
+ while (true) {
+ BatteryEntry be;
+ synchronized (mRequestQueue) {
+ if (mRequestQueue.isEmpty() || mAbort) {
+ mHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN);
+ mRequestQueue.clear();
+ return;
+ }
+ be = mRequestQueue.remove(0);
+ }
+ be.loadNameAndIcon();
+ }
+ }
+ }
+
+ private static NameAndIconLoader mRequestThread;
+
+ public static void startRequestQueue() {
+ if (mHandler != null) {
+ synchronized (mRequestQueue) {
+ if (!mRequestQueue.isEmpty()) {
+ if (mRequestThread != null) {
+ mRequestThread.abort();
+ }
+ mRequestThread = new NameAndIconLoader();
+ mRequestThread.setPriority(Thread.MIN_PRIORITY);
+ mRequestThread.start();
+ mRequestQueue.notify();
+ }
+ }
+ }
+ }
+
+ public static void stopRequestQueue() {
+ synchronized (mRequestQueue) {
+ if (mRequestThread != null) {
+ mRequestThread.abort();
+ mRequestThread = null;
+ mHandler = null;
+ }
+ }
+ }
+
+ public static void clearUidCache() {
+ sUidCache.clear();
+ }
+
+ public final Context context;
+ public final BatterySipper sipper;
+
+ public String name;
+ public Drawable icon;
+ public int iconId; // For passing to the detail screen.
+ public String defaultPackageName;
+
+ static class UidToDetail {
+ String name;
+ String packageName;
+ Drawable icon;
+ }
+
+ public BatteryEntry(Context context, Handler handler, UserManager um, BatterySipper sipper) {
+ mHandler = handler;
+ this.context = context;
+ this.sipper = sipper;
+ switch (sipper.drainType) {
+ case IDLE:
+ name = context.getResources().getString(R.string.power_idle);
+ iconId = R.drawable.ic_settings_phone_idle;
+ break;
+ case CELL:
+ name = context.getResources().getString(R.string.power_cell);
+ iconId = R.drawable.ic_settings_cell_standby;
+ break;
+ case PHONE:
+ name = context.getResources().getString(R.string.power_phone);
+ iconId = R.drawable.ic_settings_voice_calls;
+ break;
+ case WIFI:
+ name = context.getResources().getString(R.string.power_wifi);
+ iconId = R.drawable.ic_settings_wifi;
+ break;
+ case BLUETOOTH:
+ name = context.getResources().getString(R.string.power_bluetooth);
+ iconId = R.drawable.ic_settings_bluetooth;
+ break;
+ case SCREEN:
+ name = context.getResources().getString(R.string.power_screen);
+ iconId = R.drawable.ic_settings_display;
+ break;
+ case APP:
+ name = sipper.packageWithHighestDrain;
+ break;
+ case USER: {
+ UserInfo info = um.getUserInfo(sipper.userId);
+ if (info != null) {
+ icon = UserUtils.getUserIcon(context, um, info, context.getResources());
+ name = info != null ? info.name : null;
+ if (name == null) {
+ name = Integer.toString(info.id);
+ }
+ name = context.getResources().getString(
+ R.string.running_process_item_user_label, name);
+ } else {
+ icon = null;
+ name = context.getResources().getString(
+ R.string.running_process_item_removed_user_label);
+ }
+ } break;
+ case UNACCOUNTED:
+ name = context.getResources().getString(R.string.power_unaccounted);
+ iconId = R.drawable.ic_power_system;
+ break;
+ case OVERCOUNTED:
+ name = context.getResources().getString(R.string.power_overcounted);
+ iconId = R.drawable.ic_power_system;
+ break;
+ }
+ if (iconId > 0) {
+ icon = context.getResources().getDrawable(iconId);
+ }
+ if ((name == null || iconId == 0) && this.sipper.uidObj != null) {
+ getQuickNameIconForUid(this.sipper.uidObj);
+ }
+ }
+
+ public Drawable getIcon() {
+ return icon;
+ }
+
+ /**
+ * Gets the application name
+ */
+ public String getLabel() {
+ return name;
+ }
+
+ void getQuickNameIconForUid(BatteryStats.Uid uidObj) {
+ final int uid = uidObj.getUid();
+ final String uidString = Integer.toString(uid);
+ if (sUidCache.containsKey(uidString)) {
+ UidToDetail utd = sUidCache.get(uidString);
+ defaultPackageName = utd.packageName;
+ name = utd.name;
+ icon = utd.icon;
+ return;
+ }
+ PackageManager pm = context.getPackageManager();
+ String[] packages = pm.getPackagesForUid(uid);
+ icon = pm.getDefaultActivityIcon();
+ if (packages == null) {
+ //name = Integer.toString(uid);
+ if (uid == 0) {
+ name = context.getResources().getString(R.string.process_kernel_label);
+ } else if ("mediaserver".equals(name)) {
+ name = context.getResources().getString(R.string.process_mediaserver_label);
+ }
+ iconId = R.drawable.ic_power_system;
+ icon = context.getResources().getDrawable(iconId);
+ return;
+ } else {
+ //name = packages[0];
+ }
+ if (mHandler != null) {
+ synchronized (mRequestQueue) {
+ mRequestQueue.add(this);
+ }
+ }
+ }
+
+ /**
+ * Loads the app label and icon image and stores into the cache.
+ */
+ public void loadNameAndIcon() {
+ // Bail out if the current sipper is not an App sipper.
+ if (sipper.uidObj == null) {
+ return;
+ }
+ PackageManager pm = context.getPackageManager();
+ final int uid = sipper.uidObj.getUid();
+ final Drawable defaultActivityIcon = pm.getDefaultActivityIcon();
+ sipper.mPackages = pm.getPackagesForUid(uid);
+ if (sipper.mPackages == null) {
+ name = Integer.toString(uid);
+ return;
+ }
+
+ String[] packageLabels = new String[sipper.mPackages.length];
+ System.arraycopy(sipper.mPackages, 0, packageLabels, 0, sipper.mPackages.length);
+
+ int preferredIndex = -1;
+ // Convert package names to user-facing labels where possible
+ for (int i = 0; i < packageLabels.length; i++) {
+ // Check if package matches preferred package
+ if (packageLabels[i].equals(name)) preferredIndex = i;
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(packageLabels[i], 0);
+ CharSequence label = ai.loadLabel(pm);
+ if (label != null) {
+ packageLabels[i] = label.toString();
+ }
+ if (ai.icon != 0) {
+ defaultPackageName = sipper.mPackages[i];
+ icon = ai.loadIcon(pm);
+ break;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ }
+ if (icon == null) icon = defaultActivityIcon;
+
+ if (packageLabels.length == 1) {
+ name = packageLabels[0];
+ } else {
+ // Look for an official name for this UID.
+ for (String pkgName : sipper.mPackages) {
+ try {
+ final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
+ if (pi.sharedUserLabel != 0) {
+ final CharSequence nm = pm.getText(pkgName,
+ pi.sharedUserLabel, pi.applicationInfo);
+ if (nm != null) {
+ name = nm.toString();
+ if (pi.applicationInfo.icon != 0) {
+ defaultPackageName = pkgName;
+ icon = pi.applicationInfo.loadIcon(pm);
+ }
+ break;
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ }
+ }
+ final String uidString = Integer.toString(sipper.uidObj.getUid());
+ UidToDetail utd = new UidToDetail();
+ utd.name = name;
+ utd.icon = icon;
+ utd.packageName = defaultPackageName;
+ sUidCache.put(uidString, utd);
+ if (mHandler != null) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_NAME_ICON, this));
+ }
+ }
+}
+++ /dev/null
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * 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.android.settings.fuelgauge;
-
-import static android.os.BatteryStats.NETWORK_MOBILE_RX_DATA;
-import static android.os.BatteryStats.NETWORK_MOBILE_TX_DATA;
-import static android.os.BatteryStats.NETWORK_WIFI_RX_DATA;
-import static android.os.BatteryStats.NETWORK_WIFI_TX_DATA;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.pm.UserInfo;
-import android.graphics.drawable.Drawable;
-import android.hardware.Sensor;
-import android.hardware.SensorManager;
-import android.os.BatteryStats;
-import android.os.BatteryStats.Uid;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Parcel;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.preference.PreferenceActivity;
-import android.telephony.SignalStrength;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.os.BatteryStatsImpl;
-import com.android.internal.os.PowerProfile;
-import com.android.internal.util.FastPrintWriter;
-import com.android.settings.R;
-import com.android.settings.fuelgauge.PowerUsageDetail.DrainType;
-import com.android.settings.users.UserUtils;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A helper class for retrieving the power usage information for all applications and services.
- *
- * The caller must initialize this class as soon as activity object is ready to use (for example, in
- * onAttach() for Fragment), call create() in onCreate() and call destroy() in onDestroy().
- */
-public class BatteryStatsHelper {
-
- private static final boolean DEBUG = false;
-
- private static final String TAG = BatteryStatsHelper.class.getSimpleName();
-
- private static BatteryStatsImpl sStatsXfer;
- private IBatteryStats mBatteryInfo;
- private UserManager mUm;
- private BatteryStatsImpl mStats;
- private PowerProfile mPowerProfile;
-
- private final List<BatterySipper> mUsageList = new ArrayList<BatterySipper>();
- private final List<BatterySipper> mWifiSippers = new ArrayList<BatterySipper>();
- private final List<BatterySipper> mBluetoothSippers = new ArrayList<BatterySipper>();
- private final SparseArray<List<BatterySipper>> mUserSippers
- = new SparseArray<List<BatterySipper>>();
- private final SparseArray<Double> mUserPower = new SparseArray<Double>();
-
- private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
-
- private long mStatsPeriod = 0;
- private double mMaxPower = 1;
- private double mTotalPower;
- private double mTotalPowermAh;
- private double mWifiPower;
- private double mBluetoothPower;
- private double mMinDrainedPower;
- private double mMaxDrainedPower;
-
- // How much the apps together have left WIFI running.
- private long mAppWifiRunning;
-
- /** Queue for fetching name and icon for an application */
- private ArrayList<BatterySipper> mRequestQueue = new ArrayList<BatterySipper>();
-
- private Activity mActivity;
- private Handler mHandler;
-
- private class NameAndIconLoader extends Thread {
- private boolean mAbort = false;
-
- public NameAndIconLoader() {
- super("BatteryUsage Icon Loader");
- }
-
- public void abort() {
- mAbort = true;
- }
-
- @Override
- public void run() {
- while (true) {
- BatterySipper bs;
- synchronized (mRequestQueue) {
- if (mRequestQueue.isEmpty() || mAbort) {
- mHandler.sendEmptyMessage(MSG_REPORT_FULLY_DRAWN);
- return;
- }
- bs = mRequestQueue.remove(0);
- }
- bs.loadNameAndIcon();
- }
- }
- }
-
- private NameAndIconLoader mRequestThread;
-
- public BatteryStatsHelper(Activity activity, Handler handler) {
- mActivity = activity;
- mHandler = handler;
- }
-
- /** Clears the current stats and forces recreating for future use. */
- public void clearStats() {
- mStats = null;
- }
-
- public BatteryStatsImpl getStats() {
- if (mStats == null) {
- load();
- }
- return mStats;
- }
-
- public PowerProfile getPowerProfile() {
- return mPowerProfile;
- }
-
- public void create(Bundle icicle) {
- if (icicle != null) {
- mStats = sStatsXfer;
- }
- mBatteryInfo = IBatteryStats.Stub.asInterface(
- ServiceManager.getService(BatteryStats.SERVICE_NAME));
- mUm = (UserManager) mActivity.getSystemService(Context.USER_SERVICE);
- mPowerProfile = new PowerProfile(mActivity);
- }
-
- public void pause() {
- if (mRequestThread != null) {
- mRequestThread.abort();
- }
- }
-
- public void destroy() {
- if (mActivity.isChangingConfigurations()) {
- sStatsXfer = mStats;
- } else {
- BatterySipper.sUidCache.clear();
- }
- }
-
- public void startBatteryDetailPage(
- PreferenceActivity caller, BatterySipper sipper, boolean showLocationButton) {
- // Initialize mStats if necessary.
- getStats();
-
- Bundle args = new Bundle();
- args.putString(PowerUsageDetail.EXTRA_TITLE, sipper.name);
- args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int)
- Math.ceil(sipper.getSortValue() * 100 / mTotalPower));
- args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int)
- Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
- args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, mStatsPeriod);
- args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
- args.putInt(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
- args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent);
- if (sipper.uidObj != null) {
- args.putInt(PowerUsageDetail.EXTRA_UID, sipper.uidObj.getUid());
- }
- args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, sipper.drainType);
- args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton);
-
- int[] types;
- double[] values;
- switch (sipper.drainType) {
- case APP:
- case USER:
- {
- Uid uid = sipper.uidObj;
- types = new int[] {
- R.string.usage_type_cpu,
- R.string.usage_type_cpu_foreground,
- R.string.usage_type_wake_lock,
- R.string.usage_type_gps,
- R.string.usage_type_wifi_running,
- R.string.usage_type_data_recv,
- R.string.usage_type_data_send,
- R.string.usage_type_data_wifi_recv,
- R.string.usage_type_data_wifi_send,
- R.string.usage_type_audio,
- R.string.usage_type_video,
- };
- values = new double[] {
- sipper.cpuTime,
- sipper.cpuFgTime,
- sipper.wakeLockTime,
- sipper.gpsTime,
- sipper.wifiRunningTime,
- sipper.mobileRxPackets,
- sipper.mobileTxPackets,
- sipper.wifiRxPackets,
- sipper.wifiTxPackets,
- 0,
- 0
- };
-
- if (sipper.drainType == DrainType.APP) {
- Writer result = new StringWriter();
- PrintWriter printWriter = new FastPrintWriter(result, false, 1024);
- mStats.dumpLocked(printWriter, "", mStatsType, uid.getUid());
- printWriter.flush();
- args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
-
- result = new StringWriter();
- printWriter = new FastPrintWriter(result, false, 1024);
- mStats.dumpCheckinLocked(printWriter, mStatsType, uid.getUid());
- printWriter.flush();
- args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
- result.toString());
- }
- }
- break;
- case CELL:
- {
- types = new int[] {
- R.string.usage_type_on_time,
- R.string.usage_type_no_coverage
- };
- values = new double[] {
- sipper.usageTime,
- sipper.noCoveragePercent
- };
- }
- break;
- case WIFI:
- {
- types = new int[] {
- R.string.usage_type_wifi_running,
- R.string.usage_type_cpu,
- R.string.usage_type_cpu_foreground,
- R.string.usage_type_wake_lock,
- R.string.usage_type_data_recv,
- R.string.usage_type_data_send,
- R.string.usage_type_data_wifi_recv,
- R.string.usage_type_data_wifi_send,
- };
- values = new double[] {
- sipper.usageTime,
- sipper.cpuTime,
- sipper.cpuFgTime,
- sipper.wakeLockTime,
- sipper.mobileRxPackets,
- sipper.mobileTxPackets,
- sipper.wifiRxPackets,
- sipper.wifiTxPackets,
- };
- } break;
- case BLUETOOTH:
- {
- types = new int[] {
- R.string.usage_type_on_time,
- R.string.usage_type_cpu,
- R.string.usage_type_cpu_foreground,
- R.string.usage_type_wake_lock,
- R.string.usage_type_data_recv,
- R.string.usage_type_data_send,
- R.string.usage_type_data_wifi_recv,
- R.string.usage_type_data_wifi_send,
- };
- values = new double[] {
- sipper.usageTime,
- sipper.cpuTime,
- sipper.cpuFgTime,
- sipper.wakeLockTime,
- sipper.mobileRxPackets,
- sipper.mobileTxPackets,
- sipper.wifiRxPackets,
- sipper.wifiTxPackets,
- };
- } break;
- case UNACCOUNTED:
- case OVERCOUNTED:
- {
- types = new int[] {
- R.string.usage_type_total_battery_capacity,
- R.string.usage_type_computed_power,
- R.string.usage_type_min_actual_power,
- R.string.usage_type_max_actual_power,
- };
- values = new double[] {
- mPowerProfile.getBatteryCapacity(),
- mTotalPowermAh,
- mMinDrainedPower,
- mMaxDrainedPower,
- };
- } break;
- default:
- {
- types = new int[] {
- R.string.usage_type_on_time
- };
- values = new double[] {
- sipper.usageTime
- };
- }
- }
- args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
- args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
- caller.startPreferencePanel(PowerUsageDetail.class.getName(), args,
- R.string.details_title, null, null, 0);
- }
-
- /**
- * Refreshes the power usage list.
- * @param includeZeroConsumption whether includes those applications which have consumed very
- * little power up till now.
- */
- public void refreshStats(boolean includeZeroConsumption) {
- // Initialize mStats if necessary.
- getStats();
-
- mMaxPower = 0;
- mTotalPower = 0;
- mWifiPower = 0;
- mBluetoothPower = 0;
- mAppWifiRunning = 0;
-
- mUsageList.clear();
- mWifiSippers.clear();
- mBluetoothSippers.clear();
- mUserSippers.clear();
- mUserPower.clear();
-
- mMinDrainedPower = (mStats.getLowDischargeAmountSinceCharge()
- * mPowerProfile.getBatteryCapacity()) / 100;
- mMaxDrainedPower = (mStats.getHighDischargeAmountSinceCharge()
- * mPowerProfile.getBatteryCapacity()) / 100;
-
- processAppUsage(includeZeroConsumption);
- processMiscUsage();
-
- // We have been computing totals in seconds, convert to hours.
- mTotalPowermAh = mTotalPower / 3600;
-
- if (true || mStats.getLowDischargeAmountSinceCharge() > 10) {
- if (mMinDrainedPower > mTotalPowermAh) {
- double amount = mMinDrainedPower - mTotalPowermAh;
- if (mMaxPower < amount) {
- mMaxPower = amount;
- }
- addEntryNoTotal(mActivity.getString(R.string.power_unaccounted),
- DrainType.UNACCOUNTED, 0, R.drawable.ic_power_system, amount * 3600);
- } else if (mMaxDrainedPower < mTotalPowermAh) {
- double amount = mTotalPowermAh - mMaxDrainedPower;
- if (mMaxPower < amount) {
- mMaxPower = amount;
- }
- addEntryNoTotal(mActivity.getString(R.string.power_overcounted),
- DrainType.OVERCOUNTED, 0, R.drawable.ic_power_system, amount * 3600);
- }
- }
-
- Collections.sort(mUsageList);
-
- if (mHandler != null) {
- synchronized (mRequestQueue) {
- if (!mRequestQueue.isEmpty()) {
- if (mRequestThread != null) {
- mRequestThread.abort();
- }
- mRequestThread = new NameAndIconLoader();
- mRequestThread.setPriority(Thread.MIN_PRIORITY);
- mRequestThread.start();
- mRequestQueue.notify();
- }
- }
- }
- }
-
- private void processAppUsage(boolean includeZeroConsumption) {
- SensorManager sensorManager = (SensorManager) mActivity.getSystemService(
- Context.SENSOR_SERVICE);
- final int which = mStatsType;
- final int speedSteps = mPowerProfile.getNumSpeedSteps();
- final double[] powerCpuNormal = new double[speedSteps];
- final long[] cpuSpeedStepTimes = new long[speedSteps];
- for (int p = 0; p < speedSteps; p++) {
- powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
- }
- final double mobilePowerPerPacket = getMobilePowerPerPacket();
- final double wifiPowerPerPacket = getWifiPowerPerPacket();
- long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which);
- long appWakelockTime = 0;
- BatterySipper osApp = null;
- mStatsPeriod = uSecTime;
- SparseArray<? extends Uid> uidStats = mStats.getUidStats();
- final int NU = uidStats.size();
- for (int iu = 0; iu < NU; iu++) {
- Uid u = uidStats.valueAt(iu);
- double p; // in mAs
- double power = 0; // in mAs
- double highestDrain = 0;
- String packageWithHighestDrain = null;
- //mUsageList.add(new AppUsage(u.getUid(), new double[] {power}));
- Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
- long cpuTime = 0;
- long cpuFgTime = 0;
- long wakelockTime = 0;
- long gpsTime = 0;
- if (DEBUG) Log.i(TAG, "UID " + u.getUid());
- if (processStats.size() > 0) {
- // Process CPU time
- for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
- : processStats.entrySet()) {
- Uid.Proc ps = ent.getValue();
- final long userTime = ps.getUserTime(which);
- final long systemTime = ps.getSystemTime(which);
- final long foregroundTime = ps.getForegroundTime(which);
- cpuFgTime += foregroundTime * 10; // convert to millis
- final long tmpCpuTime = (userTime + systemTime) * 10; // convert to millis
- int totalTimeAtSpeeds = 0;
- // Get the total first
- for (int step = 0; step < speedSteps; step++) {
- cpuSpeedStepTimes[step] = ps.getTimeAtCpuSpeedStep(step, which);
- totalTimeAtSpeeds += cpuSpeedStepTimes[step];
- }
- if (totalTimeAtSpeeds == 0) totalTimeAtSpeeds = 1;
- // Then compute the ratio of time spent at each speed
- double processPower = 0;
- for (int step = 0; step < speedSteps; step++) {
- double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtSpeeds;
- processPower += ratio * tmpCpuTime * powerCpuNormal[step];
- }
- cpuTime += tmpCpuTime;
- if (DEBUG && processPower != 0) {
- Log.i(TAG, String.format("process %s, cpu power=%.2f",
- ent.getKey(), processPower / 1000));
- }
- power += processPower;
- if (packageWithHighestDrain == null
- || packageWithHighestDrain.startsWith("*")) {
- highestDrain = processPower;
- packageWithHighestDrain = ent.getKey();
- } else if (highestDrain < processPower
- && !ent.getKey().startsWith("*")) {
- highestDrain = processPower;
- packageWithHighestDrain = ent.getKey();
- }
- }
- }
- if (cpuFgTime > cpuTime) {
- if (DEBUG && cpuFgTime > cpuTime + 10000) {
- Log.i(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
- }
- cpuTime = cpuFgTime; // Statistics may not have been gathered yet.
- }
- power /= 1000;
- if (DEBUG && power != 0) Log.i(TAG, String.format("total cpu power=%.2f", power));
-
- // Process wake lock usage
- Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
- for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> wakelockEntry
- : wakelockStats.entrySet()) {
- Uid.Wakelock wakelock = wakelockEntry.getValue();
- // Only care about partial wake locks since full wake locks
- // are canceled when the user turns the screen off.
- BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
- if (timer != null) {
- wakelockTime += timer.getTotalTimeLocked(uSecTime, which);
- }
- }
- wakelockTime /= 1000; // convert to millis
- appWakelockTime += wakelockTime;
-
- // Add cost of holding a wake lock
- p = (wakelockTime
- * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wakelock power=%.2f", p));
-
- // Add cost of mobile traffic
- final long mobileRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, mStatsType);
- final long mobileTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
- final long mobileRxB = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, mStatsType);
- final long mobileTxB = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, mStatsType);
- p = (mobileRx + mobileTx) * mobilePowerPerPacket;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("mobile power=%.2f", p));
-
- // Add cost of wifi traffic
- final long wifiRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, mStatsType);
- final long wifiTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, mStatsType);
- final long wifiRxB = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, mStatsType);
- final long wifiTxB = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, mStatsType);
- p = (wifiRx + wifiTx) * wifiPowerPerPacket;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wifi power=%.2f", p));
-
- // Add cost of keeping WIFI running.
- long wifiRunningTimeMs = u.getWifiRunningTime(uSecTime, which) / 1000;
- mAppWifiRunning += wifiRunningTimeMs;
- p = (wifiRunningTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wifi running power=%.2f", p));
-
- // Add cost of WIFI scans
- long wifiScanTimeMs = u.getWifiScanTime(uSecTime, which) / 1000;
- p = (wifiScanTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / 1000;
- power += p;
- if (DEBUG && p != 0) Log.i(TAG, String.format("wifi scanning power=%.2f", p));
- for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
- long batchScanTimeMs = u.getWifiBatchedScanTime(bin, uSecTime, which) / 1000;
- p = (batchScanTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin));
- power += p;
- if (DEBUG && p != 0) {
- Log.i(TAG, String.format("wifi batched scanning lvl %d = %.2f", bin, p));
- }
- }
-
- // Process Sensor usage
- Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
- for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> sensorEntry
- : sensorStats.entrySet()) {
- Uid.Sensor sensor = sensorEntry.getValue();
- int sensorHandle = sensor.getHandle();
- BatteryStats.Timer timer = sensor.getSensorTime();
- long sensorTime = timer.getTotalTimeLocked(uSecTime, which) / 1000;
- double multiplier = 0;
- switch (sensorHandle) {
- case Uid.Sensor.GPS:
- multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
- gpsTime = sensorTime;
- break;
- default:
- List<Sensor> sensorList = sensorManager.getSensorList(
- android.hardware.Sensor.TYPE_ALL);
- for (android.hardware.Sensor s : sensorList) {
- if (s.getHandle() == sensorHandle) {
- multiplier = s.getPower();
- break;
- }
- }
- }
- p = (multiplier * sensorTime) / 1000;
- power += p;
- if (DEBUG && p != 0) {
- Log.i(TAG, String.format("sensor %s power=%.2f", sensor.toString(), p));
- }
- }
-
- if (DEBUG) Log.i(TAG, String.format("UID %d total power=%.2f", u.getUid(), power));
-
- // Add the app to the list if it is consuming power
- boolean isOtherUser = false;
- final int userId = UserHandle.getUserId(u.getUid());
- if (power != 0 || includeZeroConsumption || u.getUid() == 0) {
- BatterySipper app = new BatterySipper(mActivity, mRequestQueue, mHandler,
- packageWithHighestDrain, DrainType.APP, 0, u,
- new double[] {power});
- app.cpuTime = cpuTime;
- app.gpsTime = gpsTime;
- app.wifiRunningTime = wifiRunningTimeMs;
- app.cpuFgTime = cpuFgTime;
- app.wakeLockTime = wakelockTime;
- app.mobileRxPackets = mobileRx;
- app.mobileTxPackets = mobileTx;
- app.wifiRxPackets = wifiRx;
- app.wifiTxPackets = wifiTx;
- app.mobileRxBytes = mobileRxB;
- app.mobileTxBytes = mobileTxB;
- app.wifiRxBytes = wifiRxB;
- app.wifiTxBytes = wifiTxB;
- if (u.getUid() == Process.WIFI_UID) {
- mWifiSippers.add(app);
- } else if (u.getUid() == Process.BLUETOOTH_UID) {
- mBluetoothSippers.add(app);
- } else if (userId != UserHandle.myUserId()
- && UserHandle.getAppId(u.getUid()) >= Process.FIRST_APPLICATION_UID) {
- isOtherUser = true;
- List<BatterySipper> list = mUserSippers.get(userId);
- if (list == null) {
- list = new ArrayList<BatterySipper>();
- mUserSippers.put(userId, list);
- }
- list.add(app);
- } else {
- mUsageList.add(app);
- }
- if (u.getUid() == 0) {
- osApp = app;
- }
- }
- if (power != 0 || includeZeroConsumption) {
- if (u.getUid() == Process.WIFI_UID) {
- mWifiPower += power;
- } else if (u.getUid() == Process.BLUETOOTH_UID) {
- mBluetoothPower += power;
- } else if (isOtherUser) {
- Double userPower = mUserPower.get(userId);
- if (userPower == null) {
- userPower = power;
- } else {
- userPower += power;
- }
- mUserPower.put(userId, userPower);
- } else {
- if (power > mMaxPower) mMaxPower = power;
- mTotalPower += power;
- }
- }
- }
-
- // The device has probably been awake for longer than the screen on
- // time and application wake lock time would account for. Assign
- // this remainder to the OS, if possible.
- if (osApp != null) {
- long wakeTimeMillis = mStats.computeBatteryUptime(
- SystemClock.uptimeMillis() * 1000, which) / 1000;
- wakeTimeMillis -= appWakelockTime + (mStats.getScreenOnTime(
- SystemClock.elapsedRealtime(), which) / 1000);
- if (wakeTimeMillis > 0) {
- double power = (wakeTimeMillis
- * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / 1000;
- if (DEBUG) Log.i(TAG, "OS wakeLockTime " + wakeTimeMillis + " power " + power);
- osApp.wakeLockTime += wakeTimeMillis;
- osApp.value += power;
- osApp.values[0] += power;
- if (osApp.value > mMaxPower) mMaxPower = osApp.value;
- mTotalPower += power;
- }
- }
- }
-
- private void addPhoneUsage(long uSecNow) {
- long phoneOnTimeMs = mStats.getPhoneOnTime(uSecNow, mStatsType) / 1000;
- double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
- * phoneOnTimeMs / 1000;
- addEntry(mActivity.getString(R.string.power_phone), DrainType.PHONE, phoneOnTimeMs,
- R.drawable.ic_settings_voice_calls, phoneOnPower);
- }
-
- private void addScreenUsage(long uSecNow) {
- double power = 0;
- long screenOnTimeMs = mStats.getScreenOnTime(uSecNow, mStatsType) / 1000;
- power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON);
- final double screenFullPower =
- mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
- for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
- double screenBinPower = screenFullPower * (i + 0.5f)
- / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
- long brightnessTime = mStats.getScreenBrightnessTime(i, uSecNow, mStatsType) / 1000;
- power += screenBinPower * brightnessTime;
- if (DEBUG) {
- Log.i(TAG, "Screen bin power = " + (int) screenBinPower + ", time = "
- + brightnessTime);
- }
- }
- power /= 1000; // To seconds
- addEntry(mActivity.getString(R.string.power_screen), DrainType.SCREEN, screenOnTimeMs,
- R.drawable.ic_settings_display, power);
- }
-
- private void addRadioUsage(long uSecNow) {
- double power = 0;
- final int BINS = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
- long signalTimeMs = 0;
- for (int i = 0; i < BINS; i++) {
- long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, uSecNow, mStatsType) / 1000;
- power += strengthTimeMs / 1000
- * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
- signalTimeMs += strengthTimeMs;
- }
- long scanningTimeMs = mStats.getPhoneSignalScanningTime(uSecNow, mStatsType) / 1000;
- power += scanningTimeMs / 1000 * mPowerProfile.getAveragePower(
- PowerProfile.POWER_RADIO_SCANNING);
- BatterySipper bs =
- addEntry(mActivity.getString(R.string.power_cell), DrainType.CELL,
- signalTimeMs, R.drawable.ic_settings_cell_standby, power);
- if (signalTimeMs != 0) {
- bs.noCoveragePercent = mStats.getPhoneSignalStrengthTime(0, uSecNow, mStatsType)
- / 1000 * 100.0 / signalTimeMs;
- }
- }
-
- private void aggregateSippers(BatterySipper bs, List<BatterySipper> from, String tag) {
- for (int i=0; i<from.size(); i++) {
- BatterySipper wbs = from.get(i);
- if (DEBUG) Log.i(TAG, tag + " adding sipper " + wbs + ": cpu=" + wbs.cpuTime);
- bs.cpuTime += wbs.cpuTime;
- bs.gpsTime += wbs.gpsTime;
- bs.wifiRunningTime += wbs.wifiRunningTime;
- bs.cpuFgTime += wbs.cpuFgTime;
- bs.wakeLockTime += wbs.wakeLockTime;
- bs.mobileRxPackets += wbs.mobileRxPackets;
- bs.mobileTxPackets += wbs.mobileTxPackets;
- bs.wifiRxPackets += wbs.wifiRxPackets;
- bs.wifiTxPackets += wbs.wifiTxPackets;
- bs.mobileRxBytes += wbs.mobileRxBytes;
- bs.mobileTxBytes += wbs.mobileTxBytes;
- bs.wifiRxBytes += wbs.wifiRxBytes;
- bs.wifiTxBytes += wbs.wifiTxBytes;
- }
- }
-
- private void addWiFiUsage(long uSecNow) {
- long onTimeMs = mStats.getWifiOnTime(uSecNow, mStatsType) / 1000;
- long runningTimeMs = mStats.getGlobalWifiRunningTime(uSecNow, mStatsType) / 1000;
- if (DEBUG) Log.i(TAG, "WIFI runningTime=" + runningTimeMs
- + " app runningTime=" + mAppWifiRunning);
- runningTimeMs -= mAppWifiRunning;
- if (runningTimeMs < 0) runningTimeMs = 0;
- double wifiPower = (onTimeMs * 0 /* TODO */
- * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
- + runningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000;
- if (DEBUG) Log.i(TAG, "WIFI power=" + wifiPower + " from procs=" + mWifiPower);
- BatterySipper bs = addEntry(mActivity.getString(R.string.power_wifi), DrainType.WIFI,
- runningTimeMs, R.drawable.ic_settings_wifi, wifiPower + mWifiPower);
- aggregateSippers(bs, mWifiSippers, "WIFI");
- }
-
- private void addIdleUsage(long uSecNow) {
- long idleTimeMs = (uSecNow - mStats.getScreenOnTime(uSecNow, mStatsType)) / 1000;
- double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE))
- / 1000;
- addEntry(mActivity.getString(R.string.power_idle), DrainType.IDLE, idleTimeMs,
- R.drawable.ic_settings_phone_idle, idlePower);
- }
-
- private void addBluetoothUsage(long uSecNow) {
- long btOnTimeMs = mStats.getBluetoothOnTime(uSecNow, mStatsType) / 1000;
- double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
- / 1000;
- int btPingCount = mStats.getBluetoothPingCount();
- btPower += (btPingCount
- * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD)) / 1000;
- BatterySipper bs = addEntry(mActivity.getString(R.string.power_bluetooth),
- DrainType.BLUETOOTH, btOnTimeMs, R.drawable.ic_settings_bluetooth,
- btPower + mBluetoothPower);
- aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
- }
-
- private void addUserUsage() {
- for (int i=0; i<mUserSippers.size(); i++) {
- final int userId = mUserSippers.keyAt(i);
- final List<BatterySipper> sippers = mUserSippers.valueAt(i);
- UserInfo info = mUm.getUserInfo(userId);
- Drawable icon;
- String name;
- if (info != null) {
- icon = UserUtils.getUserIcon(mActivity, mUm, info, mActivity.getResources());
- name = info != null ? info.name : null;
- if (name == null) {
- name = Integer.toString(info.id);
- }
- name = mActivity.getResources().getString(
- R.string.running_process_item_user_label, name);
- } else {
- icon = null;
- name = mActivity.getResources().getString(
- R.string.running_process_item_removed_user_label);
- }
- Double userPower = mUserPower.get(userId);
- double power = (userPower != null) ? userPower : 0.0;
- BatterySipper bs = addEntry(name, DrainType.USER, 0, 0, power);
- bs.icon = icon;
- aggregateSippers(bs, sippers, "User");
- }
- }
-
- /**
- * Return estimated power (in mAs) of sending or receiving a packet with the mobile radio.
- */
- private double getMobilePowerPerPacket() {
- final long MOBILE_BPS = 200000; // TODO: Extract average bit rates from system
- final double MOBILE_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
- / 3600;
-
- final long mobileRx = mStats.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, mStatsType);
- final long mobileTx = mStats.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
- final long mobileData = mobileRx + mobileTx;
-
- final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
- final double mobilePps = radioDataUptimeMs != 0
- ? mobileData / (double)radioDataUptimeMs
- : (((double)MOBILE_BPS) / 8 / 2048);
-
- return MOBILE_POWER / mobilePps;
- }
-
- /**
- * Return estimated power (in mAs) of sending a byte with the Wi-Fi radio.
- */
- private double getWifiPowerPerPacket() {
- final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
- final double WIFI_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
- / 3600;
- return WIFI_POWER / (((double)WIFI_BPS) / 8 / 2048);
- }
-
- private void processMiscUsage() {
- final int which = mStatsType;
- long uSecTime = SystemClock.elapsedRealtime() * 1000;
- final long uSecNow = mStats.computeBatteryRealtime(uSecTime, which);
- final long timeSinceUnplugged = uSecNow;
- if (DEBUG) {
- Log.i(TAG, "Uptime since last unplugged = " + (timeSinceUnplugged / 1000));
- }
-
- addUserUsage();
- addPhoneUsage(uSecNow);
- addScreenUsage(uSecNow);
- addWiFiUsage(uSecNow);
- addBluetoothUsage(uSecNow);
- addIdleUsage(uSecNow); // Not including cellular idle power
- // Don't compute radio usage if it's a wifi-only device
- if (!com.android.settings.Utils.isWifiOnly(mActivity)) {
- addRadioUsage(uSecNow);
- }
- }
-
- private BatterySipper addEntry(String label, DrainType drainType, long time, int iconId,
- double power) {
- mTotalPower += power;
- return addEntryNoTotal(label, drainType, time, iconId, power);
- }
-
- private BatterySipper addEntryNoTotal(String label, DrainType drainType, long time, int iconId,
- double power) {
- if (power > mMaxPower) mMaxPower = power;
- mTotalPower += power;
- BatterySipper bs = new BatterySipper(mActivity, mRequestQueue, mHandler,
- label, drainType, iconId, null, new double[] {power});
- bs.usageTime = time;
- bs.iconId = iconId;
- mUsageList.add(bs);
- return bs;
- }
-
- public List<BatterySipper> getUsageList() {
- return mUsageList;
- }
-
- static final int MSG_UPDATE_NAME_ICON = 1;
- static final int MSG_REPORT_FULLY_DRAWN = 2;
-
- public double getMaxPower() {
- return mMaxPower;
- }
-
- public double getTotalPower() {
- return mTotalPower;
- }
-
- public double getMinDrainedPower() {
- return mMinDrainedPower;
- }
-
- public double getMaxDrainedPower() {
- return mMaxDrainedPower;
- }
-
- 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);
- }
- }
-}
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.BatteryStats;
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.preference.PreferenceActivity;
import android.provider.Settings;
import android.text.TextUtils;
-import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
+import com.android.internal.util.FastPrintWriter;
import com.android.settings.DisplaySettings;
import com.android.settings.R;
import com.android.settings.WirelessSettings;
import com.android.settings.location.LocationSettings;
import com.android.settings.wifi.WifiSettings;
-public class PowerUsageDetail extends Fragment implements Button.OnClickListener {
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
- enum DrainType {
- IDLE,
- CELL,
- PHONE,
- WIFI,
- BLUETOOTH,
- SCREEN,
- APP,
- USER,
- UNACCOUNTED,
- OVERCOUNTED
- }
+public class PowerUsageDetail extends Fragment implements Button.OnClickListener {
// Note: Must match the sequence of the DrainType
private static int[] sDrainTypeDesciptions = new int[] {
R.string.battery_desc_overcounted,
};
+ public static void startBatteryDetailPage(
+ PreferenceActivity caller, BatteryStatsHelper helper, BatteryEntry entry,
+ boolean showLocationButton) {
+ // Initialize mStats if necessary.
+ helper.getStats();
+
+ Bundle args = new Bundle();
+ args.putString(PowerUsageDetail.EXTRA_TITLE, entry.name);
+ args.putInt(PowerUsageDetail.EXTRA_PERCENT, (int)
+ Math.ceil(entry.sipper.value * 100 / helper.getTotalPower()));
+ args.putInt(PowerUsageDetail.EXTRA_GAUGE, (int)
+ Math.ceil(entry.sipper.value * 100 / helper.getMaxPower()));
+ args.putLong(PowerUsageDetail.EXTRA_USAGE_DURATION, helper.getStatsPeriod());
+ args.putString(PowerUsageDetail.EXTRA_ICON_PACKAGE, entry.defaultPackageName);
+ args.putInt(PowerUsageDetail.EXTRA_ICON_ID, entry.iconId);
+ args.putDouble(PowerUsageDetail.EXTRA_NO_COVERAGE, entry.sipper.noCoveragePercent);
+ if (entry.sipper.uidObj != null) {
+ args.putInt(PowerUsageDetail.EXTRA_UID, entry.sipper.uidObj.getUid());
+ }
+ args.putSerializable(PowerUsageDetail.EXTRA_DRAIN_TYPE, entry.sipper.drainType);
+ args.putBoolean(PowerUsageDetail.EXTRA_SHOW_LOCATION_BUTTON, showLocationButton);
+
+ int[] types;
+ double[] values;
+ switch (entry.sipper.drainType) {
+ case APP:
+ case USER:
+ {
+ BatteryStats.Uid uid = entry.sipper.uidObj;
+ types = new int[] {
+ R.string.usage_type_cpu,
+ R.string.usage_type_cpu_foreground,
+ R.string.usage_type_wake_lock,
+ R.string.usage_type_gps,
+ R.string.usage_type_wifi_running,
+ R.string.usage_type_data_recv,
+ R.string.usage_type_data_send,
+ R.string.usage_type_data_wifi_recv,
+ R.string.usage_type_data_wifi_send,
+ R.string.usage_type_audio,
+ R.string.usage_type_video,
+ };
+ values = new double[] {
+ entry.sipper.cpuTime,
+ entry.sipper.cpuFgTime,
+ entry.sipper.wakeLockTime,
+ entry.sipper.gpsTime,
+ entry.sipper.wifiRunningTime,
+ entry.sipper.mobileRxPackets,
+ entry.sipper.mobileTxPackets,
+ entry.sipper.wifiRxPackets,
+ entry.sipper.wifiTxPackets,
+ 0,
+ 0
+ };
+
+ if (entry.sipper.drainType == BatterySipper.DrainType.APP) {
+ Writer result = new StringWriter();
+ PrintWriter printWriter = new FastPrintWriter(result, false, 1024);
+ helper.getStats().dumpLocked(caller, printWriter, "", helper.getStatsType(),
+ uid.getUid());
+ printWriter.flush();
+ args.putString(PowerUsageDetail.EXTRA_REPORT_DETAILS, result.toString());
+
+ result = new StringWriter();
+ printWriter = new FastPrintWriter(result, false, 1024);
+ helper.getStats().dumpCheckinLocked(caller, printWriter, helper.getStatsType(),
+ uid.getUid());
+ printWriter.flush();
+ args.putString(PowerUsageDetail.EXTRA_REPORT_CHECKIN_DETAILS,
+ result.toString());
+ }
+ }
+ break;
+ case CELL:
+ {
+ types = new int[] {
+ R.string.usage_type_on_time,
+ R.string.usage_type_no_coverage
+ };
+ values = new double[] {
+ entry.sipper.usageTime,
+ entry.sipper.noCoveragePercent
+ };
+ }
+ break;
+ case WIFI:
+ {
+ types = new int[] {
+ R.string.usage_type_wifi_running,
+ R.string.usage_type_cpu,
+ R.string.usage_type_cpu_foreground,
+ R.string.usage_type_wake_lock,
+ R.string.usage_type_data_recv,
+ R.string.usage_type_data_send,
+ R.string.usage_type_data_wifi_recv,
+ R.string.usage_type_data_wifi_send,
+ };
+ values = new double[] {
+ entry.sipper.usageTime,
+ entry.sipper.cpuTime,
+ entry.sipper.cpuFgTime,
+ entry.sipper.wakeLockTime,
+ entry.sipper.mobileRxPackets,
+ entry.sipper.mobileTxPackets,
+ entry.sipper.wifiRxPackets,
+ entry.sipper.wifiTxPackets,
+ };
+ } break;
+ case BLUETOOTH:
+ {
+ types = new int[] {
+ R.string.usage_type_on_time,
+ R.string.usage_type_cpu,
+ R.string.usage_type_cpu_foreground,
+ R.string.usage_type_wake_lock,
+ R.string.usage_type_data_recv,
+ R.string.usage_type_data_send,
+ R.string.usage_type_data_wifi_recv,
+ R.string.usage_type_data_wifi_send,
+ };
+ values = new double[] {
+ entry.sipper.usageTime,
+ entry.sipper.cpuTime,
+ entry.sipper.cpuFgTime,
+ entry.sipper.wakeLockTime,
+ entry.sipper.mobileRxPackets,
+ entry.sipper.mobileTxPackets,
+ entry.sipper.wifiRxPackets,
+ entry.sipper.wifiTxPackets,
+ };
+ } break;
+ case UNACCOUNTED:
+ case OVERCOUNTED:
+ {
+ types = new int[] {
+ R.string.usage_type_total_battery_capacity,
+ R.string.usage_type_computed_power,
+ R.string.usage_type_min_actual_power,
+ R.string.usage_type_max_actual_power,
+ };
+ values = new double[] {
+ helper.getPowerProfile().getBatteryCapacity(),
+ helper.getTotalPower(),
+ helper.getMinDrainedPower(),
+ helper.getMaxDrainedPower(),
+ };
+ } break;
+ default:
+ {
+ types = new int[] {
+ R.string.usage_type_on_time
+ };
+ values = new double[] {
+ entry.sipper.usageTime
+ };
+ }
+ }
+ args.putIntArray(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
+ args.putDoubleArray(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
+ caller.startPreferencePanel(PowerUsageDetail.class.getName(), args,
+ R.string.details_title, null, null, 0);
+ }
+
public static final int ACTION_DISPLAY_SETTINGS = 1;
public static final int ACTION_WIFI_SETTINGS = 2;
public static final int ACTION_BLUETOOTH_SETTINGS = 3;
private ViewGroup mDetailsParent;
private ViewGroup mControlsParent;
private long mStartTime;
- private DrainType mDrainType;
+ private BatterySipper.DrainType mDrainType;
private Drawable mAppIcon;
private double mNoCoverage; // Percentage of time that there was no coverage
final int gaugeValue = args.getInt(EXTRA_GAUGE, 1);
mUsageSince = args.getInt(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
mUid = args.getInt(EXTRA_UID, 0);
- mDrainType = (DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
+ mDrainType = (BatterySipper.DrainType) args.getSerializable(EXTRA_DRAIN_TYPE);
mNoCoverage = args.getDouble(EXTRA_NO_COVERAGE, 0);
String iconPackage = args.getString(EXTRA_ICON_PACKAGE);
int iconId = args.getInt(EXTRA_ICON_ID, 0);