diff options
-rw-r--r-- | res/layout/power_usage_details.xml | 15 | ||||
-rw-r--r-- | res/layout/power_usage_message_item.xml | 27 | ||||
-rw-r--r-- | res/layout/power_usage_package_item.xml | 23 | ||||
-rw-r--r-- | res/values/strings.xml | 21 | ||||
-rw-r--r-- | src/com/android/settings/fuelgauge/BatteryHistoryChart.java | 40 | ||||
-rw-r--r-- | src/com/android/settings/fuelgauge/BatteryHistoryPreference.java | 18 | ||||
-rw-r--r-- | src/com/android/settings/fuelgauge/PowerUsageDetail.java | 48 | ||||
-rw-r--r-- | src/com/android/settings/fuelgauge/PowerUsageSummary.java | 20 |
8 files changed, 171 insertions, 41 deletions
diff --git a/res/layout/power_usage_details.xml b/res/layout/power_usage_details.xml index a383a37..f711d9a 100644 --- a/res/layout/power_usage_details.xml +++ b/res/layout/power_usage_details.xml @@ -75,6 +75,21 @@ </LinearLayout> + <LinearLayout + android:id="@+id/messages" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:id="@+id/messages_title" + style="?android:attr/listSeparatorTextViewStyle" + android:layout_marginTop="6dip" /> + + <!-- Messages go here ... --> + + </LinearLayout> + <TextView android:id="@+id/packages_section_title" style="?android:attr/listSeparatorTextViewStyle" diff --git a/res/layout/power_usage_message_item.xml b/res/layout/power_usage_message_item.xml new file mode 100644 index 0000000..6f9e619 --- /dev/null +++ b/res/layout/power_usage_message_item.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. +--> + +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="2dip" + android:minHeight="?android:attr/listPreferredItemHeight" + android:paddingStart="4dip" + android:paddingEnd="?android:attr/scrollbarSize" + android:paddingBottom="4dip" + android:ellipsize="marquee" + android:textAppearance="?android:attr/textAppearanceMedium" /> diff --git a/res/layout/power_usage_package_item.xml b/res/layout/power_usage_package_item.xml index d939229..6c31792 100644 --- a/res/layout/power_usage_package_item.xml +++ b/res/layout/power_usage_package_item.xml @@ -14,18 +14,13 @@ limitations under the License. --> -<RelativeLayout +<TextView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_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:singleLine="true" - android:layout_alignParentStart="true" - android:layout_marginBottom="2dip" - android:layout_marginTop="2dip" /> -</RelativeLayout> + android:id="@+id/label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:singleLine="true" + android:layout_alignParentStart="true" + android:layout_marginBottom="2dip" + android:layout_marginTop="2dip" /> diff --git a/res/values/strings.xml b/res/values/strings.xml index ec13ce1..c7f90c4 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3876,12 +3876,11 @@ <string name="usage_type_no_coverage">Time without a signal</string> <!-- Label for the total power capacity of the device's battery --> <string name="usage_type_total_battery_capacity">Total battery capacity</string> - <!-- Label for amount of power use that was computed --> - <string name="usage_type_computed_power">Computed power</string> - <!-- Label for minimum amount of actual power use --> - <string name="usage_type_min_actual_power">Min real power</string> - <!-- Label for maximum amount of power use --> - <string name="usage_type_max_actual_power">Max real power</string> + <!-- [CHAR_LIMIT=NONE] Label for amount of power use that was computed --> + <string name="usage_type_computed_power">Computed power use</string> + <!-- [CHAR_LIMIT=NONE] Label for amount of power use that was actually observed (though + the change in battery level) --> + <string name="usage_type_actual_power">Observed power use</string> <!-- Label for force stop action --> <string name="battery_action_stop">Force stop</string> <!-- Label for app details action --> @@ -3908,6 +3907,9 @@ <!-- Suggestion to switch to airplane mode to save power --> <string name="battery_sugg_radio">Switch to airplane mode to save power in areas with no cell coverage</string> + <!-- [CHAR_LIMIT=NONE] Description for power consumed by the flashlight --> + <string name="battery_desc_flashlight">Battery used by the flashlight</string> + <!-- Description for power consumed by display --> <string name="battery_desc_display">Battery used by the display and backlight</string> <!-- Suggestion for reducing display power --> @@ -3938,7 +3940,12 @@ <string name="battery_desc_users">Battery used by user</string> <!-- [CHAR LIMIT=50] Description for unaccounted power use --> - <string name="battery_desc_unaccounted">Unknown power use</string> + <string name="battery_desc_unaccounted">Miscellaneous power use</string> + <!-- [CHAR LIMIT=NONE] Description for unaccounted power use --> + <string name="battery_msg_unaccounted">Battery use is an approximation of power + use and does not include every source of battery drain. Miscellaneous is the difference + between the computed approximate power use and the actual drain observed on the + battery.</string> <!-- [CHAR LIMIT=50] Description for over-counted power use --> <string name="battery_desc_overcounted">Over-counted power use</string> <!-- Representation of a mAh value. [CHAR LIMIT=NONE] --> diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java index 60e73f5..d88c516 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java +++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java @@ -154,6 +154,7 @@ public class BatteryHistoryChart extends View { BatteryStats mStats; Intent mBatteryBroadcast; long mStatsPeriod; + int mBatteryLevel; String mMaxPercentLabelString; String mMinPercentLabelString; String mDurationString; @@ -493,7 +494,7 @@ public class BatteryHistoryChart extends View { mMinPercentLabelString = getContext().getResources().getString( R.string.percentage, 0); - int batteryLevel = com.android.settings.Utils.getBatteryLevel(mBatteryBroadcast); + mBatteryLevel = com.android.settings.Utils.getBatteryLevel(mBatteryBroadcast); long remainingTimeUs = 0; mDischarging = true; if (mBatteryBroadcast.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) == 0) { @@ -503,10 +504,10 @@ public class BatteryHistoryChart extends View { String timeString = Formatter.formatShortElapsedTime(getContext(), drainTime / 1000); mChargeLabelString = getContext().getResources().getString( - R.string.power_discharging_duration, batteryLevel, timeString); + R.string.power_discharging_duration, mBatteryLevel, timeString); } else { mChargeLabelString = getContext().getResources().getString( - R.string.power_discharging, batteryLevel); + R.string.power_discharging, mBatteryLevel); } } else { final long chargeTime = mStats.computeChargeTimeRemaining(elapsedRealtimeUs); @@ -531,10 +532,10 @@ public class BatteryHistoryChart extends View { resId = R.string.power_charging_duration; } mChargeLabelString = getContext().getResources().getString( - resId, batteryLevel, timeString); + resId, mBatteryLevel, timeString); } else { mChargeLabelString = getContext().getResources().getString( - R.string.power_charging, batteryLevel, statusLabel); + R.string.power_charging, mBatteryLevel, statusLabel); } } mDrainString = ""; @@ -772,14 +773,11 @@ public class BatteryHistoryChart extends View { mDateLabels.clear(); final long walltimeStart = mStartWallTime; - final long walltimeChange = mEndWallTime-walltimeStart; + final long walltimeChange = mEndWallTime > walltimeStart + ? (mEndWallTime-walltimeStart) : 1; long curWalltime = 0; long lastRealtime = 0; - if (walltimeChange == 0) { - return; - } - final int batLow = mBatLow; final int batChange = mBatHigh-mBatLow; @@ -967,8 +965,26 @@ public class BatteryHistoryChart extends View { } } - // Figure out where the actual data ends on the screen. - x = mLevelLeft + (int)(((mEndDataWallTime-walltimeStart)*levelWidth)/walltimeChange); + if (lastY < 0 || lastX < 0) { + // Didn't get any data... + x = lastX = mLevelLeft; + y = lastY = mLevelTop + levelh - ((mBatteryLevel-batLow)*(levelh-1))/batChange; + Path path; + byte value = (byte)mBatteryLevel; + if (value <= mBatteryCriticalLevel) path = mBatCriticalPath; + else if (value <= mBatteryWarnLevel) path = mBatWarnPath; + else path = null; //mBatGoodPath; + if (path != null) { + path.moveTo(x, y); + lastLinePath = path; + } + mBatLevelPath.moveTo(x, y); + curLevelPath = mBatLevelPath; + x = w; + } else { + // Figure out where the actual data ends on the screen. + x = mLevelLeft + (int)(((mEndDataWallTime-walltimeStart)*levelWidth)/walltimeChange); + } finishPaths(x, h, levelh, startX, lastY, curLevelPath, lastX, lastCharging, lastScreenOn, lastGpsOn, lastWifiRunning, diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java index fd7d87a..e7326b1 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java +++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java @@ -22,6 +22,7 @@ import android.graphics.drawable.Drawable; import android.os.BatteryStats; import android.preference.Preference; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; @@ -39,6 +40,7 @@ public class BatteryHistoryPreference extends Preference { private boolean mHideLabels; private View mLabelHeader; + private BatteryHistoryChart mChart; public BatteryHistoryPreference(Context context, BatteryStats stats, Intent batteryBroadcast) { super(context); @@ -66,7 +68,21 @@ public class BatteryHistoryPreference extends Preference { BatteryHistoryChart chart = (BatteryHistoryChart)view.findViewById( R.id.battery_history_chart); - chart.setStats(mStats, mBatteryBroadcast); + if (mChart == null) { + // First time: use and initialize this chart. + chart.setStats(mStats, mBatteryBroadcast); + mChart = chart; + } else { + // All future times: forget the newly inflated chart, re-use the + // already initialized chart from last time. + ViewGroup parent = (ViewGroup)chart.getParent(); + int index = parent.indexOfChild(chart); + parent.removeViewAt(index); + if (mChart.getParent() != null) { + ((ViewGroup)mChart.getParent()).removeView(mChart); + } + parent.addView(mChart, index); + } mLabelHeader = view.findViewById(R.id.labelsHeader); mLabelHeader.setVisibility(mHideLabels ? View.GONE : View.VISIBLE); } diff --git a/src/com/android/settings/fuelgauge/PowerUsageDetail.java b/src/com/android/settings/fuelgauge/PowerUsageDetail.java index d4624c4..fe4fd81 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageDetail.java +++ b/src/com/android/settings/fuelgauge/PowerUsageDetail.java @@ -72,6 +72,7 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener R.string.battery_desc_voice, R.string.battery_desc_wifi, R.string.battery_desc_bluetooth, + R.string.battery_desc_flashlight, R.string.battery_desc_display, R.string.battery_desc_apps, R.string.battery_desc_users, @@ -217,18 +218,28 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener }; } 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, + R.string.usage_type_actual_power, }; values = new double[] { helper.getPowerProfile().getBatteryCapacity(), helper.getComputedPower(), helper.getMinDrainedPower(), + }; + } break; + case OVERCOUNTED: + { + types = new int[] { + R.string.usage_type_total_battery_capacity, + R.string.usage_type_computed_power, + R.string.usage_type_actual_power, + }; + values = new double[] { + helper.getPowerProfile().getBatteryCapacity(), + helper.getComputedPower(), helper.getMaxDrainedPower(), }; } break; @@ -290,6 +301,7 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener private Button mReportButton; private ViewGroup mDetailsParent; private ViewGroup mControlsParent; + private ViewGroup mMessagesParent; private long mStartTime; private BatterySipper.DrainType mDrainType; private Drawable mAppIcon; @@ -390,10 +402,12 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener mDetailsParent = (ViewGroup)mRootView.findViewById(R.id.details); mControlsParent = (ViewGroup)mRootView.findViewById(R.id.controls); + mMessagesParent = (ViewGroup)mRootView.findViewById(R.id.messages); fillDetailsSection(); fillPackagesSection(mUid); fillControlsSection(mUid); + fillMessagesSection(mUid); if (mUid >= Process.FIRST_APPLICATION_UID) { mForceStopButton.setText(R.string.force_stop); @@ -497,8 +511,7 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener break; case R.string.usage_type_total_battery_capacity: case R.string.usage_type_computed_power: - case R.string.usage_type_min_actual_power: - case R.string.usage_type_max_actual_power: + case R.string.usage_type_actual_power: value = getActivity().getString(R.string.mah, (long)(mValues[i])); break; case R.string.usage_type_gps: @@ -591,6 +604,28 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener actionButton.setTag(new Integer(action)); } + private void fillMessagesSection(int uid) { + boolean removeHeader = true; + switch (mDrainType) { + case UNACCOUNTED: + addMessage(R.string.battery_msg_unaccounted); + removeHeader = false; + break; + } + if (removeHeader) { + mMessagesParent.setVisibility(View.GONE); + } + } + + private void addMessage(int message) { + final Resources res = getResources(); + LayoutInflater inflater = getActivity().getLayoutInflater(); + View item = inflater.inflate(R.layout.power_usage_message_item, null); + mMessagesParent.addView(item); + TextView messageView = (TextView) item.findViewById(R.id.message); + messageView.setText(res.getText(message)); + } + private void removePackagesSection() { View view; if ((view = mRootView.findViewById(R.id.packages_section_title)) != null) { @@ -703,8 +738,7 @@ public class PowerUsageDetail extends Fragment implements Button.OnClickListener //if (ai.icon != 0) { // icon = ai.loadIcon(pm); //} - ViewGroup item = (ViewGroup) inflater.inflate(R.layout.power_usage_package_item, - null); + View item = inflater.inflate(R.layout.power_usage_package_item, null); packagesParent.addView(item); TextView labelView = (TextView) item.findViewById(R.id.label); labelView.setText(mPackages[i]); diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java index 70e9176..a691d4d 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -272,6 +272,26 @@ public class PowerUsageSummary extends PreferenceFragment { if (((int) (percentOfTotal + .5)) < 1) { continue; } + if (sipper.drainType == BatterySipper.DrainType.OVERCOUNTED) { + // Don't show over-counted unless it is at least 2/3 the size of + // the largest real entry, and its percent of total is more significant + if (sipper.value < ((mStatsHelper.getMaxRealPower()*2)/3)) { + continue; + } + if (percentOfTotal < 10) { + continue; + } + } + if (sipper.drainType == BatterySipper.DrainType.UNACCOUNTED) { + // Don't show over-counted unless it is at least 1/2 the size of + // the largest real entry, and its percent of total is more significant + if (sipper.value < (mStatsHelper.getMaxRealPower()/2)) { + continue; + } + if (percentOfTotal < 5) { + continue; + } + } final UserHandle userHandle = new UserHandle(UserHandle.getUserId(sipper.getUid())); final BatteryEntry entry = new BatteryEntry(getActivity(), mHandler, mUm, sipper); final PowerGaugePreference pref = new PowerGaugePreference(getActivity(), |