Merge "Introduce config_disable_uninstall_update flag."
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index dec12ba..5e4f1e8 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -461,6 +461,7 @@
 
         <activity android:name=".bluetooth.DevicePickerActivity"
                 android:label="@string/device_picker"
+                android:configChanges="orientation|keyboardHidden|screenSize"
                 android:clearTaskOnLaunch="true">
             <intent-filter>
                 <action android:name="android.bluetooth.devicepicker.action.LAUNCH" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7d4b3e9..d16e438 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2142,6 +2142,8 @@
     <string name="wifi_hotspot_configure_ap_text_summary">AndroidAP WPA2 PSK hotspot</string>
     <!-- Default access point SSID used for tethering -->
     <string name="wifi_tether_configure_ssid_default">AndroidHotspot</string>
+    <!-- Summary text when hotspot is disabled because airplane mode is on [CHAR LIMIT=80]-->
+    <string name="wifi_tether_disabled_by_airplane">Unavailable because airplane mode is turned on</string>
 
     <!-- Do not translate. Used for diagnostic screens, precise translation is not necessary
          Wi-Fi Testing on the diagnostic screen-->
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 7335bae..bd63225 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -470,7 +470,7 @@
         updateServicePreferences();
     }
 
-    private void updateServicePreferences() {
+    protected void updateServicePreferences() {
         // Since services category is auto generated we have to do a pass
         // to generate it since services can come and go and then based on
         // the global accessibility state to decided whether it is enabled.
@@ -611,7 +611,7 @@
         }
     }
 
-    private void updateSystemPreferences() {
+    protected void updateSystemPreferences() {
         // Move color inversion and color correction preferences to Display category if device
         // supports HWC hardware-accelerated color transform.
         if (isColorTransformAccelerated(getContext())) {
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 3583b14..659166a 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -86,9 +86,6 @@
     @VisibleForTesting
     static final int BATTERY_TIP_LOADER = 2;
     private static final int MENU_STATS_TYPE = Menu.FIRST;
-    @VisibleForTesting
-    static final int MENU_HIGH_POWER_APPS = Menu.FIRST + 3;
-    private static final int MENU_HELP = Menu.FIRST + 5;
     public static final int DEBUG_INFO_LOADER = 3;
 
     @VisibleForTesting
@@ -257,8 +254,6 @@
                     .setAlphabeticShortcut('t');
         }
 
-        menu.add(Menu.NONE, MENU_HIGH_POWER_APPS, Menu.NONE, R.string.high_power_apps);
-
         super.onCreateOptionsMenu(menu, inflater);
     }
 
@@ -283,15 +278,6 @@
                 }
                 refreshUi();
                 return true;
-            case MENU_HIGH_POWER_APPS:
-                Bundle args = new Bundle();
-                args.putString(ManageApplications.EXTRA_CLASSNAME,
-                        HighPowerApplicationsActivity.class.getName());
-                sa.startPreferencePanel(this, ManageApplications.class.getName(), args,
-                        R.string.high_power_apps, null, null, 0);
-                metricsFeatureProvider.action(context,
-                        MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION);
-                return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
index f87501f..2019b9d 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryDatabaseManager.java
@@ -17,6 +17,8 @@
 package com.android.settings.fuelgauge.batterytip;
 
 import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
+        .ANOMALY_STATE;
+import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
         .PACKAGE_NAME;
 import static com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper.AnomalyColumns
         .ANOMALY_TYPE;
@@ -28,8 +30,10 @@
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
+import android.text.TextUtils;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -55,22 +59,24 @@
             values.put(PACKAGE_NAME, packageName);
             values.put(ANOMALY_TYPE, type);
             values.put(TIME_STAMP_MS, timestampMs);
-
+            values.put(ANOMALY_STATE, AnomalyDatabaseHelper.State.NEW);
             db.insert(TABLE_ANOMALY, null, values);
         }
     }
 
     /**
-     * Query all the anomalies that happened after {@code timestampMs}.
+     * Query all the anomalies that happened after {@code timestampMsAfter} and with {@code state}.
      */
-    public List<AppInfo> queryAllAnomaliesAfter(long timestampMs) {
+    public List<AppInfo> queryAllAnomalies(long timestampMsAfter, int state) {
         final List<AppInfo> appInfos = new ArrayList<>();
         try (SQLiteDatabase db = mDatabaseHelper.getReadableDatabase()) {
             final String[] projection = {PACKAGE_NAME, ANOMALY_TYPE};
             final String orderBy = AnomalyDatabaseHelper.AnomalyColumns.TIME_STAMP_MS + " DESC";
 
-            try (Cursor cursor = db.query(TABLE_ANOMALY, projection, TIME_STAMP_MS + " > ?",
-                    new String[]{String.valueOf(timestampMs)}, null, null, orderBy)) {
+            try (Cursor cursor = db.query(TABLE_ANOMALY, projection,
+                    TIME_STAMP_MS + " > ? AND " + ANOMALY_STATE + " = ? ",
+                    new String[]{String.valueOf(timestampMsAfter), String.valueOf(state)}, null,
+                    null, orderBy)) {
                 while (cursor.moveToNext()) {
                     AppInfo appInfo = new AppInfo.Builder()
                             .setPackageName(cursor.getString(cursor.getColumnIndex(PACKAGE_NAME)))
@@ -90,4 +96,26 @@
                     new String[]{String.valueOf(timestampMs)});
         }
     }
+
+    /**
+     * Update the type of anomalies to {@code state}
+     *
+     * @param appInfos represents the anomalies
+     * @param state    which state to update to
+     */
+    public void updateAnomalies(List<AppInfo> appInfos, int state) {
+        if (!appInfos.isEmpty()) {
+            final int size = appInfos.size();
+            final String[] whereArgs = new String[size];
+            for (int i = 0; i < size; i++) {
+                whereArgs[i] = appInfos.get(i).packageName;
+            }
+            try (SQLiteDatabase db = mDatabaseHelper.getWritableDatabase()) {
+                final ContentValues values = new ContentValues();
+                values.put(ANOMALY_STATE, state);
+                db.update(TABLE_ANOMALY, values, PACKAGE_NAME + " IN (" + TextUtils.join(",",
+                        Collections.nCopies(appInfos.size(), "?")) + ")", whereArgs);
+            }
+        }
+    }
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
index a615841..ebb4790 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipLoader.java
@@ -71,7 +71,7 @@
         tips.add(new SmartBatteryDetector(policy, context.getContentResolver()).detect());
         tips.add(new EarlyWarningDetector(policy, context).detect());
         tips.add(new SummaryDetector(policy).detect());
-        tips.add(new RestrictAppDetector(policy).detect());
+        tips.add(new RestrictAppDetector(context, policy).detect());
 
         Collections.sort(tips);
         return tips;
diff --git a/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppAction.java b/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppAction.java
index 9c49822..886a6d5 100644
--- a/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppAction.java
+++ b/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppAction.java
@@ -21,7 +21,9 @@
 import android.support.annotation.VisibleForTesting;
 
 import com.android.settings.fuelgauge.BatteryUtils;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 import com.android.settings.fuelgauge.batterytip.AppInfo;
+import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
 
 import java.util.List;
@@ -32,12 +34,15 @@
 public class RestrictAppAction extends BatteryTipAction {
     private RestrictAppTip mRestrictAppTip;
     @VisibleForTesting
+    BatteryDatabaseManager mBatteryDatabaseManager;
+    @VisibleForTesting
     BatteryUtils mBatteryUtils;
 
     public RestrictAppAction(Context context, RestrictAppTip tip) {
         super(context);
         mRestrictAppTip = tip;
         mBatteryUtils = BatteryUtils.getInstance(context);
+        mBatteryDatabaseManager = new BatteryDatabaseManager(context);
     }
 
     /**
@@ -53,5 +58,7 @@
             mBatteryUtils.setForceAppStandby(mBatteryUtils.getPackageUid(packageName), packageName,
                     AppOpsManager.MODE_IGNORED);
         }
+
+        mBatteryDatabaseManager.updateAnomalies(appInfos, AnomalyDatabaseHelper.State.HANDLED);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
index 46e241a..e3c9b9e 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
@@ -16,7 +16,13 @@
 
 package com.android.settings.fuelgauge.batterytip.detectors;
 
+import android.content.Context;
+import android.support.annotation.VisibleForTesting;
+import android.text.format.DateUtils;
+
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 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.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
@@ -29,18 +35,47 @@
  * {@link BatteryTipDetector} since it need the most up-to-date {@code visibleTips}
  */
 public class RestrictAppDetector implements BatteryTipDetector {
+    @VisibleForTesting
+    static final boolean USE_FAKE_DATA = false;
     private BatteryTipPolicy mPolicy;
+    @VisibleForTesting
+    BatteryDatabaseManager mBatteryDatabaseManager;
 
-    public RestrictAppDetector(BatteryTipPolicy policy) {
+    public RestrictAppDetector(Context context, BatteryTipPolicy policy) {
         mPolicy = policy;
+        mBatteryDatabaseManager = new BatteryDatabaseManager(context);
     }
 
     @Override
     public BatteryTip detect() {
-        // TODO(b/70570352): Detect restrict apps here, get data from database
+        if (USE_FAKE_DATA) {
+            return getFakeData();
+        }
+        if (mPolicy.appRestrictionEnabled) {
+            // TODO(b/72385333): hook up the query timestamp to server side
+            final long oneDayBeforeMs = System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS;
+            final List<AppInfo> highUsageApps = mBatteryDatabaseManager.queryAllAnomalies(
+                    oneDayBeforeMs, AnomalyDatabaseHelper.State.NEW);
+            if (!highUsageApps.isEmpty()) {
+                // If there are new anomalies, show them
+                return new RestrictAppTip(BatteryTip.StateType.NEW, highUsageApps);
+            } else {
+                // Otherwise, show auto-handled one if it exists
+                final List<AppInfo> autoHandledApps = mBatteryDatabaseManager.queryAllAnomalies(
+                        oneDayBeforeMs, AnomalyDatabaseHelper.State.AUTO_HANDLED);
+                return new RestrictAppTip(autoHandledApps.isEmpty() ? BatteryTip.StateType.INVISIBLE
+                        : BatteryTip.StateType.HANDLED, autoHandledApps);
+            }
+        } else {
+            return new RestrictAppTip(BatteryTip.StateType.INVISIBLE, new ArrayList<>());
+        }
+    }
+
+    private BatteryTip getFakeData() {
         final List<AppInfo> highUsageApps = new ArrayList<>();
-        return new RestrictAppTip(
-                highUsageApps.isEmpty() ? BatteryTip.StateType.INVISIBLE : BatteryTip.StateType.NEW,
-                highUsageApps);
+        highUsageApps.add(new AppInfo.Builder()
+                .setPackageName("com.android.settings")
+                .build());
+        return new RestrictAppTip(BatteryTip.StateType.NEW, highUsageApps);
     }
 }
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
index 1d84d7f..a40f292 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
@@ -81,7 +81,14 @@
 
     @Override
     public void updateState(BatteryTip tip) {
-        mState = tip.mState;
+        if (tip.mState == StateType.NEW) {
+            // Display it if new anomaly comes
+            mState = StateType.NEW;
+            mRestrictAppList = ((RestrictAppTip) tip).mRestrictAppList;
+        } else if (mState == StateType.NEW && tip.mState == StateType.INVISIBLE) {
+            // If anomaly becomes invisible, show it as handled
+            mState = StateType.HANDLED;
+        }
     }
 
     public List<AppInfo> getRestrictAppList() {
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
index 826ed42..058ba5f 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
@@ -202,7 +202,7 @@
         boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
         if (isAirplaneMode) {
-            mPreference.setSummary(R.string.summary_placeholder);
+            mPreference.setSummary(R.string.wifi_tether_disabled_by_airplane);
         }
     }
     //
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
index ac8800e..92332f2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDatabaseManagerTest.java
@@ -24,6 +24,7 @@
 import android.text.format.DateUtils;
 
 import com.android.settings.TestConfig;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
 import com.android.settings.fuelgauge.batterytip.AppInfo;
 import com.android.settings.fuelgauge.batterytip.BatteryDatabaseManager;
 import com.android.settings.testutils.DatabaseTestUtils;
@@ -37,6 +38,7 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
+import java.util.ArrayList;
 import java.util.List;
 
 @RunWith(RobolectricTestRunner.class)
@@ -71,28 +73,54 @@
         mBatteryDatabaseManager.insertAnomaly(PACKAGE_NAME_OLD, TYPE_OLD, TWO_DAYS_BEFORE);
 
         // In database, it contains two record
-        List<AppInfo> totalAppInfos = mBatteryDatabaseManager.queryAllAnomaliesAfter(0);
+        List<AppInfo> totalAppInfos = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
+                AnomalyDatabaseHelper.State.NEW);
         assertThat(totalAppInfos).hasSize(2);
-        verifyAppInfo(totalAppInfos.get(0), PACKAGE_NAME_NEW, TYPE_NEW);
-        verifyAppInfo(totalAppInfos.get(1), PACKAGE_NAME_OLD, TYPE_OLD);
+        assertAppInfo(totalAppInfos.get(0), PACKAGE_NAME_NEW, TYPE_NEW);
+        assertAppInfo(totalAppInfos.get(1), PACKAGE_NAME_OLD, TYPE_OLD);
 
         // Only one record shows up if we query by timestamp
-        List<AppInfo> appInfos = mBatteryDatabaseManager.queryAllAnomaliesAfter(ONE_DAY_BEFORE);
+        List<AppInfo> appInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
+                AnomalyDatabaseHelper.State.NEW);
         assertThat(appInfos).hasSize(1);
-        verifyAppInfo(appInfos.get(0), PACKAGE_NAME_NEW, TYPE_NEW);
+        assertAppInfo(appInfos.get(0), PACKAGE_NAME_NEW, TYPE_NEW);
 
         mBatteryDatabaseManager.deleteAllAnomaliesBeforeTimeStamp(ONE_DAY_BEFORE);
 
         // The obsolete record is removed from database
-        List<AppInfo> appInfos1 = mBatteryDatabaseManager.queryAllAnomaliesAfter(0);
+        List<AppInfo> appInfos1 = mBatteryDatabaseManager.queryAllAnomalies(0 /* timeMsAfter */,
+                AnomalyDatabaseHelper.State.NEW);
         assertThat(appInfos1).hasSize(1);
-        verifyAppInfo(appInfos1.get(0), PACKAGE_NAME_NEW, TYPE_NEW);
-
+        assertAppInfo(appInfos1.get(0), PACKAGE_NAME_NEW, TYPE_NEW);
     }
 
-    private void verifyAppInfo(final AppInfo appInfo, String packageName, int type) {
+    @Test
+    public void testUpdateAnomalies_updateSuccessfully() {
+        mBatteryDatabaseManager.insertAnomaly(PACKAGE_NAME_NEW, TYPE_NEW, NOW);
+        mBatteryDatabaseManager.insertAnomaly(PACKAGE_NAME_OLD, TYPE_OLD, NOW);
+        final AppInfo appInfo = new AppInfo.Builder().setPackageName(PACKAGE_NAME_OLD).build();
+        final List<AppInfo> updateAppInfos = new ArrayList<>();
+        updateAppInfos.add(appInfo);
+
+        // Change state of PACKAGE_NAME_OLD to handled
+        mBatteryDatabaseManager.updateAnomalies(updateAppInfos,
+                AnomalyDatabaseHelper.State.HANDLED);
+
+        // The state of PACKAGE_NAME_NEW is still new
+        List<AppInfo> newAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
+                AnomalyDatabaseHelper.State.NEW);
+        assertThat(newAppInfos).hasSize(1);
+        assertAppInfo(newAppInfos.get(0), PACKAGE_NAME_NEW, TYPE_NEW);
+
+        // The state of PACKAGE_NAME_OLD is changed to handled
+        List<AppInfo> handledAppInfos = mBatteryDatabaseManager.queryAllAnomalies(ONE_DAY_BEFORE,
+                AnomalyDatabaseHelper.State.HANDLED);
+        assertThat(handledAppInfos).hasSize(1);
+        assertAppInfo(handledAppInfos.get(0), PACKAGE_NAME_OLD, TYPE_OLD);
+    }
+
+    private void assertAppInfo(final AppInfo appInfo, String packageName, int type) {
         assertThat(appInfo.packageName).isEqualTo(packageName);
         assertThat(appInfo.anomalyType).isEqualTo(type);
     }
-
 }
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 35af8bb..32e2b0b 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -15,8 +15,6 @@
  */
 package com.android.settings.fuelgauge;
 
-import static com.android.settings.fuelgauge.PowerUsageSummary.MENU_HIGH_POWER_APPS;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Matchers.any;
@@ -108,14 +106,6 @@
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Menu mMenu;
-    @Mock
-    private MenuItem mToggleAppsMenu;
-    @Mock
-    private MenuItem mHighPowerMenu;
-    @Mock
-    private MenuInflater mMenuInflater;
     @Mock
     private BatterySipper mNormalBatterySipper;
     @Mock
@@ -169,7 +159,6 @@
         doReturn(mock(LoaderManager.class)).when(mFragment).getLoaderManager();
 
         when(mFragment.getActivity()).thenReturn(mSettingsActivity);
-        when(mHighPowerMenu.getItemId()).thenReturn(MENU_HIGH_POWER_APPS);
         when(mFeatureFactory.powerUsageFeatureProvider.getAdditionalBatteryInfoIntent())
                 .thenReturn(sAdditionalBatteryInfoIntent);
         when(mBatteryHelper.getTotalPower()).thenReturn(TOTAL_POWER);
@@ -205,14 +194,6 @@
     }
 
     @Test
-    public void testOptionsMenu_menuHighPower_metricEventInvoked() {
-        mFragment.onOptionsItemSelected(mHighPowerMenu);
-
-        verify(mFeatureFactory.metricsFeatureProvider).action(mContext,
-                MetricsProto.MetricsEvent.ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION);
-    }
-
-    @Test
     public void testUpdateLastFullChargePreference_showCorrectSummary() {
         doReturn(mRealContext).when(mFragment).getContext();
 
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppActionTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppActionTest.java
index 47785d5..728bbff 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppActionTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppActionTest.java
@@ -27,8 +27,10 @@
 import com.android.settings.fuelgauge.batterytip.AppInfo;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
+import com.android.settings.testutils.DatabaseTestUtils;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -69,6 +71,11 @@
         mRestrictAppAction.mBatteryUtils = mBatteryUtils;
     }
 
+    @After
+    public void cleanUp() {
+        DatabaseTestUtils.clearDb(mContext);
+    }
+
     @Test
     public void testHandlePositiveAction() {
         mRestrictAppAction.handlePositiveAction();
@@ -79,5 +86,4 @@
                 eq(AppOpsManager.MODE_IGNORED));
     }
 
-
 }
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
new file mode 100644
index 0000000..6a25c6d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetectorTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 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.batterytip.detectors;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.Context;
+
+import com.android.settings.TestConfig;
+import com.android.settings.fuelgauge.batterytip.AnomalyDatabaseHelper;
+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.BatteryTip;
+import com.android.settings.testutils.DatabaseTestUtils;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class RestrictAppDetectorTest {
+    private static final String PACKAGE_NAME = "com.android.app";
+    private Context mContext;
+    private BatteryTipPolicy mPolicy;
+    private RestrictAppDetector mRestrictAppDetector;
+    private List<AppInfo> mAppInfoList;
+    @Mock
+    private BatteryDatabaseManager mBatteryDatabaseManager;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mAppInfoList = new ArrayList<>();
+        mAppInfoList.add(new AppInfo.Builder()
+                .setPackageName(PACKAGE_NAME)
+                .build());
+
+        mContext = RuntimeEnvironment.application;
+        mPolicy = spy(new BatteryTipPolicy(mContext));
+        mRestrictAppDetector = new RestrictAppDetector(mContext, mPolicy);
+        mRestrictAppDetector.mBatteryDatabaseManager = mBatteryDatabaseManager;
+    }
+
+    @After
+    public void cleanUp() {
+        DatabaseTestUtils.clearDb(mContext);
+    }
+
+    @Test
+    public void testDetect_hasAnomaly_tipNew() {
+        doReturn(mAppInfoList).when(mBatteryDatabaseManager).queryAllAnomalies(anyLong(),
+                eq(AnomalyDatabaseHelper.State.NEW));
+
+        assertThat(mRestrictAppDetector.detect().getState()).isEqualTo(BatteryTip.StateType.NEW);
+    }
+
+    @Test
+    public void testDetect_hasAutoHandledAnomaly_tipHandled() {
+        doReturn(new ArrayList<AppInfo>()).when(mBatteryDatabaseManager).queryAllAnomalies(
+                anyLong(), eq(AnomalyDatabaseHelper.State.NEW));
+        doReturn(mAppInfoList).when(mBatteryDatabaseManager).queryAllAnomalies(anyLong(),
+                eq(AnomalyDatabaseHelper.State.AUTO_HANDLED));
+
+        assertThat(mRestrictAppDetector.detect().getState()).isEqualTo(
+                BatteryTip.StateType.HANDLED);
+    }
+
+    @Test
+    public void testDetect_noAnomaly_tipInvisible() {
+        doReturn(new ArrayList<AppInfo>()).when(mBatteryDatabaseManager).queryAllAnomalies(
+                anyLong(), anyInt());
+
+        assertThat(mRestrictAppDetector.detect().getState()).isEqualTo(
+                BatteryTip.StateType.INVISIBLE);
+    }
+
+    @Test
+    public void testUseFakeData_alwaysFalse() {
+        assertThat(RestrictAppDetector.USE_FAKE_DATA).isFalse();
+    }
+}
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 e1dea17..74536a5 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
@@ -49,6 +49,7 @@
     private Context mContext;
     private RestrictAppTip mNewBatteryTip;
     private RestrictAppTip mHandledBatteryTip;
+    private RestrictAppTip mInvisibleBatteryTip;
     private List<AppInfo> mUsageAppList;
     @Mock
     private ApplicationInfo mApplicationInfo;
@@ -71,6 +72,7 @@
                 .build());
         mNewBatteryTip = new RestrictAppTip(BatteryTip.StateType.NEW, mUsageAppList);
         mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
+        mInvisibleBatteryTip = new RestrictAppTip(BatteryTip.StateType.INVISIBLE, mUsageAppList);
     }
 
     @Test
@@ -108,4 +110,20 @@
         assertThat(mHandledBatteryTip.getSummary(mContext)).isEqualTo(
                 "App changes are in progress");
     }
+
+    @Test
+    public void testUpdate_anomalyBecomeInvisible_stateHandled() {
+        mNewBatteryTip.updateState(mInvisibleBatteryTip);
+
+        assertThat(mNewBatteryTip.getState()).isEqualTo(BatteryTip.StateType.HANDLED);
+    }
+
+    @Test
+    public void testUpdate_newAnomalyComes_stateNew() {
+        mInvisibleBatteryTip.updateState(mNewBatteryTip);
+        assertThat(mInvisibleBatteryTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
+
+        mHandledBatteryTip.updateState(mNewBatteryTip);
+        assertThat(mHandledBatteryTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
+    }
 }
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
index 4b18fcf..92303e0 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
@@ -185,7 +185,7 @@
         receiver.onReceive(RuntimeEnvironment.application, broadcast);
 
         assertThat(mPreference.getSummary().toString()).isEqualTo(
-                RuntimeEnvironment.application.getString(R.string.summary_placeholder));
+                "Unavailable because airplane mode is turned on");
     }
 
     @Test