Merge "[Audiosharing] Update the volume control registration flow." into main
diff --git a/aconfig/settings_security_flag_declarations.aconfig b/aconfig/settings_security_flag_declarations.aconfig
new file mode 100644
index 0000000..42ef4d0
--- /dev/null
+++ b/aconfig/settings_security_flag_declarations.aconfig
@@ -0,0 +1,8 @@
+package: "com.android.settings.flags"
+
+flag {
+  name: "protect_lock_after_timeout_with_auth"
+  namespace: "safety_center"
+  description: "Require an auth challenge to open Lock after timeout page"
+  bug: "315937886"
+}
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 402f526..bd9ae3b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11285,7 +11285,7 @@
     <string name="mobile_network_sim_name_rename">Save</string>
     <!-- Label for the on position of a switch on the mobile network details page which allows
          disabling/enabling a SIM. The SIM is enabled in this state. [CHAR LIMIT=40] -->
-    <string name="mobile_network_use_sim_on">Use SIM</string>
+    <string name="mobile_network_use_sim_on">Use this SIM</string>
     <!-- Label for the off position of a switch on the mobile network details page which allows
          disabling/enabling a SIM. The SIM is disabled in this state. [CHAR LIMIT=40] -->
     <string name="mobile_network_use_sim_off">Off</string>
@@ -11428,6 +11428,56 @@
     <!-- Body text of DSDS activation failure dialog. Users could toggle the selected SIM again or reboot to recover. [CHAR LIMIT=NONE] -->
     <string name="dsds_activation_failure_body_msg2">Try turning on the SIM again. If the problem continues, restart your device.</string>
 
+    <!-- Strings for dual SIM onboarding -->
+    <!-- Title of dual sim onboarding's bottom sheets. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_bottomsheets_title">Set up your SIM</string>
+    <!-- Body text of dual sim onboarding's bottom sheets. [CHAR LIMIT=NONE] -->
+    <string name="sim_onboarding_bottomsheets_msg">Set your mobile network preferences to use multiple SIMs on this device</string>
+    <!-- Title of dual sim onboarding's label sim page. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_label_sim_title">Label your SIMs</string>
+    <!-- Body text of dual sim onboarding's label sim page. [CHAR LIMIT=NONE] -->
+    <string name="sim_onboarding_label_sim_msg">You’ll see these labels when making calls, sending texts, and using data, and in Settings</string>
+    <!-- Title of dual sim onboarding's label sim dialog. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_label_sim_dialog_title">SIM label</string>
+    <!-- Label text of dual sim onboarding's label sim dialog. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_label_sim_dialog_label">Label</string>
+    <!-- Title of dual sim onboarding's select sim page. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_select_sim_title">Select which SIMs to use</string>
+    <!-- Body text of dual sim onboarding's select sim page. [CHAR LIMIT=NONE] -->
+    <string name="sim_onboarding_select_sim_msg">You can use 2 SIMs at a time</string>
+    <!-- Title of dual sim onboarding's primary sim page. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_primary_sim_title">Set your primary SIMs</string>
+    <!-- Body text of dual sim onboarding's primary sim page. [CHAR LIMIT=NONE] -->
+    <string name="sim_onboarding_primary_sim_msg">Choose which SIMs to use by default for calls, texts, and data</string>
+
+    <!-- Title of primary sim at SIMs page. [CHAR LIMIT=30] -->
+    <string name="primary_sim_title">Your primary SIMs</string>
+
+    <!-- Title of Calls item/dialog at dual sim onboarding's primary sim page or SIMs page. [CHAR LIMIT=30] -->
+    <string name="primary_sim_calls_title">Calls</string>
+    <!-- Title of Texts item/dialog at dual sim onboarding's primary sim page or SIMs page. [CHAR LIMIT=30] -->
+    <string name="primary_sim_texts_title">Texts</string>
+    <!-- Title of automatic data switching at dual sim onboarding's primary sim page or SIMs page. [CHAR LIMIT=30] -->
+    <string name="primary_sim_automatic_data_title">Automatic data switching</string>
+    <!-- Body text of automatic data switching at dual sim onboarding's primary sim page or SIMs page. [CHAR LIMIT=NONE] -->
+    <string name="primary_sim_automatic_data_msg">Use data from either SIM depending on coverage and availability</string>
+
+    <!-- Text of phone number item when the sim is data only. [CHAR LIMIT=NONE] -->
+    <string name="sim_onboarding_phoneNumber_data_only">Data only</string>
+
+    <!-- Button on the dual sim onboarding to start to set up sim. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_setup">Set up</string>
+    <!-- Button on the dual sim onboarding to go to next page. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_next">Next</string>
+    <!-- Text on the progressbar of dual sim onboarding for turning sim on. [CHAR LIMIT=30] -->
+    <string name="sim_onboarding_profressbar_turning_sim_on">Turning on <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>&#8230;</string>
+    <!-- Title of service provider name(SPN) at mobile network settings page. [CHAR LIMIT=30] -->
+    <string name="mobile_network_spn_title">Mobile network</string>
+    <!-- Title of phone number at mobile network settings page. [CHAR LIMIT=30] -->
+    <string name="mobile_network_phone_number_title">Phone number</string>
+    <!-- Title of SIM label and color editor dialog at mobile network settings page. [CHAR LIMIT=30] -->
+    <string name="mobile_network_sim_label_color_title">SIM label and color</string>
+
     <!--  Strings for SIM push notifications  -->
     <!-- Category name of the notifications related to SIM setup. [CHAR LIMIT=NONE] -->
     <string name="sim_setup_channel_id">Network activation</string>
diff --git a/res/xml/screen_lock_settings.xml b/res/xml/screen_lock_settings.xml
index 3f732b9..19061d9 100644
--- a/res/xml/screen_lock_settings.xml
+++ b/res/xml/screen_lock_settings.xml
@@ -40,7 +40,7 @@
 
 
     <!-- available in pin/pattern/password -->
-    <com.android.settings.display.TimeoutListPreference
+    <com.android.settings.security.screenlock.ProtectedTimeoutListPreference
         android:key="lock_after_timeout"
         android:title="@string/lock_after_timeout"
         android:summary="@string/summary_placeholder"
diff --git a/src/com/android/settings/security/screenlock/ProtectedTimeoutListPreference.java b/src/com/android/settings/security/screenlock/ProtectedTimeoutListPreference.java
new file mode 100644
index 0000000..26d914c
--- /dev/null
+++ b/src/com/android/settings/security/screenlock/ProtectedTimeoutListPreference.java
@@ -0,0 +1,40 @@
+/*
+ * 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.security.screenlock;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+import com.android.settings.display.TimeoutListPreference;
+import com.android.settings.flags.Flags;
+import com.android.settings.wifi.dpp.WifiDppUtils;
+
+/** Wraps {@link TimeoutListPreference} with an authentication challenge for user. */
+public class ProtectedTimeoutListPreference extends TimeoutListPreference {
+    public ProtectedTimeoutListPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void performClick() {
+        if (Flags.protectLockAfterTimeoutWithAuth()) {
+            WifiDppUtils.showLockScreen(getContext(), super::performClick);
+        } else {
+            super.performClick();
+        }
+    }
+}
diff --git a/src/com/android/settings/spa/app/appinfo/AppArchiveButton.kt b/src/com/android/settings/spa/app/appinfo/AppArchiveButton.kt
index 0eef9c3..e4fb1ea 100644
--- a/src/com/android/settings/spa/app/appinfo/AppArchiveButton.kt
+++ b/src/com/android/settings/spa/app/appinfo/AppArchiveButton.kt
@@ -54,6 +54,7 @@
     private val packageName = packageInfoPresenter.packageName
     private val userHandle = UserHandle.of(packageInfoPresenter.userId)
     private var broadcastReceiverIsCreated = false
+    private lateinit var appLabel: CharSequence
 
     @Composable
     fun getActionButton(app: ApplicationInfo): ActionButton {
@@ -61,11 +62,12 @@
             val intentFilter = IntentFilter(INTENT_ACTION)
             DisposableBroadcastReceiverAsUser(intentFilter, userHandle) { intent ->
                 if (app.packageName == intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)) {
-                    onReceive(intent, app)
+                    onReceive(intent)
                 }
             }
             broadcastReceiverIsCreated = true
         }
+        appLabel = userPackageManager.getApplicationLabel(app)
         return ActionButton(
             text = context.getString(R.string.archive),
             imageVector = Icons.Outlined.CloudUpload,
@@ -113,10 +115,9 @@
         }
     }
 
-    private fun onReceive(intent: Intent, app: ApplicationInfo) {
+    private fun onReceive(intent: Intent) {
         when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, Int.MIN_VALUE)) {
             PackageInstaller.STATUS_SUCCESS -> {
-                val appLabel = userPackageManager.getApplicationLabel(app)
                 Toast.makeText(
                     context,
                     context.getString(R.string.archiving_succeeded, appLabel),
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
index 5d9202f..e259cad 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowContentResolver.java
@@ -16,16 +16,10 @@
 
 package com.android.settings.testutils.shadow;
 
-import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
-
 import android.accounts.Account;
 import android.annotation.UserIdInt;
 import android.content.ContentResolver;
 import android.content.SyncAdapterType;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.provider.SearchIndexablesContract;
 import android.text.TextUtils;
 
 import org.robolectric.annotation.Implementation;
@@ -35,7 +29,7 @@
 import java.util.Map;
 
 @Implements(ContentResolver.class)
-public class ShadowContentResolver {
+public class ShadowContentResolver extends org.robolectric.shadows.ShadowContentResolver {
 
     private static SyncAdapterType[] sSyncAdapterTypes = new SyncAdapterType[0];
     private static Map<String, Integer> sSyncable = new HashMap<>();
@@ -48,23 +42,14 @@
     }
 
     @Implementation
-    protected final Cursor query(Uri uri, String[] projection, String selection,
-            String[] selectionArgs, String sortOrder) {
-        MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
-        MatrixCursor.RowBuilder builder = cursor.newRow()
-                .add(SearchIndexablesContract.NonIndexableKey.COLUMN_KEY_VALUE, "");
-        return cursor;
-    }
-
-    @Implementation
     protected static int getIsSyncableAsUser(Account account, String authority, int userId) {
-        return sSyncable.containsKey(authority) ? sSyncable.get(authority) : 1;
+        return sSyncable.getOrDefault(authority, 1);
     }
 
     @Implementation
     protected static boolean getSyncAutomaticallyAsUser(Account account, String authority,
             int userId) {
-        return sSyncAutomatically.containsKey(authority) ? sSyncAutomatically.get(authority) : true;
+        return sSyncAutomatically.getOrDefault(authority, true);
     }
 
     @Implementation
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
index d66aa61..5989d49 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowRestrictedLockUtilsInternal.java
@@ -50,7 +50,7 @@
     }
 
     @Implementation
-    protected static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
+    protected static EnforcedAdmin checkIfMeteredDataUsageUserControlDisabled(Context context,
             String packageName, int userId) {
         if (sIsRestricted) {
             return new EnforcedAdmin();
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppArchiveButtonTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppArchiveButtonTest.kt
index df1f153..6b4cc0d 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppArchiveButtonTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppArchiveButtonTest.kt
@@ -63,8 +63,10 @@
         whenever(packageInfoPresenter.context).thenReturn(context)
         whenever(packageInfoPresenter.userPackageManager).thenReturn(userPackageManager)
         whenever(userPackageManager.packageInstaller).thenReturn(packageInstaller)
+        whenever(userPackageManager.getApplicationLabel(any())).thenReturn(APP_LABEL)
         whenever(packageInfoPresenter.packageName).thenReturn(PACKAGE_NAME)
-        appArchiveButton = AppArchiveButton(packageInfoPresenter, isHibernationSwitchEnabledStateFlow)
+        appArchiveButton =
+            AppArchiveButton(packageInfoPresenter, isHibernationSwitchEnabledStateFlow)
     }
 
     @Test
@@ -150,5 +152,6 @@
 
     private companion object {
         const val PACKAGE_NAME = "package.name"
+        const val APP_LABEL = "App label"
     }
 }
diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonsTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonsTest.kt
index 733e1a4..c742bd7 100644
--- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonsTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppButtonsTest.kt
@@ -45,6 +45,7 @@
 import org.mockito.Mock
 import org.mockito.MockitoSession
 import org.mockito.Spy
+import org.mockito.kotlin.any
 import org.mockito.quality.Strictness
 import org.mockito.Mockito.`when` as whenever
 
@@ -80,6 +81,7 @@
         whenever(packageInfoPresenter.context).thenReturn(context)
         whenever(packageInfoPresenter.packageName).thenReturn(PACKAGE_NAME)
         whenever(packageInfoPresenter.userPackageManager).thenReturn(packageManager)
+        whenever(packageManager.getApplicationLabel(any())).thenReturn(APP_LABEL)
         whenever(packageManager.packageInstaller).thenReturn(packageInstaller)
         whenever(packageManager.getPackageInfo(PACKAGE_NAME, 0)).thenReturn(PACKAGE_INFO)
         whenever(AppUtils.isMainlineModule(packageManager, PACKAGE_NAME)).thenReturn(false)
@@ -113,7 +115,8 @@
         featureFlags.setFlag(Flags.FLAG_ARCHIVING, false)
         setContent()
 
-        composeTestRule.onNodeWithText(context.getString(R.string.launch_instant_app)).assertIsDisplayed()
+        composeTestRule.onNodeWithText(context.getString(R.string.launch_instant_app))
+            .assertIsDisplayed()
     }
 
     @Test
@@ -122,7 +125,8 @@
         featureFlags.setFlag(Flags.FLAG_ARCHIVING, true)
         setContent()
 
-        composeTestRule.onNodeWithText(context.getString(R.string.launch_instant_app)).assertIsNotDisplayed()
+        composeTestRule.onNodeWithText(context.getString(R.string.launch_instant_app))
+            .assertIsNotDisplayed()
     }
 
     @Test
@@ -184,6 +188,7 @@
 
     private companion object {
         const val PACKAGE_NAME = "package.name"
+        const val APP_LABEL = "App label"
         val PACKAGE_INFO = PackageInfo().apply {
             applicationInfo = ApplicationInfo().apply {
                 packageName = PACKAGE_NAME