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:
jackqdyulei
2017-01-27 16:11:13 -08:00
parent 58f729537f
commit a224b010b9
15 changed files with 569 additions and 12 deletions

View 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -433,5 +433,4 @@
</style>
<style name="AppActionPrimaryButton" parent="android:Widget.Material.Button.Colored"/>
</resources>

View 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>

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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();
}

View 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);
}
};
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}
}