Merge "Add keywords for wifi slice"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index b708471..92a1066 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2622,6 +2622,8 @@
             android:name=".wifi.NetworkRequestDialogActivity"
             android:theme="@style/Transparent"
             android:excludeFromRecents="true"
+            android:launchMode="singleTop"
+            android:taskAffinity=".wifi.NetworkRequestDialogActivity"
             android:exported="true"
             android:permission="android.permission.NETWORK_SETTINGS">
             <intent-filter>
@@ -2971,6 +2973,17 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name=".development.qstile.DevelopmentTiles$SensorsOff"
+            android:label="@string/sensors_off_quick_settings_title"
+            android:icon="@drawable/tile_icon_sensors_off"
+            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
+            android:enabled="false">
+            <intent-filter>
+                <action android:name="android.service.quicksettings.action.QS_TILE" />
+            </intent-filter>
+        </service>
+
         <activity
             android:name=".HelpTrampoline"
             android:exported="true"
diff --git a/res/drawable/tile_icon_sensors_off.xml b/res/drawable/tile_icon_sensors_off.xml
new file mode 100644
index 0000000..890fa83
--- /dev/null
+++ b/res/drawable/tile_icon_sensors_off.xml
@@ -0,0 +1,39 @@
+<!--
+     Copyright (C) 2019 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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:pathData="M21.966,2 L2,22"
+        android:strokeLineCap="round"
+        android:strokeColor="#000000"
+        android:fillColor="#00000000"
+        android:strokeWidth="1.6521436"
+        android:strokeLineJoin="miter"
+        android:strokeAlpha="1"/>
+    <path
+        android:pathData="M0.752,12L4.496,12l2.496,-6.25 2.496,12.5 2.496,-15 2.496,12.5 2.496,-7.5 1.248,3.75h4.992"
+        android:strokeLineCap="round"
+        android:strokeColor="#000000"
+        android:fillColor="#00000000"
+        android:strokeWidth="1.25090861"
+        android:strokeLineJoin="round"
+        android:strokeAlpha="1"/>
+</vector>
+
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
index 3a0e659..c408a97 100644
--- a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -60,10 +60,10 @@
                 android:id="@+id/error_message"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
                 android:textAlignment="center"
-                android:layout_marginTop="8dp"
-                android:visibility="invisible"
-                android:textColor="?android:attr/colorError"/>
+                android:textColor="?android:attr/colorError"
+                android:visibility="invisible"/>
 
         </LinearLayout>
 
diff --git a/res/layout/manage_applications_apps.xml b/res/layout/manage_applications_apps.xml
index 87db820..9c90f02 100644
--- a/res/layout/manage_applications_apps.xml
+++ b/res/layout/manage_applications_apps.xml
@@ -26,41 +26,34 @@
         android:layout_height="match_parent"
         settings:layout_behavior="com.android.settings.widget.FloatingAppBarScrollingViewBehavior">
 
-        <LinearLayout
+        <FrameLayout
             android:id="@+id/list_container"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:orientation="vertical"
             android:visibility="gone">
 
-            <FrameLayout
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/apps_list"
                 android:layout_width="match_parent"
-                android:layout_height="match_parent">
+                android:layout_height="match_parent"
+                android:clipToPadding="false"
+                settings:fastScrollEnabled="true"
+                settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
+                settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
+                settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
+                settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
 
-                <androidx.recyclerview.widget.RecyclerView
-                    android:id="@+id/apps_list"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:clipToPadding="false"
-                    settings:fastScrollEnabled="true"
-                    settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
-                    settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
-                    settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
-                    settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
+            <TextView
+                android:id="@android:id/empty"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:gravity="center"
+                android:layout_gravity="center"
+                android:text="@string/no_applications"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:visibility="invisible"/>
 
-                <TextView
-                    android:id="@android:id/empty"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:gravity="center"
-                    android:layout_gravity="center"
-                    android:text="@string/no_applications"
-                    android:textAppearance="?android:attr/textAppearanceLarge"
-                    android:visibility="invisible"/>
-
-            </FrameLayout>
-
-        </LinearLayout>
+        </FrameLayout>
 
         <include layout="@layout/loading_container"/>
 
diff --git a/res/layout/settings_homepage.xml b/res/layout/settings_homepage.xml
index e04b372..6e2b302 100644
--- a/res/layout/settings_homepage.xml
+++ b/res/layout/settings_homepage.xml
@@ -21,7 +21,7 @@
     android:layout_height="wrap_content"
     android:orientation="vertical">
 
-    <androidx.recyclerview.widget.RecyclerView
+    <com.android.settings.homepage.contextualcards.FocusRecyclerView
         android:id="@+id/card_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/res/layout/wifi_dpp_qrcode_generator_fragment.xml b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
index 2617aea..31bf7cc 100644
--- a/res/layout/wifi_dpp_qrcode_generator_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_generator_fragment.xml
@@ -40,6 +40,14 @@
                 android:layout_height="@dimen/qrcode_size"
                 android:src="@android:color/transparent"/>
 
+            <TextView
+                android:id="@+id/password"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
+                android:textAlignment="center"
+                android:textAppearance="@android:style/TextAppearance.Material.Body1"
+                android:textColor="?android:attr/textColorSecondary"/>
         </LinearLayout>
 
     </ScrollView>
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 4fa8e8b..9bd742a 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -60,10 +60,10 @@
                 android:id="@+id/error_message"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
+                android:layout_marginTop="16dp"
                 android:textAlignment="center"
-                android:layout_marginTop="8dp"
-                android:visibility="invisible"
-                android:textColor="?android:attr/colorError"/>
+                android:textColor="?android:attr/colorError"
+                android:visibility="invisible"/>
 
         </LinearLayout>
 
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 088be5c..0986634 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2129,7 +2129,9 @@
     <!-- Title for the fragment to share Wi-Fi [CHAR LIMIT=50]  -->
     <string name="wifi_dpp_share_wifi">Share Wi\u2011Fi</string>
     <!-- Hint for the user to use another device to scan QR code on screen to join Wi-Fi [CHAR LIMIT=NONE] -->
-    <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code with another device to join \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+    <string name="wifi_dpp_scan_qr_code_with_another_device">Scan this QR code to connect to \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d and share the password</string>
+    <!-- Hint for the user to use another device to scan QR code on screen to join a open Wi-Fi [CHAR LIMIT=NONE] -->
+    <string name="wifi_dpp_scan_open_network_qr_code_with_another_device">Scan this QR code to connect to \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
     <!-- Hint for QR code detection [CHAR LIMIT=NONE]  -->
     <string name="wifi_dpp_could_not_detect_valid_qr_code">Couldn\u2019t read QR code. Re-center code and try again</string>
     <!-- Hint for Wi-Fi DPP handshake failure [CHAR LIMIT=NONE]  -->
@@ -2166,8 +2168,16 @@
     <string name="wifi_dpp_connecting">Connecting\u2026</string>
     <!-- Title for the fragment to show that the QR code is for sharing Wi-Fi hotspot network [CHAR LIMIT=50] -->
     <string name="wifi_dpp_share_hotspot">Share hotspot</string>
-    <!-- Hint for the user to share Wi-Fi hotspot network [CHAR LIMIT=NONE] -->
-    <string name="wifi_dpp_scan_qr_code_to_share_hotspot">Scan this QR code with another device to join hotspot \u201c<xliff:g id="ssid" example="OfficeWifi">%1$s</xliff:g>\u201d</string>
+    <!-- Title for Wi-Fi DPP lockscreen title [CHAR LIMIT=50] -->
+    <string name="wifi_dpp_lockscreen_title">Verify it\u0027s you</string>
+    <!-- Hint for Wi-Fi password [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_wifi_password">Wi\u2011Fi password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
+    <!-- Hint for Wi-Fi hotspot password [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_hotspot_password">Hotspot password: <xliff:g id="password" example="my password">%1$s</xliff:g></string>
+    <!-- Label for "Connect to this network using a QR code" [CHAR LIMIT=50]  -->
+    <string name="wifi_dpp_add_device">Add device</string>
+    <!-- Hint for "Add device" [CHAR LIMIT=NONE]  -->
+    <string name="wifi_dpp_connect_network_using_qr_code">Connect to this network using a QR code</string>
      <!-- Label for the try again button [CHAR LIMIT=20]-->
     <string name="retry">Retry</string>
     <!-- Label for the check box to share a network with other users on the same device -->
@@ -3945,8 +3955,6 @@
     <string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
     <!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
     <string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
-    <!-- Message on Wi-Fi Sharing screen [CHAR LIMIT=NONE] -->
-    <string name="wifi_sharing_message">Your Wi\u2011Fi name and password for \"<xliff:g id="SSID" example="GoogleGuest">%1$s</xliff:g>\" will be shared.</string>
 
     <!-- Message to be used to explain the user that he needs to enter his pattern to continue a
          particular operation. [CHAR LIMIT=70]-->
@@ -5268,11 +5276,13 @@
     <!-- Summary for the battery high usage tip, which presents battery may run out earlier [CHAR LIMIT=NONE] -->
     <string name="battery_tip_high_usage_summary">Battery may run out earlier than usual</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dialog_message" product="default">Your phone has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+    <string name="battery_tip_dialog_message" product="default">Your phone has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dialog_message" product="tablet">Your tablet has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+    <string name="battery_tip_dialog_message" product="tablet">Your tablet has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
     <!-- Message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
-    <string name="battery_tip_dialog_message" product="device">Your device has been used more than usual. Your battery may run out sooner than expected.\n\nTop <xliff:g id="number">%1$d</xliff:g> apps you used since full charge:</string>
+    <string name="battery_tip_dialog_message" product="device">Your device has been used more than usual. Your battery may run out sooner than expected.\n\nMost used apps since full charge:</string>
+    <!-- Footer message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
+    <string name="battery_tip_dialog_message_footer">Includes high-power background activity</string>
     <!-- Title for restricted app preference, showing how many app need to be restricted [CHAR LIMIT=NONE] -->
     <plurals name="battery_tip_restrict_title">
         <item quantity="one">Restrict %1$d app</item>
@@ -9801,6 +9811,9 @@
     <!-- [CHAR LIMIT=25] Title of developer tile to toggle winscope trace -->
     <string name="winscope_trace_quick_settings_title">Winscope Trace</string>
 
+    <!-- [CHAR LIMIT=25] Title of developer tile to toggle sensors -->
+    <string name="sensors_off_quick_settings_title">Sensors Off</string>
+
     <!-- [CHAR LIMIT=60] Title of work profile setting page -->
     <string name="managed_profile_settings_title">Work profile settings</string>
     <!-- [CHAR LIMIT=60] The preference title for enabling cross-profile remote contact search -->
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 097ffe2..81b70b5 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -140,7 +140,7 @@
         if (!mHasPassword) {
             // No password registered, launch into enrollment wizard.
             launchChooseLock();
-        } else {
+        } else if (!mLaunchedConfirmLock || mToken == null) {
             launchConfirmLock(getConfirmLockTitleResId(), getChallenge());
         }
     }
diff --git a/src/com/android/settings/development/qstile/DevelopmentTiles.java b/src/com/android/settings/development/qstile/DevelopmentTiles.java
index 5edbc70..bb791ab 100644
--- a/src/com/android/settings/development/qstile/DevelopmentTiles.java
+++ b/src/com/android/settings/development/qstile/DevelopmentTiles.java
@@ -16,9 +16,12 @@
 
 package com.android.settings.development.qstile;
 
+import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.hardware.SensorPrivacyManager;
+import android.app.KeyguardManager;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.RemoteException;
@@ -38,6 +41,8 @@
 
 import com.android.internal.app.LocalePicker;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.development.SystemPropPoker;
 
@@ -273,4 +278,45 @@
             }
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * Tile to toggle sensors off to control camera, mic, and sensors managed by the SensorManager.
+     */
+    public static class SensorsOff extends DevelopmentTiles {
+        private Context mContext;
+        private SensorPrivacyManager mSensorPrivacyManager;
+        private KeyguardManager mKeyguardManager;
+        private MetricsFeatureProvider mMetricsFeatureProvider;
+        private boolean mIsEnabled;
+
+        @Override
+        public void onCreate() {
+            super.onCreate();
+            mContext = getApplicationContext();
+            mSensorPrivacyManager = (SensorPrivacyManager) mContext.getSystemService(
+                    Context.SENSOR_PRIVACY_SERVICE);
+            mIsEnabled = mSensorPrivacyManager.isSensorPrivacyEnabled();
+            mMetricsFeatureProvider = FeatureFactory.getFactory(
+                    mContext).getMetricsFeatureProvider();
+            mKeyguardManager = (KeyguardManager) mContext.getSystemService(
+                    Context.KEYGUARD_SERVICE);
+        }
+
+        @Override
+        protected boolean isEnabled() {
+            return mIsEnabled;
+        }
+
+        @Override
+        public void setIsEnabled(boolean isEnabled) {
+            // Don't allow sensors to be reenabled from the lock screen.
+            if (mIsEnabled && mKeyguardManager.isKeyguardLocked()) {
+                return;
+            }
+            mMetricsFeatureProvider.action(getApplicationContext(), SettingsEnums.QS_SENSOR_PRIVACY,
+                    isEnabled);
+            mIsEnabled = isEnabled;
+            mSensorPrivacyManager.setSensorPrivacy(isEnabled);
+        }
+    }
+}
diff --git a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java b/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
deleted file mode 100644
index e9d03d7..0000000
--- a/src/com/android/settings/gestures/WakeScreenGesturePreferenceController.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.gestures;
-
-import static android.provider.Settings.Secure.DOZE_WAKE_SCREEN_GESTURE;
-
-import android.annotation.UserIdInt;
-import android.content.Context;
-import android.hardware.display.AmbientDisplayConfiguration;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.settings.aware.AwareFeatureProvider;
-import com.android.settings.overlay.FeatureFactory;
-
-public class WakeScreenGesturePreferenceController extends GesturePreferenceController {
-
-    private static final int ON = 1;
-    private static final int OFF = 0;
-
-    private static final String PREF_KEY_VIDEO = "gesture_wake_screen_video";
-
-    private final AwareFeatureProvider mFeatureProvider;
-    private AmbientDisplayConfiguration mAmbientConfig;
-    @UserIdInt
-    private final int mUserId;
-
-    public WakeScreenGesturePreferenceController(Context context, String key) {
-        super(context, key);
-        mUserId = UserHandle.myUserId();
-        mFeatureProvider = FeatureFactory.getFactory(context).getAwareFeatureProvider();
-    }
-
-    @Override
-    public int getAvailabilityStatus() {
-        if (!getAmbientConfig().wakeScreenGestureAvailable()
-                || !mFeatureProvider.isSupported(mContext)) {
-            return UNSUPPORTED_ON_DEVICE;
-        }
-
-        if (!mFeatureProvider.isEnabled(mContext)) {
-            return CONDITIONALLY_UNAVAILABLE;
-        }
-
-        return getAmbientConfig().alwaysOnEnabled(mUserId)
-                ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
-    }
-
-    @Override
-    protected boolean canHandleClicks() {
-        return getAmbientConfig().alwaysOnEnabled(mUserId);
-    }
-
-    @Override
-    public boolean isSliceable() {
-        return TextUtils.equals(getPreferenceKey(), "gesture_wake_screen");
-    }
-
-    @Override
-    protected String getVideoPrefKey() {
-        return PREF_KEY_VIDEO;
-    }
-
-    @Override
-    public boolean isChecked() {
-        return getAmbientConfig().wakeScreenGestureEnabled(mUserId);
-    }
-
-    @Override
-    public boolean setChecked(boolean isChecked) {
-        return Settings.Secure.putInt(mContext.getContentResolver(), DOZE_WAKE_SCREEN_GESTURE,
-                isChecked ? ON : OFF);
-    }
-
-    private AmbientDisplayConfiguration getAmbientConfig() {
-        if (mAmbientConfig == null) {
-            mAmbientConfig = new AmbientDisplayConfiguration(mContext);
-        }
-
-        return mAmbientConfig;
-    }
-
-    @VisibleForTesting
-    public void setConfig(AmbientDisplayConfiguration config) {
-        mAmbientConfig = config;
-    }
-}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 7df322d..92108f0 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -43,6 +43,8 @@
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -98,7 +100,6 @@
         mLifecycleObservers = new ArrayList<>();
         mControllerRendererPool = new ControllerRendererPool();
         mLifecycle.addObserver(this);
-
         if (savedInstanceState == null) {
             mIsFirstLaunch = true;
             mSavedCards = null;
@@ -240,6 +241,21 @@
         outState.putStringArrayList(KEY_CONTEXTUAL_CARDS, cards);
     }
 
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        // Duplicate a list to avoid java.util.ConcurrentModificationException.
+        final List<ContextualCard> cards = new ArrayList<>(mContextualCards);
+        for (ContextualCard card : cards) {
+            final ContextualCardController controller = mControllerRendererPool
+                    .getController(mContext, card.getCardType());
+            if (hasWindowFocus && controller instanceof OnStart) {
+                ((OnStart) controller).onStart();
+            }
+            if (!hasWindowFocus && controller instanceof OnStop) {
+                ((OnStop) controller).onStop();
+            }
+        }
+    }
+
     public ControllerRendererPool getControllerRendererPool() {
         return mControllerRendererPool;
     }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
index 72ddb50..bd25866 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsFragment.java
@@ -27,17 +27,17 @@
 
 import androidx.loader.app.LoaderManager;
 import androidx.recyclerview.widget.GridLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
 
 import com.android.settings.R;
 import com.android.settings.core.InstrumentedFragment;
 import com.android.settings.overlay.FeatureFactory;
 
-public class ContextualCardsFragment extends InstrumentedFragment {
+public class ContextualCardsFragment extends InstrumentedFragment implements
+        FocusRecyclerView.FocusListener {
 
     private static final String TAG = "ContextualCardsFragment";
 
-    private RecyclerView mCardsContainer;
+    private FocusRecyclerView mCardsContainer;
     private GridLayoutManager mLayoutManager;
     private ContextualCardsAdapter mContextualCardsAdapter;
     private ContextualCardManager mContextualCardManager;
@@ -72,11 +72,17 @@
                 this /* lifecycleOwner */, mContextualCardManager);
         mCardsContainer.setAdapter(mContextualCardsAdapter);
         mContextualCardManager.setListener(mContextualCardsAdapter);
+        mCardsContainer.setListener(this);
 
         return rootView;
     }
 
     @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        mContextualCardManager.onWindowFocusChanged(hasWindowFocus);
+    }
+
+    @Override
     public int getMetricsCategory() {
         return SettingsEnums.SETTINGS_HOMEPAGE;
     }
diff --git a/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java b/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java
new file mode 100644
index 0000000..a2ec9af
--- /dev/null
+++ b/src/com/android/settings/homepage/contextualcards/FocusRecyclerView.java
@@ -0,0 +1,36 @@
+package com.android.settings.homepage.contextualcards;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.RecyclerView;
+
+public class FocusRecyclerView extends RecyclerView {
+
+    private FocusListener mListener;
+
+    public FocusRecyclerView(Context context) {
+        super(context);
+    }
+
+    public FocusRecyclerView(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        super.onWindowFocusChanged(hasWindowFocus);
+        if (mListener != null) {
+            mListener.onWindowFocusChanged(hasWindowFocus);
+        }
+    }
+
+    public void setListener(FocusListener listener) {
+        mListener = listener;
+    }
+
+    public interface FocusListener {
+        void onWindowFocusChanged(boolean hasWindowFocus);
+    }
+}
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index 28c6cb7..e9057e6 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -138,6 +138,10 @@
                 .setOnItemClickListener(
                         (parent, view, position, id) -> this.onClick(dialog, position));
 
+        // Don't dismiss dialog when touching outside. User report it is easy to touch outside.
+        // This causes dialog to close. Which is concerned as a bad UX (b/128877712).
+        dialog.setCanceledOnTouchOutside(false);
+
         dialog.setOnShowListener((dialogInterface) -> {
             // Replace NeutralButton onClickListener to avoid closing dialog
             final Button neutralBtn = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index f328dba..cf59dbd 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -771,14 +771,7 @@
      * Share the wifi network with QR code.
      */
     private void shareNetwork() {
-        final String title = mContext.getString(
-                R.string.lockpassword_confirm_your_pattern_header);
-        final String description = String.format(
-                mContext.getString(R.string.wifi_sharing_message),
-                mAccessPoint.getSsidStr());
-
-        WifiDppUtils.showLockScreen(mContext, title, description,
-                () -> launchWifiDppConfiguratorActivity());
+        WifiDppUtils.showLockScreen(mContext, () -> launchWifiDppConfiguratorActivity());
     }
 
     /**
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
index 2cd5e23..4e6a0d6 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeGeneratorFragment.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -29,6 +30,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ImageView;
+import android.widget.TextView;
 
 import com.android.settings.R;
 import com.android.settings.wifi.qrcode.QrCodeGenerator;
@@ -43,6 +45,7 @@
     private static final String TAG = "WifiDppQrCodeGeneratorFragment";
 
     private ImageView mQrCodeView;
+    private TextView mPasswordView;
     private String mQrCode;
 
     @Override
@@ -138,12 +141,27 @@
         final WifiNetworkConfig wifiNetworkConfig = getWifiNetworkConfigFromHostActivity();
         if (wifiNetworkConfig.isHotspot()) {
             mTitle.setText(R.string.wifi_dpp_share_hotspot);
-            mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_to_share_hotspot,
-                    wifiNetworkConfig.getSsid()));
         } else {
             mTitle.setText(R.string.wifi_dpp_share_wifi);
+        }
+
+        final String password = wifiNetworkConfig.getPreSharedKey();
+        mPasswordView = view.findViewById(R.id.password);
+        if (TextUtils.isEmpty(password)) {
+            mSummary.setText(getString(
+                    R.string.wifi_dpp_scan_open_network_qr_code_with_another_device,
+                    wifiNetworkConfig.getSsid()));
+
+            mPasswordView.setVisibility(View.GONE);
+        } else {
             mSummary.setText(getString(R.string.wifi_dpp_scan_qr_code_with_another_device,
                     wifiNetworkConfig.getSsid()));
+
+            if (wifiNetworkConfig.isHotspot()) {
+               mPasswordView.setText(getString(R.string.wifi_dpp_hotspot_password, password));
+            } else {
+                mPasswordView.setText(getString(R.string.wifi_dpp_wifi_password, password));
+            }
         }
 
         mQrCode = wifiNetworkConfig.getQrCode();
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index fe7af27..bf78b3f 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -29,6 +29,8 @@
 import android.text.TextUtils;
 import android.util.FeatureFlagUtils;
 
+import com.android.settings.R;
+
 import com.android.settingslib.wifi.AccessPoint;
 
 import java.util.List;
@@ -273,13 +275,10 @@
      * user of the device.
      *
      * @param context The {@code Context} used to get {@code KeyguardManager} service
-     * @param title The title on lock screen
-     * @param description The description on lock screen
      * @param successRunnable The {@code Runnable} which will be executed if the user does not setup
      *                        device security or if lock screen is unlocked
      */
-    public static void showLockScreen(Context context, String title, String description,
-            Runnable successRunnable) {
+    public static void showLockScreen(Context context, Runnable successRunnable) {
         final KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(
                 Context.KEYGUARD_SERVICE);
 
@@ -299,8 +298,7 @@
             };
 
             final BiometricPrompt.Builder builder = new BiometricPrompt.Builder(context)
-                    .setTitle(title)
-                    .setDescription(description);
+                    .setTitle(context.getText(R.string.wifi_dpp_lockscreen_title));
 
             if (keyguardManager.isDeviceSecure()) {
                 builder.setDeviceCredentialAllowed(true);
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
index 10f3e56..b7ddcae 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSSIDPreferenceController.java
@@ -104,13 +104,7 @@
     }
 
     private void shareHotspotNetwork(Intent intent) {
-        final String title = mContext.getString(
-                R.string.lockpassword_confirm_your_pattern_header);
-        final String description = String.format(
-                mContext.getString(R.string.wifi_sharing_message), mSSID);
-
-        WifiDppUtils.showLockScreen(mContext, title, description,
-                () -> mContext.startActivity(intent));
+        WifiDppUtils.showLockScreen(mContext, () -> mContext.startActivity(intent));
     }
 
     @VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java
deleted file mode 100644
index 471914a..0000000
--- a/tests/robotests/src/com/android/settings/gestures/WakeScreenGesturePreferenceControllerTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.gestures;
-
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
-import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.hardware.display.AmbientDisplayConfiguration;
-
-import com.android.settings.aware.AwareFeatureProvider;
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-
-@RunWith(RobolectricTestRunner.class)
-public class WakeScreenGesturePreferenceControllerTest {
-
-    private static final String KEY_WAKE_SCREEN = "gesture_wake_screen";
-
-    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
-    private Context mContext;
-    @Mock
-    private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
-    private WakeScreenGesturePreferenceController mController;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        AwareFeatureProvider featureProvider =
-                FakeFeatureFactory.setupForTest().getAwareFeatureProvider();
-        when(featureProvider.isSupported(any())).thenReturn(true);
-        when(featureProvider.isEnabled(any())).thenReturn(true);
-        mController = new WakeScreenGesturePreferenceController(mContext, KEY_WAKE_SCREEN);
-        mController.setConfig(mAmbientDisplayConfiguration);
-    }
-
-    @Test
-    public void testIsChecked_configIsSet_shouldReturnTrue() {
-        // Set the setting to be enabled.
-        when(mAmbientDisplayConfiguration.wakeScreenGestureEnabled(anyInt())).thenReturn(true);
-        assertThat(mController.isChecked()).isTrue();
-    }
-
-    @Test
-    public void testIsChecked_configIsNotSet_shouldReturnFalse() {
-        // Set the setting to be disabled.
-        when(mAmbientDisplayConfiguration.wakeScreenGestureEnabled(anyInt())).thenReturn(false);
-        assertThat(mController.isChecked()).isFalse();
-    }
-
-    @Test
-    public void getAvailabilityStatus_gestureNotSupported_UNSUPPORTED_ON_DEVICE() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
-        when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(false);
-        final int availabilityStatus = mController.getAvailabilityStatus();
-
-        assertThat(availabilityStatus).isEqualTo(UNSUPPORTED_ON_DEVICE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_gestureSupported_AVAILABLE() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
-        when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(true);
-        final int availabilityStatus = mController.getAvailabilityStatus();
-
-        assertThat(availabilityStatus).isEqualTo(AVAILABLE);
-    }
-
-    @Test
-    public void getAvailabilityStatus_gestureSupported_DISABLED_DEPENDENT_SETTING() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
-        when(mAmbientDisplayConfiguration.wakeScreenGestureAvailable()).thenReturn(true);
-        final int availabilityStatus = mController.getAvailabilityStatus();
-
-        assertThat(availabilityStatus).isEqualTo(DISABLED_DEPENDENT_SETTING);
-    }
-
-    @Test
-    public void canHandleClicks_onlyWhenAlwaysOn() {
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
-        assertThat(mController.canHandleClicks()).isEqualTo(false);
-
-        reset(mAmbientDisplayConfiguration);
-        when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
-        assertThat(mController.canHandleClicks()).isEqualTo(true);
-    }
-
-    @Test
-    public void isSliceableCorrectKey_returnsTrue() {
-        final WakeScreenGesturePreferenceController controller =
-                new WakeScreenGesturePreferenceController(mContext, "gesture_wake_screen");
-        assertThat(controller.isSliceable()).isTrue();
-    }
-
-    @Test
-    public void isSliceableIncorrectKey_returnsFalse() {
-        final WakeScreenGesturePreferenceController controller =
-                new WakeScreenGesturePreferenceController(mContext, "bad_key");
-        assertThat(controller.isSliceable()).isFalse();
-    }
-}