Merge "Add batterysipper type check in PowerUsageFeatureProvider"
diff --git a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
index 826ec09..fc96340 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageAdvanced.java
@@ -71,9 +71,11 @@
 
         mHistPref = (BatteryHistoryPreference) findPreference(KEY_BATTERY_GRAPH);
         mUsageListGroup = (PreferenceGroup) findPreference(KEY_BATTERY_USAGE_LIST);
-        mPowerUsageFeatureProvider = FeatureFactory.getFactory(getContext())
-                .getPowerUsageFeatureProvider(getContext());
-        mPackageManager = getContext().getPackageManager();
+
+        final Context context = getContext();
+        mPowerUsageFeatureProvider = FeatureFactory.getFactory(context)
+                .getPowerUsageFeatureProvider(context);
+        mPackageManager = context.getPackageManager();
     }
 
     @Override
@@ -137,9 +139,9 @@
             return UsageType.USER;
         } else if (drainType == DrainType.CELL) {
             return UsageType.CELL;
-        } else if (uid == Process.SYSTEM_UID || uid == Process.ROOT_UID) {
+        } else if (mPowerUsageFeatureProvider.isTypeSystem(sipper)) {
             return UsageType.SYSTEM;
-        } else if (mPowerUsageFeatureProvider.isTypeService(sipper.mPackages)) {
+        } else if (mPowerUsageFeatureProvider.isTypeService(sipper)) {
             return UsageType.SERVICE;
         } else {
             return UsageType.APP;
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
index 3dab38e..7cb6c00 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java
@@ -17,38 +17,44 @@
 package com.android.settings.fuelgauge;
 
 import android.content.Intent;
+import com.android.internal.os.BatterySipper;
 
 /**
  * Feature Provider used in power usage
  */
 public interface PowerUsageFeatureProvider {
-  /**
-   * Check whether location setting is enabled
-   */
-  boolean isLocationSettingEnabled(String[] packages);
+    /**
+     * Check whether location setting is enabled
+     */
+    boolean isLocationSettingEnabled(String[] packages);
 
-  /**
-   * Check whether additional battery info feature is enabled.
-   */
-  boolean isAdditionalBatteryInfoEnabled();
+    /**
+     * Check whether additional battery info feature is enabled.
+     */
+    boolean isAdditionalBatteryInfoEnabled();
 
-  /**
-   * Gets an {@link Intent} to show additional battery info.
-   */
-  Intent getAdditionalBatteryInfoIntent();
+    /**
+     * Gets an {@link Intent} to show additional battery info.
+     */
+    Intent getAdditionalBatteryInfoIntent();
 
-  /**
-   * Check whether advanced ui is enabled
-   */
-  boolean isAdvancedUiEnabled();
+    /**
+     * Check whether advanced ui is enabled
+     */
+    boolean isAdvancedUiEnabled();
 
-  /**
-   * Check whether it is type service
-   */
-  boolean isTypeService(String[] packages);
+    /**
+     * Check whether it is type service
+     */
+    boolean isTypeService(BatterySipper sipper);
 
-  /**
-   * Check whether the toggle for power accounting is enabled
-   */
-  boolean isPowerAccountingToggleEnabled();
+    /**
+     * Check whether it is type system
+     */
+    boolean isTypeSystem(BatterySipper sipper);
+
+    /**
+     * Check whether the toggle for power accounting is enabled
+     */
+    boolean isPowerAccountingToggleEnabled();
 }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
index 7f843e2..011f417 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java
@@ -16,9 +16,40 @@
 
 package com.android.settings.fuelgauge;
 
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.util.ArrayUtils;
 
 public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider {
+
+    private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar";
+
+    protected PackageManager mPackageManager;
+
+    public PowerUsageFeatureProviderImpl(Context context) {
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Override
+    public boolean isTypeService(BatterySipper sipper) {
+        return false;
+    }
+
+    @Override
+    public boolean isTypeSystem(BatterySipper sipper) {
+        final int uid = sipper.uidObj == null ? -1 : sipper.getUid();
+        sipper.mPackages = mPackageManager.getPackagesForUid(uid);
+        // Classify all the sippers to type system if the range of uid is 0...FIRST_APPLICATION_UID
+        if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) {
+            return true;
+        } else {
+            return ArrayUtils.contains(sipper.mPackages, PACKAGE_CALENDAR_PROVIDER);
+        }
+    }
+
     @Override
     public boolean isLocationSettingEnabled(String[] packages) {
         return false;
@@ -40,11 +71,6 @@
     }
 
     @Override
-    public boolean isTypeService(String[] packages) {
-        return false;
-    }
-
-    @Override
     public boolean isPowerAccountingToggleEnabled() {
         return false;
     }
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 5f0e6e0..18ba1aa 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -99,16 +99,17 @@
 
     @VisibleForTesting
     boolean mShowAllApps = false;
-
+    @VisibleForTesting
     Preference mScreenUsagePref;
     @VisibleForTesting
     Preference mScreenConsumptionPref;
     @VisibleForTesting
     Preference mCellularNetworkPref;
+    @VisibleForTesting
+    PowerUsageFeatureProvider mPowerFeatureProvider;
 
     private LayoutPreference mBatteryLayoutPref;
     private PreferenceGroup mAppListGroup;
-
     private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
 
     @Override
@@ -121,6 +122,8 @@
         mScreenUsagePref = findPreference(KEY_SCREEN_USAGE);
         mScreenConsumptionPref = findPreference(KEY_SCREEN_CONSUMPTION);
         mCellularNetworkPref = findPreference(KEY_CELLULAR_NETWORK);
+
+        initFeatureProvider();
     }
 
     @Override
@@ -193,14 +196,11 @@
 
         menu.add(Menu.NONE, MENU_HIGH_POWER_APPS, Menu.NONE, R.string.high_power_apps);
 
-        PowerUsageFeatureProvider powerUsageFeatureProvider =
-                FeatureFactory.getFactory(getContext()).getPowerUsageFeatureProvider(getContext());
-        if (powerUsageFeatureProvider != null &&
-                powerUsageFeatureProvider.isAdditionalBatteryInfoEnabled()) {
+        if (mPowerFeatureProvider.isAdditionalBatteryInfoEnabled()) {
             menu.add(Menu.NONE, MENU_ADDITIONAL_BATTERY_INFO,
                     Menu.NONE, R.string.additional_battery_info);
         }
-        if (powerUsageFeatureProvider.isPowerAccountingToggleEnabled()) {
+        if (mPowerFeatureProvider.isPowerAccountingToggleEnabled()) {
             menu.add(Menu.NONE, MENU_TOGGLE_APPS, Menu.NONE,
                     mShowAllApps ? R.string.hide_extra_apps : R.string.show_all_apps);
         }
@@ -579,12 +579,12 @@
     @VisibleForTesting
     boolean shouldHideSipper(BatterySipper sipper) {
         final DrainType drainType = sipper.drainType;
-        final int uid = sipper.getUid();
 
         return drainType == DrainType.IDLE || drainType == DrainType.CELL
-                || drainType == DrainType.SCREEN || uid == Process.ROOT_UID
-                || uid == Process.SYSTEM_UID
-                || (sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP;
+                || drainType == DrainType.SCREEN
+                || (sipper.totalPowerMah * SECONDS_IN_HOUR) < MIN_POWER_THRESHOLD_MILLI_AMP
+                || mPowerFeatureProvider.isTypeService(sipper)
+                || mPowerFeatureProvider.isTypeSystem(sipper);
     }
 
     @VisibleForTesting
@@ -620,6 +620,13 @@
         mBatteryLayoutPref = layoutPreference;
     }
 
+    @VisibleForTesting
+    void initFeatureProvider() {
+        final Context context = getContext();
+        mPowerFeatureProvider = FeatureFactory.getFactory(context)
+                .getPowerUsageFeatureProvider(context);
+    }
+
     private static List<BatterySipper> getFakeStats() {
         ArrayList<BatterySipper> stats = new ArrayList<>();
         float use = 5;
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 377e6bb..e72ee03 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -80,7 +80,7 @@
     @Override
     public PowerUsageFeatureProvider getPowerUsageFeatureProvider(Context context) {
         if (mPowerUsageFeatureProvider == null) {
-            mPowerUsageFeatureProvider = new PowerUsageFeatureProviderImpl();
+            mPowerUsageFeatureProvider = new PowerUsageFeatureProviderImpl(context);
         }
         return mPowerUsageFeatureProvider;
     }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
index e47aac9..ed7e48b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageAdvancedTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.pm.PackageManager;
@@ -70,13 +85,10 @@
     @Test
     public void testExtractUsageType_TypeSystem_ReturnSystem() {
         mBatterySipper.drainType = DrainType.APP;
-        final int uids[] = {Process.SYSTEM_UID, Process.ROOT_UID};
+        when(mPowerUsageFeatureProvider.isTypeSystem(any())).thenReturn(true);
 
-        for (int uid : uids) {
-            when(mBatterySipper.getUid()).thenReturn(uid);
-            assertThat(mPowerUsageAdvanced.extractUsageType(mBatterySipper))
-                    .isEqualTo(UsageType.SYSTEM);
-        }
+        assertThat(mPowerUsageAdvanced.extractUsageType(mBatterySipper))
+                .isEqualTo(UsageType.SYSTEM);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
new file mode 100644
index 0000000..bfb4bc6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImplTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.content.pm.PackageManager;
+import android.os.Process;
+import com.android.internal.os.BatterySipper;
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+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 static org.mockito.Mockito.when;
+import static com.google.common.truth.Truth.assertThat;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class PowerUsageFeatureProviderImplTest {
+    private static final int UID_CALENDAR = 1234;
+    private static final int UID_OTHER = Process.FIRST_APPLICATION_UID + 2;
+    private static final String[] PACKAGES_CALENDAR = {"com.android.providers.calendar"};
+    @Mock
+    private Context mContext;
+    @Mock
+    private BatterySipper mBatterySipper;
+    @Mock
+    private PackageManager mPackageManager;
+    private PowerUsageFeatureProviderImpl mPowerFeatureProvider;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mPowerFeatureProvider = new PowerUsageFeatureProviderImpl(mContext);
+        when(mPackageManager.getPackagesForUid(UID_CALENDAR)).thenReturn(PACKAGES_CALENDAR);
+        mPowerFeatureProvider.mPackageManager = mPackageManager;
+        mBatterySipper.uidObj = new FakeUid(UID_OTHER);
+    }
+
+    @Test
+    public void testIsTypeSystem_UidRoot_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
+
+        assertThat(mPowerFeatureProvider.isTypeSystem(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testIsTypeSystem_UidSystem_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(Process.SYSTEM_UID);
+
+        assertThat(mPowerFeatureProvider.isTypeSystem(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testIsTypeSystem_UidMedia_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(Process.MEDIA_UID);
+
+        assertThat(mPowerFeatureProvider.isTypeSystem(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testIsTypeSystem_AppCalendar_ReturnTrue() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(UID_CALENDAR);
+
+        assertThat(mPowerFeatureProvider.isTypeSystem(mBatterySipper)).isTrue();
+    }
+
+    @Test
+    public void testIsTypeSystem_UidOther_ReturnFalse() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mBatterySipper.getUid()).thenReturn(UID_OTHER);
+
+        assertThat(mPowerFeatureProvider.isTypeSystem(mBatterySipper)).isFalse();
+    }
+
+    @Test
+    public void testIsTypeSystem_UidObjNull_ReturnFalse() {
+        mBatterySipper.drainType = BatterySipper.DrainType.APP;
+        mBatterySipper.uidObj = null;
+
+        assertThat(mPowerFeatureProvider.isTypeSystem(mBatterySipper)).isFalse();
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 0755a36..9513507 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -17,6 +17,7 @@
 
 import android.content.Context;
 import android.content.Intent;
+import android.os.PowerManager;
 import android.os.Process;
 import android.support.v7.preference.Preference;
 import android.text.TextUtils;
@@ -54,6 +55,7 @@
 import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_TOGGLE_APPS;
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
@@ -124,12 +126,13 @@
     private Preference mCellularNetworkPref;
     @Mock
     private BatteryStatsHelper mBatteryHelper;
+    @Mock
+    private PowerManager mPowerManager;
 
+    private List<BatterySipper> mUsageList;
     private Context mRealContext;
     private TestFragment mFragment;
     private FakeFeatureFactory mFeatureFactory;
-    private PowerUsageSummary mPowerUsageSummary;
-    private List<BatterySipper> mUsageList;
 
     @Before
     public void setUp() {
@@ -138,8 +141,10 @@
         mRealContext = RuntimeEnvironment.application;
         FakeFeatureFactory.setupForTest(mContext);
         mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext);
+        when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(mPowerManager);
 
-        mFragment = new TestFragment(mContext);
+        mFragment = spy(new TestFragment(mContext));
+        mFragment.initFeatureProvider();
 
         when(mAdditionalBatteryInfoMenu.getItemId())
                 .thenReturn(MENU_ADDITIONAL_BATTERY_INFO);
@@ -148,9 +153,6 @@
                 .thenReturn(ADDITIONAL_BATTERY_INFO_INTENT);
         when(mBatteryHelper.getTotalPower()).thenReturn(TOTAL_POWER);
 
-        mPowerUsageSummary = spy(new PowerUsageSummary());
-
-        when(mPowerUsageSummary.getContext()).thenReturn(mRealContext);
         when(mNormalBatterySipper.getPackages()).thenReturn(PACKAGE_NAMES);
         when(mNormalBatterySipper.getUid()).thenReturn(UID);
         mNormalBatterySipper.totalPowerMah = POWER_MAH;
@@ -164,7 +166,7 @@
         when(mBatteryLayoutPref.findViewById(R.id.time)).thenReturn(mTimeText);
         when(mBatteryLayoutPref.findViewById(R.id.battery_header_icon))
                 .thenReturn(mBatteryMeterView);
-        mPowerUsageSummary.setBatteryLayoutPreference(mBatteryLayoutPref);
+        mFragment.setBatteryLayoutPreference(mBatteryLayoutPref);
 
         mScreenBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
         mScreenBatterySipper.totalPowerMah = BATTERY_SCREEN_USAGE;
@@ -179,11 +181,11 @@
         mUsageList.add(mScreenBatterySipper);
         mUsageList.add(mCellBatterySipper);
 
-        mPowerUsageSummary.mStatsHelper = mBatteryHelper;
+        mFragment.mStatsHelper = mBatteryHelper;
         when(mBatteryHelper.getUsageList()).thenReturn(mUsageList);
-        mPowerUsageSummary.mScreenUsagePref = mScreenUsagePref;
-        mPowerUsageSummary.mScreenConsumptionPref = mScreenConsumptionPref;
-        mPowerUsageSummary.mCellularNetworkPref = mCellularNetworkPref;
+        mFragment.mScreenUsagePref = mScreenUsagePref;
+        mFragment.mScreenConsumptionPref = mScreenConsumptionPref;
+        mFragment.mCellularNetworkPref = mCellularNetworkPref;
     }
 
     @Test
@@ -235,7 +237,7 @@
         mNormalBatterySipper.uidObj = null;
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
 
-        final String key = mPowerUsageSummary.extractKeyFromSipper(mNormalBatterySipper);
+        final String key = mFragment.extractKeyFromSipper(mNormalBatterySipper);
         assertThat(key).isEqualTo(TextUtils.concat(mNormalBatterySipper.getPackages()).toString());
     }
 
@@ -244,7 +246,7 @@
         mNormalBatterySipper.uidObj = null;
         mNormalBatterySipper.drainType = BatterySipper.DrainType.BLUETOOTH;
 
-        final String key = mPowerUsageSummary.extractKeyFromSipper(mNormalBatterySipper);
+        final String key = mFragment.extractKeyFromSipper(mNormalBatterySipper);
         assertThat(key).isEqualTo(mNormalBatterySipper.drainType.toString());
     }
 
@@ -253,7 +255,7 @@
         mNormalBatterySipper.uidObj = new BatteryStatsImpl.Uid(new BatteryStatsImpl(), UID);
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
 
-        final String key = mPowerUsageSummary.extractKeyFromSipper(mNormalBatterySipper);
+        final String key = mFragment.extractKeyFromSipper(mNormalBatterySipper);
         assertThat(key).isEqualTo(Integer.toString(mNormalBatterySipper.getUid()));
     }
 
@@ -263,8 +265,10 @@
         sippers.add(mNormalBatterySipper);
         sippers.add(mScreenBatterySipper);
         sippers.add(mSystemBatterySipper);
+        when(mFeatureFactory.powerUsageFeatureProvider.isTypeSystem(mSystemBatterySipper))
+                .thenReturn(true);
 
-        final double totalUsage = mPowerUsageSummary.removeHiddenBatterySippers(sippers);
+        final double totalUsage = mFragment.removeHiddenBatterySippers(sippers);
         assertThat(sippers).containsExactly(mNormalBatterySipper);
         assertThat(totalUsage).isWithin(PRECISION).of(BATTERY_SCREEN_USAGE + BATTERY_SYSTEM_USAGE);
     }
@@ -272,47 +276,52 @@
     @Test
     public void testShouldHideSipper_TypeIdle_ReturnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.IDLE;
-        assertThat(mPowerUsageSummary.shouldHideSipper(mNormalBatterySipper)).isTrue();
+        assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
     public void testShouldHideSipper_TypeCell_ReturnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.CELL;
-        assertThat(mPowerUsageSummary.shouldHideSipper(mNormalBatterySipper)).isTrue();
+        assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
     public void testShouldHideSipper_TypeScreen_ReturnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.SCREEN;
-        assertThat(mPowerUsageSummary.shouldHideSipper(mNormalBatterySipper)).isTrue();
+        assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
-    public void testShouldHideSipper_UidRoot_ReturnTrue() {
+    public void testShouldHideSipper_TypeSystem_ReturnTrue() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
         when(mNormalBatterySipper.getUid()).thenReturn(Process.ROOT_UID);
-        assertThat(mPowerUsageSummary.shouldHideSipper(mNormalBatterySipper)).isTrue();
-    }
-
-    @Test
-    public void testShouldHideSipper_UidSystem_ReturnTrue() {
-        mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
-        when(mNormalBatterySipper.getUid()).thenReturn(Process.SYSTEM_UID);
-        assertThat(mPowerUsageSummary.shouldHideSipper(mNormalBatterySipper)).isTrue();
+        when(mFeatureFactory.powerUsageFeatureProvider.isTypeSystem(Matchers.<BatterySipper>any()))
+                .thenReturn(true);
+        assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
     public void testShouldHideSipper_UidNormal_ReturnFalse() {
         mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
         when(mNormalBatterySipper.getUid()).thenReturn(UID);
-        assertThat(mPowerUsageSummary.shouldHideSipper(mNormalBatterySipper)).isFalse();
+        assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isFalse();
+    }
+
+    @Test
+    public void testShouldHideSipper_TypeService_ReturnTrue() {
+        mNormalBatterySipper.drainType = BatterySipper.DrainType.APP;
+        when(mNormalBatterySipper.getUid()).thenReturn(UID);
+        when(mFeatureFactory.powerUsageFeatureProvider.isTypeService(Matchers.<BatterySipper>any()))
+                .thenReturn(true);
+
+        assertThat(mFragment.shouldHideSipper(mNormalBatterySipper)).isTrue();
     }
 
     @Test
     public void testSetUsageSummary_TimeLessThanOneMinute_DoNotSetSummary() {
         final long usageTimeMs = 59 * DateUtils.SECOND_IN_MILLIS;
 
-        mPowerUsageSummary.setUsageSummary(mPreference, "", usageTimeMs);
+        mFragment.setUsageSummary(mPreference, "", usageTimeMs);
         verify(mPreference, never()).setSummary(anyString());
     }
 
@@ -320,7 +329,7 @@
     public void testSetUsageSummary_TimeMoreThanOneMinute_SetSummary() {
         final long usageTimeMs = 2 * DateUtils.MINUTE_IN_MILLIS;
 
-        mPowerUsageSummary.setUsageSummary(mPreference, "", usageTimeMs);
+        mFragment.setUsageSummary(mPreference, "", usageTimeMs);
         verify(mPreference).setSummary(anyString());
     }
 
@@ -328,7 +337,7 @@
     public void testUpdatePreference_NoEstimatedTime_DoNotShowSummary() {
         mBatteryInfo.remainingTimeUs = 0;
         mBatteryInfo.remainingLabel = TIME_LEFT;
-        mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
+        mFragment.updateHeaderPreference(mBatteryInfo);
 
         verify(mSummary1).setVisibility(View.INVISIBLE);
         verify(mSummary2).setVisibility(View.INVISIBLE);
@@ -338,7 +347,7 @@
     public void testUpdatePreference_HasEstimatedTime_ShowSummary() {
         mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
         mBatteryInfo.remainingLabel = TIME_LEFT;
-        mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
+        mFragment.updateHeaderPreference(mBatteryInfo);
 
         verify(mSummary1).setVisibility(View.VISIBLE);
         verify(mSummary2).setVisibility(View.VISIBLE);
@@ -349,7 +358,7 @@
         mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
         mBatteryInfo.mDischarging = false;
 
-        mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
+        mFragment.updateHeaderPreference(mBatteryInfo);
         verify(mSummary1).setText(R.string.estimated_charging_time_left);
     }
 
@@ -358,17 +367,17 @@
         mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
         mBatteryInfo.mDischarging = true;
 
-        mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
+        mFragment.updateHeaderPreference(mBatteryInfo);
         verify(mSummary1).setText(R.string.estimated_time_left);
     }
 
     @Test
     public void testUpdateHeaderPreference_AsyncUpdate_ShouldNotCrash() {
-        when(mPowerUsageSummary.getContext()).thenReturn(null);
+        when(mFragment.getContext()).thenReturn(null);
         mBatteryInfo.remainingTimeUs = REMAINING_TIME_US;
 
         //Should not crash
-        mPowerUsageSummary.updateHeaderPreference(mBatteryInfo);
+        mFragment.updateHeaderPreference(mBatteryInfo);
     }
 
     private void testToggleAllApps(final boolean isShowApps) {
@@ -380,7 +389,7 @@
 
     @Test
     public void testFindBatterySipperByType_findTypeScreen() {
-        BatterySipper sipper = mPowerUsageSummary.findBatterySipperByType(mUsageList,
+        BatterySipper sipper = mFragment.findBatterySipperByType(mUsageList,
                 BatterySipper.DrainType.SCREEN);
 
         assertThat(sipper).isSameAs(mScreenBatterySipper);
@@ -388,7 +397,7 @@
 
     @Test
     public void testFindBatterySipperByType_findTypeApp() {
-        BatterySipper sipper = mPowerUsageSummary.findBatterySipperByType(mUsageList,
+        BatterySipper sipper = mFragment.findBatterySipperByType(mUsageList,
                 BatterySipper.DrainType.APP);
 
         assertThat(sipper).isSameAs(mNormalBatterySipper);
@@ -399,9 +408,9 @@
         final double percent = POWER_MAH / TOTAL_POWER * DISCHARGE_AMOUNT;
         final String expectedSummary = mRealContext.getString(R.string.battery_overall_usage,
                 Utils.formatPercentage((int) percent));
-        doReturn(expectedSummary).when(mPowerUsageSummary)
+        doReturn(expectedSummary).when(mFragment)
                 .getString(eq(R.string.battery_overall_usage), anyInt());
-        mPowerUsageSummary.updateCellularPreference(DISCHARGE_AMOUNT);
+        mFragment.updateCellularPreference(DISCHARGE_AMOUNT);
 
         verify(mCellularNetworkPref).setSummary(expectedSummary);
     }
@@ -413,12 +422,12 @@
         final double percent = BATTERY_SCREEN_USAGE / TOTAL_POWER * DISCHARGE_AMOUNT;
         final String expectedOverallUsage = mRealContext.getString(R.string.battery_overall_usage,
                 Utils.formatPercentage((int) percent));
-        doReturn(expectedUsedTime).when(mPowerUsageSummary).getString(
+        doReturn(expectedUsedTime).when(mFragment).getString(
                 eq(R.string.battery_used_for), anyInt());
-        doReturn(expectedOverallUsage).when(mPowerUsageSummary).getString(
+        doReturn(expectedOverallUsage).when(mFragment).getString(
                 eq(R.string.battery_overall_usage), anyInt());
 
-        mPowerUsageSummary.updateScreenPreference(DISCHARGE_AMOUNT);
+        mFragment.updateScreenPreference(DISCHARGE_AMOUNT);
 
         verify(mScreenUsagePref).setSummary(expectedUsedTime);
         verify(mScreenConsumptionPref).setSummary(expectedOverallUsage);
@@ -427,16 +436,16 @@
     @Test
     public void testUpdatePreference_UsageListEmpty_ShouldNotCrash() {
         when(mBatteryHelper.getUsageList()).thenReturn(new ArrayList<BatterySipper>());
-        doReturn("").when(mPowerUsageSummary).getString(anyInt(), Matchers.anyObject());
+        doReturn("").when(mFragment).getString(anyInt(), Matchers.anyObject());
 
         // Should not crash when update
-        mPowerUsageSummary.updateScreenPreference(DISCHARGE_AMOUNT);
-        mPowerUsageSummary.updateCellularPreference(DISCHARGE_AMOUNT);
+        mFragment.updateScreenPreference(DISCHARGE_AMOUNT);
+        mFragment.updateCellularPreference(DISCHARGE_AMOUNT);
     }
 
     @Test
     public void testCalculatePercentage() {
-        final double percent = mPowerUsageSummary.calculatePercentage(POWER_MAH, DISCHARGE_AMOUNT);
+        final double percent = mFragment.calculatePercentage(POWER_MAH, DISCHARGE_AMOUNT);
         assertThat(percent).isWithin(PRECISION).of(POWER_USAGE_PERCENTAGE);
     }