Merge "Add getDescendants to Settings Slice Provider" into pi-dev
diff --git a/res/drawable/empty_search_results.xml b/res/drawable/empty_search_results.xml
deleted file mode 100644
index 9162107..0000000
--- a/res/drawable/empty_search_results.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="96dp"
-    android:height="96dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24"
-    android:tint="?android:attr/colorControlNormal">
-
-    <path
-        android:fillColor="#000000"
-        android:pathData="M15.5,14h-0.79l-0.28-0.27c1.2-1.4,1.82-3.31,1.48-5.34c-0.47-2.78-2.79-5-5.59-5.34c-4.23-0.52-7.79,3.04-7.27,7.27
-c0.34,2.8,2.56,5.12,5.34,5.59c2.03,0.34,3.94-0.28,5.34-1.48L14,14.71v0.79l5.2,5.19c0.41,0.41,1.07,0.41,1.48,0l0.01-0.01
-c0.41-0.41,0.41-1.07,0-1.48L15.5,14z M9.5,14C7.01,14,5,11.99,5,9.5S7.01,5,9.5,5S14,7.01,14,9.5S11.99,14,9.5,14z" />
-</vector>
\ No newline at end of file
diff --git a/res/layout/preference_volume_slider.xml b/res/layout/preference_volume_slider.xml
index 7e146b8..89ecec0 100644
--- a/res/layout/preference_volume_slider.xml
+++ b/res/layout/preference_volume_slider.xml
@@ -72,9 +72,10 @@
                 android:orientation="vertical"/>
         </LinearLayout>
 
-        <FrameLayout
+        <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
+            android:orientation="vertical"
             android:layout_marginTop="6dp">
 
             <SeekBar
@@ -93,10 +94,11 @@
                 android:textAlignment="viewStart"
                 android:singleLine="true"
                 android:ellipsize="end"
+                android:visibility="gone"
                 android:textAppearance="@android:style/TextAppearance.Material.Body1"
                 android:textColor="?android:attr/textColorSecondary"/>
 
-        </FrameLayout>
+        </LinearLayout>
     </LinearLayout>
 
 </LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 062648a..7ba4715 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -9265,6 +9265,9 @@
     <!-- [CHAR_LIMIT=NONE] Developer Settings: Title of the setting which turns on emulation of a display cutout. -->
     <string name="display_cutout_emulation">Simulate a display with a cutout</string>
 
+    <!-- [CHAR_LIMIT=NONE] Developer Settings: Search keywords for the setting which turns on emulation of a display cutout. -->
+    <string name="display_cutout_emulation_keywords">display cutout, notch</string>
+
     <!-- [CHAR_LIMIT=NONE] Developer Settings: Label for the option that turns off display cutout emulation. -->
     <string name="display_cutout_emulation_none">None</string>
 
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 77d4a7d..c491980 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -382,7 +382,8 @@
 
         <ListPreference
             android:key="display_cutout_emulation"
-            android:title="@string/display_cutout_emulation" />
+            android:title="@string/display_cutout_emulation"
+            settings:keywords="@string/display_cutout_emulation_keywords" />
 
     </PreferenceCategory>
 
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index 7ba1c76..704d553 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -141,11 +141,6 @@
           android:key="screen_locking_sounds"
           android:title="@string/screen_locking_sounds_title" />
 
-        <!-- Charging sounds -->
-        <SwitchPreference
-          android:key="charging_sounds"
-          android:title="@string/charging_sounds_title" />
-
         <!-- Docking sounds -->
         <SwitchPreference
           android:key="docking_sounds"
diff --git a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
index 017cd3f..5a640e5 100644
--- a/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
+++ b/src/com/android/settings/fuelgauge/batterytip/detectors/RestrictAppDetector.java
@@ -25,6 +25,7 @@
 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.AppInfoPredicate;
 import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
 import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
 
@@ -44,17 +45,13 @@
     BatteryDatabaseManager mBatteryDatabaseManager;
     private Context mContext;
 
-    private Predicate<AppInfo> mAppInfoPredicate = new Predicate<AppInfo>() {
-        @Override
-        public boolean test(AppInfo appInfo) {
-            return Utils.getApplicationLabel(mContext, appInfo.packageName) == null;
-        }
-    };
+    private AppInfoPredicate mAppInfoPredicate;
 
     public RestrictAppDetector(Context context, BatteryTipPolicy policy) {
         mContext = context;
         mPolicy = policy;
         mBatteryDatabaseManager = BatteryDatabaseManager.getInstance(context);
+        mAppInfoPredicate = new AppInfoPredicate(context);
     }
 
     @Override
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/AppInfoPredicate.java b/src/com/android/settings/fuelgauge/batterytip/tips/AppInfoPredicate.java
new file mode 100644
index 0000000..df78caa
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/AppInfoPredicate.java
@@ -0,0 +1,46 @@
+/*
+ * 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.tips;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+
+import com.android.settings.Utils;
+import com.android.settings.fuelgauge.batterytip.AppInfo;
+
+import java.util.function.Predicate;
+
+/**
+ * {@link Predicate} for {@link AppInfo} to check whether it has label or restricted.
+ */
+public class AppInfoPredicate implements Predicate<AppInfo> {
+    private Context mContext;
+    private AppOpsManager mAppOpsManager;
+
+    public AppInfoPredicate(Context context) {
+        mContext = context;
+        mAppOpsManager = context.getSystemService(AppOpsManager.class);
+    }
+
+    @Override
+    public boolean test(AppInfo appInfo) {
+        // Return true if app doesn't have label or already been restricted
+        return Utils.getApplicationLabel(mContext, appInfo.packageName) == null
+                || mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
+                appInfo.uid, appInfo.packageName) == AppOpsManager.MODE_IGNORED;
+    }
+}
diff --git a/src/com/android/settings/gestures/SwipeUpPreferenceController.java b/src/com/android/settings/gestures/SwipeUpPreferenceController.java
index a20cd97..c3abd46 100644
--- a/src/com/android/settings/gestures/SwipeUpPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeUpPreferenceController.java
@@ -16,8 +16,11 @@
 
 package com.android.settings.gestures;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -33,6 +36,7 @@
     private final int ON = 1;
     private final int OFF = 0;
 
+    private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
     private static final String PREF_KEY_VIDEO = "gesture_swipe_up_video";
     private final UserManager mUserManager;
 
@@ -42,6 +46,14 @@
     }
 
     static boolean isGestureAvailable(Context context) {
+        final ComponentName recentsComponentName = ComponentName.unflattenFromString(
+                context.getString(com.android.internal.R.string.config_recentsComponentName));
+        final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
+                .setPackage(recentsComponentName.getPackageName());
+        if (context.getPackageManager().resolveService(quickStepIntent,
+                PackageManager.MATCH_SYSTEM_ONLY) == null) {
+            return false;
+        }
         return true;
     }
 
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index 61f1243..d0ecb71 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -1195,12 +1195,19 @@
         }
     }
 
-    private ApnData getApnDataFromUri(Uri uri) {
-        ApnData apnData;
-        try (Cursor cursor = getActivity().managedQuery(
-                uri, sProjection, null /* selection */, null /* sortOrder */)) {
-            cursor.moveToFirst();
-            apnData = new ApnData(uri, cursor);
+    @VisibleForTesting
+    ApnData getApnDataFromUri(Uri uri) {
+        ApnData apnData = null;
+        try (Cursor cursor = getContentResolver().query(
+                uri,
+                sProjection,
+                null /* selection */,
+                null /* selectionArgs */,
+                null /* sortOrder */)) {
+            if (cursor != null) {
+                cursor.moveToFirst();
+                apnData = new ApnData(uri, cursor);
+            }
         }
 
         if (apnData == null) {
diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java
index ea071fa..e74b110 100644
--- a/src/com/android/settings/notification/RingVolumePreferenceController.java
+++ b/src/com/android/settings/notification/RingVolumePreferenceController.java
@@ -17,6 +17,8 @@
 package com.android.settings.notification;
 
 import android.app.NotificationManager;
+import android.arch.lifecycle.LifecycleObserver;
+import android.arch.lifecycle.OnLifecycleEvent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -31,6 +33,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import java.util.Objects;
 
@@ -58,6 +61,7 @@
         updateRingerMode();
     }
 
+    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
     @Override
     public void onResume() {
         super.onResume();
@@ -66,6 +70,7 @@
         updatePreferenceIcon();
     }
 
+    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
     @Override
     public void onPause() {
         super.onPause();
@@ -118,11 +123,10 @@
 
     private void updatePreferenceIcon() {
         if (mPreference != null) {
-            mPreference.showIcon(mSuppressor != null
-                ? com.android.internal.R.drawable.ic_audio_ring_notif_mute
-                : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate()
-                    ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate
-                    : com.android.internal.R.drawable.ic_audio_ring_notif);
+            mPreference.showIcon(
+                    mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate()
+                            ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate
+                            : com.android.internal.R.drawable.ic_audio_ring_notif);
         }
     }
 
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index 4c9ee38..6535812 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -146,10 +146,16 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        use(AlarmVolumePreferenceController.class).setCallback(mVolumeCallback);
-        use(MediaVolumePreferenceController.class).setCallback(mVolumeCallback);
-        use(RingVolumePreferenceController.class).setCallback(mVolumeCallback);
-        use(NotificationVolumePreferenceController.class).setCallback(mVolumeCallback);
+        ArrayList<VolumeSeekBarPreferenceController> volumeControllers = new ArrayList<>();
+        volumeControllers.add(use(AlarmVolumePreferenceController.class));
+        volumeControllers.add(use(MediaVolumePreferenceController.class));
+        volumeControllers.add(use(RingVolumePreferenceController.class));
+        volumeControllers.add(use(NotificationVolumePreferenceController.class));
+
+        for (VolumeSeekBarPreferenceController controller : volumeControllers) {
+            controller.setCallback(mVolumeCallback);
+            getLifecycle().addObserver(controller);
+        }
     }
 
     // === Volumes ===
@@ -205,8 +211,6 @@
                 new DialPadTonePreferenceController(context, fragment, lifecycle);
         final ScreenLockSoundPreferenceController screenLockSoundPreferenceController =
                 new ScreenLockSoundPreferenceController(context, fragment, lifecycle);
-        final ChargingSoundPreferenceController chargingSoundPreferenceController =
-                new ChargingSoundPreferenceController(context, fragment, lifecycle);
         final DockingSoundPreferenceController dockingSoundPreferenceController =
                 new DockingSoundPreferenceController(context, fragment, lifecycle);
         final TouchSoundPreferenceController touchSoundPreferenceController =
@@ -222,7 +226,6 @@
 
         controllers.add(dialPadTonePreferenceController);
         controllers.add(screenLockSoundPreferenceController);
-        controllers.add(chargingSoundPreferenceController);
         controllers.add(dockingSoundPreferenceController);
         controllers.add(touchSoundPreferenceController);
         controllers.add(vibrateOnTouchPreferenceController);
@@ -233,7 +236,6 @@
                 "other_sounds_and_vibrations_category").setChildren(
                 Arrays.asList(dialPadTonePreferenceController,
                         screenLockSoundPreferenceController,
-                        chargingSoundPreferenceController,
                         dockingSoundPreferenceController,
                         touchSoundPreferenceController,
                         vibrateOnTouchPreferenceController,
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index 8a48e95..d7b5e52 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -196,8 +196,7 @@
         if (mSuppressionTextView != null && mSeekBar != null) {
             mSuppressionTextView.setText(mSuppressionText);
             final boolean showSuppression = !TextUtils.isEmpty(mSuppressionText);
-            mSuppressionTextView.setVisibility(showSuppression ? View.VISIBLE : View.INVISIBLE);
-            mSeekBar.setVisibility(showSuppression ? View.INVISIBLE : View.VISIBLE);
+            mSuppressionTextView.setVisibility(showSuppression ? View.VISIBLE : View.GONE);
         }
     }
 
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 80b7519..d2a6d10 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -54,16 +54,16 @@
     public void onReceive(Context context, Intent intent) {
         final String action = intent.getAction();
         final String key = intent.getStringExtra(EXTRA_SLICE_KEY);
-        final boolean isPlatformDefined = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
+        final boolean isPlatformSlice = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
                 false /* default */);
 
         switch (action) {
             case ACTION_TOGGLE_CHANGED:
-                handleToggleAction(context, key, isPlatformDefined);
+                handleToggleAction(context, key, isPlatformSlice);
                 break;
             case ACTION_SLIDER_CHANGED:
                 int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
-                handleSliderAction(context, key, newPosition);
+                handleSliderAction(context, key, newPosition, isPlatformSlice);
                 break;
             case ACTION_WIFI_CHANGED:
                 WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -95,6 +95,7 @@
         if (!controller.isAvailable()) {
             Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
             updateUri(context, key, isPlatformSlice);
+            return;
         }
 
         // TODO post context.getContentResolver().notifyChanged(uri, null) in the Toggle controller
@@ -107,7 +108,8 @@
         updateUri(context, key, isPlatformSlice);
     }
 
-    private void handleSliderAction(Context context, String key, int newPosition) {
+    private void handleSliderAction(Context context, String key, int newPosition,
+            boolean isPlatformSlice) {
         if (TextUtils.isEmpty(key)) {
             throw new IllegalArgumentException(
                     "No key passed to Intent for slider controller. Use extra: " + EXTRA_SLICE_KEY);
@@ -123,6 +125,12 @@
             throw new IllegalArgumentException("Slider action passed for a non-slider key: " + key);
         }
 
+        if (!controller.isAvailable()) {
+            Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
+            updateUri(context, key, isPlatformSlice);
+            return;
+        }
+
         final SliderPreferenceController sliderController = (SliderPreferenceController) controller;
         final int maxSteps = sliderController.getMaxSteps();
         if (newPosition < 0 || newPosition > maxSteps) {
diff --git a/src/com/android/settings/wifi/WifiNoInternetDialog.java b/src/com/android/settings/wifi/WifiNoInternetDialog.java
index 6b7b2db..b175665 100644
--- a/src/com/android/settings/wifi/WifiNoInternetDialog.java
+++ b/src/com/android/settings/wifi/WifiNoInternetDialog.java
@@ -25,6 +25,7 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkRequest;
+import android.net.wifi.WifiInfo;
 import android.os.Bundle;
 import android.provider.Settings;
 import android.util.Log;
@@ -107,14 +108,15 @@
         mCM.registerNetworkCallback(request, mNetworkCallback);
 
         final NetworkInfo ni = mCM.getNetworkInfo(mNetwork);
-        if (ni == null || !ni.isConnectedOrConnecting()) {
+        final NetworkCapabilities nc = mCM.getNetworkCapabilities(mNetwork);
+        if (ni == null || !ni.isConnectedOrConnecting() || nc == null) {
             Log.d(TAG, "Network " + mNetwork + " is not connected: " + ni);
             finish();
             return;
         }
-        mNetworkName = ni.getExtraInfo();
+        mNetworkName = nc.getSSID();
         if (mNetworkName != null) {
-            mNetworkName = mNetworkName.replaceAll("^\"|\"$", "");  // Remove double quotes
+            mNetworkName = WifiInfo.removeDoubleQuotes(mNetworkName);
         }
 
         createDialog();
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 23f08c0..76e2928 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
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.spy;
 
+import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -53,8 +54,10 @@
 @RunWith(SettingsRobolectricTestRunner.class)
 public class RestrictAppDetectorTest {
 
+    private static final int RESTRICTED_UID = 222;
     private static final String PACKAGE_NAME = "com.android.app";
     private static final String UNINSTALLED_PACKAGE_NAME = "com.android.uninstalled";
+    private static final String RESTRICTED_PACKAGE_NAME = "com.android.restricted";
     private Context mContext;
     private BatteryTipPolicy mPolicy;
     private RestrictAppDetector mRestrictAppDetector;
@@ -66,6 +69,8 @@
     private PackageManager mPackageManager;
     @Mock
     private ApplicationInfo mApplicationInfo;
+    @Mock
+    private AppOpsManager mAppOpsManager;
 
     @Before
     public void setUp() throws PackageManager.NameNotFoundException {
@@ -79,8 +84,10 @@
 
         mContext = spy(RuntimeEnvironment.application);
         mPolicy = spy(new BatteryTipPolicy(mContext));
-        mRestrictAppDetector = new RestrictAppDetector(mContext, mPolicy);
-        mRestrictAppDetector.mBatteryDatabaseManager = mBatteryDatabaseManager;
+
+        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);
 
         doReturn(mPackageManager).when(mContext).getPackageManager();
         doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(eq(PACKAGE_NAME),
@@ -88,6 +95,10 @@
         doReturn(PACKAGE_NAME).when(mApplicationInfo).loadLabel(any());
         doThrow(new PackageManager.NameNotFoundException()).when(
                 mPackageManager).getApplicationInfo(eq(UNINSTALLED_PACKAGE_NAME), anyInt());
+
+        mRestrictAppDetector = new RestrictAppDetector(mContext, mPolicy);
+        mRestrictAppDetector.mBatteryDatabaseManager = mBatteryDatabaseManager;
+
     }
 
     @After
@@ -128,6 +139,23 @@
     }
 
     @Test
+    public void testDetect_hasRestrictedAnomaly_removeIt() throws
+            PackageManager.NameNotFoundException {
+        mAppInfoList.add(new AppInfo.Builder()
+                .setUid(RESTRICTED_UID)
+                .setPackageName(RESTRICTED_PACKAGE_NAME)
+                .build());
+        doReturn(mAppInfoList).when(mBatteryDatabaseManager)
+                .queryAllAnomalies(anyLong(), eq(AnomalyDatabaseHelper.State.NEW));
+        doReturn(mApplicationInfo).when(mPackageManager).getApplicationInfo(
+                eq(RESTRICTED_PACKAGE_NAME), anyInt());
+
+        final RestrictAppTip restrictAppTip = (RestrictAppTip) mRestrictAppDetector.detect();
+        assertThat(restrictAppTip.getState()).isEqualTo(BatteryTip.StateType.NEW);
+        assertThat(restrictAppTip.getRestrictAppList()).containsExactly(mAppInfo);
+    }
+
+    @Test
     public void testDetect_noAnomaly_tipInvisible() {
         doReturn(new ArrayList<AppInfo>()).when(mBatteryDatabaseManager)
                 .queryAllAnomalies(anyLong(), anyInt());
diff --git a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
index f9a6e9c..360609b 100644
--- a/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/SwipeUpPreferenceControllerTest.java
@@ -17,12 +17,14 @@
 package com.android.settings.gestures;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
 import android.os.UserManager;
@@ -38,7 +40,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowPackageManager;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -47,16 +50,36 @@
 public class SwipeUpPreferenceControllerTest {
 
     private Context mContext;
+    private ShadowPackageManager mPackageManager;
     private SwipeUpPreferenceController mController;
+
+    private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
     private static final String KEY_SWIPE_UP = "gesture_swipe_up";
 
     @Before
     public void setUp() {
         mContext = RuntimeEnvironment.application;
+        mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
         mController = new SwipeUpPreferenceController(mContext, KEY_SWIPE_UP);
     }
 
     @Test
+    public void testIsGestureAvailable_matchingServiceExists_shouldReturnTrue() {
+        final ComponentName recentsComponentName = ComponentName.unflattenFromString(
+                mContext.getString(com.android.internal.R.string.config_recentsComponentName));
+        final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
+                .setPackage(recentsComponentName.getPackageName());
+        mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo());
+
+        assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isTrue();
+    }
+
+    @Test
+    public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() {
+        assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse();
+    }
+
+    @Test
     public void testIsChecked_configIsSet_shouldReturnTrue() {
         // Set the setting to be enabled.
         mController.setChecked(true);
diff --git a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
index f3315e5..1b34fd3 100644
--- a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
+++ b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
@@ -116,6 +117,24 @@
     }
 
     @Test
+    public void testApnEditor_doesNotUseManagedQuery() {
+        mApnEditorUT.getApnDataFromUri(Mockito.mock(Uri.class));
+
+        verify(mActivity, never()).managedQuery(
+                any(Uri.class),
+                any(String[].class),
+                any(String.class),
+                any(String.class));
+
+        verify(mActivity, never()).managedQuery(
+                any(Uri.class),
+                any(String[].class),
+                any(String.class),
+                any(String[].class),
+                any(String.class));
+  }
+
+    @Test
     public void testSetStringValue_valueChanged_shouldSetValue() {
         // GIVEN an APN value which is different than the APN value in database
         final String apnKey = "apn";
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
index 0cdb2f4..0b6e4b5 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
@@ -18,17 +18,28 @@
 package com.android.settings.slices;
 
 import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.app.slice.Slice;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
+import android.database.ContentObserver;
 import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.provider.Settings;
+import android.provider.SettingsSlicesContract;
 import android.util.Pair;
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settings.search.FakeIndexProvider;
 import com.android.settings.search.SearchFeatureProvider;
 import com.android.settings.search.SearchFeatureProviderImpl;
@@ -36,6 +47,7 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.FakeSliderController;
 import com.android.settings.testutils.FakeToggleController;
+import com.android.settings.testutils.FakeUnavailablePreferenceController;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
 import org.junit.After;
@@ -65,7 +77,7 @@
 
     @Before
     public void setUp() {
-        mContext = RuntimeEnvironment.application;
+        mContext = spy(RuntimeEnvironment.application);
         mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
         mReceiver = new SliceBroadcastReceiver();
         SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext);
@@ -192,6 +204,77 @@
         mReceiver.onReceive(mContext, intent);
     }
 
+    @Test
+    public void toggleUpdate_unavailableUriNotified() {
+        // Monitor the ContentResolver
+        final ContentResolver resolver = spy(mContext.getContentResolver());
+        doReturn(resolver).when(mContext).getContentResolver();
+
+        // Disable Setting
+        Settings.Global.putInt(mContext.getContentResolver(),
+                FakeToggleController.AVAILABILITY_KEY,
+                BasePreferenceController.DISABLED_UNSUPPORTED);
+
+        // Insert Fake Toggle into Database
+        final String key = "key";
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        insertSpecialCase(FakeToggleController.class, key);
+
+        // Turn on toggle setting
+        final FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
+        fakeToggleController.setChecked(true);
+
+        // Build Action
+        final Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
+        intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+        // Trigger Slice change
+        mReceiver.onReceive(mContext, intent);
+
+        // Check the value is the same and the Uri has been notified.
+        assertThat(fakeToggleController.isChecked()).isTrue();
+        final Uri expectedUri = SliceBuilderUtils.getUri(
+                SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+        verify(resolver).notifyChange(eq(expectedUri), eq(null));
+    }
+
+    @Test
+    public void sliderUpdate_unavailableUriNotified() {
+        // Monitor the ContentResolver
+        final ContentResolver resolver = spy(mContext.getContentResolver());
+        doReturn(resolver).when(mContext).getContentResolver();
+
+        // Disable Setting
+        Settings.Global.putInt(mContext.getContentResolver(),
+                FakeSliderController.AVAILABILITY_KEY,
+                BasePreferenceController.DISABLED_UNSUPPORTED);
+
+        // Insert Fake Slider into Database
+        final String key = "key";
+        final int position = FakeSliderController.MAX_STEPS - 1;
+        final int oldPosition = FakeSliderController.MAX_STEPS;
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        insertSpecialCase(FakeSliderController.class, key);
+
+        // Set slider setting
+        final FakeSliderController fakeSliderController = new FakeSliderController(mContext, key);
+        fakeSliderController.setSliderPosition(oldPosition);
+
+        // Build action
+        final Intent intent = new Intent(SettingsSliceProvider.ACTION_SLIDER_CHANGED);
+        intent.putExtra(Slice.EXTRA_RANGE_VALUE, position);
+        intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+        // Trigger Slice change
+        mReceiver.onReceive(mContext, intent);
+
+        // Check position is the same and the Uri has been notified.
+        assertThat(fakeSliderController.getSliderPosition()).isEqualTo(oldPosition);
+        final Uri expectedUri = SliceBuilderUtils.getUri(
+                SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+        verify(resolver).notifyChange(eq(expectedUri), eq(null));
+    }
+
     private void insertSpecialCase(String key) {
         insertSpecialCase(fakeControllerName, key);
     }
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index a2a9e8f..8b99c4a 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -24,7 +24,6 @@
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
-import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +39,7 @@
 import com.android.settings.testutils.FakeFeatureFactory;
 import com.android.settings.testutils.FakeSliderController;
 import com.android.settings.testutils.FakeToggleController;
+import com.android.settings.testutils.FakeUnavailablePreferenceController;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 import com.android.settings.testutils.SliceTester;
 
@@ -326,7 +326,7 @@
     public void testUnsupportedSlice_validTitleSummary() {
         final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
                 SliceData.SliceType.SWITCH);
-        Settings.System.putInt(mContext.getContentResolver(),
+        Settings.Global.putInt(mContext.getContentResolver(),
                 FakeUnavailablePreferenceController.AVAILABILITY_KEY,
                 BasePreferenceController.DISABLED_UNSUPPORTED);
 
@@ -339,7 +339,7 @@
     public void testDisabledForUserSlice_validTitleSummary() {
         final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
                 SliceData.SliceType.SWITCH);
-        Settings.System.putInt(mContext.getContentResolver(),
+        Settings.Global.putInt(mContext.getContentResolver(),
                 FakeUnavailablePreferenceController.AVAILABILITY_KEY,
                 BasePreferenceController.DISABLED_FOR_USER);
 
@@ -352,7 +352,7 @@
     public void testDisabledDependentSettingSlice_validTitleSummary() {
         final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
                 SliceData.SliceType.INTENT);
-        Settings.System.putInt(mContext.getContentResolver(),
+        Settings.Global.putInt(mContext.getContentResolver(),
                 FakeUnavailablePreferenceController.AVAILABILITY_KEY,
                 BasePreferenceController.DISABLED_DEPENDENT_SETTING);
 
@@ -374,7 +374,7 @@
     public void testUnavailableUnknownSlice_validTitleSummary() {
         final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
                 SliceData.SliceType.SWITCH);
-        Settings.System.putInt(mContext.getContentResolver(),
+        Settings.Global.putInt(mContext.getContentResolver(),
                 FakeUnavailablePreferenceController.AVAILABILITY_KEY,
                 BasePreferenceController.UNAVAILABLE_UNKNOWN);
 
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java b/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java
index f4f91ed..530bdee 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java
@@ -19,13 +19,14 @@
 import android.content.Context;
 import android.provider.Settings;
 
-import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.SliderPreferenceController;
 
 public class FakeSliderController extends SliderPreferenceController {
 
     private final String settingKey = "fake_slider_key";
 
+    public static final String AVAILABILITY_KEY = "fake_slider_availability_key";
+
     public static final int MAX_STEPS = 9;
 
     public FakeSliderController(Context context, String key) {
@@ -49,6 +50,7 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return BasePreferenceController.AVAILABLE;
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                AVAILABILITY_KEY, AVAILABLE);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java b/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
index c984c6c..d0ce76f 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
@@ -26,6 +26,8 @@
 
     private String settingKey = "toggle_key";
 
+    public static final String AVAILABILITY_KEY = "fake_toggle_availability_key";
+
     private final int ON = 1;
     private final int OFF = 0;
 
@@ -47,6 +49,7 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return AVAILABLE;
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                AVAILABILITY_KEY, AVAILABLE);
     }
 }
diff --git a/tests/robotests/src/com/android/settings/slices/FakeUnavailablePreferenceController.java b/tests/robotests/src/com/android/settings/testutils/FakeUnavailablePreferenceController.java
similarity index 82%
rename from tests/robotests/src/com/android/settings/slices/FakeUnavailablePreferenceController.java
rename to tests/robotests/src/com/android/settings/testutils/FakeUnavailablePreferenceController.java
index a7e5d75..1ceaad8 100644
--- a/tests/robotests/src/com/android/settings/slices/FakeUnavailablePreferenceController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeUnavailablePreferenceController.java
@@ -1,4 +1,4 @@
-package com.android.settings.slices;
+package com.android.settings.testutils;
 
 import android.content.Context;
 import android.provider.Settings;
@@ -15,7 +15,7 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return Settings.System.getInt(mContext.getContentResolver(),
+        return Settings.Global.getInt(mContext.getContentResolver(),
                 AVAILABILITY_KEY, 0);
     }
 }