Merge "Import translations. DO NOT MERGE"
diff --git a/res/drawable/ic_settings_close.xml b/res/drawable/ic_settings_close.xml
index 058b4b5..141a2c3 100644
--- a/res/drawable/ic_settings_close.xml
+++ b/res/drawable/ic_settings_close.xml
@@ -18,7 +18,8 @@
     android:width="24dp"
     android:height="24dp"
     android:viewportWidth="24"
-    android:viewportHeight="24">
+    android:viewportHeight="24"
+    android:tint="?android:attr/colorControlNormal">
   <path
       android:fillColor="#FF000000"
       android:pathData="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41z"/>
diff --git a/res/drawable/signal_strength_5g.xml b/res/drawable/signal_strength_5g.xml
new file mode 100644
index 0000000..fdaea7e
--- /dev/null
+++ b/res/drawable/signal_strength_5g.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  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.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="9.208dp"
+    android:height="17dp"
+    android:viewportWidth="14.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M13.9,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07s-0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13s1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.23,0.79s0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45s-0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7S8.72,6.37 8.71,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M1.15,8.47l0.43,-4.96h4.33v1.17H2.6L2.37,7.39C2.78,7.1 3.22,6.96 3.69,6.96c0.77,0 1.38,0.3 1.83,0.9s0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43S4.32,13.6 3.48,13.6c-0.75,0 -1.36,-0.24 -1.83,-0.73s-0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59S3.88,8.09 3.4,8.09c-0.4,0 -0.72,0.1 -0.96,0.31L2.11,8.73L1.15,8.47z"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/accessibility_shortcut_secondary_action.xml b/res/layout/accessibility_shortcut_secondary_action.xml
index b46c303..caf9b1c 100644
--- a/res/layout/accessibility_shortcut_secondary_action.xml
+++ b/res/layout/accessibility_shortcut_secondary_action.xml
@@ -87,6 +87,7 @@
     </LinearLayout>
 
     <View
+        android:id="@+id/divider"
         android:layout_width="1dp"
         android:layout_height="match_parent"
         android:layout_marginTop="16dp"
diff --git a/res/xml/wifi_settings.xml b/res/xml/wifi_settings.xml
index 5fac85a..a7f5a20 100644
--- a/res/xml/wifi_settings.xml
+++ b/res/xml/wifi_settings.xml
@@ -34,7 +34,7 @@
         settings:searchable="false"/>
 
     <Preference
-        android:key="configure_settings"
+        android:key="configure_wifi_settings"
         android:title="@string/wifi_configure_settings_preference_title"
         settings:allowDividerAbove="true"
         android:fragment="com.android.settings.wifi.ConfigureWifiSettings"/>
diff --git a/res/xml/wifi_settings2.xml b/res/xml/wifi_settings2.xml
index 8cd3857..2bf39dbe 100644
--- a/res/xml/wifi_settings2.xml
+++ b/res/xml/wifi_settings2.xml
@@ -32,7 +32,7 @@
         android:layout="@layout/preference_category_no_label"/>
 
     <Preference
-        android:key="configure_settings"
+        android:key="configure_wifi_settings"
         android:title="@string/wifi_configure_settings_preference_title"
         settings:allowDividerAbove="true"
         android:fragment="com.android.settings.wifi.ConfigureWifiSettings"/>
diff --git a/src/com/android/settings/AirplaneModeEnabler.java b/src/com/android/settings/AirplaneModeEnabler.java
index f1d36f2..a843a04 100644
--- a/src/com/android/settings/AirplaneModeEnabler.java
+++ b/src/com/android/settings/AirplaneModeEnabler.java
@@ -26,6 +26,8 @@
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settings.network.GlobalSettingsChangeListener;
 import com.android.settings.network.ProxySubscriptionManager;
 import com.android.settings.overlay.FeatureFactory;
@@ -57,8 +59,8 @@
     }
 
     private TelephonyManager mTelephonyManager;
-    private ProxySubscriptionManager mProxySubscriptionMgr;
-    private PhoneStateListener mPhoneStateListener;
+    @VisibleForTesting
+    PhoneStateListener mPhoneStateListener;
 
     private GlobalSettingsChangeListener mAirplaneModeObserver;
 
@@ -70,7 +72,6 @@
         mOnAirplaneModeChangedListener = listener;
 
         mTelephonyManager = context.getSystemService(TelephonyManager.class);
-        mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(context);
 
         mPhoneStateListener = new PhoneStateListener() {
             @Override
@@ -143,7 +144,7 @@
             return true;
         }
         final List<SubscriptionInfo> subInfoList =
-                mProxySubscriptionMgr.getActiveSubscriptionsInfo();
+                ProxySubscriptionManager.getInstance(mContext).getActiveSubscriptionsInfo();
         if (subInfoList == null) {
             return false;
         }
diff --git a/src/com/android/settings/accessibility/ShortcutPreference.java b/src/com/android/settings/accessibility/ShortcutPreference.java
index f76bb01..b66a2b6 100644
--- a/src/com/android/settings/accessibility/ShortcutPreference.java
+++ b/src/com/android/settings/accessibility/ShortcutPreference.java
@@ -73,9 +73,11 @@
         }
 
         final View settings = holder.itemView.findViewById(android.R.id.widget_frame);
-        if (settings != null) {
+        final View divider = holder.itemView.findViewById(R.id.divider);
+        if (settings != null && divider != null) {
             settings.setOnClickListener(view -> callOnSettingsClicked());
             settings.setVisibility(mSettingsVisibility);
+            divider.setVisibility(mSettingsVisibility);
         }
     }
 
diff --git a/src/com/android/settings/applications/RecentAppsPreferenceController.java b/src/com/android/settings/applications/RecentAppsPreferenceController.java
index 4f5ec01..7e02065 100644
--- a/src/com/android/settings/applications/RecentAppsPreferenceController.java
+++ b/src/com/android/settings/applications/RecentAppsPreferenceController.java
@@ -23,7 +23,6 @@
 import android.icu.text.RelativeDateTimeFormatter;
 import android.os.UserHandle;
 import android.util.IconDrawableFactory;
-import android.util.Log;
 import android.view.View;
 
 import androidx.annotation.NonNull;
@@ -37,7 +36,9 @@
 import com.android.settings.applications.manageapplications.ManageApplications;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.utils.StringUtil;
 import com.android.settingslib.widget.AppEntitiesHeaderController;
 import com.android.settingslib.widget.AppEntityInfo;
@@ -65,6 +66,7 @@
     private final ApplicationsState mApplicationsState;
     private final int mUserId;
     private final IconDrawableFactory mIconDrawableFactory;
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
 
     private Fragment mHost;
     private List<UsageStats> mRecentApps;
@@ -75,6 +77,7 @@
                 (Application) mContext.getApplicationContext());
         mUserId = UserHandle.myUserId();
         mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
+        mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
     }
 
     public void setFragment(Fragment fragment) {
@@ -96,6 +99,8 @@
         mAppEntitiesController = AppEntitiesHeaderController.newInstance(mContext, view)
                 .setHeaderTitleRes(R.string.recent_app_category_title)
                 .setHeaderDetailsClickListener((View v) -> {
+                    mMetricsFeatureProvider.logClickedPreference(mRecentAppsPreference,
+                            SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY);
                     new SubSettingLauncher(mContext)
                             .setDestination(ManageApplications.class.getName())
                             .setArguments(null /* arguments */)
@@ -161,11 +166,14 @@
                 .setSummary(StringUtil.formatRelativeTime(mContext,
                         System.currentTimeMillis() - stat.getLastTimeUsed(), false,
                         RelativeDateTimeFormatter.Style.SHORT))
-                .setOnClickListener(v ->
-                        AppInfoBase.startAppInfoFragment(AppInfoDashboardFragment.class,
-                                R.string.application_info_label, pkgName, appEntry.info.uid,
-                                mHost, 1001 /*RequestCode*/,
-                                SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY))
+                .setOnClickListener(v -> {
+                    mMetricsFeatureProvider.logClickedPreference(mRecentAppsPreference,
+                            SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY);
+                    AppInfoBase.startAppInfoFragment(AppInfoDashboardFragment.class,
+                            R.string.application_info_label, pkgName, appEntry.info.uid,
+                            mHost, 1001 /*RequestCode*/,
+                            SettingsEnums.SETTINGS_APP_NOTIF_CATEGORY);
+                })
                 .build();
     }
 }
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
index 73acc12..0f8849d 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java
@@ -46,6 +46,9 @@
 import androidx.preference.SwitchPreference;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.LifecycleObserver;
 import com.android.settingslib.core.lifecycle.events.OnStart;
 import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -71,6 +74,7 @@
     private final UserManager mUm;
     private final PackageManager mPackageManager;
     private final IPackageManager mIPackageManager;
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
     /**
      * Internal collection of device admin info objects for all profiles associated with the current
      * user.
@@ -102,6 +106,7 @@
         mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mPackageManager = mContext.getPackageManager();
         mIPackageManager = AppGlobals.getPackageManager();
+        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     }
 
     @Override
@@ -197,6 +202,8 @@
         pref.setSummary(item.getDescription());
         pref.setEnabled(item.isEnabled());
         pref.setOnPreferenceClickListener(preference -> {
+            mMetricsFeatureProvider.logClickedPreference(preference,
+                    pref.getExtras().getInt(DashboardFragment.CATEGORY));
             final UserHandle user = item.getUser();
             mContext.startActivityAsUser(item.getLaunchIntent(mContext), user);
             return true;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java
index c23aee6..308878f 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollBase.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java
@@ -36,6 +36,7 @@
 
 import com.google.android.setupcompat.template.FooterBarMixin;
 import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupcompat.util.WizardManagerHelper;
 import com.google.android.setupdesign.GlifLayout;
 
 /**
@@ -120,6 +121,19 @@
         initViews();
     }
 
+    @Override
+    protected void onStop() {
+        super.onStop();
+        if (!isChangingConfigurations() && shouldFinishWhenBackgrounded()) {
+            setResult(RESULT_TIMEOUT);
+            finish();
+        }
+    }
+
+    protected boolean shouldFinishWhenBackgrounded() {
+        return !WizardManagerHelper.isAnySetupWizard(getIntent());
+    }
+
     protected void initViews() {
         getWindow().setStatusBarColor(Color.TRANSPARENT);
     }
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index d94686e..d815f57 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -178,6 +178,11 @@
         }
     }
 
+    @Override
+    protected boolean shouldFinishWhenBackgrounded() {
+        return super.shouldFinishWhenBackgrounded() && !mConfirmingCredentials && !mNextClicked;
+    }
+
     private void updatePasswordQuality() {
         final int passwordQuality = new ChooseLockSettingsHelper(this).utils()
                 .getActivePasswordQuality(mUserManager.getCredentialOwnerProfile(mUserId));
@@ -243,7 +248,8 @@
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
-            if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP) {
+            if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP
+                    || resultCode == RESULT_TIMEOUT) {
                 setResult(resultCode, data);
                 finish();
                 return;
diff --git a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
index a246055..17a933b 100644
--- a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
@@ -23,6 +23,8 @@
 import com.android.settings.R;
 import com.android.settings.password.ChooseLockSettingsHelper;
 
+import com.google.android.setupcompat.util.WizardManagerHelper;
+
 /**
  * Abstract base activity which handles the actual enrolling for biometrics.
  */
@@ -58,7 +60,6 @@
 
     @Override
     protected void onStop() {
-        super.onStop();
         if (mSidecar != null) {
             mSidecar.setListener(null);
         }
@@ -69,6 +70,9 @@
                 getSupportFragmentManager()
                         .beginTransaction().remove(mSidecar).commitAllowingStateLoss();
             }
+            if (!WizardManagerHelper.isAnySetupWizard(getIntent())) {
+                setResult(RESULT_TIMEOUT);
+            }
             finish();
         }
     }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
index e1253c1..3b84c35 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -16,17 +16,13 @@
 
 package com.android.settings.biometrics.face;
 
-import static android.security.KeyStore.getApplicationContext;
-
 import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
 import android.hardware.face.FaceManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.accessibility.AccessibilityManager;
@@ -173,14 +169,8 @@
     }
 
     @Override
-    protected void onStop() {
-        super.onStop();
-
-        if (!isChangingConfigurations() && !WizardManagerHelper.isAnySetupWizard(getIntent())
-                && !mNextClicked) {
-            setResult(RESULT_SKIP);
-            finish();
-        }
+    protected boolean shouldFinishWhenBackgrounded() {
+        return super.shouldFinishWhenBackgrounded() && !mNextClicked;
     }
 
     @Override
@@ -216,11 +206,13 @@
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        super.onActivityResult(requestCode, resultCode, data);
         mResultIntent = data;
         if (requestCode == BIOMETRIC_FIND_SENSOR_REQUEST) {
             // If the user finished or skipped enrollment, finish this activity
-            if (resultCode == RESULT_SKIP || resultCode == RESULT_FINISHED) {
-                setResult(resultCode);
+            if (resultCode == RESULT_FINISHED || resultCode == RESULT_SKIP
+                    || resultCode == RESULT_TIMEOUT) {
+                setResult(resultCode, data);
                 finish();
             }
         }
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index 073c7e6..6709a6a 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -100,16 +100,6 @@
     }
 
     @Override
-    protected void onStop() {
-        super.onStop();
-
-        if (!isChangingConfigurations() && !mConfirmingCredentials && !mNextClicked
-                && !WizardManagerHelper.isAnySetupWizard(getIntent())) {
-            finish();
-        }
-    }
-
-    @Override
     protected boolean isDisabledByAdmin() {
         return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
                 this, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId) != null;
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index 5795e65..e1ca4f7 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -19,7 +19,9 @@
 import static android.app.Activity.RESULT_OK;
 
 import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
+import static com.android.settings.biometrics.BiometricEnrollBase.ENROLL_REQUEST;
 import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
+import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;
 
 import android.app.settings.SettingsEnums;
 import android.content.Context;
@@ -90,6 +92,9 @@
         mEnrollButton.setVisible(true);
     };
 
+    private final FaceSettingsEnrollButtonPreferenceController.Listener mEnrollListener = intent ->
+            startActivityForResult(intent, ENROLL_REQUEST);
+
     public static boolean isAvailable(Context context) {
         FaceManager manager = Utils.getFaceManagerOrNull(context);
         return manager != null && manager.isHardwareDetected();
@@ -230,11 +235,16 @@
                     }
                 }
             }
+        } else if (requestCode == ENROLL_REQUEST) {
+            if (resultCode == RESULT_TIMEOUT) {
+                setResult(resultCode, data);
+                finish();
+            }
         }
 
         if (mToken == null) {
             // Didn't get an authentication, finishing
-            getActivity().finish();
+            finish();
         }
     }
 
@@ -252,7 +262,7 @@
                 }
                 mToken = null;
             }
-            getActivity().finish();
+            finish();
         }
     }
 
@@ -277,6 +287,7 @@
                 mRemoveController.setActivity((SettingsActivity) getActivity());
             } else if (controller instanceof FaceSettingsEnrollButtonPreferenceController) {
                 mEnrollController = (FaceSettingsEnrollButtonPreferenceController) controller;
+                mEnrollController.setListener(mEnrollListener);
                 mEnrollController.setActivity((SettingsActivity) getActivity());
             }
         }
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java
index a087ccc..e89eca4 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsEnrollButtonPreferenceController.java
@@ -43,6 +43,7 @@
     private SettingsActivity mActivity;
     private Button mButton;
     private boolean mIsClicked;
+    private Listener mListener;
 
     public FaceSettingsEnrollButtonPreferenceController(Context context) {
         this(context, KEY);
@@ -69,7 +70,11 @@
         intent.setClassName("com.android.settings", FaceEnrollIntroduction.class.getName());
         intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, mToken);
-        mContext.startActivity(intent);
+        if (mListener != null) {
+            mListener.onStartEnrolling(intent);
+        } else {
+            mContext.startActivity(intent);
+        }
     }
 
     @Override
@@ -95,4 +100,19 @@
     public void setActivity(SettingsActivity activity) {
         mActivity = activity;
     }
+
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Interface for registering callbacks related to the face enroll preference button.
+     */
+    public interface Listener {
+        /**
+         * Called when the user has indicated an intent to begin enrolling a new face.
+         * @param intent The Intent that should be used to launch face enrollment.
+         */
+        void onStartEnrolling(Intent intent);
+    }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index e92c967..8194878 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -222,8 +222,8 @@
 
     @Override
     protected void onStop() {
-        super.onStop();
         stopIconAnimation();
+        super.onStop();
     }
 
     private void animateProgress(int progress) {
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
index 733fb3f..9508268 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
@@ -115,10 +115,15 @@
 
     @Override
     protected void onStop() {
-        super.onStop();
         if (mAnimation != null) {
             mAnimation.pauseAnimation();
         }
+        super.onStop();
+    }
+
+    @Override
+    protected boolean shouldFinishWhenBackgrounded() {
+        return super.shouldFinishWhenBackgrounded() && !mNextClicked;
     }
 
     @Override
@@ -163,26 +168,25 @@
                 finish();
             }
         } else if (requestCode == ENROLL_REQUEST) {
-            if (resultCode == RESULT_FINISHED) {
-                setResult(RESULT_FINISHED);
-                finish();
-            } else if (resultCode == RESULT_SKIP) {
-                setResult(RESULT_SKIP);
-                finish();
-            } else if (resultCode == RESULT_TIMEOUT) {
-                setResult(RESULT_TIMEOUT);
-                finish();
-            } else {
-                FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this);
-                int enrolled = fpm.getEnrolledFingerprints().size();
-                int max = getResources().getInteger(
-                        com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
-                if (enrolled >= max) {
+            switch (resultCode) {
+                case RESULT_FINISHED:
+                case RESULT_SKIP:
+                case RESULT_TIMEOUT:
+                    setResult(resultCode);
                     finish();
-                } else {
-                    // We came back from enrolling but it wasn't completed, start again.
-                    startLookingForFingerprint();
-                }
+                    break;
+                default:
+                    FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this);
+                    int enrolled = fpm.getEnrolledFingerprints().size();
+                    int max = getResources().getInteger(
+                            com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
+                    if (enrolled >= max) {
+                        finish();
+                    } else {
+                        // We came back from enrolling but it wasn't completed, start again.
+                        startLookingForFingerprint();
+                    }
+                    break;
             }
         } else {
             super.onActivityResult(requestCode, resultCode, data);
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index 68b21f5..1a8e481 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -133,6 +133,7 @@
         private Drawable mHighlightDrawable;
         private int mUserId;
         private CharSequence mFooterTitle;
+        private boolean mEnrollClicked;
 
         private static final String TAG_AUTHENTICATE_SIDECAR = "authenticate_sidecar";
         private static final String TAG_REMOVAL_SIDECAR = "removal_sidecar";
@@ -464,6 +465,14 @@
         }
 
         @Override
+        public void onStop() {
+            super.onStop();
+            if (!getActivity().isChangingConfigurations() && !mLaunchedConfirm && !mEnrollClicked) {
+                getActivity().finish();
+            }
+        }
+
+        @Override
         public void onSaveInstanceState(final Bundle outState) {
             outState.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN,
                     mToken);
@@ -475,6 +484,7 @@
         public boolean onPreferenceTreeClick(Preference pref) {
             final String key = pref.getKey();
             if (KEY_FINGERPRINT_ADD.equals(key)) {
+                mEnrollClicked = true;
                 Intent intent = new Intent();
                 intent.setClassName(SETTINGS_PACKAGE_NAME,
                         FingerprintEnrollEnrolling.class.getName());
@@ -564,9 +574,10 @@
                     }
                 }
             } else if (requestCode == ADD_FINGERPRINT_REQUEST) {
+                mEnrollClicked = false;
                 if (resultCode == RESULT_TIMEOUT) {
                     Activity activity = getActivity();
-                    activity.setResult(RESULT_TIMEOUT);
+                    activity.setResult(resultCode);
                     activity.finish();
                 }
             }
diff --git a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
index 45ac7f7..aa4f869 100644
--- a/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/AvailableMediaBluetoothDeviceUpdater.java
@@ -35,6 +35,8 @@
     private static final String TAG = "AvailableMediaBluetoothDeviceUpdater";
     private static final boolean DBG = false;
 
+    private static final String PREF_KEY = "available_media_bt";
+
     private final AudioManager mAudioManager;
 
     public AvailableMediaBluetoothDeviceUpdater(Context context, DashboardFragment fragment,
@@ -97,9 +99,14 @@
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
+        mMetricsFeatureProvider.logClickedPreference(preference, mFragment.getMetricsCategory());
         final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference)
                 .getBluetoothDevice();
         return device.setActive();
     }
-}
 
+    @Override
+    protected String getPreferenceKey() {
+        return PREF_KEY;
+    }
+}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
index 7cf7fd5..e2715d3 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
@@ -28,12 +28,14 @@
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.widget.GearPreference;
 import com.android.settingslib.bluetooth.BluetoothCallback;
 import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.bluetooth.LocalBluetoothManager;
 import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -52,6 +54,7 @@
     private static final String TAG = "BluetoothDeviceUpdater";
     private static final boolean DBG = false;
 
+    protected final MetricsFeatureProvider mMetricsFeatureProvider;
     protected final DevicePreferenceCallback mDevicePreferenceCallback;
     protected final Map<BluetoothDevice, Preference> mPreferenceMap;
     protected Context mPrefContext;
@@ -76,6 +79,8 @@
         mDevicePreferenceCallback = devicePreferenceCallback;
         mPreferenceMap = new HashMap<>();
         mLocalManager = localManager;
+        mMetricsFeatureProvider = FeatureFactory.getFactory(mFragment.getContext())
+                .getMetricsFeatureProvider();
     }
 
     /**
@@ -207,6 +212,11 @@
     public abstract boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice);
 
     /**
+     * Return a preference key for logging
+     */
+    protected abstract String getPreferenceKey();
+
+    /**
      * Update whether to show {@link CachedBluetoothDevice} in the list.
      */
     protected void update(CachedBluetoothDevice cachedBluetoothDevice) {
@@ -228,6 +238,7 @@
                     new BluetoothDevicePreference(mPrefContext, cachedDevice,
                             true /* showDeviceWithoutNames */,
                             BluetoothDevicePreference.SortType.TYPE_DEFAULT);
+            btPreference.setKey(getPreferenceKey());
             btPreference.setOnGearClickListener(mDeviceProfilesListener);
             if (this instanceof Preference.OnPreferenceClickListener) {
                 btPreference.setOnPreferenceClickListener(
@@ -264,6 +275,7 @@
      * {@link SubSettingLauncher} to launch {@link BluetoothDeviceDetailsFragment}
      */
     protected void launchDeviceDetails(Preference preference) {
+        mMetricsFeatureProvider.logClickedPreference(preference, mFragment.getMetricsCategory());
         final CachedBluetoothDevice device =
                 ((BluetoothDevicePreference) preference).getBluetoothDevice();
         if (device == null) {
diff --git a/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
index 3ae081c..c7cae7f 100644
--- a/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/ConnectedBluetoothDeviceUpdater.java
@@ -35,6 +35,8 @@
     private static final String TAG = "ConnBluetoothDeviceUpdater";
     private static final boolean DBG = false;
 
+    private static final String PREF_KEY = "connected_bt";
+
     private final AudioManager mAudioManager;
 
     public ConnectedBluetoothDeviceUpdater(Context context, DashboardFragment fragment,
@@ -111,4 +113,9 @@
             });
         }
     }
+
+    @Override
+    protected String getPreferenceKey() {
+        return PREF_KEY;
+    }
 }
diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
index 6381b84..8d91dfc 100644
--- a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java
@@ -30,9 +30,12 @@
  */
 public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater
         implements Preference.OnPreferenceClickListener {
+
     private static final String TAG = "SavedBluetoothDeviceUpdater";
     private static final boolean DBG = false;
 
+    private static final String PREF_KEY = "saved_bt";
+
     public SavedBluetoothDeviceUpdater(Context context, DashboardFragment fragment,
             DevicePreferenceCallback devicePreferenceCallback) {
         super(context, fragment, devicePreferenceCallback);
@@ -51,9 +54,15 @@
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
+        mMetricsFeatureProvider.logClickedPreference(preference, mFragment.getMetricsCategory());
         final CachedBluetoothDevice device = ((BluetoothDevicePreference) preference)
                 .getBluetoothDevice();
         device.connect(true);
         return true;
     }
+
+    @Override
+    protected String getPreferenceKey() {
+        return PREF_KEY;
+    }
 }
diff --git a/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java b/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
index 0be1438..1078a21 100644
--- a/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
+++ b/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
@@ -29,11 +29,18 @@
 import com.android.settings.connecteddevice.DevicePreferenceCallback;
 import com.android.settings.core.SubSettingLauncher;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 
 /**
  * Controller to maintain connected usb device
  */
 public class ConnectedUsbDeviceUpdater {
+
+    private static final String PREF_KEY = "connected_usb";
+
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
+
     private DashboardFragment mFragment;
     private UsbBackend mUsbBackend;
     private DevicePreferenceCallback mDevicePreferenceCallback;
@@ -67,6 +74,8 @@
         mUsbBackend = usbBackend;
         mUsbReceiver = new UsbConnectionBroadcastReceiver(context,
                 mUsbConnectionListener, mUsbBackend);
+        mMetricsFeatureProvider = FeatureFactory.getFactory(mFragment.getContext())
+                .getMetricsFeatureProvider();
     }
 
     public void registerCallback() {
@@ -82,7 +91,9 @@
         mUsbPreference = new Preference(context, null /* AttributeSet */);
         mUsbPreference.setTitle(R.string.usb_pref);
         mUsbPreference.setIcon(R.drawable.ic_usb);
+        mUsbPreference.setKey(PREF_KEY);
         mUsbPreference.setOnPreferenceClickListener((Preference p) -> {
+            mMetricsFeatureProvider.logClickedPreference(p, mFragment.getMetricsCategory());
             // New version - uses a separate screen.
             new SubSettingLauncher(mFragment.getContext())
                     .setDestination(UsbDetailsFragment.class.getName())
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index f680bdd..5efd175 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -150,12 +150,15 @@
     @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (preference == mBillingCycle) {
+            writePreferenceClickMetric(preference);
             CycleEditorFragment.show(this);
             return true;
         } else if (preference == mDataWarning) {
+            writePreferenceClickMetric(preference);
             BytesEditorFragment.show(this, false);
             return true;
         } else if (preference == mDataLimit) {
+            writePreferenceClickMetric(preference);
             BytesEditorFragment.show(this, true);
             return true;
         }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 5a04143..b9b8b87 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -49,7 +49,7 @@
 public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>> {
 
     @VisibleForTesting
-    static final int DEFAULT_CARD_COUNT = 2;
+    static final int DEFAULT_CARD_COUNT = 3;
     static final int CARD_CONTENT_LOADER_ID = 1;
 
     private static final String TAG = "ContextualCardLoader";
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index 861adf1..9e3f1e8 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -27,22 +27,25 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.euicc.EuiccManager;
 
-import com.android.settings.R;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.network.telephony.MobileNetworkActivity;
-import com.android.settings.network.telephony.MobileNetworkUtils;
-import com.android.settings.widget.AddPreference;
-import com.android.settingslib.Utils;
-import com.android.settingslib.core.AbstractPreferenceController;
-
-import java.util.List;
-
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.OnLifecycleEvent;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.network.telephony.MobileNetworkActivity;
+import com.android.settings.network.telephony.MobileNetworkUtils;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.widget.AddPreference;
+import com.android.settingslib.Utils;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+
+import java.util.List;
+
 public class MobileNetworkSummaryController extends AbstractPreferenceController implements
         SubscriptionsChangeListener.SubscriptionsChangeListenerClient, LifecycleObserver,
         PreferenceControllerMixin {
@@ -50,6 +53,8 @@
 
     private static final String KEY = "mobile_network_list";
 
+    private final MetricsFeatureProvider mMetricsFeatureProvider;
+
     private SubscriptionManager mSubscriptionManager;
     private UserManager mUserManager;
     private SubscriptionsChangeListener mChangeListener;
@@ -72,6 +77,7 @@
      */
     public MobileNetworkSummaryController(Context context, Lifecycle lifecycle) {
         super(context);
+        mMetricsFeatureProvider = FeatureFactory.getFactory(mContext).getMetricsFeatureProvider();
         mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
         mUserManager = context.getSystemService(UserManager.class);
         if (lifecycle != null) {
@@ -146,6 +152,8 @@
         if (subs.isEmpty()) {
             if (MobileNetworkUtils.showEuiccSettings(mContext)) {
                 mPreference.setOnPreferenceClickListener((Preference pref) -> {
+                    mMetricsFeatureProvider.logClickedPreference(pref,
+                            pref.getExtras().getInt(DashboardFragment.CATEGORY));
                     startAddSimFlow();
                     return true;
                 });
@@ -157,11 +165,17 @@
             // supported.
             if (MobileNetworkUtils.showEuiccSettings(mContext)) {
                 mPreference.setAddWidgetEnabled(!mChangeListener.isAirplaneModeOn());
-                mPreference.setOnAddClickListener(p -> startAddSimFlow());
+                mPreference.setOnAddClickListener(p -> {
+                    mMetricsFeatureProvider.logClickedPreference(p,
+                            p.getExtras().getInt(DashboardFragment.CATEGORY));
+                    startAddSimFlow();
+                });
             }
 
             if (subs.size() == 1) {
                 mPreference.setOnPreferenceClickListener((Preference pref) -> {
+                    mMetricsFeatureProvider.logClickedPreference(pref,
+                            pref.getExtras().getInt(DashboardFragment.CATEGORY));
                     final SubscriptionInfo info = subs.get(0);
                     final int subId = info.getSubscriptionId();
                     if (!info.isEmbedded() && !mSubscriptionManager.isActiveSubscriptionId(subId)
diff --git a/src/com/android/settings/network/MobilePlanPreferenceController.java b/src/com/android/settings/network/MobilePlanPreferenceController.java
index dc41708..255dfcd 100644
--- a/src/com/android/settings/network/MobilePlanPreferenceController.java
+++ b/src/com/android/settings/network/MobilePlanPreferenceController.java
@@ -85,6 +85,7 @@
         if (mHost != null && KEY_MANAGE_MOBILE_PLAN.equals(preference.getKey())) {
             mMobilePlanDialogMessage = null;
             onManageMobilePlanClick();
+            return true;
         }
         return false;
     }
diff --git a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
index db7c864..29b3374 100644
--- a/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
+++ b/src/com/android/settings/network/telephony/NetworkOperatorPreference.java
@@ -187,6 +187,9 @@
             return mShow4GForLTE
                     ? R.drawable.ic_signal_strength_4g : R.drawable.signal_strength_lte;
         }
+        if (ci instanceof CellInfoNr) {
+            return R.drawable.signal_strength_5g;
+        }
         return MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
     }
 
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index abbd9a7..0a9a5b1 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -133,6 +133,7 @@
     @Override
     public boolean onPreferenceTreeClick(Preference preference) {
         if (preference instanceof RingtonePreference) {
+            writePreferenceClickMetric(preference);
             mRequestPreference = (RingtonePreference) preference;
             mRequestPreference.onPrepareRingtonePickerIntent(mRequestPreference.getIntent());
             getActivity().startActivityForResultAsUser(
diff --git a/src/com/android/settings/notification/zen/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeButtonPreferenceController.java
index 270fb73..a53b4fa 100644
--- a/src/com/android/settings/notification/zen/ZenModeButtonPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModeButtonPreferenceController.java
@@ -27,6 +27,7 @@
 
 import com.android.settings.R;
 import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.notification.SettingsEnableZenModeDialog;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.widget.LayoutPreference;
@@ -65,23 +66,22 @@
             mZenButtonOn = ((LayoutPreference) preference)
                     .findViewById(R.id.zen_mode_settings_turn_on_button);
             mZenButtonOn.setFocusableInTouchMode(true);
-            updateZenButtonOnClickListener();
+            updateZenButtonOnClickListener(preference);
         }
 
         if (null == mZenButtonOff) {
             mZenButtonOff = ((LayoutPreference) preference)
                     .findViewById(R.id.zen_mode_settings_turn_off_button);
             mZenButtonOff.setOnClickListener(v -> {
-                mMetricsFeatureProvider.action(mContext,
-                        SettingsEnums.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+                writeMetrics(preference, false);
                 mBackend.setZenMode(Settings.Global.ZEN_MODE_OFF);
             });
         }
 
-        updateButtons();
+        updateButtons(preference);
     }
 
-    private void updateButtons() {
+    private void updateButtons(Preference preference) {
         switch (getZenMode()) {
             case Settings.Global.ZEN_MODE_ALARMS:
             case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
@@ -93,35 +93,39 @@
             case Settings.Global.ZEN_MODE_OFF:
             default:
                 mZenButtonOff.setVisibility(View.GONE);
-                updateZenButtonOnClickListener();
+                updateZenButtonOnClickListener(preference);
                 mZenButtonOn.setVisibility(View.VISIBLE);
                 mZenButtonOn.requestFocus();
         }
     }
 
-    private void updateZenButtonOnClickListener() {
+    private void updateZenButtonOnClickListener(Preference preference) {
         int zenDuration = getZenDuration();
         switch (zenDuration) {
             case Settings.Secure.ZEN_DURATION_PROMPT:
                 mZenButtonOn.setOnClickListener(v -> {
-                    mMetricsFeatureProvider.action(mContext,
-                            SettingsEnums.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+                    writeMetrics(preference, true);
                     new SettingsEnableZenModeDialog().show(mFragment, TAG);
                 });
                 break;
             case Settings.Secure.ZEN_DURATION_FOREVER:
                 mZenButtonOn.setOnClickListener(v -> {
-                    mMetricsFeatureProvider.action(mContext,
-                            SettingsEnums.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+                    writeMetrics(preference, true);
                     mBackend.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
                 });
                 break;
             default:
                 mZenButtonOn.setOnClickListener(v -> {
-                    mMetricsFeatureProvider.action(mContext,
-                            SettingsEnums.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
+                    writeMetrics(preference, true);
                     mBackend.setZenModeForDuration(zenDuration);
                 });
         }
     }
+
+    private void writeMetrics(Preference preference, boolean buttonOn) {
+        mMetricsFeatureProvider.logClickedPreference(preference,
+                preference.getExtras().getInt(DashboardFragment.CATEGORY));
+        mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_ZEN_TOGGLE_DND_BUTTON,
+                buttonOn);
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceController.java
index 80fae97..64f2010 100644
--- a/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceController.java
@@ -28,6 +28,7 @@
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.dashboard.DashboardFragment;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class ZenModeStarredContactsPreferenceController extends
@@ -89,6 +90,8 @@
 
     @Override
     public boolean onPreferenceClick(Preference preference) {
+        mMetricsFeatureProvider.logClickedPreference(preference,
+                 preference.getExtras().getInt(DashboardFragment.CATEGORY));
         if (mStarredContactsIntent.resolveActivity(mPackageManager) != null) {
             mContext.startActivity(mStarredContactsIntent);
         } else {
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index 4310476..27b5c3b 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -118,7 +118,7 @@
     private static final String PREF_KEY_EMPTY_WIFI_LIST = "wifi_empty_list";
     private static final String PREF_KEY_CONNECTED_ACCESS_POINTS = "connected_access_point";
     private static final String PREF_KEY_ACCESS_POINTS = "access_points";
-    private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_settings";
+    private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_wifi_settings";
     private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks";
     private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message";
     @VisibleForTesting
diff --git a/src/com/android/settings/wifi/WifiSettings2.java b/src/com/android/settings/wifi/WifiSettings2.java
index bd79b3f..a1f1ad9 100644
--- a/src/com/android/settings/wifi/WifiSettings2.java
+++ b/src/com/android/settings/wifi/WifiSettings2.java
@@ -76,11 +76,8 @@
 import com.android.settingslib.search.SearchIndexableRaw;
 import com.android.settingslib.wifi.LongPressWifiEntryPreference;
 import com.android.wifitrackerlib.WifiEntry;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ConnectStatus;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.DisconnectStatus;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ForgetStatus;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.SignInStatus;
+import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
+import com.android.wifitrackerlib.WifiEntry.ConnectCallback.ConnectStatus;
 import com.android.wifitrackerlib.WifiPickerTracker;
 
 import java.time.Clock;
@@ -120,7 +117,7 @@
     // TODO(b/70983952): Rename these to use WifiEntry instead of AccessPoint.
     private static final String PREF_KEY_CONNECTED_ACCESS_POINTS = "connected_access_point";
     private static final String PREF_KEY_ACCESS_POINTS = "access_points";
-    private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_settings";
+    private static final String PREF_KEY_CONFIGURE_WIFI_SETTINGS = "configure_wifi_settings";
     private static final String PREF_KEY_SAVED_NETWORKS = "saved_networks";
     private static final String PREF_KEY_STATUS_MESSAGE = "wifi_status_message";
     @VisibleForTesting
@@ -543,7 +540,7 @@
                 connect(mSelectedWifiEntry, true /* editIfNoConfig */, false /* fullScreenEdit */);
                 return true;
             case MENU_ID_DISCONNECT:
-                mSelectedWifiEntry.disconnect();
+                mSelectedWifiEntry.disconnect(null /* callback */);
                 return true;
             case MENU_ID_FORGET:
                 forget(mSelectedWifiEntry);
@@ -624,6 +621,16 @@
         mDialogWifiEntryKey = null;
     }
 
+    @Override
+    public int getDialogMetricsCategory(int dialogId) {
+        switch (dialogId) {
+            case WIFI_DIALOG_ID:
+                return SettingsEnums.DIALOG_WIFI_AP_EDIT;
+            default:
+                return 0;
+        }
+    }
+
     /** Called when the state of Wifi has changed. */
     @Override
     public void onWifiStateChanged() {
@@ -720,7 +727,7 @@
                 mConnectedWifiEntryPreferenceCategory.addPreference(pref);
                 pref.setOnPreferenceClickListener(preference -> {
                     if (connectedEntry.canSignIn()) {
-                        connectedEntry.signIn();
+                        connectedEntry.signIn(null /* callback */);
                     } else {
                         launchNetworkDetailsFragment(pref);
                     }
@@ -961,7 +968,7 @@
 
     private void forget(WifiEntry wifiEntry) {
         mMetricsFeatureProvider.action(getActivity(), SettingsEnums.ACTION_WIFI_FORGET);
-        wifiEntry.forget();
+        wifiEntry.forget(null /* callback */);
     }
 
     private void connect(WifiEntry wifiEntry, boolean editIfNoConfig, boolean fullScreenEdit) {
@@ -969,11 +976,9 @@
                 wifiEntry.isSaved());
 
         // If it's an unsaved secure WifiEntry, it will callback
-        // WifiEntryCallback#onConnectResult with
-        // WifiEntryCallback#CONNECT_STATUS_FAILURE_NO_CONFIG
-        wifiEntry.setListener(new WifiEntryConnectCallback(wifiEntry, editIfNoConfig,
+        // ConnectCallback#onConnectResult with ConnectCallback#CONNECT_STATUS_FAILURE_NO_CONFIG
+        wifiEntry.connect(new WifiEntryConnectCallback(wifiEntry, editIfNoConfig,
                 fullScreenEdit));
-        wifiEntry.connect();
     }
 
     private class WifiSaveThenConnectActionListener implements WifiManager.ActionListener {
@@ -1039,7 +1044,7 @@
                 }
             };
 
-    private class WifiEntryConnectCallback implements WifiEntryCallback {
+    private class WifiEntryConnectCallback implements ConnectCallback {
         final WifiEntry mConnectWifiEntry;
         final boolean mEditIfNoConfig;
         final boolean mFullScreenEdit;
@@ -1052,18 +1057,13 @@
         }
 
         @Override
-        public void onUpdated() {
-            // Do nothing.
-        }
-
-        @Override
         public void onConnectResult(@ConnectStatus int status) {
             final Activity activity = getActivity();
             if (isFisishingOrDestroyed(activity)) {
                 return;
             }
 
-            if (status == WifiEntryCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) {
+            if (status == ConnectCallback.CONNECT_STATUS_FAILURE_NO_CONFIG) {
                 if (mEditIfNoConfig) {
                     // Edit an unsaved secure Wi-Fi network.
                     if (mFullScreenEdit) {
@@ -1077,21 +1077,6 @@
                         Toast.LENGTH_SHORT).show();
             }
         }
-
-        @Override
-        public void onDisconnectResult(@DisconnectStatus int status) {
-            // Do nothing.
-        }
-
-        @Override
-        public void onForgetResult(@ForgetStatus int status) {
-            // Do nothing.
-        }
-
-        @Override
-        public void onSignInResult(@SignInStatus int status) {
-            // Do nothing.
-        }
     }
 
     private boolean isFisishingOrDestroyed(Activity activity) {
@@ -1111,7 +1096,7 @@
                 .launch();
     }
 
-    /** Helper method to return whether an WifiEntry is disabled due to a wrong password */
+    /** Helper method to return whether a WifiEntry is disabled due to a wrong password */
     private static boolean isDisabledByWrongPassword(WifiEntry wifiEntry) {
         WifiConfiguration config = wifiEntry.getWifiConfiguration();
         if (config == null) {
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 5f74d56..5eed9e3 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -75,12 +75,16 @@
 import com.android.settingslib.widget.ActionButtonsPreference;
 import com.android.settingslib.widget.LayoutPreference;
 import com.android.wifitrackerlib.WifiEntry;
+import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
+import com.android.wifitrackerlib.WifiEntry.ConnectCallback.ConnectStatus;
 import com.android.wifitrackerlib.WifiEntry.ConnectedInfo;
+import com.android.wifitrackerlib.WifiEntry.DisconnectCallback;
+import com.android.wifitrackerlib.WifiEntry.DisconnectCallback.DisconnectStatus;
+import com.android.wifitrackerlib.WifiEntry.ForgetCallback;
+import com.android.wifitrackerlib.WifiEntry.ForgetCallback.ForgetStatus;
+import com.android.wifitrackerlib.WifiEntry.SignInCallback;
+import com.android.wifitrackerlib.WifiEntry.SignInCallback.SignInStatus;
 import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ConnectStatus;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.DisconnectStatus;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.ForgetStatus;
-import com.android.wifitrackerlib.WifiEntry.WifiEntryCallback.SignInStatus;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -95,7 +99,8 @@
  */
 public class WifiDetailPreferenceController2 extends AbstractPreferenceController
         implements PreferenceControllerMixin, WifiDialog2Listener, LifecycleObserver, OnPause,
-        OnResume, WifiEntryCallback {
+        OnResume, WifiEntryCallback, ConnectCallback, DisconnectCallback, ForgetCallback,
+        SignInCallback {
 
     private static final String TAG = "WifiDetailsPrefCtrl2";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -214,8 +219,6 @@
                         || hasCapabilityChanged(nc, NET_CAPABILITY_VALIDATED)
                         || hasCapabilityChanged(nc, NET_CAPABILITY_CAPTIVE_PORTAL)
                         || hasCapabilityChanged(nc, NET_CAPABILITY_PARTIAL_CONNECTIVITY)) {
-                    // TODO(b/143326832): What to do with WifiEntry?
-                    // mAccessPoint.update(mWifiConfig, mWifiInfo, mNetworkInfo);
                     refreshEntityHeader();
                 }
                 mNetworkCapabilities = nc;
@@ -298,17 +301,15 @@
         setupEntityHeader(screen);
 
         mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY_BUTTONS_PREF))
-                .setButton1Text(!mWifiEntry.isSaved()
-                        ? R.string.wifi_disconnect_button_text : R.string.forget)
+                .setButton1Text(R.string.forget)
                 .setButton1Icon(R.drawable.ic_settings_delete)
                 .setButton1OnClickListener(view -> forgetNetwork())
                 .setButton2Text(R.string.wifi_sign_in_button_text)
                 .setButton2Icon(R.drawable.ic_settings_sign_in)
                 .setButton2OnClickListener(view -> signIntoNetwork())
-                .setButton3Text(R.string.wifi_connect)
-                .setButton3Icon(R.drawable.ic_settings_wireless)
-                .setButton3OnClickListener(view -> connectNetwork())
-                .setButton3Enabled(true)
+                .setButton3Text(getConnectDisconnectButtonTextResource())
+                .setButton3Icon(getConnectDisconnectButtonIconResource())
+                .setButton3OnClickListener(view -> connectDisconnectNetwork())
                 .setButton4Text(R.string.share)
                 .setButton4Icon(R.drawable.ic_qrcode_24dp)
                 .setButton4OnClickListener(view -> shareNetwork());
@@ -587,29 +588,50 @@
     }
 
     private void refreshButtons() {
-        boolean canForgetNetwork = mWifiEntry.canForget();
-        boolean canSignIntoNetwork = canSignIntoNetwork();
-        boolean showConnectButton = mWifiEntry.canConnect()
-                || mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTING;
-        boolean canShareNetwork = canShareNetwork();
+        final boolean canForgetNetwork = mWifiEntry.canForget();
+        final boolean canSignIntoNetwork = canSignIntoNetwork();
+        final boolean canConnectDisconnectNetwork = mWifiEntry.canConnect()
+                || mWifiEntry.canDisconnect();
+        final boolean canShareNetwork = canShareNetwork();
 
         mButtonsPref.setButton1Visible(canForgetNetwork);
         mButtonsPref.setButton2Visible(canSignIntoNetwork);
-        mButtonsPref.setButton3Visible(showConnectButton);
-        if (showConnectButton) {
-            if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTING) {
-                mButtonsPref.setButton3Text(R.string.wifi_connecting).setButton3Enabled(false);
-            } else {
-                mButtonsPref.setButton3Text(R.string.wifi_connect).setButton3Enabled(true);
-            }
-        }
+        mButtonsPref.setButton3Visible(mWifiEntry.getLevel() != WifiEntry.WIFI_LEVEL_UNREACHABLE);
+        mButtonsPref.setButton3Enabled(canConnectDisconnectNetwork);
+        mButtonsPref.setButton3Text(getConnectDisconnectButtonTextResource());
+        mButtonsPref.setButton3Icon(getConnectDisconnectButtonIconResource());
         mButtonsPref.setButton4Visible(canShareNetwork);
         mButtonsPref.setVisible(canForgetNetwork
                 || canSignIntoNetwork
-                || showConnectButton
+                || canConnectDisconnectNetwork
                 || canShareNetwork);
     }
 
+    private int getConnectDisconnectButtonTextResource() {
+        switch (mWifiEntry.getConnectedState()) {
+            case WifiEntry.CONNECTED_STATE_DISCONNECTED:
+                return R.string.wifi_connect;
+            case WifiEntry.CONNECTED_STATE_CONNECTED:
+                return R.string.wifi_disconnect_button_text;
+            case WifiEntry.CONNECTED_STATE_CONNECTING:
+                return R.string.wifi_connecting;
+            default:
+                throw new IllegalStateException("Invalid WifiEntry connected state");
+        }
+    }
+
+    private int getConnectDisconnectButtonIconResource() {
+        switch (mWifiEntry.getConnectedState()) {
+            case WifiEntry.CONNECTED_STATE_DISCONNECTED:
+            case WifiEntry.CONNECTED_STATE_CONNECTING:
+                return R.drawable.ic_settings_wireless;
+            case WifiEntry.CONNECTED_STATE_CONNECTED:
+                return R.drawable.ic_settings_close;
+            default:
+                throw new IllegalStateException("Invalid WifiEntry connected state");
+        }
+    }
+
     private void refreshIpLayerInfo() {
         // Hide IP layer info if not a connected network.
         if (mWifiEntry.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED
@@ -706,7 +728,7 @@
             showConfirmForgetDialog();
             return;
         } else {
-            mWifiEntry.forget();
+            mWifiEntry.forget(this);
         }
 
         mMetricsFeatureProvider.action(
@@ -719,7 +741,7 @@
         final AlertDialog dialog = new AlertDialog.Builder(mContext)
                 .setPositiveButton(R.string.forget, ((dialog1, which) -> {
                     try {
-                        mWifiEntry.forget();
+                        mWifiEntry.forget(this);
                     } catch (RuntimeException e) {
                         Log.e(TAG, "Failed to remove Passpoint configuration for "
                                 + WifiEntryShell.getPasspointFqdn(mWifiEntry));
@@ -768,7 +790,7 @@
     private void signIntoNetwork() {
         mMetricsFeatureProvider.action(
                 mFragment.getActivity(), SettingsEnums.ACTION_WIFI_SIGNIN);
-        mConnectivityManager.startCaptivePortalApp(mNetwork);
+        mWifiEntry.signIn(this);
     }
 
     @Override
@@ -813,8 +835,12 @@
     }
 
     @VisibleForTesting
-    void connectNetwork() {
-        mWifiEntry.connect();
+    void connectDisconnectNetwork() {
+        if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_DISCONNECTED) {
+            mWifiEntry.connect(this);
+        } else {
+            mWifiEntry.disconnect(this);
+        }
     }
 
     private void refreshMacTitle() {
@@ -849,7 +875,7 @@
      */
     @Override
     public void onConnectResult(@ConnectStatus int status) {
-        if (status == WifiEntryCallback.CONNECT_STATUS_SUCCESS) {
+        if (status == ConnectCallback.CONNECT_STATUS_SUCCESS) {
             Toast.makeText(mContext,
                     mContext.getString(R.string.wifi_connected_to_message, mWifiEntry.getTitle()),
                     Toast.LENGTH_SHORT).show();
@@ -862,10 +888,6 @@
                     R.string.wifi_failed_connect_message,
                     Toast.LENGTH_SHORT).show();
         }
-        mButtonsPref.setButton3Text(R.string.wifi_connect)
-                .setButton3Icon(R.drawable.ic_settings_wireless)
-                .setButton3Enabled(true)
-                .setButton3Visible(true);
     }
 
     /**
@@ -873,12 +895,9 @@
      */
     @Override
     public void onDisconnectResult(@DisconnectStatus int status) {
-        if (status != WifiEntryCallback.DISCONNECT_STATUS_SUCCESS) {
+        if (status != DisconnectCallback.DISCONNECT_STATUS_SUCCESS) {
             Log.e(TAG, "Disconnect Wi-Fi network failed");
         }
-
-        updateNetworkInfo();
-        refreshPage();
     }
 
     /**
@@ -886,7 +905,7 @@
      */
     @Override
     public void onForgetResult(@ForgetStatus int status) {
-        if (status != WifiEntryCallback.FORGET_STATUS_SUCCESS) {
+        if (status != ForgetCallback.FORGET_STATUS_SUCCESS) {
             Log.e(TAG, "Forget Wi-Fi network failed");
         }
 
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
index db4cb6c..b87b05d 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPreferenceController2.java
@@ -88,7 +88,7 @@
             // To activate changing, we need to reconnect network. WiFi will auto connect to
             // current network after disconnect(). Only needed when this is connected network.
             if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
-                mWifiEntry.disconnect();
+                mWifiEntry.disconnect(null /* callback */);
             }
         }
         updateSummary((DropDownPreference) preference, privacy);
diff --git a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java
index 2315c9b..fc91f6b 100644
--- a/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java
+++ b/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceController.java
@@ -59,6 +59,7 @@
 
     @Override
     public int getAvailabilityStatus() {
+        refreshSavedAccessPoints();
         return mAccessPoints.size() > 0 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
     }
 
diff --git a/tests/robotests/src/com/android/settings/AirplaneModeEnablerTest.java b/tests/robotests/src/com/android/settings/AirplaneModeEnablerTest.java
new file mode 100644
index 0000000..24abac9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/AirplaneModeEnablerTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+package com.android.settings;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.telephony.TelephonyManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+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.shadows.ShadowSettings;
+
+
+@RunWith(AndroidJUnit4.class)
+public final class AirplaneModeEnablerTest {
+
+    private Context mContext;
+
+    @Mock
+    private AirplaneModeChangedListener mAirplaneModeChangedListener;
+    private AirplaneModeEnabler mAirplaneModeEnabler;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        mContext = RuntimeEnvironment.application.getBaseContext();
+        mAirplaneModeEnabler = new AirplaneModeEnabler(mContext,
+                mAirplaneModeChangedListener);
+    }
+
+    @Test
+    public void onRadioPowerStateChanged_beenInvoke_invokeOnAirplaneModeChanged() {
+        mAirplaneModeEnabler.resume();
+
+        ShadowSettings.setAirplaneMode(true);
+
+        mAirplaneModeEnabler.mPhoneStateListener.onRadioPowerStateChanged(
+                TelephonyManager.RADIO_POWER_OFF);
+
+        verify(mAirplaneModeChangedListener, times(1)).onAirplaneModeChanged(true);
+    }
+
+    private class AirplaneModeChangedListener
+            implements AirplaneModeEnabler.OnAirplaneModeChangedListener {
+        public void onAirplaneModeChanged(boolean isAirplaneModeOn) {}
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
index 66bf959..260fc41 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
@@ -82,7 +82,7 @@
     private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
     private BluetoothDevicePreference mPreference;
     private ShadowBluetoothAdapter mShadowBluetoothAdapter;
-    private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<CachedBluetoothDevice>();
+    private List<CachedBluetoothDevice> mCachedDevices = new ArrayList<>();
 
     @Before
     public void setUp() {
@@ -104,11 +104,16 @@
         mBluetoothDeviceUpdater =
             new BluetoothDeviceUpdater(mDashboardFragment, mDevicePreferenceCallback,
                     mLocalManager) {
-            @Override
-            public boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice) {
-                return true;
-            }
-        };
+                @Override
+                public boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice) {
+                    return true;
+                }
+
+                @Override
+                protected String getPreferenceKey() {
+                    return "test_bt";
+                }
+            };
         mBluetoothDeviceUpdater.setPrefContext(mContext);
     }
 
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index e60303e..b48cd3c 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -1303,22 +1303,35 @@
     }
 
     @Test
-    public void testConnectButton_shouldInvisibleForConnectNetwork() {
+    public void testDisconnectButton_connectedNetwork_shouldVisible() {
         setUpForConnectedNetwork();
+        when(mMockWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_MAX);
 
         displayAndResume();
 
-        verify(mMockButtonsPref, times(1)).setButton3Visible(false);
+        verify(mMockButtonsPref).setButton3Visible(true);
+        verify(mMockButtonsPref).setButton3Text(R.string.wifi_disconnect);
     }
 
     @Test
-    public void testConnectButton_shouldVisibleForDisconnectNetwork() {
+    public void testConnectButton_disconnectedNetwork_shouldVisibleIfReachable() {
         setUpForDisconnectedNetwork();
+        when(mMockWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_MAX);
 
         displayAndResume();
 
-        verify(mMockButtonsPref, times(1)).setButton3Visible(true);
-        verify(mMockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
+        verify(mMockButtonsPref).setButton3Visible(true);
+        verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
+    }
+
+    @Test
+    public void testConnectButton_disconnectedNetwork_shouldInvisibleIfUnreachable() {
+        setUpForDisconnectedNetwork();
+        when(mMockWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_UNREACHABLE);
+
+        displayAndResume();
+
+        verify(mMockButtonsPref).setButton3Visible(false);
     }
 
     private void setUpForToast() {
@@ -1337,11 +1350,11 @@
 
         displayAndResume();
 
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
+        // check connect button enabled
+        verifyConnectBtnSetUpAsEnabled(inOrder);
 
         // click connect button
-        mController.connectNetwork();
+        mController.connectDisconnectNetwork();
 
         // check display button as connecting
         verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
@@ -1352,7 +1365,7 @@
 
         // check connect button invisible, be init as default state and toast success message
         verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(false);
+        inOrder.verify(mMockButtonsPref).setButton3Enabled(false);
         assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
                 mContext.getString(R.string.wifi_connected_to_message, label));
     }
@@ -1368,11 +1381,11 @@
 
         displayAndResume();
 
-        // check connect button exist
-        verifyConnectBtnSetUpAsVisible(inOrder);
+        // check connect button enabled
+        verifyConnectBtnSetUpAsEnabled(inOrder);
 
         // click connect button
-        mController.connectNetwork();
+        mController.connectDisconnectNetwork();
 
         // check display button as connecting
         verify(mMockWifiManager, times(1)).connect(anyInt(), connectListenerCaptor.capture());
@@ -1383,26 +1396,26 @@
 
         // check connect button visible, be init as default and toast failed message
         verifyConnectBtnBeInitAsDefault(inOrder);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
+        inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
         assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
                 mContext.getString(R.string.wifi_failed_connect_message));
     }
 
-    private void verifyConnectBtnSetUpAsVisible(InOrder inOrder) {
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Icon(R.drawable.ic_settings_wireless);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Visible(true);
+    private void verifyConnectBtnSetUpAsEnabled(InOrder inOrder) {
+        inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
+        inOrder.verify(mMockButtonsPref).setButton3Icon(R.drawable.ic_settings_wireless);
+        inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
     }
 
     private void verifyConnectBtnSetUpAsConnecting(InOrder inOrder) {
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Text(R.string.wifi_connecting);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Enabled(false);
+        inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connecting);
+        inOrder.verify(mMockButtonsPref).setButton3Enabled(false);
     }
 
     private void verifyConnectBtnBeInitAsDefault(InOrder inOrder) {
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Text(R.string.wifi_connect);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Icon(R.drawable.ic_settings_wireless);
-        inOrder.verify(mMockButtonsPref, times(1)).setButton3Enabled(true);
+        inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
+        inOrder.verify(mMockButtonsPref).setButton3Icon(R.drawable.ic_settings_wireless);
+        inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java
index e955224..483e259 100644
--- a/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/savedaccesspoints/SavedAccessPointsPreferenceControllerTest.java
@@ -16,7 +16,6 @@
 
 package com.android.settings.wifi.savedaccesspoints;
 
-import static com.android.settings.core.BasePreferenceController.AVAILABLE;
 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -30,19 +29,14 @@
 import android.content.Context;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
-import android.os.Bundle;
 
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.testutils.shadow.ShadowAccessPoint;
 import com.android.settings.testutils.shadow.ShadowWifiManager;
-import com.android.settingslib.wifi.AccessPoint;
 import com.android.settingslib.wifi.AccessPointPreference;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,6 +47,8 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 
+import java.util.ArrayList;
+
 @RunWith(RobolectricTestRunner.class)
 @Config(shadows = {ShadowWifiManager.class})
 public class SavedAccessPointsPreferenceControllerTest {
@@ -89,11 +85,10 @@
     }
 
     @Test
-    public void getAvailability_oneSavedAccessPoint_shouldAvailable() {
-        final AccessPoint accessPoint = new AccessPoint(mContext, new Bundle() /* savedState */);
-        mController.mAccessPoints = new ArrayList<AccessPoint>(Arrays.asList(accessPoint));
+    public void getAvailability_shouldRefreshSavedAccessPoints() {
+        mController.getAvailabilityStatus();
 
-        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+        verify(mController).refreshSavedAccessPoints();
     }
 
     @Test