Merge changes from topic "cherrypick-volume-gar-chain-" into udc-qpr-dev

* changes:
  Trigger talkback for notification volume change
  Add content description to volume title in settings.
diff --git a/res/layout/preference_check_icon.xml b/res/layout/preference_check_icon.xml
index 1b759fc..bd0dd79 100644
--- a/res/layout/preference_check_icon.xml
+++ b/res/layout/preference_check_icon.xml
@@ -20,4 +20,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_centerVertical="true"
-    android:layout_marginHorizontal="16dp"/>
\ No newline at end of file
+    android:layout_marginHorizontal="16dp"
+    android:contentDescription="@*android:string/checked"/>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3a46343..897d76a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1526,8 +1526,6 @@
     <string name="bluetooth_companion_app_remove_association_dialog_title">Disconnect App?</string>
     <!-- Bluetooth device details companion apps. The body of confirmation dialog for remove association. [CHAR LIMIT=60] -->
     <string name="bluetooth_companion_app_body"><xliff:g id="app_name" example="App Name">%1$s</xliff:g> app will no longer connect to your <xliff:g id="device_name" example="Device Name">%2$s</xliff:g></string>
-    <!-- Summary of Bluetooth LE Audio toggle in Device Details. [CHAR LIMIT=40] -->
-    <string name="device_details_leaudio_toggle_summary">Experimental. Improves audio quality.</string>
 
     <!--  Bluetooth device details. In the confirmation dialog for unpairing a paired device, this is the label on the button that will complete the unpairing action. -->
     <string name="bluetooth_unpair_dialog_forget_confirm_button">Forget device</string>
@@ -6431,7 +6429,7 @@
     <!-- Search keywords for the "Delete Guest Activity" section in Multiple Users Screen. [CHAR LIMIT=NONE] -->
     <string name="remove_guest_on_exit_keywords">delete, guest, activity, remove, data, visitor, erase</string>
     <!-- Title of preference to enable guest calling[CHAR LIMIT=40] -->
-    <string name="enable_guest_calling">Allow guest to use phone</string>
+    <string name="enable_guest_calling">Allow guest to make phone calls</string>
     <!-- Summary of preference to enable guest calling [CHAR LIMIT=NONE] -->
     <string name="enable_guest_calling_summary">Call history will be shared with guest user</string>
 
diff --git a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
index 0767e65..6bee62c 100644
--- a/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
+++ b/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceController.java
@@ -81,6 +81,8 @@
         final RestrictedSwitchPreference preference =
                 (RestrictedSwitchPreference) pref;
         final CharSequence label = mPkgInfo.applicationInfo.loadLabel(mPm);
+        final boolean isAllowedCn = mCn.flattenToShortString().length()
+                <= NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH;
         final boolean isEnabled = isServiceEnabled(mCn);
         preference.setChecked(isEnabled);
         preference.setOnPreferenceChangeListener((p, newValue) -> {
@@ -105,7 +107,8 @@
                 return false;
             }
         });
-        preference.updateState(mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isEnabled);
+        preference.updateState(
+                mCn.getPackageName(), mPkgInfo.applicationInfo.uid, isAllowedCn, isEnabled);
     }
 
     public void disable(final ComponentName cn) {
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index 701967b..00f18e8 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -116,10 +116,6 @@
         pref.setTitle(profile.getNameResource(mCachedDevice.getDevice()));
         pref.setOnPreferenceClickListener(this);
         pref.setOrder(profile.getOrdinal());
-
-        if (profile instanceof LeAudioProfile) {
-            pref.setSummary(R.string.device_details_leaudio_toggle_summary);
-        }
         return pref;
     }
 
diff --git a/src/com/android/settings/localepicker/LocaleDialogFragment.java b/src/com/android/settings/localepicker/LocaleDialogFragment.java
index ad9e10f..f54446a 100644
--- a/src/com/android/settings/localepicker/LocaleDialogFragment.java
+++ b/src/com/android/settings/localepicker/LocaleDialogFragment.java
@@ -164,15 +164,18 @@
         public void onClick(DialogInterface dialog, int which) {
             if (mDialogType == DIALOG_CONFIRM_SYSTEM_DEFAULT) {
                 int result = Activity.RESULT_CANCELED;
+                boolean changed = false;
                 if (which == DialogInterface.BUTTON_POSITIVE) {
                     result = Activity.RESULT_OK;
+                    changed = true;
                 }
                 Intent intent = new Intent();
                 Bundle bundle = new Bundle();
                 bundle.putInt(ARG_DIALOG_TYPE, DIALOG_CONFIRM_SYSTEM_DEFAULT);
                 intent.putExtras(bundle);
                 mParent.onActivityResult(DIALOG_CONFIRM_SYSTEM_DEFAULT, result, intent);
-                mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_CHANGE_LANGUAGE);
+                mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_CHANGE_LANGUAGE,
+                        changed);
             }
             mShouldKeepDialog = false;
         }
diff --git a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
index edd3026..3d7976a 100644
--- a/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
+++ b/src/com/android/settings/localepicker/LocaleDragAndDropAdapter.java
@@ -16,6 +16,7 @@
 
 package com.android.settings.localepicker;
 
+import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.os.Bundle;
@@ -37,6 +38,7 @@
 import com.android.internal.app.LocalePicker;
 import com.android.internal.app.LocaleStore;
 import com.android.settings.R;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.shortcut.ShortcutsUpdateTask;
 
 import java.text.NumberFormat;
@@ -210,6 +212,13 @@
             Log.e(TAG, String.format(Locale.US,
                     "Negative position in onItemMove %d -> %d", fromPosition, toPosition));
         }
+
+        if (fromPosition != toPosition) {
+            FeatureFactory.getFactory(mContext).getMetricsFeatureProvider()
+                    .action(mContext, SettingsEnums.ACTION_REORDER_LANGUAGE,
+                            mDragLocale.getLocale().toLanguageTag() + " move to " + toPosition);
+        }
+
         notifyItemChanged(fromPosition); // to update the numbers
         notifyItemChanged(toPosition);
         notifyItemMoved(fromPosition, toPosition);
@@ -244,8 +253,13 @@
 
     void removeChecked() {
         int itemCount = mFeedItemList.size();
+        LocaleStore.LocaleInfo localeInfo;
         for (int i = itemCount - 1; i >= 0; i--) {
-            if (mFeedItemList.get(i).getChecked()) {
+            localeInfo = mFeedItemList.get(i);
+            if (localeInfo.getChecked()) {
+                FeatureFactory.getFactory(mContext).getMetricsFeatureProvider()
+                        .action(mContext, SettingsEnums.ACTION_REMOVE_LANGUAGE,
+                                localeInfo.getLocale().toLanguageTag());
                 mFeedItemList.remove(i);
             }
         }
diff --git a/src/com/android/settings/localepicker/LocaleListEditor.java b/src/com/android/settings/localepicker/LocaleListEditor.java
index 55cff3b..dfdb942 100644
--- a/src/com/android/settings/localepicker/LocaleListEditor.java
+++ b/src/com/android/settings/localepicker/LocaleListEditor.java
@@ -199,9 +199,11 @@
             localeInfo = (LocaleStore.LocaleInfo) data.getSerializableExtra(INTENT_LOCALE_KEY);
             String preferencesTags = Settings.System.getString(
                     getContext().getContentResolver(), Settings.System.LOCALE_PREFERENCES);
-
-            mAdapter.addLocale(mayAppendUnicodeTags(localeInfo, preferencesTags));
+            localeInfo = mayAppendUnicodeTags(localeInfo, preferencesTags);
+            mAdapter.addLocale(localeInfo);
             updateVisibilityOfRemoveMenu();
+            mMetricsFeatureProvider.action(getContext(), SettingsEnums.ACTION_ADD_LANGUAGE,
+                    localeInfo.getLocale().toLanguageTag());
         } else if (requestCode == DIALOG_CONFIRM_SYSTEM_DEFAULT) {
             localeInfo = mAdapter.getFeedItemList().get(0);
             if (resultCode == Activity.RESULT_OK) {
@@ -214,6 +216,9 @@
                     LocaleDialogFragment localeDialogFragment = LocaleDialogFragment.newInstance();
                     localeDialogFragment.setArguments(args);
                     localeDialogFragment.show(mFragmentManager, TAG_DIALOG_NOT_AVAILABLE);
+                    mMetricsFeatureProvider.action(getContext(),
+                            SettingsEnums.ACTION_NOT_SUPPORTED_SYSTEM_LANGUAGE,
+                            localeInfo.getLocale().toLanguageTag());
                 }
             } else {
                 mAdapter.notifyListChanged(localeInfo);
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 9d953bf..0cd12fe 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -23,6 +23,7 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.ParcelUuid;
 import android.provider.Settings;
 import android.telephony.PhoneNumberUtils;
@@ -61,6 +62,10 @@
 public class SubscriptionUtil {
     private static final String TAG = "SubscriptionUtil";
     private static final String PROFILE_GENERIC_DISPLAY_NAME = "CARD";
+    @VisibleForTesting
+    static final String SUB_ID = "sub_id";
+    @VisibleForTesting
+    static final String KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME = "unique_subscription_displayName";
     private static List<SubscriptionInfo> sAvailableResultsForTesting;
     private static List<SubscriptionInfo> sActiveResultsForTesting;
 
@@ -265,20 +270,21 @@
         // Map of SubscriptionId to DisplayName
         final Supplier<Stream<DisplayInfo>> originalInfos =
                 () -> getAvailableSubscriptions(context)
-                .stream()
-                .filter(i -> {
-                    // Filter out null values.
-                    return (i != null && i.getDisplayName() != null);
-                })
-                .map(i -> {
-                    DisplayInfo info = new DisplayInfo();
-                    info.subscriptionInfo = i;
-                    String displayName = i.getDisplayName().toString();
-                    info.originalName = TextUtils.equals(displayName, PROFILE_GENERIC_DISPLAY_NAME)
-                            ? context.getResources().getString(R.string.sim_card)
-                            : displayName.trim();
-                    return info;
-                });
+                        .stream()
+                        .filter(i -> {
+                            // Filter out null values.
+                            return (i != null && i.getDisplayName() != null);
+                        })
+                        .map(i -> {
+                            DisplayInfo info = new DisplayInfo();
+                            info.subscriptionInfo = i;
+                            String displayName = i.getDisplayName().toString();
+                            info.originalName =
+                                    TextUtils.equals(displayName, PROFILE_GENERIC_DISPLAY_NAME)
+                                    ? context.getResources().getString(R.string.sim_card)
+                                    : displayName.trim();
+                            return info;
+                        });
 
         // TODO(goldmanj) consider using a map of DisplayName to SubscriptionInfos.
         // A Unique set of display names
@@ -292,6 +298,14 @@
         // If a display name is duplicate, append the final 4 digits of the phone number.
         // Creates a mapping of Subscription id to original display name + phone number display name
         final Supplier<Stream<DisplayInfo>> uniqueInfos = () -> originalInfos.get().map(info -> {
+            String cachedDisplayName = getDisplayNameFromSharedPreference(
+                    context, info.subscriptionInfo.getSubscriptionId());
+            if (!TextUtils.isEmpty(cachedDisplayName)) {
+                Log.d(TAG, "use cached display name : " + cachedDisplayName);
+                info.uniqueName = cachedDisplayName;
+                return info;
+            }
+
             if (duplicateOriginalNames.contains(info.originalName)) {
                 // This may return null, if the user cannot view the phone number itself.
                 final String phoneNumber = getBidiFormattedPhoneNumber(context,
@@ -299,15 +313,17 @@
                 String lastFourDigits = "";
                 if (phoneNumber != null) {
                     lastFourDigits = (phoneNumber.length() > 4)
-                        ? phoneNumber.substring(phoneNumber.length() - 4) : phoneNumber;
+                            ? phoneNumber.substring(phoneNumber.length() - 4) : phoneNumber;
                 }
-
                 if (TextUtils.isEmpty(lastFourDigits)) {
                     info.uniqueName = info.originalName;
                 } else {
                     info.uniqueName = info.originalName + " " + lastFourDigits;
+                    Log.d(TAG, "Cache display name [" + info.uniqueName + "] for sub id "
+                            + info.subscriptionInfo.getSubscriptionId());
+                    saveDisplayNameToSharedPreference(
+                            context, info.subscriptionInfo.getSubscriptionId(), info.uniqueName);
                 }
-
             } else {
                 info.uniqueName = info.originalName;
             }
@@ -371,6 +387,27 @@
         return getUniqueSubscriptionDisplayName(info.getSubscriptionId(), context);
     }
 
+
+    private static SharedPreferences getDisplayNameSharedPreferences(Context context) {
+        return context.getSharedPreferences(
+                KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME, Context.MODE_PRIVATE);
+    }
+
+    private static SharedPreferences.Editor getDisplayNameSharedPreferenceEditor(Context context) {
+        return getDisplayNameSharedPreferences(context).edit();
+    }
+
+    private static void saveDisplayNameToSharedPreference(
+            Context context, int subId, CharSequence displayName) {
+        getDisplayNameSharedPreferenceEditor(context)
+                .putString(SUB_ID + subId, String.valueOf(displayName))
+                .apply();
+    }
+
+    private static String getDisplayNameFromSharedPreference(Context context, int subid) {
+        return getDisplayNameSharedPreferences(context).getString(SUB_ID + subid, "");
+    }
+
     public static String getDisplayName(SubscriptionInfo info) {
         final CharSequence name = info.getDisplayName();
         if (name != null) {
diff --git a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
index dfe6df2..a6b565a 100644
--- a/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
+++ b/src/com/android/settings/notification/NotificationAccessConfirmationActivity.java
@@ -67,7 +67,9 @@
         mUserId = getIntent().getIntExtra(EXTRA_USER_ID, UserHandle.USER_NULL);
         CharSequence mAppLabel;
 
-        if (mComponentName == null || mComponentName.getPackageName() == null) {
+        if (mComponentName == null || mComponentName.getPackageName() == null
+                || mComponentName.flattenToString().length()
+                > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
             finish();
             return;
         }
diff --git a/src/com/android/settings/notification/NotificationAccessSettings.java b/src/com/android/settings/notification/NotificationAccessSettings.java
index 369c4f6..e2ef0dd 100644
--- a/src/com/android/settings/notification/NotificationAccessSettings.java
+++ b/src/com/android/settings/notification/NotificationAccessSettings.java
@@ -66,7 +66,6 @@
     private static final String TAG = "NotifAccessSettings";
     static final String ALLOWED_KEY = "allowed";
     static final String NOT_ALLOWED_KEY = "not_allowed";
-    private static final int MAX_CN_LENGTH = 500;
 
     private static final ManagedServiceSettings.Config CONFIG =
             new ManagedServiceSettings.Config.Builder()
@@ -150,7 +149,8 @@
         for (ServiceInfo service : services) {
             final ComponentName cn = new ComponentName(service.packageName, service.name);
             boolean isAllowed = mNm.isNotificationListenerAccessGranted(cn);
-            if (!isAllowed && cn.flattenToString().length() > MAX_CN_LENGTH) {
+            if (!isAllowed && cn.flattenToString().length()
+                    > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
                 continue;
             }
 
diff --git a/src/com/android/settings/password/SetupChooseLockPattern.java b/src/com/android/settings/password/SetupChooseLockPattern.java
index 2cad181..4424b4f 100644
--- a/src/com/android/settings/password/SetupChooseLockPattern.java
+++ b/src/com/android/settings/password/SetupChooseLockPattern.java
@@ -90,6 +90,12 @@
             }
             // Show the skip button during SUW but not during Settings > Biometric Enrollment
             mSkipOrClearButton.setOnClickListener(this::onSkipOrClearButtonClick);
+
+            final View headerView = view.findViewById(R.id.sud_layout_header);
+            final ViewGroup.MarginLayoutParams lp =
+                    (ViewGroup.MarginLayoutParams) headerView.getLayoutParams();
+            lp.bottomMargin = 0;
+            view.setLayoutParams(lp);
             return view;
         }
 
diff --git a/src/com/android/settings/users/GuestTelephonyPreferenceController.java b/src/com/android/settings/users/GuestTelephonyPreferenceController.java
index a935b8a..2aa808f 100644
--- a/src/com/android/settings/users/GuestTelephonyPreferenceController.java
+++ b/src/com/android/settings/users/GuestTelephonyPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.users;
 
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.UserManager;
 
@@ -73,6 +74,7 @@
     public void updateState(Preference preference) {
         super.updateState(preference);
         mUserCaps.updateAddUserCapabilities(mContext);
-        preference.setVisible(isAvailable() && mUserCaps.mUserSwitcherEnabled);
+        preference.setVisible(isAvailable() && mUserCaps.mUserSwitcherEnabled && mContext
+                .getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
     }
 }
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index d9fbc42..93b7c78 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -977,10 +977,10 @@
             return;
         }
         try {
-            getContext().getSystemService(UserManager.class)
-                    .removeUserWhenPossible(UserHandle.of(UserHandle.myUserId()),
-                            /* overrideDevicePolicy= */ false);
-            ActivityManager.getService().switchUser(UserHandle.USER_SYSTEM);
+            mUserManager.removeUserWhenPossible(
+                    UserHandle.of(UserHandle.myUserId()), /* overrideDevicePolicy= */ false);
+            ActivityManager.getService().switchUser(
+                    mUserManager.getPreviousForegroundUser().getIdentifier());
         } catch (RemoteException re) {
             Log.e(TAG, "Unable to remove self user");
         }
@@ -1099,7 +1099,7 @@
         }
         mMetricsFeatureProvider.action(getActivity(),
                 SettingsEnums.ACTION_USER_GUEST_EXIT_CONFIRMED);
-        switchToUserId(UserHandle.USER_SYSTEM);
+        switchToUserId(mUserManager.getPreviousForegroundUser().getIdentifier());
     }
 
     private int createGuest() {
@@ -1139,8 +1139,8 @@
             // Create a new guest in the foreground, and then immediately switch to it
             int newGuestUserId = createGuest();
             if (newGuestUserId == UserHandle.USER_NULL) {
-                Log.e(TAG, "Could not create new guest, switching back to system user");
-                switchToUserId(UserHandle.USER_SYSTEM);
+                Log.e(TAG, "Could not create new guest, switching back to previous user");
+                switchToUserId(mUserManager.getPreviousForegroundUser().getIdentifier());
                 mUserManager.removeUser(oldGuestUserId);
                 WindowManagerGlobal.getWindowManagerService().lockNow(/* options= */ null);
                 return;
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationAccessConfirmationActivityTest.java b/tests/robotests/src/com/android/settings/notification/NotificationAccessConfirmationActivityTest.java
new file mode 100644
index 0000000..86631ff
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/NotificationAccessConfirmationActivityTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2023 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.notification;
+
+import static com.android.internal.notification.NotificationAccessConfirmationActivityContract.EXTRA_COMPONENT_NAME;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.Shadows.shadowOf;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+import com.google.common.base.Strings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class NotificationAccessConfirmationActivityTest {
+
+    @Test
+    public void start_showsDialog() {
+        ComponentName cn = new ComponentName("com.example", "com.example.SomeService");
+        installPackage(cn.getPackageName(), "X");
+
+        NotificationAccessConfirmationActivity activity = startActivityWithIntent(cn);
+
+        assertThat(activity.isFinishing()).isFalse();
+        assertThat(getDialogText(activity)).isEqualTo(
+                activity.getString(R.string.notification_listener_security_warning_summary, "X"));
+    }
+
+    @Test
+    public void start_withMissingPackage_finishes() {
+        ComponentName cn = new ComponentName("com.example", "com.example.SomeService");
+
+        NotificationAccessConfirmationActivity activity = startActivityWithIntent(cn);
+
+        assertThat(getDialogText(activity)).isNull();
+        assertThat(activity.isFinishing()).isTrue();
+    }
+
+    @Test
+    public void start_componentNameTooLong_finishes() {
+        ComponentName longCn = new ComponentName("com.example", Strings.repeat("Blah", 150));
+        installPackage(longCn.getPackageName(), "<Unused>");
+
+        NotificationAccessConfirmationActivity activity = startActivityWithIntent(longCn);
+
+        assertThat(getDialogText(activity)).isNull();
+        assertThat(activity.isFinishing()).isTrue();
+    }
+
+    private static NotificationAccessConfirmationActivity startActivityWithIntent(
+            ComponentName cn) {
+        return Robolectric.buildActivity(
+                        NotificationAccessConfirmationActivity.class,
+                        new Intent().putExtra(EXTRA_COMPONENT_NAME, cn))
+                .setup()
+                .get();
+    }
+
+    private static void installPackage(String packageName, String appName) {
+        PackageInfo pi = new PackageInfo();
+        pi.packageName = packageName;
+        pi.applicationInfo = new ApplicationInfo();
+        pi.applicationInfo.packageName = packageName;
+        pi.applicationInfo.name = appName;
+        shadowOf(RuntimeEnvironment.application.getPackageManager()).installPackage(pi);
+    }
+
+    @Nullable
+    private static String getDialogText(Activity activity) {
+        TextView tv = activity.getWindow().findViewById(android.R.id.message);
+        CharSequence text = (tv != null ? tv.getText() : null);
+        return text != null ? text.toString() : null;
+    }
+
+}
diff --git a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
index c5e0813..2f46986 100644
--- a/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
+++ b/tests/robotests/src/com/android/settings/password/SetupChooseLockPatternTest.java
@@ -28,6 +28,7 @@
 import android.os.UserHandle;
 import android.util.TypedValue;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.TextView;
 
@@ -114,6 +115,14 @@
         assertThat(button.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
+    @Test
+    public void headerView_noBottomMargin() {
+        final View header = mActivity.findViewById(R.id.sud_layout_header);
+        final ViewGroup.MarginLayoutParams lp =
+                (ViewGroup.MarginLayoutParams) header.getLayoutParams();
+        assertThat(lp.bottomMargin).isEqualTo(0);
+    }
+
     private void verifyScreenLockOptionsShown() {
         final Button button = mActivity.findViewById(R.id.screen_lock_options);
         assertThat(button).isNotNull();
diff --git a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
index 249b713..4601a1c 100644
--- a/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/applications/specialaccess/notificationaccess/ApprovalPreferenceControllerTest.java
@@ -84,6 +84,36 @@
     }
 
     @Test
+    public void updateState_enabled() {
+        when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
+                AppOpsManager.MODE_ALLOWED);
+        when(mNm.isNotificationListenerAccessGranted(mCn)).thenReturn(true);
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
+                mContext);
+        pref.setAppOps(mAppOpsManager);
+
+        mController.updateState(pref);
+
+        assertThat(pref.isEnabled()).isTrue();
+    }
+
+    @Test
+    public void updateState_invalidCn_disabled() {
+        ComponentName longCn = new ComponentName("com.example.package",
+                com.google.common.base.Strings.repeat("Blah", 150));
+        mController.setCn(longCn);
+        when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
+                AppOpsManager.MODE_ALLOWED);
+        RestrictedSwitchPreference pref = new RestrictedSwitchPreference(
+                mContext);
+        pref.setAppOps(mAppOpsManager);
+
+        mController.updateState(pref);
+
+        assertThat(pref.isEnabled()).isFalse();
+    }
+
+    @Test
     public void updateState_checked() {
         when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), anyString())).thenReturn(
                 AppOpsManager.MODE_ALLOWED);
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
index 63dca7e..f063042 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -16,26 +16,32 @@
 
 package com.android.settings.network;
 
+import static com.android.settings.network.SubscriptionUtil.KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME;
+import static com.android.settings.network.SubscriptionUtil.SUB_ID;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
-import com.android.settings.R;
-
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 
+import com.android.settings.R;
+
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -445,6 +451,35 @@
     }
 
     @Test
+    public void getUniqueDisplayName_hasRecord_useRecordBeTheResult() {
+        final SubscriptionInfo info1 = mock(SubscriptionInfo.class);
+        final SubscriptionInfo info2 = mock(SubscriptionInfo.class);
+        when(info1.getSubscriptionId()).thenReturn(SUBID_1);
+        when(info2.getSubscriptionId()).thenReturn(SUBID_2);
+        when(info1.getDisplayName()).thenReturn(CARRIER_1);
+        when(info2.getDisplayName()).thenReturn(CARRIER_1);
+        when(mSubMgr.getAvailableSubscriptionInfoList()).thenReturn(
+                Arrays.asList(info1, info2));
+
+        SharedPreferences sp = mock(SharedPreferences.class);
+        when(mContext.getSharedPreferences(
+                KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME, Context.MODE_PRIVATE)).thenReturn(sp);
+        when(sp.getString(eq(SUB_ID + SUBID_1), anyString())).thenReturn(CARRIER_1 + "6789");
+        when(sp.getString(eq(SUB_ID + SUBID_2), anyString())).thenReturn(CARRIER_1 + "4321");
+
+
+        final CharSequence nameOfSub1 =
+                SubscriptionUtil.getUniqueSubscriptionDisplayName(info1, mContext);
+        final CharSequence nameOfSub2 =
+                SubscriptionUtil.getUniqueSubscriptionDisplayName(info2, mContext);
+
+        assertThat(nameOfSub1).isNotNull();
+        assertThat(nameOfSub2).isNotNull();
+        assertEquals(CARRIER_1 + "6789", nameOfSub1.toString());
+        assertEquals(CARRIER_1 + "4321", nameOfSub2.toString());
+    }
+
+    @Test
     public void isInactiveInsertedPSim_nullSubInfo_doesNotCrash() {
         assertThat(SubscriptionUtil.isInactiveInsertedPSim(null)).isFalse();
     }