Battery chart fixes.
When there is no data to show, don't make a crazy collapsed chart. Also avoid re-creating the chart when scrolling. And fix various other things. Change-Id: Ia1895bc7c46e6d830e66f66e66f17726e1e23e3f
This commit is contained in:
@@ -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"
|
||||
|
27
res/layout/power_usage_message_item.xml
Normal file
27
res/layout/power_usage_message_item.xml
Normal file
@@ -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" />
|
@@ -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" />
|
||||
|
@@ -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] -->
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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]);
|
||||
|
@@ -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(),
|
||||
|
Reference in New Issue
Block a user