Add batterysipper type check in PowerUsageFeatureProvider

This cl adds isTypeSystem to PowerUsageFeatureProvider and
changes isTypeService. After this cl, the following items will
be moved to advanced battery page:
1. Calendar Storage(Move to System)
2. MediaServer(Move to System)

Create this check in FeatureProvider to make sure this check
is flexible in different cases. Also refactor the PowerUsageSummary
to use same test fragment

Bug: 35629871
Bug: 35628690
Bug: 35317876
Test: RunSettingsRoboTest
Change-Id: I8c083cb2557a7e900aea01e682c13a000bacb7a9
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);
     }