Merge "Make app predicates singleton"
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
index dfb7f97..8debf6b 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtils.java
@@ -136,8 +136,8 @@
         final List<AppInfo> highUsageApps = BatteryDatabaseManager.getInstance(context)
                 .queryAllAnomalies(timeAfterMs, AnomalyDatabaseHelper.State.NEW);
         // Remove it if it doesn't have label or been restricted
-        highUsageApps.removeIf(
-                new AppLabelPredicate(context).or(new AppRestrictionPredicate(context)));
+        highUsageApps.removeIf(AppLabelPredicate.getInstance(context)
+                .or(AppRestrictionPredicate.getInstance(context)));
 
         return highUsageApps;
     }
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
index 7a0a272..e6c0837 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
@@ -54,8 +54,8 @@
         mContext = context;
         mPolicy = policy;
         mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
-        mAppRestrictionPredicate = new AppRestrictionPredicate(context);
-        mAppLabelPredicate = new AppLabelPredicate(context);
+        mAppRestrictionPredicate = AppRestrictionPredicate.getInstance(context);
+        mAppLabelPredicate = AppLabelPredicate.getInstance(context);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/AppLabelPredicate.java b/src/com/android/settings/fuelgauge/batterytip/tips/AppLabelPredicate.java
index 13a2452..1444b12 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/AppLabelPredicate.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/AppLabelPredicate.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.fuelgauge.batterytip.tips;
 
-import android.app.AppOpsManager;
 import android.content.Context;
 
 import com.android.settings.Utils;
@@ -28,12 +27,20 @@
  * {@link Predicate} for {@link AppInfo} to check whether it has label
  */
 public class AppLabelPredicate implements Predicate<AppInfo> {
-    private Context mContext;
-    private AppOpsManager mAppOpsManager;
 
-    public AppLabelPredicate(Context context) {
+    private static AppLabelPredicate sInstance;
+    private Context mContext;
+
+    public static AppLabelPredicate getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new AppLabelPredicate(context.getApplicationContext());
+        }
+
+        return sInstance;
+    }
+
+    private AppLabelPredicate(Context context) {
         mContext = context;
-        mAppOpsManager = context.getSystemService(AppOpsManager.class);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/AppRestrictionPredicate.java b/src/com/android/settings/fuelgauge/batterytip/tips/AppRestrictionPredicate.java
index 3650fe3..43a4d90 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/AppRestrictionPredicate.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/AppRestrictionPredicate.java
@@ -27,9 +27,19 @@
  * {@link Predicate} for {@link AppInfo} to check whether it is restricted.
  */
 public class AppRestrictionPredicate implements Predicate<AppInfo> {
+
+    private static AppRestrictionPredicate sInstance;
     private AppOpsManager mAppOpsManager;
 
-    public AppRestrictionPredicate(Context context) {
+    public static AppRestrictionPredicate getInstance(Context context) {
+        if (sInstance == null) {
+            sInstance = new AppRestrictionPredicate(context.getApplicationContext());
+        }
+
+        return sInstance;
+    }
+
+    private AppRestrictionPredicate(Context context) {
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
     }
 
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
index 8a2d86d..0d91c74 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
@@ -112,7 +112,7 @@
         super.sanityCheck(context);
 
         // Set it invisible if there is no valid app
-        mRestrictAppList.removeIf(new AppLabelPredicate(context));
+        mRestrictAppList.removeIf(AppLabelPredicate.getInstance(context));
         if (mRestrictAppList.isEmpty()) {
             mState = StateType.INVISIBLE;
         }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
index b0d6a7d..3ada030 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoaderTest.java
@@ -28,9 +28,13 @@
 import com.android.internal.os.BatteryStatsHelper;
 import com.android.settings.fuelgauge.BatteryInfo;
 import com.android.settings.fuelgauge.BatteryUtils;
+import com.android.settings.fuelgauge.batterytip.tips.AppLabelPredicate;
+import com.android.settings.fuelgauge.batterytip.tips.AppRestrictionPredicate;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
+import com.android.settings.testutils.BatteryTestUtils;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -77,6 +81,12 @@
         mBatteryTipLoader.mBatteryUtils = mBatteryUtils;
     }
 
+    @After
+    public void tearDown() {
+        BatteryTestUtils.clearStaticInstance(AppLabelPredicate.class, "sInstance");
+        BatteryTestUtils.clearStaticInstance(AppRestrictionPredicate.class, "sInstance");
+    }
+
     @Test
     public void testLoadBackground_containsAllTipsWithOrder() {
         final List<BatteryTip> batteryTips = mBatteryTipLoader.loadInBackground();
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java
index 459c4e2..3882e8c 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/BatteryTipUtilsTest.java
@@ -17,6 +17,7 @@
 package com.android.settings.fuelgauge.batterytip;
 
 import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetectorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetectorTest.java
index 9b0007b..179f2a1 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetectorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetectorTest.java
@@ -34,8 +34,11 @@
 import com.android.settings.fuelgauge.batterytip.AppInfo;
 import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
 import com.android.settings.fuelgauge.batterytip.BatteryTipPolicy;
+import com.android.settings.fuelgauge.batterytip.tips.AppLabelPredicate;
+import com.android.settings.fuelgauge.batterytip.tips.AppRestrictionPredicate;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
+import com.android.settings.testutils.BatteryTestUtils;
 import com.android.settings.testutils.DatabaseTestUtils;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
@@ -86,6 +89,7 @@
         mContext = spy(RuntimeEnvironment.application);
         mPolicy = spy(new BatteryTipPolicy(mContext));
 
+        doReturn(mContext).when(mContext).getApplicationContext();
         doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
         doReturn(AppOpsManager.MODE_IGNORED).when(mAppOpsManager).checkOpNoThrow(
                 AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, RESTRICTED_UID, RESTRICTED_PACKAGE_NAME);
@@ -103,7 +107,12 @@
 
         mRestrictAppDetector = new RestrictAppDetector(mContext, mPolicy);
         mRestrictAppDetector.mBatteryDatabaseManager = mBatteryDatabaseManager;
+    }
 
+    @After
+    public void tearDown() {
+        BatteryTestUtils.clearStaticInstance(AppLabelPredicate.class, "sInstance");
+        BatteryTestUtils.clearStaticInstance(AppRestrictionPredicate.class, "sInstance");
     }
 
     @After
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
index 5c8b7d9..dd3e281 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTipTest.java
@@ -34,9 +34,11 @@
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settings.testutils.BatteryTestUtils;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -74,6 +76,7 @@
         MockitoAnnotations.initMocks(this);
 
         mContext = spy(RuntimeEnvironment.application);
+        doReturn(mContext).when(mContext).getApplicationContext();
         doReturn(mPackageManager).when(mContext).getPackageManager();
         doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(PACKAGE_NAME,
                 PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER);
@@ -98,6 +101,12 @@
         mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, new ArrayList<>());
     }
 
+    @After
+    public void tearDown() {
+        BatteryTestUtils.clearStaticInstance(AppLabelPredicate.class, "sInstance");
+        BatteryTestUtils.clearStaticInstance(AppRestrictionPredicate.class, "sInstance");
+    }
+
     @Test
     public void parcelable() {
         Parcel parcel = Parcel.obtain();
diff --git a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
index 2bdab27..eed2009 100644
--- a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java
@@ -19,6 +19,8 @@
 import android.content.Intent;
 import android.os.BatteryManager;
 
+import java.lang.reflect.Field;
+
 public class BatteryTestUtils {
 
     public static Intent getChargingIntent() {
@@ -47,4 +49,15 @@
         return intent;
     }
 
+    public static void clearStaticInstance(Class clazz, String fieldName) {
+        Field instance;
+        try {
+            instance = clazz.getDeclaredField(fieldName);
+            instance.setAccessible(true);
+            instance.set(null, null);
+        } catch (Exception e) {
+            throw new RuntimeException();
+        }
+    }
+
 }