am 8fb0ec36: UI improvements for "Battery use" app.

Merge commit '8fb0ec36ec2f4cb8e0a48020b1b6e79b7f45635c'

* commit '8fb0ec36ec2f4cb8e0a48020b1b6e79b7f45635c':
  UI improvements for "Battery use" app.
This commit is contained in:
Amith Yamasani
2009-07-20 23:33:46 -07:00
committed by Android Git Automerger
5 changed files with 230 additions and 135 deletions

View File

@@ -0,0 +1,53 @@
<?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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:gravity="center_vertical"
android:paddingLeft="4dip"
android:focusable="true"
android:orientation="vertical"
android:paddingRight="?android:attr/scrollbarSize">
<TextView android:id="@+id/summary"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dip"
android:ellipsize="marquee"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!-- Spacer -->
<View
android:id="@+id/buttons_spacer_left"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="0.7"
android:visibility="invisible" />
<Button
android:id="@+id/action_button"
android:layout_width="150dip"
android:paddingRight="6dip"
android:layout_weight="0.3"
android:layout_height="wrap_content"/>
</LinearLayout>
</LinearLayout>

View File

@@ -103,43 +103,18 @@
</LinearLayout>
<LinearLayout
android:id="@+id/controls_section"
android:id="@+id/controls"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/controls_section_title"
android:id="@+id/controls_title"
style="?android:attr/listSeparatorTextViewStyle"
android:layout_marginTop="6dip"
android:text="@string/controls_subtitle" />
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/action_button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_marginRight="6dip"
android:layout_alignParentLeft="true"
android:layout_weight="1"/>
<Button
android:id="@+id/action_button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
android:layout_marginRight="6dip"
android:layout_alignParentRight="true"
android:layout_weight="1"/>
</RelativeLayout>
<!-- Controls go here ... -->
</LinearLayout>

View File

@@ -1662,6 +1662,8 @@ found in the list of installed applications.</string>
<string name="battery_since_reset">Battery use since reset</string>
<!-- Battery usage duration -->
<string name="battery_stats_duration"><xliff:g id="time">%1$s</xliff:g> since unplugged</string>
<!-- Battery usage during last unplugged period -->
<string name="battery_stats_last_duration">@string/menu_stats_last_unplugged</string>
<!-- CPU awake time title -->
<string name="awake">Device awake time</string>
<!-- Wifi on time -->
@@ -1711,7 +1713,9 @@ found in the list of installed applications.</string>
<!-- Label for Video usage time -->
<string name="usage_type_video">Video</string>
<!-- Label for time that a feature has been on -->
<string name="usage_type_on_time">On time</string>
<string name="usage_type_on_time">Time on</string>
<!-- Label for time that there was no cell coverage -->
<string name="usage_type_no_coverage">Time without a signal</string>
<!-- Label for force stop action -->
<string name="battery_action_stop">Force stop</string>
<!-- Label for app details action -->
@@ -1758,7 +1762,7 @@ found in the list of installed applications.</string>
<!-- Suggestion for exploring application info to stop or uninstall -->
<string name="battery_sugg_apps_info">Stop or uninstall the application</string>
<!-- Suggestion for getting apps to consume less power due to GPS-->
<string name="battery_sugg_apps_gps">Turn off GPS when you're not using it</string>
<string name="battery_sugg_apps_gps">"Turn off GPS when you're not using it"</string>
<!-- Suggestion for getting apps to consume less power -->
<string name="battery_sugg_apps_settings">The application may offer settings to reduce battery use</string>

View File

@@ -24,6 +24,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.provider.Settings;
@@ -60,12 +61,13 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
R.string.battery_desc_display,
R.string.battery_desc_apps
};
public static final int ACTION_DISPLAY_SETTINGS = 1;
public static final int ACTION_WIFI_SETTINGS = 2;
public static final int ACTION_BLUETOOTH_SETTINGS = 3;
public static final int ACTION_WIRELESS_SETTINGS = 4;
public static final int ACTION_APP_DETAILS = 6;
public static final int ACTION_APP_DETAILS = 5;
public static final int ACTION_SECURITY_SETTINGS = 6;
public static final int USAGE_SINCE_UNPLUGGED = 1;
public static final int USAGE_SINCE_RESET = 2;
@@ -80,6 +82,7 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
public static final String EXTRA_DETAIL_VALUES = "values"; // Array of doubles
public static final String EXTRA_DRAIN_TYPE = "drainType"; // DrainType
public static final String EXTRA_ICON_PACKAGE = "iconPackage"; // String
public static final String EXTRA_NO_COVERAGE = "noCoverage";
public static final String EXTRA_ICON_ID = "iconId"; // Int
private static final boolean DEBUG = true;
@@ -90,16 +93,16 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
private double[] mValues;
private TextView mTitleView;
private ViewGroup mDetailsParent;
private ViewGroup mControlsParent;
private long mStartTime;
private DrainType mDrainType;
private int mAction1;
private int mAction2;
private PercentageBar mGauge;
private Drawable mAppIcon;
private double mNoCoverage; // Percentage of time that there was no coverage
private boolean mUsesGps;
private static final String TAG = "PowerUsageDetail";
private Button mButton1;
private Button mButton2;
private String[] mPackages;
@Override
@@ -128,6 +131,7 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
mUsageSince = intent.getIntExtra(EXTRA_USAGE_SINCE, USAGE_SINCE_UNPLUGGED);
mUid = intent.getIntExtra(EXTRA_UID, 0);
mDrainType = (DrainType) intent.getSerializableExtra(EXTRA_DRAIN_TYPE);
mNoCoverage = intent.getDoubleExtra(EXTRA_NO_COVERAGE, 0);
String iconPackage = intent.getStringExtra(EXTRA_ICON_PACKAGE);
int iconId = intent.getIntExtra(EXTRA_ICON_ID, 0);
if (!TextUtils.isEmpty(iconPackage)) {
@@ -167,8 +171,46 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
ImageView iconImage = (ImageView) findViewById(R.id.icon);
iconImage.setImageDrawable(mAppIcon);
mDetailsParent = (ViewGroup) findViewById(R.id.details);
mControlsParent = (ViewGroup) findViewById(R.id.controls);
fillDetailsSection();
fillPackagesSection(mUid);
fillControlsSection(mUid);
}
public void onClick(View v) {
doAction((Integer) v.getTag());
}
private void doAction(int action) {
switch (action) {
case ACTION_DISPLAY_SETTINGS:
startActivity(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
break;
case ACTION_WIFI_SETTINGS:
startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
break;
case ACTION_BLUETOOTH_SETTINGS:
startActivity(new Intent(Settings.ACTION_BLUETOOTH_SETTINGS));
break;
case ACTION_WIRELESS_SETTINGS:
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
break;
case ACTION_APP_DETAILS:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClass(this, InstalledAppDetails.class);
intent.putExtra("com.android.settings.ApplicationPkgName", mPackages[0]);
startActivity(intent);
break;
case ACTION_SECURITY_SETTINGS:
startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS));
break;
}
}
private void fillDetailsSection() {
LayoutInflater inflater = getLayoutInflater();
if (mTypes != null && mValues != null) {
for (int i = 0; i < mTypes.length; i++) {
@@ -181,6 +223,12 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
case R.string.usage_type_data_send:
value = Utils.formatBytes(this, mValues[i]);
break;
case R.string.usage_type_no_coverage:
value = String.format("%d%%", (int) Math.floor(mValues[i]));
break;
case R.string.usage_type_gps:
mUsesGps = true;
// Fall through
default:
value = Utils.formatElapsedTime(this, mValues[i]);
}
@@ -193,41 +241,9 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
valueView.setText(value);
}
}
fillPackagesSection(mUid);
fillControlsSection(mUid);
}
public void onClick(View v) {
int action = v == mButton1 ? mAction1 : mAction2;
doAction(action);
}
private void doAction(int action) {
switch (action) {
case ACTION_DISPLAY_SETTINGS:
startActivity(new Intent(Settings.ACTION_DISPLAY_SETTINGS));
break;
case ACTION_WIFI_SETTINGS:
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
break;
case ACTION_BLUETOOTH_SETTINGS:
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
break;
case ACTION_APP_DETAILS:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClass(this, InstalledAppDetails.class);
intent.putExtra("com.android.settings.ApplicationPkgName", mPackages[0]);
startActivity(intent);
break;
}
}
private void fillControlsSection(int uid) {
String label1 = null;
String label2 = null;
mAction1 = 0;
mAction2 = 0;
PackageManager pm = getPackageManager();
String[] packages = pm.getPackagesForUid(uid);
PackageInfo pi = null;
@@ -237,45 +253,68 @@ public class PowerUsageDetail extends Activity implements Button.OnClickListener
ApplicationInfo ai = pi != null? pi.applicationInfo : null;
boolean isSystem = ai != null? (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0 : false;
if (uid < 1000 || !isSystem) {
switch (mDrainType) {
case APP:
//label1 = getString(R.string.battery_action_stop);
if (packages != null) {
label2 = getString(R.string.battery_action_app_details);
mAction2 = ACTION_APP_DETAILS;
}
break;
case SCREEN:
label2 = getString(R.string.battery_action_display);
mAction2 = ACTION_DISPLAY_SETTINGS;
break;
case WIFI:
label2 = getString(R.string.battery_action_wifi);
mAction2 = ACTION_WIRELESS_SETTINGS;
break;
case BLUETOOTH:
//label2 = getString(R.string.battery_action_bluetooth);
//mAction2 = ACTION_BLUETOOTH_SETTINGS;
break;
}
boolean removeHeader = true;
switch (mDrainType) {
case APP:
// If it is a Java application and it's not a system application
if (packages != null && !isSystem) {
addControl(R.string.battery_action_app_details,
R.string.battery_sugg_apps_info, ACTION_APP_DETAILS);
removeHeader = false;
// If the application has a settings screen, jump to that
// TODO:
}
if (mUsesGps) {
addControl(R.string.security_settings_title,
R.string.battery_sugg_apps_gps, ACTION_SECURITY_SETTINGS);
removeHeader = false;
}
break;
case SCREEN:
addControl(R.string.sound_and_display_settings,
R.string.battery_sugg_display,
ACTION_DISPLAY_SETTINGS);
removeHeader = false;
break;
case WIFI:
addControl(R.string.wifi_settings,
R.string.battery_sugg_wifi,
ACTION_WIFI_SETTINGS);
removeHeader = false;
break;
case BLUETOOTH:
addControl(R.string.bluetooth_settings,
R.string.battery_sugg_bluetooth_basic,
ACTION_BLUETOOTH_SETTINGS);
removeHeader = false;
break;
case CELL:
if (mNoCoverage > 10) {
addControl(R.string.radio_controls_title,
R.string.battery_sugg_radio,
ACTION_WIRELESS_SETTINGS);
removeHeader = false;
}
break;
}
mButton1 = (Button) findViewById(R.id.action_button1);
mButton2 = (Button) findViewById(R.id.action_button2);
mButton1.setOnClickListener(this);
mButton2.setOnClickListener(this);
if (label1 == null) {
mButton1.setVisibility(View.GONE);
} else {
mButton1.setText(label1);
}
if (label2 == null) {
findViewById(R.id.controls_section).setVisibility(View.GONE);
} else {
mButton2.setText(label2);
if (removeHeader) {
mControlsParent.setVisibility(View.GONE);
}
}
private void addControl(int title, int summary, int action) {
final Resources res = getResources();
LayoutInflater inflater = getLayoutInflater();
ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_action_item,null);
mControlsParent.addView(item);
Button actionButton = (Button) item.findViewById(R.id.action_button);
TextView summaryView = (TextView) item.findViewById(R.id.summary);
actionButton.setText(res.getString(title));
summaryView.setText(res.getString(summary));
actionButton.setOnClickListener(this);
actionButton.setTag(new Integer(action));
}
private void removePackagesSection() {
View view;
if ((view = findViewById(R.id.packages_section_title)) != null) {

View File

@@ -80,9 +80,6 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
private double mMaxPower = 1;
private double mTotalPower;
private boolean mScaleByMax = true;
private PowerProfile mPowerProfile;
private HashMap<String,UidToDetail> mUidCache = new HashMap<String,UidToDetail>();
@@ -137,15 +134,19 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
Math.ceil(sipper.getSortValue() * 100 / mMaxPower));
intent.putExtra(PowerUsageDetail.EXTRA_ICON_PACKAGE, sipper.defaultPackageName);
intent.putExtra(PowerUsageDetail.EXTRA_ICON_ID, sipper.iconId);
intent.putExtra(PowerUsageDetail.EXTRA_NO_COVERAGE, sipper.noCoveragePercent);
if (sipper.uidObj != null) {
intent.putExtra(PowerUsageDetail.EXTRA_UID, sipper.uidObj.getUid());
}
intent.putExtra(PowerUsageDetail.EXTRA_DRAIN_TYPE, sipper.drainType);
int[] types;
double[] values;
switch (sipper.drainType) {
case APP:
{
Uid uid = sipper.uidObj;
int[] types = new int[] {
types = new int[] {
R.string.usage_type_cpu,
R.string.usage_type_cpu_foreground,
R.string.usage_type_gps,
@@ -154,7 +155,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
R.string.usage_type_audio,
R.string.usage_type_video,
};
double[] values = new double[] {
values = new double[] {
sipper.cpuTime,
sipper.cpuFgTime,
sipper.gpsTime,
@@ -163,23 +164,33 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
0,
0
};
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
}
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;
default:
{
int[] types = new int[] {
types = new int[] {
R.string.usage_type_on_time
};
double[] values = new double[] {
values = new double[] {
sipper.usageTime
};
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
}
}
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_TYPES, types);
intent.putExtra(PowerUsageDetail.EXTRA_DETAIL_VALUES, values);
startActivity(intent);
return super.onPreferenceTreeClick(preferenceScreen, preference);
@@ -243,19 +254,19 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
mAppListGroup.setOrderingAsAdded(false);
Collections.sort(mUsageList);
for (BatterySipper g : mUsageList) {
if (g.getSortValue() < MIN_POWER_THRESHOLD) continue;
double percent = ((g.getSortValue() / mTotalPower) * 100);
if (percent < 1) continue;
PowerGaugePreference pref = new PowerGaugePreference(this, g.getIcon(), g);
double scaleByMax = (g.getSortValue() * 100) / mMaxPower;
g.percent = percent;
pref.setTitle(g.name);
pref.setPercent(percent);
pref.setOrder(Integer.MAX_VALUE - (int) g.getSortValue()); // Invert the order
pref.setGaugeValue(mScaleByMax ? scaleByMax : percent);
if (g.uidObj != null) {
pref.setKey(Integer.toString(g.uidObj.getUid()));
for (BatterySipper sipper : mUsageList) {
if (sipper.getSortValue() < MIN_POWER_THRESHOLD) continue;
final double percentOfTotal = ((sipper.getSortValue() / mTotalPower) * 100);
if (percentOfTotal < 1) continue;
PowerGaugePreference pref = new PowerGaugePreference(this, sipper.getIcon(), sipper);
double percentOfMax = (sipper.getSortValue() * 100) / mMaxPower;
sipper.percent = percentOfTotal;
pref.setTitle(sipper.name);
pref.setPercent(percentOfTotal);
pref.setOrder(Integer.MAX_VALUE - (int) sipper.getSortValue()); // Invert the order
pref.setGaugeValue(percentOfMax);
if (sipper.uidObj != null) {
pref.setKey(Integer.toString(sipper.uidObj.getUid()));
}
mAppListGroup.addPreference(pref);
if (mAppListGroup.getPreferenceCount() > MAX_ITEMS_TO_LIST) break;
@@ -275,7 +286,9 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
private void updateStatsPeriod(long duration) {
String durationString = Utils.formatElapsedTime(this, duration / 1000);
String label = getString(R.string.battery_stats_duration, durationString);
String label = getString(mStats.isOnBattery()
? R.string.battery_stats_duration
: R.string.battery_stats_last_duration, durationString);
setTitle(label);
}
@@ -415,8 +428,13 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
* mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i);
signalTimeMs += strengthTimeMs;
}
addEntry(getString(R.string.power_cell), DrainType.CELL, signalTimeMs,
BatterySipper bs =
addEntry(getString(R.string.power_cell), DrainType.CELL, signalTimeMs,
android.R.drawable.ic_menu_sort_by_size, power);
if (signalTimeMs != 0) {
bs.noCoveragePercent = mStats.getPhoneSignalStrengthTime(0, uSecNow, mStatsType)
/ 1000 * 100.0 / signalTimeMs;
}
}
private void addWiFiUsage(long uSecNow) {
@@ -441,6 +459,10 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
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;
addEntry(getString(R.string.power_bluetooth), DrainType.IDLE, btOnTimeMs,
com.android.internal.R.drawable.ic_volume_bluetooth_in_call, btPower);
}
@@ -456,7 +478,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
mStats.getMobileTcpBytesSent(mStatsType);
final long wifiData = mStats.getTotalTcpBytesReceived(mStatsType) +
mStats.getTotalTcpBytesSent(mStatsType) - mobileData;
final long radioDataUptimeMs = mStats.getRadioDataUptimeMs();
final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
final long mobileBps = radioDataUptimeMs != 0
? mobileData * 8 * 1000 / radioDataUptimeMs
: MOBILE_BPS;
@@ -488,13 +510,15 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
addRadioUsage(uSecNow);
}
private void addEntry(String label, DrainType drainType, long time, int iconId, double power) {
private BatterySipper addEntry(String label, DrainType drainType, long time, int iconId,
double power) {
if (power > mMaxPower) mMaxPower = power;
mTotalPower += power;
BatterySipper bs = new BatterySipper(label, drainType, iconId, null, new double[] {power});
bs.usageTime = time;
bs.iconId = iconId;
mUsageList.add(bs);
return bs;
}
private void load() {
@@ -523,6 +547,7 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
long gpsTime;
long cpuFgTime;
double percent;
double noCoveragePercent;
String defaultPackageName;
BatterySipper(String label, DrainType drainType, int iconId, Uid uid, double[] values) {
@@ -533,7 +558,6 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
icon = getResources().getDrawable(iconId);
}
if (values != null) value = values[0];
//if (uid > 0 && (mLabel == null || mIcon == null) // TODO:
if ((label == null || iconId == 0) && uid != null) {
getQuickNameIconForUid(uid);
}
@@ -631,9 +655,9 @@ public class PowerUsageSummary extends PreferenceActivity implements Runnable {
// Look for an official name for this UID.
for (String pkgName : packages) {
try {
PackageInfo pi = pm.getPackageInfo(pkgName, 0);
final PackageInfo pi = pm.getPackageInfo(pkgName, 0);
if (pi.sharedUserLabel != 0) {
CharSequence nm = pm.getText(pkgName,
final CharSequence nm = pm.getText(pkgName,
pi.sharedUserLabel, pi.applicationInfo);
if (nm != null) {
name = nm.toString();