Merge "Preserve icon for "manage space""
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6514d26..50a26c2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -24,6 +24,8 @@
     <string name="allow">Allow</string>
     <!-- Strings for Dialog deny button -->
     <string name="deny">Deny</string>
+    <!-- Used in confirmation dialogs as the action that the user will tap to turn on the feature. [CHAR LIMIT=40]-->
+    <string name="confirmation_turn_on">Turn on</string>
 
     <!-- Device Info screen. Used for a status item's value when the proper value is not known -->
     <string name="device_info_default">Unknown</string>
@@ -6996,19 +6998,33 @@
     <string name="enhanced_4g_lte_mode_summary">Use LTE services to improve voice and other communications (recommended)</string>
     <!-- Enhaced 4G LTE Mode summary for 4g calling.  [CHAR LIMIT=100] -->
     <string name="enhanced_4g_lte_mode_summary_4g_calling">Use 4G services to improve voice and other communications (recommended)</string>
-    <!-- Title of a preference determining whether or not the user has enabled contact discovery,
-         which is a service that uses the phone numbers in your contacts to determine if your
+    <!-- Title of a preference determining whether or not the user has allowed the device to share
+         their contacts' phone numbers with their carrier in order to implement contact discovery,
+         which is a service that exchanges contacts with the carrier to determine if your
          contacts support advanced calling features, such as video calling. [CHAR LIMIT=50]-->
-    <string name="contact_discovery_opt_in_title">Contact discovery</string>
-    <!-- Summary of a preference determining whether or not the user has enabled contact discovery.
-         [CHAR LIMIT=100] -->
-    <string name="contact_discovery_opt_in_summary">Allows your carrier to discover which calling features your contacts support.</string>
-    <!-- Title of the dialog shown when the user tries to enable Contact Discovery.
+    <string name="contact_discovery_opt_in_title">Send contacts to carrier</string>
+    <!-- Summary of a preference determining whether or not the user has enabled contact discovery,
+         which is a service that exchanges contacts with the carrier to determine if your contacts
+         support enhanced features, such as video calling and RCS messaging. [CHAR LIMIT=110] -->
+    <string name="contact_discovery_opt_in_summary">Send your contacts\u2019 phone numbers to provide enhanced features</string>
+    <!-- Title of the dialog shown when the user tries to enable Contact Discovery, which is a
+         service that exchanges contacts with the carrier to determine if your contacts support
+         enhanced features, such as video calling and RCS messaging. [CHAR LIMIT=50] -->
+    <string name="contact_discovery_opt_in_dialog_title">Send contacts to <xliff:g id="carrier" example="T-mobile">%1$s</xliff:g>?</string>
+    <!-- Title of the dialog shown when the carrier name is not known and the user tries to enable
+         Contact Discovery, which is a service that exchanges contacts with the carrier to determine
+         if your contacts support enhanced features, such as video calling and RCS messaging.
          [CHAR LIMIT=50] -->
-    <string name="contact_discovery_opt_in_dialog_title">Enable contact discovery?</string>
-    <!-- Text displayed in the dialog shown when the user tries to enable Contact Discovery.
-         [CHAR LIMIT=NONE]-->
-    <string name="contact_discovery_opt_in_dialog_message">Enabling this feature will allow your carrier access to phone numbers in your contacts in order to discover which calling features they support.</string>
+    <string name="contact_discovery_opt_in_dialog_title_no_carrier_defined">Send contacts to your carrier?</string>
+    <!-- The text displayed in the dialog shown when the user tries to enable Contact Discovery,
+         which is a service that exchanges contacts with the carrier to determine if your contacts
+         support enhanced features, such as video calling and RCS messaging. [CHAR LIMIT=NONE]-->
+    <string name="contact_discovery_opt_in_dialog_message">Your contacts\u2019 phone numbers will be periodically sent to <xliff:g id="carrier" example="T-mobile">%1$s</xliff:g>.<xliff:g id="empty_line" example="  ">\n\n</xliff:g>This info identifies whether your contacts can use certain features, like video calls or some messaging features.</string>
+    <!-- The text displayed in the dialog shown when the mobile carrier's name is not known and the
+         user tries to enable Contact Discovery, which is a service that exchanges contacts with
+         the carrier to determine if your contacts support enhanced features, such as video calling
+         and RCS messaging. [CHAR LIMIT=NONE]-->
+    <string name="contact_discovery_opt_in_dialog_message_no_carrier_defined">Your contacts\u2019 phone numbers will be periodically sent to your carrier.<xliff:g id="empty_line" example="  ">\n\n</xliff:g>This info identifies whether your contacts can use certain features, like video calls or some messaging features.</string>
     <!-- Preferred network type title.  [CHAR LIMIT=50] -->
     <string name="preferred_network_type_title">Preferred network type</string>
     <!-- Preferred network type summary.  [CHAR LIMIT=100] -->
@@ -10893,6 +10909,9 @@
     <string name="mobile_data_settings_summary_auto_switch">
         Phone will automatically switch to this carrier when in range
     </string>
+    <!-- Mobile network setting screen, summary of Mobile data switch preference when the network
+         is unavailable, the preference selection will be disabled. [CHAR LIMIT=NONE] -->
+    <string name="mobile_data_settings_summary_unavailable">No SIM card available</string>
 
     <!-- Mobile network settings screen, title of item showing the name of the default subscription
      that will be used for calls. This only appears in multi-SIM mode. [CHAR LIMIT=NONE] -->
@@ -11310,4 +11329,12 @@
     <!-- Subtext for showing the option of RTT setting. [CHAR LIMIT=NONE] -->
     <string name="rtt_settings_always_visible"></string>
 
+    <!-- Footer to show current limitation of 5G on DSDS mode. [CHAR LIMIT=NONE] -->
+    <string name="no_5g_in_dsds_text" product="default">When using 2 SIMs, this phone will be limited to 4G. <annotation id="url">Learn more</annotation>.</string>
+    <!-- Footer to show current limitation of 5G on DSDS mode for tablets. [CHAR LIMIT=NONE] -->
+    <string name="no_5g_in_dsds_text" product="tablet">When using 2 SIMs, this tablet will be limited to 4G. <annotation id="url">Learn more</annotation>.</string>
+    <!-- Footer to show current limitation of 5G on DSDS mode for general devices. [CHAR LIMIT=NONE] -->
+    <string name="no_5g_in_dsds_text" product="device">When using 2 SIMs, this device will be limited to 4G. <annotation id="url">Learn more</annotation>.</string>
+    <!-- Help URI, 5G limitation in DSDS condition. [DO NOT TRANSLATE] -->
+    <string name="help_uri_5g_dsds" translatable="false"></string>
 </resources>
diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java
index dea915a..2ee804e 100644
--- a/src/com/android/settings/IccLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -246,7 +246,7 @@
 
         if (componenterList.size() == 0) {
             Log.e(TAG, "onCreateView: no sim info");
-            return null;
+            return super.onCreateView(inflater, container, savedInstanceState);
         }
 
         if (componenterList.size() > 1) {
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 6b29b2e..45c9e16 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -264,6 +264,18 @@
         return 0;
     }
 
+    /**
+     * Whether preference is allowing to be displayed to the user.
+     *
+     * @param preference to check if it can be displayed to the user (not hidding in expand area).
+     * @return {@code true} when preference is allowing to be displayed to the user.
+     * {@code false} when preference is hidden in expand area and not been displayed to the user.
+     */
+    protected boolean isPreferenceExpanded(Preference preference) {
+        return ((mAdapter == null)
+                || (mAdapter.getPreferenceAdapterPosition(preference) != RecyclerView.NO_POSITION));
+    }
+
     protected void onDataSetChanged() {
         highlightPreferenceIfNeeded();
         updateEmptyView();
diff --git a/src/com/android/settings/core/SettingsBaseActivity.java b/src/com/android/settings/core/SettingsBaseActivity.java
index 6e37b16..993c9b0 100644
--- a/src/com/android/settings/core/SettingsBaseActivity.java
+++ b/src/com/android/settings/core/SettingsBaseActivity.java
@@ -63,7 +63,7 @@
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        if (isLockTaskModePinned() && !isSettingsRunOnTop()) {
+        if (isLockTaskModePinned() && !isSettingsRunOnTop() && !isLaunchableInTaskModePinned()) {
             Log.w(TAG, "Devices lock task mode pinned.");
             finish();
         }
@@ -147,6 +147,13 @@
         ((ViewGroup) findViewById(R.id.content_frame)).addView(view, params);
     }
 
+    /**
+     * @return whether or not the activity can be launched from other apps in the pinning screen.
+     */
+    public boolean isLaunchableInTaskModePinned() {
+        return false;
+    }
+
     private void onCategoriesChanged() {
         final int N = mCategoryListeners.size();
         for (int i = 0; i < N; i++) {
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index f2e3d73..6c8a7d5 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -314,6 +314,13 @@
     }
 
     /**
+     * Get current PreferenceController(s)
+     */
+    protected Collection<List<AbstractPreferenceController>> getPreferenceControllers() {
+        return mPreferenceControllers.values();
+    }
+
+    /**
      * Update state of each preference managed by PreferenceController.
      */
     protected void updatePreferenceStates() {
diff --git a/src/com/android/settings/datetime/timezone/TimeZoneInfo.java b/src/com/android/settings/datetime/timezone/TimeZoneInfo.java
index c036eac..f74614d 100644
--- a/src/com/android/settings/datetime/timezone/TimeZoneInfo.java
+++ b/src/com/android/settings/datetime/timezone/TimeZoneInfo.java
@@ -149,22 +149,31 @@
          * @return TimeZoneInfo containing time zone names, exemplar locations and GMT offset
          */
         public TimeZoneInfo format(TimeZone timeZone) {
-            final String id = timeZone.getID();
+            String canonicalZoneId = getCanonicalZoneId(timeZone);
             final TimeZoneNames timeZoneNames = mTimeZoneFormat.getTimeZoneNames();
-            final java.util.TimeZone javaTimeZone = java.util.TimeZone.getTimeZone(id);
+            final java.util.TimeZone javaTimeZone = java.util.TimeZone.getTimeZone(canonicalZoneId);
             final CharSequence gmtOffset = ZoneGetter.getGmtOffsetText(mTimeZoneFormat, mLocale,
                 javaTimeZone, mNow);
             return new TimeZoneInfo.Builder(timeZone)
-                    .setGenericName(timeZoneNames.getDisplayName(id,
+                    .setGenericName(timeZoneNames.getDisplayName(canonicalZoneId,
                             TimeZoneNames.NameType.LONG_GENERIC, mNow.getTime()))
-                    .setStandardName(timeZoneNames.getDisplayName(id,
+                    .setStandardName(timeZoneNames.getDisplayName(canonicalZoneId,
                             TimeZoneNames.NameType.LONG_STANDARD, mNow.getTime()))
-                    .setDaylightName(timeZoneNames.getDisplayName(id,
+                    .setDaylightName(timeZoneNames.getDisplayName(canonicalZoneId,
                             TimeZoneNames.NameType.LONG_DAYLIGHT, mNow.getTime()))
-                    .setExemplarLocation(timeZoneNames.getExemplarLocationName(id))
+                    .setExemplarLocation(timeZoneNames.getExemplarLocationName(canonicalZoneId))
                     .setGmtOffset(gmtOffset)
                     .build();
         }
+
+        private static String getCanonicalZoneId(TimeZone timeZone) {
+            final String id = timeZone.getID();
+            final String canonicalId = TimeZone.getCanonicalID(id);
+            if (canonicalId != null) {
+                return canonicalId;
+            }
+            return id;
+        }
     }
 
 }
diff --git a/src/com/android/settings/network/telephony/AbstractMobileNetworkSettings.java b/src/com/android/settings/network/telephony/AbstractMobileNetworkSettings.java
new file mode 100644
index 0000000..e92cdfc
--- /dev/null
+++ b/src/com/android/settings/network/telephony/AbstractMobileNetworkSettings.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2020 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.network.telephony;
+
+import android.text.TextUtils;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+abstract class AbstractMobileNetworkSettings extends RestrictedDashboardFragment {
+
+    private static final String LOG_TAG = "AbsNetworkSettings";
+
+    private List<AbstractPreferenceController> mHiddenControllerList =
+            new ArrayList<AbstractPreferenceController>();
+
+    /**
+     * @param restrictionKey The restriction key to check before pin protecting
+     *            this settings page. Pass in {@link RESTRICT_IF_OVERRIDABLE} if it should
+     *            be protected whenever a restrictions provider is set. Pass in
+     *            null if it should never be protected.
+     */
+    AbstractMobileNetworkSettings(String restrictionKey) {
+        super(restrictionKey);
+    }
+
+    List<AbstractPreferenceController> getPreferenceControllersAsList() {
+        final List<AbstractPreferenceController> result =
+                new ArrayList<AbstractPreferenceController>();
+        getPreferenceControllers().forEach(controllers -> result.addAll(controllers));
+        return result;
+    }
+
+    TelephonyStatusControlSession setTelephonyAvailabilityStatus(
+            Collection<AbstractPreferenceController> listOfPrefControllers) {
+        return (new TelephonyStatusControlSession.Builder(listOfPrefControllers))
+                .build();
+    }
+
+    @Override
+    public void onExpandButtonClick() {
+        final PreferenceScreen screen = getPreferenceScreen();
+        mHiddenControllerList.stream()
+                .filter(controller -> controller.isAvailable())
+                .forEach(controller -> {
+                    final String key = controller.getPreferenceKey();
+                    final Preference preference = screen.findPreference(key);
+                    controller.updateState(preference);
+                });
+        super.onExpandButtonClick();
+    }
+
+    /*
+     * Replace design within {@link DashboardFragment#updatePreferenceStates()}
+     */
+    @Override
+    protected void updatePreferenceStates() {
+        mHiddenControllerList.clear();
+
+        final PreferenceScreen screen = getPreferenceScreen();
+        getPreferenceControllersAsList().forEach(controller -> {
+            final String key = controller.getPreferenceKey();
+            if (TextUtils.isEmpty(key)) {
+                return;
+            }
+            final Preference preference = screen.findPreference(key);
+            if (preference == null) {
+                return;
+            }
+            if (!isPreferenceExpanded(preference)) {
+                mHiddenControllerList.add(controller);
+                return;
+            }
+            if (!controller.isAvailable()) {
+                return;
+            }
+            controller.updateState(preference);
+        });
+    }
+
+
+}
diff --git a/src/com/android/settings/network/telephony/CarrierSettingsVersionPreferenceController.java b/src/com/android/settings/network/telephony/CarrierSettingsVersionPreferenceController.java
index a6db773..aec3648 100644
--- a/src/com/android/settings/network/telephony/CarrierSettingsVersionPreferenceController.java
+++ b/src/com/android/settings/network/telephony/CarrierSettingsVersionPreferenceController.java
@@ -20,6 +20,7 @@
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
 
 import com.android.settings.core.BasePreferenceController;
 
@@ -49,6 +50,6 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return AVAILABLE;
+        return TextUtils.isEmpty(getSummary()) ? UNSUPPORTED_ON_DEVICE : AVAILABLE;
     }
 }
diff --git a/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragment.java b/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragment.java
index 7273010..26398d7 100644
--- a/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragment.java
+++ b/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragment.java
@@ -23,6 +23,7 @@
 import android.os.Bundle;
 import android.telephony.ims.ImsManager;
 import android.telephony.ims.ImsRcsManager;
+import android.text.TextUtils;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.FragmentManager;
@@ -39,9 +40,11 @@
         implements DialogInterface.OnClickListener {
 
     private static final String SUB_ID_KEY = "sub_id_key";
+    private static final String CARRIER_NAME_KEY = "carrier_name_key";
     private static final String DIALOG_TAG = "discovery_dialog:";
 
     private int mSubId;
+    private CharSequence mCarrierName;
     private ImsManager mImsManager;
 
     /**
@@ -50,10 +53,11 @@
      * @param subId The subscription ID to associate with this Dialog.
      * @return a new instance of ContactDiscoveryDialogFragment.
      */
-    public static ContactDiscoveryDialogFragment newInstance(int subId) {
+    public static ContactDiscoveryDialogFragment newInstance(int subId, CharSequence carrierName) {
         final ContactDiscoveryDialogFragment dialogFragment = new ContactDiscoveryDialogFragment();
         final Bundle args = new Bundle();
         args.putInt(SUB_ID_KEY, subId);
+        args.putCharSequence(CARRIER_NAME_KEY, carrierName);
         dialogFragment.setArguments(args);
 
         return dialogFragment;
@@ -64,18 +68,30 @@
         super.onAttach(context);
         final Bundle args = getArguments();
         mSubId = args.getInt(SUB_ID_KEY);
+        mCarrierName = args.getCharSequence(CARRIER_NAME_KEY);
         mImsManager = getImsManager(context);
     }
 
     @Override
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
-        final int title = R.string.contact_discovery_opt_in_dialog_title;
-        int message = R.string.contact_discovery_opt_in_dialog_message;
-        builder.setMessage(getResources().getString(message))
+        CharSequence title;
+        CharSequence message;
+        if (!TextUtils.isEmpty(mCarrierName)) {
+            title = getContext().getString(
+                    R.string.contact_discovery_opt_in_dialog_title, mCarrierName);
+            message = getContext().getString(
+                    R.string.contact_discovery_opt_in_dialog_message, mCarrierName);
+        } else {
+            title = getContext().getString(
+                    R.string.contact_discovery_opt_in_dialog_title_no_carrier_defined);
+            message = getContext().getString(
+                    R.string.contact_discovery_opt_in_dialog_message_no_carrier_defined);
+        }
+        builder.setMessage(message)
                 .setTitle(title)
                 .setIconAttribute(android.R.attr.alertDialogIcon)
-                .setPositiveButton(android.R.string.ok, this)
+                .setPositiveButton(R.string.confirmation_turn_on, this)
                 .setNegativeButton(android.R.string.cancel, this);
         return builder.create();
     }
diff --git a/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceController.java b/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceController.java
index 21d49d9..880c444 100644
--- a/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceController.java
+++ b/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceController.java
@@ -22,6 +22,7 @@
 import android.os.PersistableBundle;
 import android.provider.Telephony;
 import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
 import android.telephony.ims.ImsManager;
 import android.util.Log;
 
@@ -34,6 +35,8 @@
 import androidx.preference.PreferenceScreen;
 import androidx.preference.SwitchPreference;
 
+import com.android.settings.network.SubscriptionUtil;
+
 
 /**
  * Controller for the "Contact Discovery" option present in MobileNetworkSettings.
@@ -130,7 +133,19 @@
 
     private void showContentDiscoveryDialog() {
         ContactDiscoveryDialogFragment dialog = ContactDiscoveryDialogFragment.newInstance(
-                mSubId);
+                mSubId, getCarrierDisplayName(preference.getContext()));
         dialog.show(mFragmentManager, ContactDiscoveryDialogFragment.getFragmentTag(mSubId));
     }
+
+    private CharSequence getCarrierDisplayName(Context context) {
+        CharSequence result = "";
+
+        for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(context)) {
+            if (mSubId == info.getSubscriptionId()) {
+                result = info.getDisplayName();
+                break;
+            }
+        }
+        return result;
+    }
 }
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index daee6ab..e5d0169 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -128,6 +128,13 @@
             preference.setEnabled(true);
             preference.setSummary(R.string.mobile_data_settings_summary);
         }
+
+        if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            preference.setSelectable(false);
+            preference.setSummary(R.string.mobile_data_settings_summary_unavailable);
+        } else {
+            preference.setSelectable(true);
+        }
     }
 
     private boolean isOpportunistic() {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index 16c5adc..90b73f8 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -205,16 +205,9 @@
         final Intent intent = getIntent();
         if (intent != null) {
             final int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID, SUB_ID_NULL);
-            if (subId != SUB_ID_NULL) {
-                for (SubscriptionInfo subscription :
-                        SubscriptionUtil.getAvailableSubscriptions(this)) {
-                    if (subscription.getSubscriptionId() == subId) {
-                        return subscription;
-                    }
-                }
-            }
+            SubscriptionInfo info = getSubscriptionInfo(subId);
+            if (info != null) return info;
         }
-
         if (CollectionUtils.isEmpty(mSubscriptionInfos)) {
             return null;
         }
@@ -222,6 +215,23 @@
     }
 
     /**
+     * @return the subscription associated with a given subscription ID or null if none can be
+     * found.
+     */
+    SubscriptionInfo getSubscriptionInfo(int subId) {
+        if (subId == SUB_ID_NULL) {
+            return null;
+        }
+
+        for (SubscriptionInfo subscription : SubscriptionUtil.getAvailableSubscriptions(this)) {
+            if (subscription.getSubscriptionId() == subId) {
+                return subscription;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Get the current subId to display.
      */
     @VisibleForTesting
@@ -340,6 +350,11 @@
     }
 
     private void maybeShowContactDiscoveryDialog(int subId) {
+        SubscriptionInfo info = getSubscriptionInfo(subId);
+        CharSequence carrierName = "";
+        if (info != null) {
+            carrierName = info.getDisplayName();
+        }
         // If this activity was launched using ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN, show the
         // associated dialog only if the opt-in has not been granted yet.
         boolean showOptInDialog = doesIntentContainOptInAction(getIntent())
@@ -350,7 +365,7 @@
         ContactDiscoveryDialogFragment fragment = getContactDiscoveryFragment(subId);
         if (showOptInDialog) {
             if (fragment == null) {
-                fragment = ContactDiscoveryDialogFragment.newInstance(subId);
+                fragment = ContactDiscoveryDialogFragment.newInstance(subId, carrierName);
             }
             // Only try to show the dialog if it has not already been added, otherwise we may
             // accidentally add it multiple times, causing multiple dialogs.
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 30ea0c0..7c1c8dd 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -32,10 +32,13 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
 import com.android.settings.core.FeatureFlags;
-import com.android.settings.dashboard.RestrictedDashboardFragment;
 import com.android.settings.datausage.BillingCyclePreferenceController;
 import com.android.settings.datausage.DataUsageSummaryPreferenceController;
 import com.android.settings.development.featureflags.FeatureFlagPersistent;
@@ -48,16 +51,19 @@
 import com.android.settings.widget.PreferenceCategoryController;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.search.SearchIndexable;
+import com.android.settingslib.utils.ThreadUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
 
 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
-public class MobileNetworkSettings extends RestrictedDashboardFragment {
+public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
 
     private static final String LOG_TAG = "NetworkSettings";
     public static final int REQUEST_CODE_EXIT_ECM = 17;
@@ -117,14 +123,14 @@
     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
         mSubId = getArguments().getInt(Settings.EXTRA_SUB_ID,
                 MobileNetworkUtils.getSearchableSubscriptionId(context));
+        Log.i(LOG_TAG, "display subId: " + mSubId);
 
-        if (FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2) &&
-            mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            return Arrays.asList(
-                    new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(),
-                            this, mSubId));
+        if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
+            return Arrays.asList();
         }
-        return Arrays.asList();
+        return Arrays.asList(
+                new DataUsageSummaryPreferenceController(getActivity(), getSettingsLifecycle(),
+                        this, mSubId));
     }
 
     @Override
@@ -185,13 +191,18 @@
     @Override
     public void onCreate(Bundle icicle) {
         Log.i(LOG_TAG, "onCreate:+");
+
+        final TelephonyStatusControlSession session =
+                setTelephonyAvailabilityStatus(getPreferenceControllersAsList());
+
         super.onCreate(icicle);
         final Context context = getContext();
-
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
         mTelephonyManager = context.getSystemService(TelephonyManager.class)
                 .createForSubscriptionId(mSubId);
 
+        session.close();
+
         onRestoreInstance(icicle);
     }
 
@@ -250,8 +261,7 @@
 
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
-        if (FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2) &&
-                mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
             final MenuItem item = menu.add(Menu.NONE, R.id.edit_sim_name, Menu.NONE,
                     R.string.mobile_network_sim_name);
             item.setIcon(com.android.internal.R.drawable.ic_mode_edit);
@@ -262,8 +272,7 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem menuItem) {
-        if (FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2) &&
-                mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+        if (SubscriptionManager.isValidSubscriptionId(mSubId)) {
             if (menuItem.getItemId() == R.id.edit_sim_name) {
                 RenameMobileNetworkDialogFragment.newInstance(mSubId).show(
                         getFragmentManager(), RenameMobileNetworkDialogFragment.TAG);
diff --git a/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceController.java b/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceController.java
index e024788..4077e91 100644
--- a/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceController.java
+++ b/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceController.java
@@ -17,10 +17,17 @@
 package com.android.settings.network.telephony;
 
 import android.content.Context;
+import android.content.Intent;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
+import androidx.preference.Preference;
+
+import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.utils.AnnotationSpan;
+import com.android.settingslib.HelpUtils;
+
 
 /**
  * Class to show the footer that can't connect to 5G when device is in DSDS mode.
@@ -44,6 +51,29 @@
     }
 
     @Override
+    public void updateState(Preference preference) {
+        super.updateState(preference);
+
+        if (preference != null) {
+            preference.setTitle(getFooterText());
+        }
+    }
+
+    private CharSequence getFooterText() {
+        final Intent helpIntent = HelpUtils.getHelpIntent(mContext,
+                mContext.getString(R.string.help_uri_5g_dsds),
+                mContext.getClass().getName());
+        final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(mContext,
+                "url", helpIntent);
+
+        if (linkInfo.isActionable()) {
+            return AnnotationSpan.linkify(mContext.getText(R.string.no_5g_in_dsds_text), linkInfo);
+        } else {
+            return mContext.getText(R.string.no_5g_in_dsds_text);
+        }
+    }
+
+    @Override
     public int getAvailabilityStatus() {
         if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
             return CONDITIONALLY_UNAVAILABLE;
@@ -52,13 +82,18 @@
         final TelephonyManager teleManager = ((TelephonyManager)
                 mContext.getSystemService(Context.TELEPHONY_SERVICE))
                 .createForSubscriptionId(mSubId);
+        final SubscriptionManager subManager = ((SubscriptionManager)
+                mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE));
+        final int[] activeSubIdList = subManager.getActiveSubscriptionIdList();
+        final int activeSubCount = activeSubIdList == null ? 0 : activeSubIdList.length;
         // Show the footer only when DSDS is enabled, and mobile data is enabled on this SIM, and
         // 5G is supported on this device.
-        if (!teleManager.isDataEnabled() || teleManager.getActiveModemCount() < 2
-                || !is5GSupportedByRadio(teleManager)) {
+        if (teleManager.isDataEnabled() && activeSubCount >= 2 && is5GSupportedByRadio(teleManager)
+                && !teleManager.canConnectTo5GInDsdsMode()) {
+            return AVAILABLE;
+        } else {
             return CONDITIONALLY_UNAVAILABLE;
         }
-        return AVAILABLE;
     }
 
     private boolean is5GSupportedByRadio(TelephonyManager tm) {
diff --git a/src/com/android/settings/network/telephony/TelephonyAvailabilityHandler.java b/src/com/android/settings/network/telephony/TelephonyAvailabilityHandler.java
new file mode 100644
index 0000000..c1acd91
--- /dev/null
+++ b/src/com/android/settings/network/telephony/TelephonyAvailabilityHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+/**
+ * Interface letting {@link TelephonyTogglePreferenceController and
+ * @link TelephonyBasePreferenceController} can handle availability status.
+ */
+package com.android.settings.network.telephony;
+
+import android.content.Context;
+
+public interface TelephonyAvailabilityHandler {
+
+    /**
+     * Set availability status of preference controller to a fixed value.
+     * @param status is the given status. Which will be reported from
+     * {@link BasePreferenceController#getAvailabilityStatus()}
+     */
+    void setAvailabilityStatus(int status);
+
+    /**
+     * Do not set availability, use
+     * {@link MobileNetworkUtils#getAvailability(Context, int, TelephonyAvailabilityCallback)}
+     * to get the availability.
+     */
+    void unsetAvailabilityStatus();
+}
diff --git a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
index 241dc5d..2bd7de9 100644
--- a/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
+++ b/src/com/android/settings/network/telephony/TelephonyBasePreferenceController.java
@@ -23,12 +23,16 @@
 
 import com.android.settings.core.BasePreferenceController;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * {@link BasePreferenceController} that used by all preferences that requires subscription id.
  */
 public abstract class TelephonyBasePreferenceController extends BasePreferenceController
-        implements TelephonyAvailabilityCallback {
+        implements TelephonyAvailabilityCallback, TelephonyAvailabilityHandler {
     protected int mSubId;
+    private AtomicInteger mAvailabilityStatus = new AtomicInteger(0);
+    private AtomicInteger mSetSessionCount = new AtomicInteger(0);
 
     public TelephonyBasePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
@@ -37,7 +41,22 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return MobileNetworkUtils.getAvailability(mContext, mSubId, this::getAvailabilityStatus);
+        if (mSetSessionCount.get() <= 0) {
+            mAvailabilityStatus.set(MobileNetworkUtils
+                    .getAvailability(mContext, mSubId, this::getAvailabilityStatus));
+        }
+        return mAvailabilityStatus.get();
+    }
+
+    @Override
+    public void setAvailabilityStatus(int status) {
+        mAvailabilityStatus.set(status);
+        mSetSessionCount.getAndIncrement();
+    }
+
+    @Override
+    public void unsetAvailabilityStatus() {
+        mSetSessionCount.getAndDecrement();
     }
 
     /**
diff --git a/src/com/android/settings/network/telephony/TelephonyStatusControlSession.java b/src/com/android/settings/network/telephony/TelephonyStatusControlSession.java
new file mode 100644
index 0000000..12c9bee
--- /dev/null
+++ b/src/com/android/settings/network/telephony/TelephonyStatusControlSession.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2020 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.network.telephony;
+
+import android.util.Log;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * Session for controlling the status of TelephonyPreferenceController(s).
+ *
+ * Within this session, result of {@link BasePreferenceController#availabilityStatus()}
+ * would be under control.
+ */
+public class TelephonyStatusControlSession implements AutoCloseable {
+
+    private static final String LOG_TAG = "TelephonyStatusControlSS";
+
+    private Collection<AbstractPreferenceController> mControllers;
+    private Future<Boolean> mResult;
+
+    /**
+     * Buider of session
+     */
+    public static class Builder {
+        private Collection<AbstractPreferenceController> mControllers;
+
+        /**
+         * Constructor
+         *
+         * @param controllers is a collection of {@link AbstractPreferenceController}
+         *        which would have {@link BasePreferenceController#availabilityStatus()}
+         *        under control within this session.
+         */
+        public Builder(Collection<AbstractPreferenceController> controllers) {
+            mControllers = controllers;
+        }
+
+        /**
+         * Method to build this session.
+         * @return {@link TelephonyStatusControlSession} session been setup.
+         */
+        public TelephonyStatusControlSession build() {
+            return new TelephonyStatusControlSession(mControllers);
+        }
+    }
+
+    private TelephonyStatusControlSession(Collection<AbstractPreferenceController> controllers) {
+        mControllers = controllers;
+        mResult = ThreadUtils.postOnBackgroundThread(() ->
+            setupAvailabilityStatus(controllers)
+        );
+    }
+
+    /**
+     * Close the session.
+     *
+     * No longer control the status.
+     */
+    public void close() {
+        //check the background thread is finished then unset the status of availability.
+        try {
+            mResult.get();
+        } catch (ExecutionException | InterruptedException exception) {
+            Log.e(LOG_TAG, "setup availability status failed!", exception);
+        }
+        unsetAvailabilityStatus(mControllers);
+    }
+
+    private Boolean setupAvailabilityStatus(
+            Collection<AbstractPreferenceController> controllerLists) {
+        try {
+            controllerLists.stream()
+                    .filter(controller -> controller instanceof TelephonyAvailabilityHandler)
+                    .map(TelephonyAvailabilityHandler.class::cast)
+                    .forEach(controller -> {
+                        int status = ((BasePreferenceController) controller)
+                                .getAvailabilityStatus();
+                        controller.setAvailabilityStatus(status);
+                    });
+            return true;
+        } catch (Exception exception) {
+            Log.e(LOG_TAG, "Setup availability status failed!", exception);
+            return false;
+        }
+    }
+
+    private void unsetAvailabilityStatus(
+            Collection<AbstractPreferenceController> controllerLists) {
+        controllerLists.stream()
+                .filter(controller -> controller instanceof TelephonyAvailabilityHandler)
+                .map(TelephonyAvailabilityHandler.class::cast)
+                .forEach(controller -> {
+                    controller.unsetAvailabilityStatus();
+                });
+    }
+}
diff --git a/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java b/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java
index fc30030..ecad755 100644
--- a/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java
+++ b/src/com/android/settings/network/telephony/TelephonyTogglePreferenceController.java
@@ -23,12 +23,16 @@
 
 import com.android.settings.core.TogglePreferenceController;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 /**
  * {@link TogglePreferenceController} that used by all preferences that requires subscription id.
  */
 public abstract class TelephonyTogglePreferenceController extends TogglePreferenceController
-        implements TelephonyAvailabilityCallback {
+        implements TelephonyAvailabilityCallback, TelephonyAvailabilityHandler {
     protected int mSubId;
+    private AtomicInteger mAvailabilityStatus = new AtomicInteger(0);
+    private AtomicInteger mSetSessionCount = new AtomicInteger(0);
 
     public TelephonyTogglePreferenceController(Context context, String preferenceKey) {
         super(context, preferenceKey);
@@ -37,9 +41,25 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return MobileNetworkUtils.getAvailability(mContext, mSubId, this::getAvailabilityStatus);
+        if (mSetSessionCount.get() <= 0) {
+            mAvailabilityStatus.set(MobileNetworkUtils
+                    .getAvailability(mContext, mSubId, this::getAvailabilityStatus));
+        }
+        return mAvailabilityStatus.get();
     }
 
+    @Override
+    public void setAvailabilityStatus(int status) {
+        mAvailabilityStatus.set(status);
+        mSetSessionCount.getAndIncrement();
+    }
+
+    @Override
+    public void unsetAvailabilityStatus() {
+        mSetSessionCount.getAndDecrement();
+    }
+
+
     /**
      * Get carrier config based on specific subscription id.
      *
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
index 5407776..e797bee 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseActivity.java
@@ -188,6 +188,11 @@
         }
     }
 
+    @Override
+    public boolean isLaunchableInTaskModePinned() {
+        return true;
+    }
+
     public void prepareEnterAnimation() {
         getFragment().prepareEnterAnimation();
     }
diff --git a/src/com/android/settings/password/PasswordUtils.java b/src/com/android/settings/password/PasswordUtils.java
index 1ead492..5b75033 100644
--- a/src/com/android/settings/password/PasswordUtils.java
+++ b/src/com/android/settings/password/PasswordUtils.java
@@ -89,7 +89,8 @@
                     /* initialPid= */ -1,
                     getCallingAppPackageName(activityToken),
                     userId,
-                    message);
+                    message,
+                    false);
         } catch (RemoteException e) {
             Log.v(TAG, "Could not talk to activity manager.", e);
         }
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index 378606a6..26c1565 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -20,6 +20,7 @@
 
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.pm.PackageManager;
 import android.net.Proxy;
 import android.net.ProxyInfo;
 import android.os.Bundle;
@@ -43,6 +44,9 @@
 import com.android.settings.R;
 
 import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Dialog showing information about a VPN configuration. The dialog
@@ -129,6 +133,7 @@
 
         // Second, copy values from the profile.
         mName.setText(mProfile.name);
+        setTypesByFeature(mType);
         mType.setSelection(mProfile.type);
         mServer.setText(mProfile.server);
         if (mProfile.saveLogin) {
@@ -487,6 +492,25 @@
         return true;
     }
 
+    private void setTypesByFeature(Spinner typeSpinner) {
+        String[] types = getContext().getResources().getStringArray(R.array.vpn_types);
+        if (!getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_IPSEC_TUNNELS)) {
+            final List<String> typesList = new ArrayList<>(Arrays.asList(types));
+
+            // This must be removed from back to front in order to ensure index consistency
+            typesList.remove(VpnProfile.TYPE_IKEV2_IPSEC_RSA);
+            typesList.remove(VpnProfile.TYPE_IKEV2_IPSEC_PSK);
+            typesList.remove(VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS);
+
+            types = typesList.toArray(new String[0]);
+        }
+        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
+                getContext(), android.R.layout.simple_spinner_item, types);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        typeSpinner.setAdapter(adapter);
+    }
+
     private void loadCertificates(Spinner spinner, String prefix, int firstId, String selected) {
         Context context = getContext();
         String first = (firstId == 0) ? "" : context.getString(firstId);
diff --git a/tests/perftests/src/com/android/settings/tests/perf/LaunchSettingsTest.java b/tests/perftests/src/com/android/settings/tests/perf/LaunchSettingsTest.java
index ec2a311..f6eac3a 100644
--- a/tests/perftests/src/com/android/settings/tests/perf/LaunchSettingsTest.java
+++ b/tests/perftests/src/com/android/settings/tests/perf/LaunchSettingsTest.java
@@ -56,6 +56,8 @@
         }
     }
 
+    private static final String SCREEN_TIME_OUT = "7200000";
+    private static final String DEFAULT_SCREEN_TIMEOUT = "15000";
     private static final int TIME_OUT = 5000;
     private static final int TEST_TIME = 10;
     private static final Pattern PATTERN = Pattern.compile("TotalTime:\\s[0-9]*");
@@ -67,7 +69,8 @@
                 new Page("android.settings.WIFI_SETTINGS", "Use Wi‑Fi", "Wi-Fi"),
                 new Page("android.settings.BLUETOOTH_SETTINGS", "Connected devices", "BlueTooth"),
                 new Page("android.settings.APPLICATION_SETTINGS", "App info", "Application"),
-                new Page("android.intent.action.POWER_USAGE_SUMMARY", "Battery", "Battery")
+                new Page("android.intent.action.POWER_USAGE_SUMMARY", "Battery", "Battery"),
+                new Page("android.settings.INTERNAL_STORAGE_SETTINGS", "Storage", "Storage")
         };
     }
 
@@ -75,6 +78,7 @@
     private UiDevice mDevice;
     private Instrumentation mInstrumentation;
     private Map<String, ArrayList<Integer>> mResult;
+    private String mDefaultScreenTimeout;
 
     @Before
     public void setUp() throws Exception {
@@ -82,6 +86,9 @@
         mDevice = UiDevice.getInstance(getInstrumentation());
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mResult = new LinkedHashMap<>();
+        mDefaultScreenTimeout = mDevice.executeShellCommand(
+                "settings get system screen_off_timeout");
+        setScreenTimeOut(SCREEN_TIME_OUT);
         mDevice.pressHome();
         mDevice.waitForIdle(TIME_OUT);
 
@@ -94,6 +101,8 @@
     public void tearDown() throws Exception {
         putResultToBundle();
         mInstrumentation.sendStatus(0, mBundle);
+        resetScreenTimeout();
+        closeApp();
     }
 
     @Test
@@ -107,11 +116,11 @@
 
     private void executePreformanceTest(String action, String displayName, String title)
             throws Exception {
+        closeApp();
+        mDevice.waitForIdle(TIME_OUT);
         final String mString = mDevice.executeShellCommand("am start -W -a" + action);
         mDevice.wait(Until.findObject(By.text(displayName)), TIME_OUT);
         handleLaunchResult(title, mString);
-        closeApp();
-        mDevice.waitForIdle(TIME_OUT);
     }
 
     private void handleLaunchResult(String title, String s) {
@@ -150,4 +159,16 @@
     private String getAvg(ArrayList<Integer> launchResult) {
         return String.valueOf((int) launchResult.stream().mapToInt(i -> i).average().orElse(0));
     }
+
+    private void setScreenTimeOut(String timeout) throws Exception {
+        mDevice.executeShellCommand("settings put system screen_off_timeout " + timeout);
+    }
+
+    private void resetScreenTimeout() throws Exception {
+        String timeout = DEFAULT_SCREEN_TIMEOUT;
+        if (!mDefaultScreenTimeout.isEmpty()) {
+            timeout = mDefaultScreenTimeout;
+        }
+        setScreenTimeOut(timeout);
+    }
 }
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragmentTest.java b/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragmentTest.java
index 6aef699..f2db71f 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryDialogFragmentTest.java
@@ -48,6 +48,7 @@
 @Config(shadows = ShadowAlertDialog.class)
 public class ContactDiscoveryDialogFragmentTest {
     private static final int TEST_SUB_ID = 2;
+    private static final String TEST_CARRIER = "TestMobile";
 
     @Mock private ImsManager mImsManager;
     @Mock private ImsRcsManager mImsRcsManager;
@@ -60,7 +61,8 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mActivity = Robolectric.buildActivity(FragmentActivity.class).setup().get();
-        mDialogFragmentUT = spy(ContactDiscoveryDialogFragment.newInstance(TEST_SUB_ID));
+        mDialogFragmentUT = spy(ContactDiscoveryDialogFragment.newInstance(TEST_SUB_ID,
+                TEST_CARRIER));
         doReturn(mImsManager).when(mDialogFragmentUT).getImsManager(any());
         doReturn(mImsRcsManager).when(mImsManager).getImsRcsManager(TEST_SUB_ID);
         doReturn(mRcsUceAdapter).when(mImsRcsManager).getUceAdapter();
diff --git a/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceControllerTest.java
index 0370bfa..3d54cfb 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/ContactDiscoveryPreferenceControllerTest.java
@@ -48,6 +48,7 @@
 import androidx.lifecycle.LifecycleOwner;
 import androidx.preference.SwitchPreference;
 
+import com.android.settings.network.SubscriptionUtil;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 import org.junit.Before;
@@ -59,6 +60,8 @@
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
 
+import java.util.Collections;
+
 @RunWith(RobolectricTestRunner.class)
 public class ContactDiscoveryPreferenceControllerTest {
 
@@ -99,6 +102,8 @@
 
         mPreferenceControllerUT = new ContactDiscoveryPreferenceController(mContext,
                 "ContactDiscovery");
+        // Ensure subscriptionInfo check doesn't fail.
+        SubscriptionUtil.setAvailableSubscriptionsForTesting(Collections.emptyList());
         mPreferenceControllerUT.init(mFragmentManager, TEST_SUB_ID, mLifecycle);
         mSwitchPreferenceUT = spy(new SwitchPreference(mContext));
         mSwitchPreferenceUT.setKey(mPreferenceControllerUT.getPreferenceKey());
diff --git a/tests/robotests/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceControllerTest.java
index c75d874..a6edae5 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/NrDisabledInDsdsFooterPreferenceControllerTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 
 import org.junit.Before;
@@ -42,6 +43,8 @@
     private Context mContext;
     @Mock
     private TelephonyManager mTelephonyManager;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
     private NrDisabledInDsdsFooterPreferenceController mController;
 
     @Before
@@ -49,6 +52,8 @@
         MockitoAnnotations.initMocks(this);
         mContext = spy(RuntimeEnvironment.application);
         doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+        doReturn(mSubscriptionManager).when(mContext).getSystemService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
         doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
         mController = new NrDisabledInDsdsFooterPreferenceController(mContext, PREF_KEY);
     }
@@ -62,7 +67,7 @@
     public void isAvailable_dataOnAndDsdsAnd5GSupported_Available() {
         when(mTelephonyManager.getSupportedRadioAccessFamily())
                 .thenReturn(TelephonyManager.NETWORK_TYPE_BITMASK_NR);
-        when(mTelephonyManager.getActiveModemCount()).thenReturn(2);
+        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1, 2});
         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
         mController.init(SUB_ID);
         assertThat(mController.isAvailable()).isTrue();
@@ -72,7 +77,7 @@
     public void isAvailable_5gNotSupported_notAvailable() {
         when(mTelephonyManager.getSupportedRadioAccessFamily())
                 .thenReturn(TelephonyManager.NETWORK_TYPE_BITMASK_LTE);
-        when(mTelephonyManager.getActiveModemCount()).thenReturn(2);
+        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1, 2});
         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
         mController.init(SUB_ID);
         assertThat(mController.isAvailable()).isFalse();
@@ -82,7 +87,7 @@
     public void isAvailable_mobileDataOff_notAvailable() {
         when(mTelephonyManager.getSupportedRadioAccessFamily())
                 .thenReturn(TelephonyManager.NETWORK_TYPE_BITMASK_NR);
-        when(mTelephonyManager.getActiveModemCount()).thenReturn(2);
+        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1, 2});
         when(mTelephonyManager.isDataEnabled()).thenReturn(false);
         mController.init(SUB_ID);
         assertThat(mController.isAvailable()).isFalse();
@@ -92,7 +97,7 @@
     public void isAvailable_singleSimMode_notAvailable() {
         when(mTelephonyManager.getSupportedRadioAccessFamily())
                 .thenReturn(TelephonyManager.NETWORK_TYPE_BITMASK_NR);
-        when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
+        when(mSubscriptionManager.getActiveSubscriptionIdList()).thenReturn(new int[] {1});
         when(mTelephonyManager.isDataEnabled()).thenReturn(true);
         mController.init(SUB_ID);
         assertThat(mController.isAvailable()).isFalse();