am 7f6aa628: Add detail page for Battery usage and track GPS and foreground CPU.

Merge commit '7f6aa6283ae759c5b013c142be036617cf79f725'

* commit '7f6aa6283ae759c5b013c142be036617cf79f725':
  Add detail page for Battery usage and track GPS and foreground CPU.
This commit is contained in:
Amith Yamasani
2009-06-03 16:57:28 -07:00
committed by The Android Open Source Project
8 changed files with 520 additions and 41 deletions

View File

@@ -505,7 +505,16 @@
</intent-filter>
</activity>
<activity android:name=".fuelgauge.PowerUsageSummary" android:label="@string/power_usage_summary_title">
<activity android:name=".fuelgauge.PowerUsageSummary"
android:label="@string/power_usage_summary_title">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity android:name=".fuelgauge.PowerUsageDetail"
android:label="@string/details_title">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<!--Label for the item-->
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:singleLine="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="2dip"
android:layout_marginTop="2dip" />
<TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="normal"
android:singleLine="true"
android:layout_marginBottom="2dip"
android:layout_marginTop="2dip"
android:layout_marginRight="4dip"/>
</RelativeLayout>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="@+id/all_details"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:paddingRight="6dip"
android:paddingTop="5dip"
android:paddingBottom="5dip"
android:orientation="vertical">
<!-- Details header - icon, label and percentage -->
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical">
<LinearLayout
android:orientation="vertical"
android:layout_alignParentLeft="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingRight="6dip"
android:paddingLeft="6dip" >
<!-- application name -->
<TextView android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold"
android:singleLine="true"
android:ellipsize="marquee"
android:layout_marginBottom="2dip" />
<!-- application version -->
<TextView android:id="@+id/battery_percentage"
android:layout_marginTop="-4dip"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<!-- application icon -->
<ImageView android:id="@+id/icon"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_alignParentRight="true"
android:paddingTop="6dip"
android:paddingBottom="6dip"
android:paddingRight="6dip"
android:scaleType="fitCenter" />
</RelativeLayout>
<TextView
style="?android:attr/listSeparatorTextViewStyle"
android:text="@string/details_subtitle" />
<LinearLayout
android:id="@+id/details"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="6dip"
android:orientation="vertical">
<!-- Insert detail items here -->
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -1503,16 +1503,16 @@ found in the list of installed applications.</string>
<string name="battery_history_starts">Starts: <xliff:g id="starts">%1$d</xliff:g></string>
<!-- Used to show an amount of time in the form "d days, h hours, m minutes, s seconds" in BatteryHistory -->
<string name="battery_history_days"><xliff:g id="days">%1$d</xliff:g> days, <xliff:g id="hours">%2$d</xliff:g> hours, <xliff:g id="minutes">%3$d</xliff:g> minutes, <xliff:g id="seconds">%4$d</xliff:g> seconds</string>
<string name="battery_history_days"><xliff:g id="days">%1$d</xliff:g> d, <xliff:g id="hours">%2$d</xliff:g> h, <xliff:g id="minutes">%3$d</xliff:g> m, <xliff:g id="seconds">%4$d</xliff:g> s</string>
<!-- Used to show an amount of time in the form "h hours, m minutes, s seconds" in BatteryHistory -->
<string name="battery_history_hours"><xliff:g id="hours">%1$d</xliff:g> hours, <xliff:g id="minutes">%2$d</xliff:g> minutes, <xliff:g id="seconds">%3$d</xliff:g> seconds</string>
<string name="battery_history_hours"><xliff:g id="hours">%1$d</xliff:g> h, <xliff:g id="minutes">%2$d</xliff:g> m, <xliff:g id="seconds">%3$d</xliff:g> s</string>
<!-- Used to show an amount of time in the form "m minutes, s seconds" in BatteryHistory -->
<string name="battery_history_minutes"><xliff:g id="minutes">%1$d</xliff:g> minutes, <xliff:g id="seconds">%2$d</xliff:g> seconds</string>
<string name="battery_history_minutes"><xliff:g id="minutes">%1$d</xliff:g> m, <xliff:g id="seconds">%2$d</xliff:g> s</string>
<!-- Used to show an amount of time in the form "s seconds" in BatteryHistory -->
<string name="battery_history_seconds"><xliff:g id="seconds">%1$d</xliff:g> seconds</string>
<string name="battery_history_seconds"><xliff:g id="seconds">%1$d</xliff:g> s</string>
<!-- Used to head a list of packages that share a given user id BatteryHistory -->
<string name="battery_history_packages_sharing_this_uid">Packages sharing this UID:</string>
@@ -1604,12 +1604,23 @@ found in the list of installed applications.</string>
<skip/>
<!-- Activity title for App Fuel Gauge summary -->
<string name="power_usage_summary_title">Power usage summary</string>
<string name="power_usage_summary_title">Battery usage</string>
<!-- Battery usage since unplugged -->
<string name="battery_since_unplugged">Battery usage since unplugged</string>
<!-- Battery usage since user reset the stats -->
<string name="battery_since_reset">Battery usage since reset</string>
<!-- CPU awake time title -->
<string name="awake">Device awake time</string>
<!-- Wifi on time -->
<string name="wifi_on_time">WiFi on time</string>
<!-- Activity title for battery usage details for an app. or power consumer -->
<string name="details_title">Battery usage details</string>
<!-- Subtitle for application/subsystem details -->
<string name="details_subtitle">Usage details</string>
<!-- Subtitle for possible options -->
<string name="controls_subtitle">Controls</string>
<!-- Label for power consumed by the screen -->
<string name="power_screen">Screen on</string>
<!-- Label for power consumed by WiFi -->
@@ -1620,6 +1631,31 @@ found in the list of installed applications.</string>
<string name="power_phone">Voice</string>
<!-- Label for power consumed when Idle -->
<string name="power_idle">Standby</string>
<!-- Label for CPU usage time -->
<string name="usage_type_cpu">CPU total</string>
<!-- Label for CPU usage in foreground -->
<string name="usage_type_cpu_foreground">CPU foreground</string>
<!-- Label for GPU usage time -->
<string name="usage_type_gps">GPS</string>
<!-- Label for Phone usage time -->
<string name="usage_type_phone">Phone</string>
<!-- Label for Data sent -->
<string name="usage_type_data_send">Data sent</string>
<!-- Label for Data received -->
<string name="usage_type_data_recv">Data received</string>
<!-- Label for Audio usage time -->
<string name="usage_type_audio">Audio</string>
<!-- Label for Video usage time -->
<string name="usage_type_video">Video</string>
<!-- Menu label for viewing battery usage since unplugged -->
<string name="menu_stats_unplugged">Usage since unplugged</string>
<!-- Menu label for viewing battery usage total -->
<string name="menu_stats_total">Usage totals</string>
<!-- Menu label for refreshing with latest usage numbers -->
<string name="menu_stats_refresh">Refresh</string>
</resources>

View File

@@ -15,10 +15,6 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/power_usage_summary_title">
<PreferenceCategory
android:key="app_list"
android:title="Application usage"/>
android:title="@string/battery_since_unplugged">
</PreferenceScreen>

View File

@@ -26,6 +26,7 @@ import android.view.View;
import android.widget.ImageView;
import com.android.settings.R;
import com.android.settings.fuelgauge.PowerUsageSummary.BatterySipper;
/**
* Custom preference for displaying power consumption as a bar and an icon on the left for the
@@ -37,13 +38,15 @@ public class PowerGaugePreference extends Preference {
private Drawable mIcon;
private GaugeDrawable mGauge;
private double mValue;
private BatterySipper mInfo;
public PowerGaugePreference(Context context, Drawable icon) {
public PowerGaugePreference(Context context, Drawable icon, BatterySipper info) {
super(context);
setLayoutResource(R.layout.preference_powergauge);
mIcon = icon;
mGauge = new GaugeDrawable();
mGauge.bar = context.getResources().getDrawable(R.drawable.app_gauge);
mInfo = info;
}
/**
@@ -55,6 +58,10 @@ public class PowerGaugePreference extends Preference {
mGauge.percent = mValue;
}
BatterySipper getInfo() {
return mInfo;
}
@Override
protected void onBindView(View view) {
super.onBindView(view);

View File

@@ -0,0 +1,156 @@
/*
* 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 android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.TextView;
import com.android.settings.R;
public class PowerUsageDetail extends Activity {
public static final int USAGE_SINCE_UNPLUGGED = 1;
public static final int USAGE_SINCE_RESET = 2;
public static final String EXTRA_TITLE = "title";
public static final String EXTRA_PERCENT = "percent";
public static final String EXTRA_USAGE_SINCE = "since";
public static final String EXTRA_USAGE_DURATION = "duration";
public static final String EXTRA_DETAIL_TYPES = "types";
public static final String EXTRA_DETAIL_VALUES = "values";
private static final int SECONDS_PER_MINUTE = 60;
private static final int SECONDS_PER_HOUR = 60 * 60;
private static final int SECONDS_PER_DAY = 24 * 60 * 60;
private static final boolean DEBUG = true;
private String mTitle;
private double mPercentage;
private int mUsageSince;
private int[] mTypes;
private double[] mValues;
private TextView mTitleView;
private ViewGroup mDetailsParent;
private long mStartTime;
private static final String TAG = "PowerUsageDetail";
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.power_usage_details);
createDetails();
}
@Override
protected void onResume() {
super.onResume();
mStartTime = android.os.Process.getElapsedCpuTime();
}
@Override
protected void onPause() {
super.onPause();
}
private void createDetails() {
final Intent intent = getIntent();
mTitle = intent.getStringExtra(EXTRA_TITLE);
mPercentage = intent.getDoubleExtra(EXTRA_PERCENT, -1);
mUsageSince = intent.getIntExtra(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
mTypes = intent.getIntArrayExtra(EXTRA_DETAIL_TYPES);
mValues = intent.getDoubleArrayExtra(EXTRA_DETAIL_VALUES);
mTitleView = (TextView) findViewById(R.id.name);
mTitleView.setText(mTitle);
// TODO: I18N
((TextView)findViewById(R.id.battery_percentage))
.setText(String.format("%3.2f%% of battery usage since last unplugged", mPercentage));
mDetailsParent = (ViewGroup) findViewById(R.id.details);
LayoutInflater inflater = getLayoutInflater();
if (mTypes != null && mValues != null) {
for (int i = 0; i < mTypes.length; i++) {
// Only add an item if the time is greater than zero
if (mValues[i] <= 0) continue;
final String label = getString(mTypes[i]);
String value = null;
switch (mTypes[i]) {
case R.string.usage_type_data_recv:
case R.string.usage_type_data_send:
value = formatBytes(mValues[i]);
break;
default:
value = formatTime(mValues[i]);
}
ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_detail_item_text,
null);
mDetailsParent.addView(item);
TextView labelView = (TextView) item.findViewById(R.id.label);
TextView valueView = (TextView) item.findViewById(R.id.value);
labelView.setText(label);
valueView.setText(value);
}
}
}
private String formatTime(double millis) {
StringBuilder sb = new StringBuilder();
int seconds = (int) Math.floor(millis / 1000);
int days = 0, hours = 0, minutes = 0;
if (seconds > SECONDS_PER_DAY) {
days = seconds / SECONDS_PER_DAY;
seconds -= days * SECONDS_PER_DAY;
}
if (seconds > SECONDS_PER_HOUR) {
hours = seconds / SECONDS_PER_HOUR;
seconds -= hours * SECONDS_PER_HOUR;
}
if (seconds > SECONDS_PER_MINUTE) {
minutes = seconds / SECONDS_PER_MINUTE;
seconds -= minutes * SECONDS_PER_MINUTE;
}
if (days > 0) {
sb.append(getString(R.string.battery_history_days, days, hours, minutes, seconds));
} else if (hours > 0) {
sb.append(getString(R.string.battery_history_hours, hours, minutes, seconds));
} else if (minutes > 0) {
sb.append(getString(R.string.battery_history_minutes, minutes, seconds));
} else {
sb.append(getString(R.string.battery_history_seconds, seconds));
}
return sb.toString();
}
private String formatBytes(double bytes) {
// TODO: I18N
if (bytes > 1000 * 1000) {
return String.format("%.2f MB", ((int) (bytes / 1000)) / 1000f);
} else if (bytes > 1024) {
return String.format("%.2f KB", ((int) (bytes / 10)) / 100f);
} else {
return String.format("%d bytes", (int) bytes);
}
}
}

View File

@@ -16,22 +16,31 @@
package com.android.settings.fuelgauge;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.Drawable;
import android.hardware.SensorManager;
import android.os.BatteryStats;
import android.os.Bundle;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.BatteryStats.Timer;
import android.os.BatteryStats.Uid;
import android.os.BatteryStats.Uid.Sensor;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.Log;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuItem;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsImpl;
@@ -52,7 +61,19 @@ public class PowerUsageSummary extends PreferenceActivity {
private static final boolean DEBUG = true;
private static final String TAG = "PowerUsageSummary";
private static final String PREF_APP_LIST = "app_list";
private static final int MENU_STATS_TYPE = Menu.FIRST;
private static final int MENU_STATS_REFRESH = Menu.FIRST + 1;
enum DrainType {
IDLE,
CELL,
PHONE,
WIFI,
BLUETOOTH,
SCREEN,
APP
}
IBatteryStats mBatteryInfo;
BatteryStatsImpl mStats;
@@ -72,8 +93,6 @@ public class PowerUsageSummary extends PreferenceActivity {
private PowerProfile mPowerProfile;
private static final long BATTERY_SIZE = 1200;
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -81,7 +100,7 @@ public class PowerUsageSummary extends PreferenceActivity {
addPreferencesFromResource(R.xml.power_usage_summary);
mBatteryInfo = IBatteryStats.Stub.asInterface(
ServiceManager.getService("batteryinfo"));
mAppListGroup = (PreferenceGroup) findPreference(PREF_APP_LIST);
mAppListGroup = getPreferenceScreen();
mPowerProfile = new PowerProfile(this, "power_profile_default");
}
@@ -92,14 +111,100 @@ public class PowerUsageSummary extends PreferenceActivity {
updateAppsList();
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
PowerGaugePreference pgp = (PowerGaugePreference) preference;
BatterySipper sipper = pgp.getInfo();
Intent intent = new Intent(this, PowerUsageDetail.class);
intent.putExtra(PowerUsageDetail.EXTRA_TITLE, sipper.mLabel);
intent.putExtra(PowerUsageDetail.EXTRA_PERCENT, sipper.getSortValue() * 100 / mTotalPower);
switch (sipper.mDrainType) {
case APP:
{
Uid uid = sipper.mUid;
int[] types = new int[] {
R.string.usage_type_cpu,
R.string.usage_type_cpu_foreground,
R.string.usage_type_gps,
R.string.usage_type_data_send,
R.string.usage_type_data_recv,
R.string.usage_type_audio,
R.string.usage_type_video,
};
double[] values = new double[] {
sipper.mCpuTime,
sipper.mCpuFgTime,
sipper.mGpsTime,
uid != null? uid.getTcpBytesSent(mStatsType) : 0,
uid != null? uid.getTcpBytesReceived(mStatsType) : 0,
0,
0
};
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
}
break;
}
startActivity(intent);
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
/*
menu.add(0, MENU_STATS_TYPE, 0, R.string.menu_stats_total)
.setIcon(com.android.internal.R.drawable.ic_menu_info_details)
.setAlphabeticShortcut('t');
*/
menu.add(0, MENU_STATS_REFRESH, 0, R.string.menu_stats_refresh)
.setIcon(com.android.internal.R.drawable.ic_menu_refresh)
.setAlphabeticShortcut('r');
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
/*
menu.findItem(MENU_STATS_TYPE).setTitle(mStatsType == BatteryStats.STATS_TOTAL
? R.string.menu_stats_unplugged
: R.string.menu_stats_total);
*/
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case MENU_STATS_TYPE:
if (mStatsType == BatteryStats.STATS_TOTAL) {
mStatsType = BatteryStats.STATS_UNPLUGGED;
} else {
mStatsType = BatteryStats.STATS_TOTAL;
}
updateAppsList();
return true;
case MENU_STATS_REFRESH:
mStats = null;
updateAppsList();
return true;
default:
return false;
}
}
private void updateAppsList() {
if (mStats == null) {
load();
}
mMaxPower = 0;
mTotalPower = 0;
mAppListGroup.removeAll();
mUsageList.clear();
processCpuUsage();
processAppUsage();
processMiscUsage();
mAppListGroup.setOrderingAsAdded(false);
@@ -107,11 +212,10 @@ public class PowerUsageSummary extends PreferenceActivity {
Collections.sort(mUsageList);
for (BatterySipper g : mUsageList) {
if (g.getSortValue() < MIN_POWER_THRESHOLD) continue;
double percent = ((g.getSortValue() / mTotalPower) * 100 / BATTERY_SIZE);
PowerGaugePreference pref = new PowerGaugePreference(this, g.getIcon());
double scaleByMax = (g.getSortValue() * 100) / mTotalPower;
pref.setSummary(g.getLabel() + " ( " + (int) g.getSortValue() + "mA, "
+ String.format("%3.2f", scaleByMax) + "% )");
double percent = ((g.getSortValue() / mTotalPower) * 100);
PowerGaugePreference pref = new PowerGaugePreference(this, g.getIcon(), g);
double scaleByMax = (g.getSortValue() * 100) / mMaxPower;
pref.setSummary(g.getLabel() + " ( " + String.format("%3.2f", percent) + "% )");
pref.setOrder(Integer.MAX_VALUE - (int) g.getSortValue()); // Invert the order
pref.setGaugeValue(mScaleByMax ? scaleByMax : percent);
mAppListGroup.addPreference(pref);
@@ -119,7 +223,8 @@ public class PowerUsageSummary extends PreferenceActivity {
}
}
private void processCpuUsage() {
private void processAppUsage() {
SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
final int which = mStatsType;
final double powerCpuNormal = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_NORMAL);
long uSecTime = mStats.computeBatteryRealtime(SystemClock.elapsedRealtime(), which) * 1000;
@@ -131,6 +236,9 @@ public class PowerUsageSummary extends PreferenceActivity {
double power = 0;
//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 gpsTime = 0;
if (processStats.size() > 0) {
for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
: processStats.entrySet()) {
@@ -138,12 +246,20 @@ public class PowerUsageSummary extends PreferenceActivity {
Uid.Proc ps = ent.getValue();
long userTime = ps.getUserTime(which);
long systemTime = ps.getSystemTime(which);
//long starts = ps.getStarts(which);
power += (userTime + systemTime) * 10 /* convert to milliseconds */
* powerCpuNormal;
long foregroundTime = ps.getForegroundTime(which);
cpuFgTime += foregroundTime * 10; // convert to millis
if (DEBUG) Log.i(TAG, "CPU Fg time for " + u.getUid() + " = " + foregroundTime);
cpuTime = (userTime + systemTime) * 10; // convert to millis
power += cpuTime * powerCpuNormal;
}
}
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;
Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
@@ -152,17 +268,32 @@ public class PowerUsageSummary extends PreferenceActivity {
Uid.Sensor sensor = sensorEntry.getValue();
int sensorType = sensor.getHandle();
BatteryStats.Timer timer = sensor.getSensorTime();
long sensorTime = timer.getTotalTimeLocked(uSecTime, which);
long sensorTime = timer.getTotalTimeLocked(uSecTime, which) / 1000;
double multiplier = 0;
switch (sensorType) {
case Uid.Sensor.GPS:
multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
gpsTime = sensorTime;
break;
default:
android.hardware.Sensor sensorData =
sensorManager.getDefaultSensor(sensorType);
if (sensorData != null) {
multiplier = sensorData.getPower();
if (DEBUG) {
Log.i(TAG, "Got sensor " + sensorData.getName() + " with power = "
+ multiplier);
}
power += multiplier * sensorTime;
}
}
power += (multiplier * sensorTime) / 1000;
}
if (power != 0) {
BatterySipper app = new BatterySipper(null, 0, u.getUid(), new double[] {power});
BatterySipper app = new BatterySipper(null, DrainType.APP, 0, u,
new double[] {power});
app.mCpuTime = cpuTime;
app.mGpsTime = gpsTime;
app.mCpuFgTime = cpuFgTime;
mUsageList.add(app);
}
if (power > mMaxPower) mMaxPower = power;
@@ -183,7 +314,8 @@ public class PowerUsageSummary extends PreferenceActivity {
final double screenFullPower =
mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
double screenBinPower = screenFullPower * i / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
double screenBinPower = screenFullPower * (i + 0.5f)
/ BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
long brightnessTime = mStats.getScreenBrightnessTime(i, uSecNow, mStatsType) / 1000;
power += screenBinPower * brightnessTime;
if (DEBUG) {
@@ -215,30 +347,34 @@ public class PowerUsageSummary extends PreferenceActivity {
}
double phoneOnPower = getPhoneOnPower(uSecNow);
addEntry(getString(R.string.power_phone), android.R.drawable.ic_menu_call, phoneOnPower);
addEntry(getString(R.string.power_phone), DrainType.PHONE,
android.R.drawable.ic_menu_call, phoneOnPower);
double screenOnPower = getScreenOnPower(uSecNow);
addEntry(getString(R.string.power_screen), android.R.drawable.ic_menu_view, screenOnPower);
addEntry(getString(R.string.power_screen), DrainType.SCREEN,
android.R.drawable.ic_menu_view, screenOnPower);
double wifiPower = (mStats.getWifiOnTime(uSecNow, which) * 0 /* TODO */
* mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
+ mStats.getWifiRunningTime(uSecNow, which)
* mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / 1000 / 1000;
addEntry(getString(R.string.power_wifi), R.drawable.ic_wifi_signal_4, wifiPower);
addEntry(getString(R.string.power_wifi), DrainType.WIFI,
R.drawable.ic_wifi_signal_4, wifiPower);
double idlePower = ((timeSinceUnplugged - mStats.getScreenOnTime(uSecNow, mStatsType))
* mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE)) / 1000 / 1000;
addEntry(getString(R.string.power_idle), android.R.drawable.ic_lock_power_off, idlePower);
addEntry(getString(R.string.power_idle), DrainType.IDLE,
android.R.drawable.ic_lock_power_off, idlePower);
double radioPower = getRadioPower(uSecNow, which);
addEntry(getString(R.string.power_cell),
addEntry(getString(R.string.power_cell), DrainType.CELL,
android.R.drawable.ic_menu_sort_by_size, radioPower);
}
private void addEntry(String label, int iconId, double power) {
private void addEntry(String label, DrainType drainType, int iconId, double power) {
if (power > mMaxPower) mMaxPower = power;
mTotalPower += power;
BatterySipper bs = new BatterySipper(label, iconId, 0, new double[] {power});
BatterySipper bs = new BatterySipper(label, drainType, iconId, null, new double[] {power});
mUsageList.add(bs);
}
@@ -258,21 +394,27 @@ public class PowerUsageSummary extends PreferenceActivity {
class BatterySipper implements Comparable<BatterySipper> {
String mLabel;
Drawable mIcon;
int mUid;
Uid mUid;
double mValue;
double[] mValues;
DrainType mDrainType;
long mCpuTime;
long mGpsTime;
long mCpuFgTime;
BatterySipper(String label, int iconId, int uid, double[] values) {
BatterySipper(String label, DrainType drainType, int iconId, Uid uid, double[] values) {
mValues = values;
mLabel = label;
mDrainType = drainType;
if (iconId > 0) {
mIcon = getResources().getDrawable(iconId);
}
if (mValues != null) mValue = mValues[0];
//if (uid > 0 && (mLabel == null || mIcon == null) // TODO:
if ((label == null || iconId == 0) && uid > 0) {
getNameForUid(uid);
if ((label == null || iconId == 0) && uid!= null) {
getNameForUid(uid.getUid());
}
mUid = uid;
}
double getSortValue() {