Make the list in advanced battery page sorted by usage.
1. Make the preference dynamically generated in code 2. Make PowerUsageData comparable and add title resource id. Bug: 34385770 Test: RunSettingsRoboTests Change-Id: I1b90b4c6cc7107bc146e3554db04cec7641e1cde
This commit is contained in:
@@ -25,40 +25,6 @@
|
|||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="battery_usage_list"
|
android:key="battery_usage_list"
|
||||||
android:title="@string/battery_detail_since_full_charge">
|
android:title="@string/battery_detail_since_full_charge"/>
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_apps"
|
|
||||||
android:title="@string/power_apps"/>
|
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_wifi"
|
|
||||||
android:title="@string/power_wifi"/>
|
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_cell"
|
|
||||||
android:title="@string/power_cell"/>
|
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_service"
|
|
||||||
android:title="@string/power_service"/>
|
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_system"
|
|
||||||
android:title="@string/power_system"/>
|
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_bluetooth"
|
|
||||||
android:title="@string/power_bluetooth"/>
|
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_idle"
|
|
||||||
android:title="@string/power_idle"/>
|
|
||||||
|
|
||||||
<com.android.settings.fuelgauge.PowerGaugePreference
|
|
||||||
android:key="battery_user"
|
|
||||||
android:title="@string/power_user"/>
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
@@ -49,13 +49,8 @@ public class PowerGaugePreference extends TintablePreference {
|
|||||||
mIconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
|
mIconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PowerGaugePreference(Context context, AttributeSet attrs) {
|
public PowerGaugePreference(Context context) {
|
||||||
super(context, attrs);
|
this(context, null, null, null);
|
||||||
final Drawable icon = context.getDrawable(R.drawable.ic_battery_circle);
|
|
||||||
|
|
||||||
setIcon(icon);
|
|
||||||
setWidgetLayoutResource(R.layout.preference_widget_summary);
|
|
||||||
mIconSize = icon.getIntrinsicWidth();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContentDescription(String name) {
|
public void setContentDescription(String name) {
|
||||||
|
@@ -19,8 +19,10 @@ import android.os.Process;
|
|||||||
import android.provider.SearchIndexableResource;
|
import android.provider.SearchIndexableResource;
|
||||||
import android.support.annotation.ColorInt;
|
import android.support.annotation.ColorInt;
|
||||||
import android.support.annotation.IntDef;
|
import android.support.annotation.IntDef;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
import android.support.annotation.VisibleForTesting;
|
import android.support.annotation.VisibleForTesting;
|
||||||
import android.util.SparseArray;
|
import android.support.v7.preference.PreferenceGroup;
|
||||||
import com.android.internal.logging.nano.MetricsProto;
|
import com.android.internal.logging.nano.MetricsProto;
|
||||||
import com.android.internal.os.BatterySipper;
|
import com.android.internal.os.BatterySipper;
|
||||||
import com.android.internal.os.BatterySipper.DrainType;
|
import com.android.internal.os.BatterySipper.DrainType;
|
||||||
@@ -35,32 +37,37 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class PowerUsageAdvanced extends PowerUsageBase {
|
public class PowerUsageAdvanced extends PowerUsageBase {
|
||||||
private static final String TAG = "AdvancedBatteryUsage";
|
private static final String TAG = "AdvancedBatteryUsage";
|
||||||
private static final String KEY_BATTERY_GRAPH = "battery_graph";
|
private static final String KEY_BATTERY_GRAPH = "battery_graph";
|
||||||
private static final String KEY_BATTERY_APPS = "battery_apps";
|
private static final String KEY_BATTERY_USAGE_LIST = "battery_usage_list";
|
||||||
private static final String KEY_BATTERY_WIFI = "battery_wifi";
|
|
||||||
private static final String KEY_BATTERY_CELL = "battery_cell";
|
|
||||||
private static final String KEY_BATTERY_BLUETOOTH = "battery_bluetooth";
|
|
||||||
private static final String KEY_BATTERY_IDLE = "battery_idle";
|
|
||||||
private static final String KEY_BATTERY_SERVICE = "battery_service";
|
|
||||||
private static final String KEY_BATTERY_SYSTEM = "battery_system";
|
|
||||||
private static final String KEY_BATTERY_USER = "battery_user";
|
|
||||||
|
|
||||||
private BatteryHistoryPreference mHistPref;
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
SparseArray<String> mUsageTypeMap;
|
final int[] mUsageTypes = {
|
||||||
|
UsageType.WIFI,
|
||||||
|
UsageType.CELL,
|
||||||
|
UsageType.SERVICE,
|
||||||
|
UsageType.SYSTEM,
|
||||||
|
UsageType.BLUETOOTH,
|
||||||
|
UsageType.USER,
|
||||||
|
UsageType.IDLE,
|
||||||
|
UsageType.APP};
|
||||||
|
private BatteryHistoryPreference mHistPref;
|
||||||
|
private PreferenceGroup mUsageListGroup;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle icicle) {
|
public void onCreate(Bundle icicle) {
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
|
|
||||||
mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
|
mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
|
||||||
init();
|
mUsageListGroup = (PreferenceGroup) findPreference(KEY_BATTERY_USAGE_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -96,12 +103,15 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
|||||||
updatePreference(mHistPref);
|
updatePreference(mHistPref);
|
||||||
|
|
||||||
List<PowerUsageData> dataList = parsePowerUsageData(mStatsHelper);
|
List<PowerUsageData> dataList = parsePowerUsageData(mStatsHelper);
|
||||||
|
mUsageListGroup.removeAll();
|
||||||
for (int i = 0, size = dataList.size(); i < size; i++) {
|
for (int i = 0, size = dataList.size(); i < size; i++) {
|
||||||
final PowerUsageData data = dataList.get(i);
|
final PowerUsageData batteryData = dataList.get(i);
|
||||||
final String key = mUsageTypeMap.get(data.usageType);
|
final PowerGaugePreference pref = new PowerGaugePreference(getContext());
|
||||||
if (key != null) {
|
|
||||||
bindData(key, data);
|
pref.setTitle(batteryData.titleResId);
|
||||||
}
|
pref.setSummary(batteryData.summary);
|
||||||
|
pref.setPercent(batteryData.percentage);
|
||||||
|
mUsageListGroup.addPreference(pref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,28 +138,13 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
void init() {
|
|
||||||
// Store projection from UsageType to preference key
|
|
||||||
mUsageTypeMap = new SparseArray<>();
|
|
||||||
mUsageTypeMap.put(UsageType.APP, KEY_BATTERY_APPS);
|
|
||||||
mUsageTypeMap.put(UsageType.WIFI, KEY_BATTERY_WIFI);
|
|
||||||
mUsageTypeMap.put(UsageType.CELL, KEY_BATTERY_CELL);
|
|
||||||
mUsageTypeMap.put(UsageType.BLUETOOTH, KEY_BATTERY_BLUETOOTH);
|
|
||||||
mUsageTypeMap.put(UsageType.IDLE, KEY_BATTERY_IDLE);
|
|
||||||
mUsageTypeMap.put(UsageType.SERVICE, KEY_BATTERY_SERVICE);
|
|
||||||
mUsageTypeMap.put(UsageType.USER, KEY_BATTERY_USER);
|
|
||||||
mUsageTypeMap.put(UsageType.SYSTEM, KEY_BATTERY_SYSTEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
List<PowerUsageData> parsePowerUsageData(BatteryStatsHelper statusHelper) {
|
List<PowerUsageData> parsePowerUsageData(BatteryStatsHelper statusHelper) {
|
||||||
final List<BatterySipper> batterySippers = statusHelper.getUsageList();
|
final List<BatterySipper> batterySippers = statusHelper.getUsageList();
|
||||||
final Map<Integer, PowerUsageData> batteryDataMap = new HashMap<>();
|
final Map<Integer, PowerUsageData> batteryDataMap = new HashMap<>();
|
||||||
|
|
||||||
for (int i = 0, size = mUsageTypeMap.size(); i < size; i++) {
|
for (final @UsageType Integer type : mUsageTypes) {
|
||||||
@UsageType final int type = mUsageTypeMap.keyAt(i);
|
batteryDataMap.put(type, new PowerUsageData(type));
|
||||||
batteryDataMap.put(type, PowerUsageData.createBatteryUsageData(type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate power usage based on usage type
|
// Accumulate power usage based on usage type
|
||||||
@@ -165,21 +160,17 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
|||||||
usageData.percentage = (usageData.totalPowerMah / totalPower) * 100;
|
usageData.percentage = (usageData.totalPowerMah / totalPower) * 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Collections.sort(batteryDataList);
|
||||||
|
|
||||||
return batteryDataList;
|
return batteryDataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bindData(String key, PowerUsageData batteryData) {
|
|
||||||
final PowerGaugePreference pref = (PowerGaugePreference) findPreference(key);
|
|
||||||
|
|
||||||
pref.setSummary(batteryData.summary);
|
|
||||||
pref.setPercent(batteryData.percentage);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that contains data used in {@link PowerGaugePreference}.
|
* Class that contains data used in {@link PowerGaugePreference}.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static class PowerUsageData {
|
static class PowerUsageData implements Comparable<PowerUsageData> {
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@IntDef({UsageType.APP,
|
@IntDef({UsageType.APP,
|
||||||
UsageType.WIFI,
|
UsageType.WIFI,
|
||||||
@@ -200,6 +191,8 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
|||||||
int IDLE = 7;
|
int IDLE = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@StringRes
|
||||||
|
public int titleResId;
|
||||||
public String summary;
|
public String summary;
|
||||||
public double percentage;
|
public double percentage;
|
||||||
public double totalPowerMah;
|
public double totalPowerMah;
|
||||||
@@ -208,14 +201,43 @@ public class PowerUsageAdvanced extends PowerUsageBase {
|
|||||||
@UsageType
|
@UsageType
|
||||||
public int usageType;
|
public int usageType;
|
||||||
|
|
||||||
private PowerUsageData(@UsageType int usageType) {
|
public PowerUsageData(@UsageType int usageType) {
|
||||||
this.usageType = usageType;
|
this(usageType, 0);
|
||||||
totalPowerMah = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PowerUsageData createBatteryUsageData(@UsageType int usageType) {
|
public PowerUsageData(@UsageType int usageType, double totalPower) {
|
||||||
// TODO(b/34385770): add color logic in this part
|
this.usageType = usageType;
|
||||||
return new PowerUsageData(usageType);
|
totalPowerMah = 0;
|
||||||
|
titleResId = getTitleResId(usageType);
|
||||||
|
totalPowerMah = totalPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getTitleResId(@UsageType int usageType) {
|
||||||
|
switch (usageType) {
|
||||||
|
case UsageType.WIFI:
|
||||||
|
return R.string.power_wifi;
|
||||||
|
case UsageType.CELL:
|
||||||
|
return R.string.power_cell;
|
||||||
|
case UsageType.SERVICE:
|
||||||
|
return R.string.power_service;
|
||||||
|
case UsageType.SYSTEM:
|
||||||
|
return R.string.power_system;
|
||||||
|
case UsageType.BLUETOOTH:
|
||||||
|
return R.string.power_bluetooth;
|
||||||
|
case UsageType.USER:
|
||||||
|
return R.string.power_user;
|
||||||
|
case UsageType.IDLE:
|
||||||
|
return R.string.power_idle;
|
||||||
|
case UsageType.APP:
|
||||||
|
default:
|
||||||
|
return R.string.power_apps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(@NonNull PowerUsageData powerUsageData) {
|
||||||
|
final int diff = Double.compare(powerUsageData.totalPowerMah, totalPowerMah);
|
||||||
|
return diff != 0 ? diff : usageType - powerUsageData.usageType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package com.android.settings.fuelgauge;
|
package com.android.settings.fuelgauge;
|
||||||
|
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.util.SparseArray;
|
|
||||||
import com.android.internal.os.BatterySipper;
|
import com.android.internal.os.BatterySipper;
|
||||||
import com.android.internal.os.BatterySipper.DrainType;
|
import com.android.internal.os.BatterySipper.DrainType;
|
||||||
import com.android.internal.os.BatteryStatsHelper;
|
import com.android.internal.os.BatteryStatsHelper;
|
||||||
@@ -17,7 +16,9 @@ import org.mockito.MockitoAnnotations;
|
|||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -33,7 +34,6 @@ public class PowerUsageAdvancedTest {
|
|||||||
private static final double TOTAL_USAGE = TYPE_APP_USAGE * 2 + TYPE_BLUETOOTH_USAGE
|
private static final double TOTAL_USAGE = TYPE_APP_USAGE * 2 + TYPE_BLUETOOTH_USAGE
|
||||||
+ TYPE_WIFI_USAGE;
|
+ TYPE_WIFI_USAGE;
|
||||||
private static final double PRECISION = 0.001;
|
private static final double PRECISION = 0.001;
|
||||||
private static final String STRING_NOT_FOUND = "not_found";
|
|
||||||
@Mock
|
@Mock
|
||||||
private BatterySipper mBatterySipper;
|
private BatterySipper mBatterySipper;
|
||||||
@Mock
|
@Mock
|
||||||
@@ -92,7 +92,6 @@ public class PowerUsageAdvancedTest {
|
|||||||
final double percentWifi = TYPE_WIFI_USAGE / TOTAL_USAGE * 100;
|
final double percentWifi = TYPE_WIFI_USAGE / TOTAL_USAGE * 100;
|
||||||
final double percentBluetooth = TYPE_BLUETOOTH_USAGE / TOTAL_USAGE * 100;
|
final double percentBluetooth = TYPE_BLUETOOTH_USAGE / TOTAL_USAGE * 100;
|
||||||
|
|
||||||
mPowerUsageAdvanced.init();
|
|
||||||
List<PowerUsageData> batteryData =
|
List<PowerUsageData> batteryData =
|
||||||
mPowerUsageAdvanced.parsePowerUsageData(mBatteryStatsHelper);
|
mPowerUsageAdvanced.parsePowerUsageData(mBatteryStatsHelper);
|
||||||
for (PowerUsageData data : batteryData) {
|
for (PowerUsageData data : batteryData) {
|
||||||
@@ -114,24 +113,24 @@ public class PowerUsageAdvancedTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInit_ContainsAllUsageType() {
|
public void testInit_ContainsAllUsageType() {
|
||||||
mPowerUsageAdvanced.init();
|
final int[] usageTypeSet = mPowerUsageAdvanced.mUsageTypes;
|
||||||
final SparseArray<String> array = mPowerUsageAdvanced.mUsageTypeMap;
|
|
||||||
|
|
||||||
assertThat(array.get(UsageType.APP, STRING_NOT_FOUND))
|
assertThat(usageTypeSet).asList().containsExactly(UsageType.APP, UsageType.WIFI,
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
UsageType.CELL, UsageType.BLUETOOTH, UsageType.IDLE, UsageType.SERVICE,
|
||||||
assertThat(array.get(UsageType.WIFI, STRING_NOT_FOUND))
|
UsageType.USER, UsageType.SYSTEM);
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
}
|
||||||
assertThat(array.get(UsageType.CELL, STRING_NOT_FOUND))
|
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
@Test
|
||||||
assertThat(array.get(UsageType.BLUETOOTH, STRING_NOT_FOUND))
|
public void testPowerUsageData_SortedByUsage() {
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
List<PowerUsageData> dataList = new ArrayList<>();
|
||||||
assertThat(array.get(UsageType.IDLE, STRING_NOT_FOUND))
|
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
dataList.add(new PowerUsageData(UsageType.WIFI, TYPE_WIFI_USAGE));
|
||||||
assertThat(array.get(UsageType.SERVICE, STRING_NOT_FOUND))
|
dataList.add(new PowerUsageData(UsageType.BLUETOOTH, TYPE_BLUETOOTH_USAGE));
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
dataList.add(new PowerUsageData(UsageType.APP, TYPE_APP_USAGE));
|
||||||
assertThat(array.get(UsageType.USER, STRING_NOT_FOUND))
|
Collections.sort(dataList);
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
|
||||||
assertThat(array.get(UsageType.SYSTEM, STRING_NOT_FOUND))
|
for (int i = 1, size = dataList.size(); i < size; i++) {
|
||||||
.isNotEqualTo(STRING_NOT_FOUND);
|
assertThat(dataList.get(i - 1).totalPowerMah).isAtLeast(dataList.get(i).totalPowerMah);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user