Merge "Create only one media session per audio stream media service." into main
diff --git a/res-product/values-pt-rPT/strings.xml b/res-product/values-pt-rPT/strings.xml
index 25f8b74..67c7b74 100644
--- a/res-product/values-pt-rPT/strings.xml
+++ b/res-product/values-pt-rPT/strings.xml
@@ -266,7 +266,7 @@
     <string name="ethernet_tethering_subtext" product="default" msgid="8652438909365718644">"Partilhar a ligação à Internet do telemóvel através de Ethernet"</string>
     <string name="ethernet_tethering_subtext" product="tablet" msgid="2227710549796706455">"Partilhar a ligação à Internet do tablet por Ethernet"</string>
     <string name="about_settings" product="tablet" msgid="1471390492111370330">"Acerca do tablet"</string>
-    <string name="about_settings" product="default" msgid="2621311564780208250">"Acerca do telefone"</string>
+    <string name="about_settings" product="default" msgid="2621311564780208250">"Acerca do telemóvel"</string>
     <string name="about_settings" product="device" msgid="7595574154492383452">"Acerca do dispositivo"</string>
     <string name="about_settings" product="emulator" msgid="1099246296173401003">"Acerca do dispositivo emulado"</string>
     <string name="install_all_warning" product="tablet" msgid="1732116924846572063">"O seu tablet e os dados pessoais são mais vulneráveis a ataques de apps desconhecidas. Ao instalar apps desta fonte, aceita ser responsável por quaisquer danos no tablet ou perdas de dados que possam resultar da utilização do mesmo."</string>
diff --git a/res-product/values-zh-rCN/strings.xml b/res-product/values-zh-rCN/strings.xml
index c11fa41..873d35e 100644
--- a/res-product/values-zh-rCN/strings.xml
+++ b/res-product/values-zh-rCN/strings.xml
@@ -297,8 +297,8 @@
     <string name="battery_tip_dialog_summary_message" product="device" msgid="7885502661524685786">"您的应用目前耗电量正常。如果应用耗电量过高,您的设备会为您提供操作建议。\n\n如果电池电量不足,您可以随时开启省电模式。"</string>
     <string name="smart_battery_summary" product="default" msgid="1210637215867635435">"限制不常用的应用的耗电量"</string>
     <string name="battery_usage_screen_footer" product="default" msgid="8872101342490341865">"手机充电时,系统不会衡量电池使用情况和屏幕使用时间"</string>
-    <string name="battery_usage_screen_footer" product="tablet" msgid="1876984641036532124">"平板电脑充电时,系统不会衡量电池用量和设备使用时间"</string>
-    <string name="battery_usage_screen_footer" product="device" msgid="6488857833906266507">"设备充电时,系统不会衡量电池用量和设备使用时间"</string>
+    <string name="battery_usage_screen_footer" product="tablet" msgid="1876984641036532124">"平板电脑充电时,系统不会衡量电池用量和屏幕使用时间"</string>
+    <string name="battery_usage_screen_footer" product="device" msgid="6488857833906266507">"设备充电时,系统不会衡量电池用量和屏幕使用时间"</string>
     <string name="credentials_install_summary" product="nosdcard" msgid="8585932964626513863">"从存储设备安装证书"</string>
     <string name="credentials_install_summary" product="default" msgid="879796378361350092">"从SD卡安装证书"</string>
     <string name="really_remove_account_message" product="tablet" msgid="5134483498496943623">"移除该账号会从平板电脑中删除所有相关的邮件、联系人以及其他数据。"</string>
diff --git a/res/layout/modes_set_schedule_layout.xml b/res/layout/modes_set_schedule_layout.xml
index e90dc7c..6b7ebc8 100644
--- a/res/layout/modes_set_schedule_layout.xml
+++ b/res/layout/modes_set_schedule_layout.xml
@@ -127,7 +127,8 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingHorizontal="8dp"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Small" />
+            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Small"
+            android:textColor="?android:attr/textColorSecondary" />
 
         <!-- right side line divider -->
         <View
diff --git a/res/xml/special_access.xml b/res/xml/special_access.xml
index 7e8969d..d0fe980 100644
--- a/res/xml/special_access.xml
+++ b/res/xml/special_access.xml
@@ -60,7 +60,7 @@
 
     <Preference
         android:key="zen_access"
-        android:title="@string/manage_zen_access_title"
+        android:title="@string/manage_zen_modes_access_title"
         android:order="-1500"
         android:fragment="com.android.settings.notification.zen.ZenAccessSettings"
         settings:controller="com.android.settings.applications.specialaccess.zenaccess.ZenAccessController" />
diff --git a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
index 90d733e..1712e85 100644
--- a/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
+++ b/src/com/android/settings/applications/appinfo/AppInfoDashboardFragment.java
@@ -715,7 +715,7 @@
         if (mPackageName == null) {
             final Intent intent = args == null ?
                     getActivity().getIntent() : (Intent) args.getParcelable("intent");
-            if (intent != null) {
+            if (intent != null && intent.getData() != null) {
                 mPackageName = intent.getData().getSchemeSpecificPart();
             }
         }
diff --git a/src/com/android/settings/network/apn/ApnEditor.java b/src/com/android/settings/network/apn/ApnEditor.java
index d1b2f2f..dc9741d 100644
--- a/src/com/android/settings/network/apn/ApnEditor.java
+++ b/src/com/android/settings/network/apn/ApnEditor.java
@@ -198,6 +198,10 @@
     public static final String APN_TYPE_MCX = "mcx";
     /** APN type for XCAP */
     public static final String APN_TYPE_XCAP = "xcap";
+    /** APN type for OEM_PAID networks (Automotive PANS) */
+    public static final String APN_TYPE_OEM_PAID = "oem_paid";
+    /** APN type for OEM_PRIVATE networks (Automotive PANS) */
+    public static final String APN_TYPE_OEM_PRIVATE = "oem_private";
     /** Array of all APN types */
     public static final String[] APN_TYPES = {APN_TYPE_DEFAULT,
             APN_TYPE_MMS,
@@ -211,6 +215,14 @@
             APN_TYPE_EMERGENCY,
             APN_TYPE_MCX,
             APN_TYPE_XCAP,
+            APN_TYPE_OEM_PAID,
+            APN_TYPE_OEM_PRIVATE,
+    };
+
+    /** Array of APN types that are never user-editable */
+    private static final String[] ALWAYS_READ_ONLY_APN_TYPES = new String[] {
+        APN_TYPE_OEM_PAID,
+        APN_TYPE_OEM_PRIVATE,
     };
 
     /**
@@ -361,6 +373,18 @@
     }
 
     /**
+     * Fetch complete list of read only APN types.
+     *
+     * The list primarily comes from carrier config, but is also supplied by APN types which are
+     * always read only.
+     */
+    static String[] getReadOnlyApnTypes(PersistableBundle b) {
+        String[] carrierReadOnlyApnTypes = b.getStringArray(
+                CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
+        return ArrayUtils.concat(String.class, carrierReadOnlyApnTypes, ALWAYS_READ_ONLY_APN_TYPES);
+    }
+
+    /**
      * Enable ProxySubscriptionMgr with Lifecycle support for all controllers
      * live within this fragment
      */
@@ -1355,8 +1379,7 @@
         if (configManager != null) {
             final PersistableBundle b = configManager.getConfigForSubId(mSubId);
             if (b != null) {
-                mReadOnlyApnTypes = b.getStringArray(
-                        CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
+                mReadOnlyApnTypes = getReadOnlyApnTypes(b);
                 if (!ArrayUtils.isEmpty(mReadOnlyApnTypes)) {
                     Log.d(TAG,
                             "onCreate: read only APN type: " + Arrays.toString(mReadOnlyApnTypes));
diff --git a/src/com/android/settings/network/apn/ApnSettings.java b/src/com/android/settings/network/apn/ApnSettings.java
index 2debba1..0e3c3a4 100644
--- a/src/com/android/settings/network/apn/ApnSettings.java
+++ b/src/com/android/settings/network/apn/ApnSettings.java
@@ -135,8 +135,7 @@
         mHideImsApn = b.getBoolean(CarrierConfigManager.KEY_HIDE_IMS_APN_BOOL);
         mAllowAddingApns = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
         if (mAllowAddingApns) {
-            final String[] readOnlyApnTypes = b.getStringArray(
-                    CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
+            final String[] readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b);
             // if no apn type can be edited, do not allow adding APNs
             if (ApnEditor.hasAllApns(readOnlyApnTypes)) {
                 Log.d(TAG, "not allowing adding APN because all APN types are read only");
diff --git a/src/com/android/settings/network/apn/ApnStatus.kt b/src/com/android/settings/network/apn/ApnStatus.kt
index 6492d39..68588bb 100644
--- a/src/com/android/settings/network/apn/ApnStatus.kt
+++ b/src/com/android/settings/network/apn/ApnStatus.kt
@@ -204,9 +204,7 @@
         CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL
     )
     val customizedConfig = CustomizedConfig(
-        readOnlyApnTypes = b.getStringArray(
-            CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY
-        )?.toList() ?: emptyList(),
+        readOnlyApnTypes = ApnEditor.getReadOnlyApnTypes(b)?.toList() ?: emptyList(),
         readOnlyApnFields = b.getStringArray(
             CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY
         )?.toList() ?: emptyList(),
diff --git a/src/com/android/settings/network/apn/ApnTypes.kt b/src/com/android/settings/network/apn/ApnTypes.kt
index b9bc480..4f84ac7 100644
--- a/src/com/android/settings/network/apn/ApnTypes.kt
+++ b/src/com/android/settings/network/apn/ApnTypes.kt
@@ -45,6 +45,8 @@
         ApnSetting.TYPE_VSIM_STRING,
         ApnSetting.TYPE_BIP_STRING,
         ApnSetting.TYPE_ENTERPRISE_STRING,
+        ApnSetting.TYPE_OEM_PAID_STRING,
+        ApnSetting.TYPE_OEM_PRIVATE_STRING,
     )
 
     private fun splitToList(apnType: String): List<String> {
diff --git a/src/com/android/settings/sim/PreferredSimDialogFragment.java b/src/com/android/settings/sim/PreferredSimDialogFragment.java
index 96c0eb6..aa42f3c 100644
--- a/src/com/android/settings/sim/PreferredSimDialogFragment.java
+++ b/src/com/android/settings/sim/PreferredSimDialogFragment.java
@@ -21,10 +21,12 @@
 import android.app.Activity;
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -91,8 +93,12 @@
         }
 
         if (dialog == null) {
-            Log.d(TAG, "Dialog is null.");
-            dismiss();
+            dismiss("Dialog is null.");
+            return;
+        }
+        Context context = getContext();
+        if (context == null) {
+            dismiss("getContext is null.");
             return;
         }
 
@@ -100,24 +106,44 @@
         if (info == null || (info.isEmbedded()
             && (info.getProfileClass() == PROFILE_CLASS_PROVISIONING
                 || (Flags.oemEnabledSatelliteFlag() && info.isOnlyNonTerrestrialNetwork())))) {
-            dismiss();
+            dismiss("SubscriptionInfo is null or other esim's cases.");
             return;
         }
         Log.d(TAG, "SubscriptionInfo: " + info);
+        TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
+        if (telephonyManager == null) {
+            dismiss("TelephonyManager is null.");
+            return;
+        }
+        telephonyManager = telephonyManager.createForSubscriptionId(info.getSubscriptionId());
+        if (telephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)) {
+            dismiss("mobile data is on.");
+            final SimDialogActivity activity = (SimDialogActivity) getActivity();
+            if (activity != null) {
+                activity.finish();
+            }
+            return;
+        }
+
         final CharSequence simName =
-                SubscriptionUtil.getUniqueSubscriptionDisplayName(info, getContext());
+                SubscriptionUtil.getUniqueSubscriptionDisplayName(info, context);
         final String title =
-                getContext().getString(
+                context.getString(
                         getTitleResId(),
                         simName);
         final String message =
-                getContext().getString(
+                context.getString(
                         R.string.sim_preferred_message,
                         simName);
         dialog.setTitle(title);
         dialog.setMessage(message);
     }
 
+    private void dismiss(String log) {
+        Log.d(TAG, log);
+        dismiss();
+    }
+
     @Override
     public void updateDialog() {
         updateDialog((AlertDialog) getDialog());
diff --git a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
index 4dc2e9e..b601eb3 100644
--- a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
+++ b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java
@@ -356,10 +356,11 @@
                 log("setSpeedType(), setBand(BAND_2GHZ)");
                 configBuilder.setBand(BAND_2GHZ);
             }
-            // Set the security type back to WPA2/WPA3 if we're moving from 6GHz to something else.
-            if ((config.getBand() & BAND_6GHZ) != 0) {
-                configBuilder.setPassphrase(
-                        generatePassword(config), SECURITY_TYPE_WPA3_SAE_TRANSITION);
+            // Set the security type back to WPA2/WPA3 if the password is at least 8 characters and
+            // we're moving from 6GHz to something else.
+            String passphrase = generatePassword(config);
+            if ((passphrase.length() >= 8) && (config.getBand() & BAND_6GHZ) != 0) {
+                configBuilder.setPassphrase(passphrase, SECURITY_TYPE_WPA3_SAE_TRANSITION);
             }
         }
         setSoftApConfiguration(configBuilder.build());
diff --git a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
index 4765d18..510ce39 100644
--- a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
+++ b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java
@@ -78,6 +78,7 @@
 public class WifiHotspotRepositoryTest {
     static final String WIFI_SSID = "wifi_ssid";
     static final String WIFI_PASSWORD = "wifi_password";
+    static final String WIFI_PASSWORD_SHORT = "wifi";
 
     static final int WIFI_5GHZ_BAND_PREFERRED = BAND_2GHZ_5GHZ;
     static final int WIFI_6GHZ_BAND_PREFERRED = BAND_2GHZ_5GHZ_6GHZ;
@@ -477,7 +478,7 @@
 
     @Test
     public void setSpeedType_2g5ghzTo6ghz_setConfigSecurityToWpa3() {
-        mockConfig(SPEED_2GHZ_5GHZ, SECURITY_TYPE_WPA3_SAE_TRANSITION);
+        mockConfig(SPEED_2GHZ_5GHZ, SECURITY_TYPE_WPA3_SAE_TRANSITION, WIFI_PASSWORD);
 
         mRepository.setSpeedType(SPEED_6GHZ);
 
@@ -497,11 +498,33 @@
         SparseIntArray channels = mSoftApConfigCaptor.getValue().getChannels();
         assertThat(channels.get(BAND_2GHZ, CHANNEL_NOT_FOUND)).isNotEqualTo(CHANNEL_NOT_FOUND);
         assertThat(channels.get(BAND_2GHZ_5GHZ, CHANNEL_NOT_FOUND)).isNotEqualTo(CHANNEL_NOT_FOUND);
+    }
+
+    @Test
+    public void setSpeedType_6ghzTo2g5ghzWith8CharPassphrase_changesSecurityToWpa3Transition() {
+        mockConfigSpeedType(SPEED_6GHZ);
+        mRepository.mIsDualBand = true;
+
+        mRepository.setSpeedType(SPEED_2GHZ_5GHZ);
+
+        verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
         assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
                 .isEqualTo(SECURITY_TYPE_WPA3_SAE_TRANSITION);
     }
 
     @Test
+    public void setSpeedType_6ghzTo2g5ghzWithLessThan8CharPassphrase_doesNotChangeSecurity() {
+        mockConfig(SECURITY_TYPE_WPA3_SAE, SPEED_6GHZ, WIFI_PASSWORD_SHORT);
+        mRepository.mIsDualBand = true;
+
+        mRepository.setSpeedType(SPEED_2GHZ_5GHZ);
+
+        verify(mWifiManager).setSoftApConfiguration(mSoftApConfigCaptor.capture());
+        assertThat(mSoftApConfigCaptor.getValue().getSecurityType())
+                .isEqualTo(SECURITY_TYPE_WPA3_SAE);
+    }
+
+    @Test
     public void setSpeedType_2ghzTo5ghz_setConfigBandTo5ghzPreferred() {
         mockConfigSpeedType(SPEED_2GHZ);
 
@@ -784,18 +807,18 @@
     }
 
     private void mockConfigSecurityType(int securityType) {
-        mockConfig(securityType, SPEED_2GHZ);
+        mockConfig(securityType, SPEED_2GHZ,
+                (securityType == SECURITY_TYPE_OPEN) ? null : WIFI_PASSWORD);
     }
 
     private void mockConfigSpeedType(int speedType) {
-        mockConfig(SECURITY_TYPE_WPA3_SAE, speedType);
+        mockConfig(SECURITY_TYPE_WPA3_SAE, speedType, WIFI_PASSWORD);
     }
 
-    private void mockConfig(int securityType, int speedType) {
+    private void mockConfig(int securityType, int speedType, String passphrase) {
         SoftApConfiguration.Builder configBuilder = new SoftApConfiguration.Builder();
         // Security Type
         doReturn(securityType).when(mSecurityType).getValue();
-        String passphrase = (securityType == SECURITY_TYPE_OPEN) ? null : WIFI_PASSWORD;
         configBuilder.setPassphrase(passphrase, securityType).build();
 
         // Speed Type