diff --git a/res/drawable/ic_battery_circle.xml b/res/drawable/ic_battery_circle.xml
new file mode 100644
index 00000000000..5c736fdf4ed
--- /dev/null
+++ b/res/drawable/ic_battery_circle.xml
@@ -0,0 +1,24 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 7d9ab4a6b52..d099cdc9304 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -153,4 +153,8 @@
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1931e67c6db..398072928ab 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4320,7 +4320,9 @@
Wi\u2011Fi on time
-
+
+ Advanced battery usage
+
History details
@@ -4354,6 +4356,14 @@
Miscellaneous
Over-counted
+
+ Apps
+
+ Services
+
+ System
+
+ User
CPU total
@@ -4473,6 +4483,8 @@
Used for %1$s
+
+ Usage breakdown since last full charge
%1$s since unplugged
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 092d9970ab1..2f6f1207efa 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -433,5 +433,4 @@
-
diff --git a/res/xml/power_usage_advanced.xml b/res/xml/power_usage_advanced.xml
new file mode 100644
index 00000000000..6422a75647b
--- /dev/null
+++ b/res/xml/power_usage_advanced.xml
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/com/android/settings/TintablePreference.java b/src/com/android/settings/TintablePreference.java
index 45f43fbe969..2e1fd3dfd54 100644
--- a/src/com/android/settings/TintablePreference.java
+++ b/src/com/android/settings/TintablePreference.java
@@ -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) {
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
index 0f36ab1f7fb..7cf07807466 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryPreference.java
@@ -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) {
diff --git a/src/com/android/settings/fuelgauge/PowerGaugePreference.java b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
index 9371a19f8aa..1d3d62b6e8e 100644
--- a/src/com/android/settings/fuelgauge/PowerGaugePreference.java
+++ b/src/com/android/settings/fuelgauge/PowerGaugePreference.java
@@ -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();
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
new file mode 100644
index 00000000000..4ccf9f7437e
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -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 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 getPreferenceControllers(Context context) {
+ return null;
+ }
+
+ @Override
+ protected void refreshStats() {
+ super.refreshStats();
+
+ updatePreference(mHistPref);
+
+ List 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 parsePowerUsageData(BatteryStatsHelper statusHelper) {
+ final List batterySippers = statusHelper.getUsageList();
+ final Map 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 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 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);
+ }
+ };
+
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index de16fe545cc..3c1b19784f8 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -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();
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
new file mode 100644
index 00000000000..b29900e1b78
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -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;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 27452920b80..c0c92f095e0 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -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)
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index c45bf0e2cce..4c81e309eda 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -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
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index cbbc0b5374f..f8384e934b0 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -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);
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
new file mode 100644
index 00000000000..17cd223fc08
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
@@ -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 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 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 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);
+ }
+}