Merge "Add some pages to search index."
diff --git a/src/com/android/settings/SetFullBackupPassword.java b/src/com/android/settings/SetFullBackupPassword.java
index 4ab096b..b6a03d5 100644
--- a/src/com/android/settings/SetFullBackupPassword.java
+++ b/src/com/android/settings/SetFullBackupPassword.java
@@ -21,6 +21,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -45,7 +46,7 @@
 
                 if (!newPw.equals(confirmPw)) {
                     // Mismatch between new pw and its confirmation re-entry
-Log.i(TAG, "password mismatch");
+                    Log.i(TAG, "password mismatch");
                     Toast.makeText(SetFullBackupPassword.this,
                             R.string.local_backup_password_toast_confirmation_mismatch,
                             Toast.LENGTH_LONG).show();
@@ -56,14 +57,14 @@
 
                 if (setBackupPassword(curPw, newPw)) {
                     // success
-Log.i(TAG, "password set successfully");
+                    Log.i(TAG, "password set successfully");
                     Toast.makeText(SetFullBackupPassword.this,
                             R.string.local_backup_password_toast_success,
                             Toast.LENGTH_LONG).show();
                     finish();
                 } else {
                     // failure -- bad existing pw, usually
-Log.i(TAG, "failure; password mismatch?");
+                    Log.i(TAG, "failure; password mismatch?");
                     Toast.makeText(SetFullBackupPassword.this,
                             R.string.local_backup_password_toast_validation_failure,
                             Toast.LENGTH_LONG).show();
@@ -96,6 +97,11 @@
     }
 
     private boolean setBackupPassword(String currentPw, String newPw) {
+        // new password can't be empty
+        if (TextUtils.isEmpty(newPw)) {
+            return false;
+        }
+
         try {
             return mBackupManager.setBackupPassword(currentPw, newPw);
         } catch (RemoteException e) {
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index 2632795..0a9a4c7 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -107,6 +107,7 @@
         mPreferenceGroup.removeAll();
         for (int i = 0, size = batteryTips.size(); i < size; i++) {
             final BatteryTip batteryTip = mBatteryTips.get(i);
+            batteryTip.sanityCheck(mContext);
             if (batteryTip.getState() != BatteryTip.StateType.INVISIBLE) {
                 final Preference preference = batteryTip.buildPreference(mPrefContext);
                 mBatteryTipMap.put(preference.getKey(), batteryTip);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
index 496320f..61a1157 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.fuelgauge.batterytip.tips;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -134,6 +135,14 @@
     public abstract void updateState(BatteryTip tip);
 
     /**
+     * Check whether data is still make sense. If not, try recover.
+     * @param context used to do sanity check
+     */
+    public void sanityCheck(Context context) {
+        // do nothing
+    }
+
+    /**
      * Log the battery tip
      */
     public abstract void log(Context context, MetricsFeatureProvider metricsFeatureProvider);
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
index 818a467..bf2dd72 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
@@ -107,6 +107,17 @@
     }
 
     @Override
+    public void sanityCheck(Context context) {
+        super.sanityCheck(context);
+
+        // Set it invisible if there is no valid app
+        mRestrictAppList.removeIf(new AppLabelPredicate(context));
+        if (mRestrictAppList.isEmpty()) {
+            mState = StateType.INVISIBLE;
+        }
+    }
+
+    @Override
     public void log(Context context, MetricsFeatureProvider metricsFeatureProvider) {
         metricsFeatureProvider.action(context, MetricsProto.MetricsEvent.ACTION_APP_RESTRICTION_TIP,
                 mState);
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 e2c80df..cab8913 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
@@ -21,6 +21,7 @@
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -51,6 +52,7 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 public class RestrictAppTipTest {
     private static final String PACKAGE_NAME = "com.android.app";
+    private static final String UNINSTALL_PACKAGE_NAME = "com.android.app.unintall";
     private static final String DISPLAY_NAME = "app";
     private static final int ANOMALY_WAKEUP = 0;
     private static final int ANOMALY_WAKELOCK = 1;
@@ -61,6 +63,7 @@
     private RestrictAppTip mInvisibleBatteryTip;
     private List<AppInfo> mUsageAppList;
     private AppInfo mAppInfo;
+    private AppInfo mUninstallAppInfo;
     @Mock
     private ApplicationInfo mApplicationInfo;
     @Mock
@@ -76,6 +79,9 @@
         doReturn(mPackageManager).when(mContext).getPackageManager();
         doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(PACKAGE_NAME,
                 PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER);
+        doThrow(new PackageManager.NameNotFoundException()).when(mPackageManager)
+                .getApplicationInfo(UNINSTALL_PACKAGE_NAME,
+                        PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_ANY_USER);
         doReturn(DISPLAY_NAME).when(mApplicationInfo).loadLabel(mPackageManager);
 
         mAppInfo = new AppInfo.Builder()
@@ -83,6 +89,10 @@
                 .addAnomalyType(ANOMALY_WAKEUP)
                 .addAnomalyType(ANOMALY_WAKELOCK)
                 .build();
+        mUninstallAppInfo = new AppInfo.Builder()
+                .setPackageName(UNINSTALL_PACKAGE_NAME)
+                .addAnomalyType(ANOMALY_WAKEUP)
+                .build();
         mUsageAppList = new ArrayList<>();
         mUsageAppList.add(mAppInfo);
         mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
@@ -174,6 +184,29 @@
     }
 
     @Test
+    public void sanityCheck_appUninstalled_stateInvisible() {
+        final List<AppInfo> appInfos = new ArrayList<>();
+        appInfos.add(mUninstallAppInfo);
+        final BatteryTip batteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, appInfos);
+
+        batteryTip.sanityCheck(mContext);
+
+        assertThat(batteryTip.getState()).isEqualTo(BatteryTip.StateType.INVISIBLE);
+    }
+
+    @Test
+    public void sanityCheck_twoRestrictedAppsWhileUninstallOne_stateVisible() {
+        final List<AppInfo> appInfos = new ArrayList<>();
+        appInfos.add(mAppInfo);
+        appInfos.add(mUninstallAppInfo);
+        final BatteryTip batteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, appInfos);
+
+        batteryTip.sanityCheck(mContext);
+
+        assertThat(batteryTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
+    }
+
+    @Test
     public void toString_containsAppData() {
         assertThat(mNewBatteryTip.toString()).isEqualTo(
                 "type=1 state=0 { packageName=com.android.app,anomalyTypes={0, 1},screenTime=0 }");