Create Advanced battery page
The advanced page shows two major parts, one is the battery usage graph and the other is battery usage list. In usage list, each item shows basic info of battery usage of one type(e.g. Apps, System) Bug: 34385770 Test: RunSettingsRoboTests Change-Id: I22475a489285787afa775af8d5ae3340eff1eed9
This commit is contained in:
24
res/drawable/ic_battery_circle.xml
Normal file
24
res/drawable/ic_battery_circle.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright (C) 2017 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0"
|
||||
android:tint="?android:attr/colorControlNormal">
|
||||
<path android:fillColor="#FF000000"
|
||||
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/>
|
||||
</vector>
|
@@ -153,4 +153,8 @@
|
||||
<attr name="aspectRatio" format="float" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="TintablePreference">
|
||||
<attr name="android:tint" format="color|reference"/>
|
||||
</declare-styleable>
|
||||
|
||||
</resources>
|
||||
|
@@ -4320,7 +4320,9 @@
|
||||
<!-- Bluetooth on time -->
|
||||
<string name="bluetooth_on_time">Wi\u2011Fi on time</string>
|
||||
|
||||
<!-- Activity title for battery usage history details -->
|
||||
<!-- Activity title for advanced battery usage page [CHAR LIMIT=60] -->
|
||||
<string name="advanced_battery_title">Advanced battery usage</string>
|
||||
<!-- Activity title for battery usage history details [CHAR LIMIT=60] -->
|
||||
<string name="history_details_title">History details</string>
|
||||
|
||||
<!-- Activity title for battery usage details for an app. or power consumer -->
|
||||
@@ -4354,6 +4356,14 @@
|
||||
<string name="power_unaccounted">Miscellaneous</string>
|
||||
<!-- Label for power that we computed too much for -->
|
||||
<string name="power_overcounted">Over-counted</string>
|
||||
<!-- Label for power consumed by apps [CHAR LIMIT=30] -->
|
||||
<string name="power_apps">Apps</string>
|
||||
<!-- Label for power consumed by services [CHAR LIMIT=30] -->
|
||||
<string name="power_service">Services</string>
|
||||
<!-- Label for power consumed by system [CHAR LIMIT=30] -->
|
||||
<string name="power_system">System</string>
|
||||
<!-- Label for power consumed by user [CHAR LIMIT=30] -->
|
||||
<string name="power_user">User</string>
|
||||
|
||||
<!-- Label for CPU usage time -->
|
||||
<string name="usage_type_cpu">CPU total</string>
|
||||
@@ -4473,6 +4483,8 @@
|
||||
|
||||
<!-- Description for battery usage time for an app, i.e. Used for 30min. [CHAR LIMIT=60] -->
|
||||
<string name="battery_used_for">Used for %1$s</string>
|
||||
<!-- Description for battery usage detail information since last full charge. [CHAR LIMIT=120] -->
|
||||
<string name="battery_detail_since_full_charge">Usage breakdown since last full charge</string>
|
||||
|
||||
<!-- Menu label for viewing battery usage since unplugged -->
|
||||
<string name="menu_stats_unplugged"><xliff:g id="unplugged">%1$s</xliff:g> since unplugged</string>
|
||||
|
@@ -433,5 +433,4 @@
|
||||
</style>
|
||||
|
||||
<style name="AppActionPrimaryButton" parent="android:Widget.Material.Button.Colored"/>
|
||||
|
||||
</resources>
|
||||
|
64
res/xml/power_usage_advanced.xml
Normal file
64
res/xml/power_usage_advanced.xml
Normal file
@@ -0,0 +1,64 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2017 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
|
||||
android:title="@string/advanced_battery_title"
|
||||
settings:keywords="@string/keywords_battery">
|
||||
|
||||
<com.android.settings.fuelgauge.BatteryHistoryPreference
|
||||
android:key="battery_graph"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="battery_usage_list"
|
||||
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>
|
@@ -17,17 +17,23 @@ package com.android.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
public class TintablePreference extends Preference {
|
||||
|
||||
@ColorInt
|
||||
private int mTintColor;
|
||||
|
||||
public TintablePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TintablePreference);
|
||||
mTintColor = a.getColor(R.styleable.TintablePreference_android_tint, 0);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public void setTint(int color) {
|
||||
|
@@ -26,6 +26,7 @@ import android.widget.TextView;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.BatteryInfo;
|
||||
import com.android.settingslib.graph.UsageView;
|
||||
|
||||
@@ -49,12 +50,22 @@ public class BatteryHistoryPreference extends Preference {
|
||||
|
||||
@Override
|
||||
public void performClick() {
|
||||
mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
|
||||
Bundle args = new Bundle();
|
||||
args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
|
||||
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST, mHelper.getBatteryBroadcast());
|
||||
Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
|
||||
null, 0, R.string.history_details_title, null);
|
||||
// TODO(b/34890746): remove this since history graph is not clickable
|
||||
final Context context = getContext();
|
||||
final PowerUsageFeatureProvider featureProvider = FeatureFactory.getFactory(context)
|
||||
.getPowerUsageFeatureProvider(context);
|
||||
|
||||
if (featureProvider.isAdvancedUiEnabled()) {
|
||||
Utils.startWithFragment(getContext(), PowerUsageAdvanced.class.getName(), null,
|
||||
null, 0, R.string.advanced_battery_title, null);
|
||||
} else {
|
||||
mHelper.storeStatsHistoryInFile(BATTERY_HISTORY_FILE);
|
||||
Bundle args = new Bundle();
|
||||
args.putString(BatteryHistoryDetail.EXTRA_STATS, BATTERY_HISTORY_FILE);
|
||||
args.putParcelable(BatteryHistoryDetail.EXTRA_BROADCAST, mHelper.getBatteryBroadcast());
|
||||
Utils.startWithFragment(getContext(), BatteryHistoryDetail.class.getName(), args,
|
||||
null, 0, R.string.history_details_title, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void setStats(BatteryStatsHelper batteryStats) {
|
||||
|
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
@@ -48,12 +49,21 @@ public class PowerGaugePreference extends TintablePreference {
|
||||
mIconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
|
||||
}
|
||||
|
||||
public PowerGaugePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
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) {
|
||||
mContentDescription = name;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
public void setPercent(double percentOfMax, double percentOfTotal) {
|
||||
public void setPercent(double percentOfTotal) {
|
||||
mProgress = Utils.formatPercentage((int) (percentOfTotal + 0.5));
|
||||
notifyChanged();
|
||||
}
|
||||
|
237
src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
Normal file
237
src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.support.annotation.ColorInt;
|
||||
import android.support.annotation.IntDef;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.util.SparseArray;
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatterySipper.DrainType;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData.UsageType;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PowerUsageAdvanced extends PowerUsageBase {
|
||||
private static final String TAG = "AdvancedBatteryUsage";
|
||||
private static final String KEY_BATTERY_GRAPH = "battery_graph";
|
||||
private static final String KEY_BATTERY_APPS = "battery_apps";
|
||||
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
|
||||
SparseArray<String> mUsageTypeMap;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
|
||||
mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
refreshStats();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.FUELGAUGE_BATTERY_HISTORY_DETAIL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.power_usage_advanced;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<PreferenceController> getPreferenceControllers(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void refreshStats() {
|
||||
super.refreshStats();
|
||||
|
||||
updatePreference(mHistPref);
|
||||
|
||||
List<PowerUsageData> dataList = parsePowerUsageData(mStatsHelper);
|
||||
for (int i = 0, size = dataList.size(); i < size; i++) {
|
||||
final PowerUsageData data = dataList.get(i);
|
||||
final String key = mUsageTypeMap.get(data.usageType);
|
||||
if (key != null) {
|
||||
bindData(key, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@UsageType int extractUsageType(BatterySipper sipper) {
|
||||
final DrainType drainType = sipper.drainType;
|
||||
final int uid = sipper.getUid();
|
||||
|
||||
// TODO(b/34385770): add logic to extract type service
|
||||
if (drainType == DrainType.WIFI) {
|
||||
return UsageType.WIFI;
|
||||
} else if (drainType == DrainType.BLUETOOTH) {
|
||||
return UsageType.BLUETOOTH;
|
||||
} else if (drainType == DrainType.IDLE) {
|
||||
return UsageType.IDLE;
|
||||
} else if (drainType == DrainType.USER) {
|
||||
return UsageType.USER;
|
||||
} else if (drainType == DrainType.CELL) {
|
||||
return UsageType.CELL;
|
||||
} else if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
|
||||
return UsageType.SYSTEM;
|
||||
} else {
|
||||
return UsageType.APP;
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
List<PowerUsageData> parsePowerUsageData(BatteryStatsHelper statusHelper) {
|
||||
final List<BatterySipper> batterySippers = statusHelper.getUsageList();
|
||||
final Map<Integer, PowerUsageData> batteryDataMap = new HashMap<>();
|
||||
|
||||
for (int i = 0, size = mUsageTypeMap.size(); i < size; i++) {
|
||||
@UsageType final int type = mUsageTypeMap.keyAt(i);
|
||||
batteryDataMap.put(type, PowerUsageData.createBatteryUsageData(type));
|
||||
}
|
||||
|
||||
// Accumulate power usage based on usage type
|
||||
for (final BatterySipper sipper : batterySippers) {
|
||||
final PowerUsageData usageData = batteryDataMap.get(extractUsageType(sipper));
|
||||
usageData.totalPowerMah += sipper.totalPowerMah;
|
||||
}
|
||||
|
||||
// TODO(b/34385770): add logic to extract the summary
|
||||
final List<PowerUsageData> batteryDataList = new ArrayList<>(batteryDataMap.values());
|
||||
final double totalPower = statusHelper.getTotalPower();
|
||||
for (final PowerUsageData usageData : batteryDataList) {
|
||||
usageData.percentage = (usageData.totalPowerMah / totalPower) * 100;
|
||||
}
|
||||
|
||||
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}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static class PowerUsageData {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({UsageType.APP,
|
||||
UsageType.WIFI,
|
||||
UsageType.CELL,
|
||||
UsageType.SERVICE,
|
||||
UsageType.SYSTEM,
|
||||
UsageType.BLUETOOTH,
|
||||
UsageType.USER,
|
||||
UsageType.IDLE})
|
||||
public @interface UsageType {
|
||||
int APP = 0;
|
||||
int WIFI = 1;
|
||||
int CELL = 2;
|
||||
int SERVICE = 3;
|
||||
int SYSTEM = 4;
|
||||
int BLUETOOTH = 5;
|
||||
int USER = 6;
|
||||
int IDLE = 7;
|
||||
}
|
||||
|
||||
public String summary;
|
||||
public double percentage;
|
||||
public double totalPowerMah;
|
||||
@ColorInt
|
||||
public int iconColor;
|
||||
@UsageType
|
||||
public int usageType;
|
||||
|
||||
private PowerUsageData(@UsageType int usageType) {
|
||||
this.usageType = usageType;
|
||||
totalPowerMah = 0;
|
||||
}
|
||||
|
||||
public static PowerUsageData createBatteryUsageData(@UsageType int usageType) {
|
||||
// TODO(b/34385770): add color logic in this part
|
||||
return new PowerUsageData(usageType);
|
||||
}
|
||||
}
|
||||
|
||||
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(
|
||||
Context context, boolean enabled) {
|
||||
if (!FeatureFactory.getFactory(context).getDashboardFeatureProvider(context)
|
||||
.isEnabled()) {
|
||||
return null;
|
||||
}
|
||||
final SearchIndexableResource sir = new SearchIndexableResource(context);
|
||||
sir.xmlResId = R.xml.power_usage_advanced;
|
||||
return Arrays.asList(sir);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@@ -36,4 +36,9 @@ public interface PowerUsageFeatureProvider {
|
||||
* Gets an {@link Intent} to show additional battery info.
|
||||
*/
|
||||
Intent getAdditionalBatteryInfoIntent();
|
||||
|
||||
/**
|
||||
* Check whether advanced ui is enabled
|
||||
*/
|
||||
boolean isAdvancedUiEnabled();
|
||||
}
|
||||
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.Intent;
|
||||
|
||||
public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider {
|
||||
@Override
|
||||
public boolean isLocationSettingEnabled(String[] packages) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdditionalBatteryInfoEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getAdditionalBatteryInfoIntent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAdvancedUiEnabled() {
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -413,7 +413,7 @@ public class PowerUsageSummary extends PowerUsageBase {
|
||||
sipper.percent = percentOfTotal;
|
||||
pref.setTitle(entry.getLabel());
|
||||
pref.setOrder(i + 1);
|
||||
pref.setPercent(percentOfMax, percentOfTotal);
|
||||
pref.setPercent(percentOfTotal);
|
||||
setUsageSummary(pref, usedTime, sipper.usageTimeMs);
|
||||
if ((sipper.drainType != DrainType.APP
|
||||
|| sipper.uidObj.getUid() == Process.ROOT_UID)
|
||||
|
@@ -37,6 +37,7 @@ import com.android.settings.enterprise.DevicePolicyManagerWrapperImpl;
|
||||
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
|
||||
import com.android.settings.enterprise.EnterprisePrivacyFeatureProviderImpl;
|
||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||
import com.android.settings.fuelgauge.PowerUsageFeatureProviderImpl;
|
||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
|
||||
import com.android.settings.search2.SearchFeatureProvider;
|
||||
@@ -59,6 +60,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
|
||||
private SearchFeatureProvider mSearchFeatureProvider;
|
||||
private SecurityFeatureProvider mSecurityFeatureProvider;
|
||||
private SuggestionFeatureProvider mSuggestionFeatureProvider;
|
||||
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
|
||||
|
||||
@Override
|
||||
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
|
||||
@@ -75,7 +77,10 @@ public class FeatureFactoryImpl extends FeatureFactory {
|
||||
|
||||
@Override
|
||||
public PowerUsageFeatureProvider getPowerUsageFeatureProvider(Context context) {
|
||||
return null;
|
||||
if (mPowerUsageFeatureProvider == null) {
|
||||
mPowerUsageFeatureProvider = new PowerUsageFeatureProviderImpl();
|
||||
}
|
||||
return mPowerUsageFeatureProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -47,6 +47,7 @@ import com.android.settings.deviceinfo.StorageSettings;
|
||||
import com.android.settings.display.ScreenZoomSettings;
|
||||
import com.android.settings.enterprise.EnterprisePrivacySettings;
|
||||
import com.android.settings.fuelgauge.BatterySaverSettings;
|
||||
import com.android.settings.fuelgauge.PowerUsageAdvanced;
|
||||
import com.android.settings.fuelgauge.PowerUsageDetail;
|
||||
import com.android.settings.fuelgauge.PowerUsageSummary;
|
||||
import com.android.settings.gestures.DoubleTapPowerSettings;
|
||||
@@ -127,6 +128,7 @@ public final class SearchIndexableResources {
|
||||
addIndex(PowerUsageSummary.class,
|
||||
R.xml.power_usage_summary, R.drawable.ic_settings_battery);
|
||||
addIndex(PowerUsageDetail.class, NO_DATA_RES_ID, R.drawable.ic_settings_battery);
|
||||
addIndex(PowerUsageAdvanced.class, NO_DATA_RES_ID, R.drawable.ic_settings_battery);
|
||||
addIndex(BatterySaverSettings.class,
|
||||
R.xml.battery_saver_settings, R.drawable.ic_settings_battery);
|
||||
addIndex(AdvancedAppSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_applications);
|
||||
|
@@ -0,0 +1,137 @@
|
||||
package com.android.settings.fuelgauge;
|
||||
|
||||
import android.os.Process;
|
||||
import android.util.SparseArray;
|
||||
import com.android.internal.os.BatterySipper;
|
||||
import com.android.internal.os.BatterySipper.DrainType;
|
||||
import com.android.internal.os.BatteryStatsHelper;
|
||||
import com.android.settings.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData;
|
||||
import com.android.settings.fuelgauge.PowerUsageAdvanced.PowerUsageData.UsageType;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class PowerUsageAdvancedTest {
|
||||
private static final int FAKE_UID_1 = 50;
|
||||
private static final int FAKE_UID_2 = 100;
|
||||
private static final double TYPE_APP_USAGE = 80;
|
||||
private static final double TYPE_BLUETOOTH_USAGE = 50;
|
||||
private static final double TYPE_WIFI_USAGE = 0;
|
||||
private static final double TOTAL_USAGE = TYPE_APP_USAGE * 2 + TYPE_BLUETOOTH_USAGE
|
||||
+ TYPE_WIFI_USAGE;
|
||||
private static final double PRECISION = 0.001;
|
||||
private static final String STRING_NOT_FOUND = "not_found";
|
||||
@Mock
|
||||
private BatterySipper mBatterySipper;
|
||||
@Mock
|
||||
private BatteryStatsHelper mBatteryStatsHelper;
|
||||
private PowerUsageAdvanced mPowerUsageAdvanced;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mPowerUsageAdvanced = new PowerUsageAdvanced();
|
||||
|
||||
List<BatterySipper> batterySippers = new ArrayList<>();
|
||||
batterySippers.add(new BatterySipper(DrainType.APP,
|
||||
new FakeUid(FAKE_UID_1), TYPE_APP_USAGE));
|
||||
batterySippers.add(new BatterySipper(DrainType.APP,
|
||||
new FakeUid(FAKE_UID_2), TYPE_APP_USAGE));
|
||||
batterySippers.add(new BatterySipper(DrainType.BLUETOOTH, new FakeUid(FAKE_UID_1),
|
||||
TYPE_BLUETOOTH_USAGE));
|
||||
batterySippers.add(new BatterySipper(DrainType.WIFI, new FakeUid(FAKE_UID_1),
|
||||
TYPE_WIFI_USAGE));
|
||||
|
||||
when(mBatteryStatsHelper.getUsageList()).thenReturn(batterySippers);
|
||||
when(mBatteryStatsHelper.getTotalPower()).thenReturn(TOTAL_USAGE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractUsageType_TypeSystem_ReturnSystem() {
|
||||
mBatterySipper.drainType = DrainType.APP;
|
||||
final int uids[] = {Process.SYSTEM_UID, Process.ROOT_UID};
|
||||
|
||||
for (int uid : uids) {
|
||||
when(mBatterySipper.getUid()).thenReturn(uid);
|
||||
assertThat(mPowerUsageAdvanced.extractUsageType(mBatterySipper))
|
||||
.isEqualTo(UsageType.SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtractUsageType_TypeEqualsToDrainType_ReturnRelevantType() {
|
||||
final DrainType drainTypes[] = {DrainType.WIFI, DrainType.BLUETOOTH, DrainType.IDLE,
|
||||
DrainType.USER, DrainType.CELL};
|
||||
final int usageTypes[] = {UsageType.WIFI, UsageType.BLUETOOTH, UsageType.IDLE,
|
||||
UsageType.USER, UsageType.CELL};
|
||||
|
||||
assertThat(drainTypes.length).isEqualTo(usageTypes.length);
|
||||
for (int i = 0, size = drainTypes.length; i < size; i++) {
|
||||
mBatterySipper.drainType = drainTypes[i];
|
||||
assertThat(mPowerUsageAdvanced.extractUsageType(mBatterySipper))
|
||||
.isEqualTo(usageTypes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParsePowerUsageData_PercentageCalculatedCorrectly() {
|
||||
final double percentApp = TYPE_APP_USAGE * 2 / TOTAL_USAGE * 100;
|
||||
final double percentWifi = TYPE_WIFI_USAGE / TOTAL_USAGE * 100;
|
||||
final double percentBluetooth = TYPE_BLUETOOTH_USAGE / TOTAL_USAGE * 100;
|
||||
|
||||
mPowerUsageAdvanced.init();
|
||||
List<PowerUsageData> batteryData =
|
||||
mPowerUsageAdvanced.parsePowerUsageData(mBatteryStatsHelper);
|
||||
for (PowerUsageData data : batteryData) {
|
||||
switch (data.usageType) {
|
||||
case UsageType.WIFI:
|
||||
assertThat(data.percentage).isWithin(PRECISION).of(percentWifi);
|
||||
break;
|
||||
case UsageType.APP:
|
||||
assertThat(data.percentage).isWithin(PRECISION).of(percentApp);
|
||||
break;
|
||||
case UsageType.BLUETOOTH:
|
||||
assertThat(data.percentage).isWithin(PRECISION).of(percentBluetooth);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInit_ContainsAllUsageType() {
|
||||
mPowerUsageAdvanced.init();
|
||||
final SparseArray<String> array = mPowerUsageAdvanced.mUsageTypeMap;
|
||||
|
||||
assertThat(array.get(UsageType.APP, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
assertThat(array.get(UsageType.WIFI, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
assertThat(array.get(UsageType.CELL, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
assertThat(array.get(UsageType.BLUETOOTH, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
assertThat(array.get(UsageType.IDLE, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
assertThat(array.get(UsageType.SERVICE, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
assertThat(array.get(UsageType.USER, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
assertThat(array.get(UsageType.SYSTEM, STRING_NOT_FOUND))
|
||||
.isNotEqualTo(STRING_NOT_FOUND);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user