Merge "Fix issues associated with hold failure"
diff --git a/Android.bp b/Android.bp
index 4925d51..7530b7a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -57,7 +57,6 @@
     static_libs: [
         "telephony-protos",
         "ecc-protos-lite",
-        "android-support-annotations",
     ],
 
     product_variables: {
diff --git a/proto/src/telephony.proto b/proto/src/telephony.proto
index 14e2e12..28e1355 100644
--- a/proto/src/telephony.proto
+++ b/proto/src/telephony.proto
@@ -50,6 +50,9 @@
 
   // Hardware revision (EVT, DVT, PVT etc.)
   optional string hardware_revision = 9;
+
+  // The last active subscription info for each slot.
+  repeated ActiveSubscriptionInfo last_active_subscription_info = 10;
 }
 
 // The time information
@@ -276,9 +279,6 @@
 
   // Current data radio technology
   optional RadioAccessTechnology data_rat = 6 [default = UNKNOWN];
-
-  // All the active subscription information.
-  repeated ActiveSubscriptionInfo active_subscription_info = 7;
 }
 
 // Radio access families
@@ -619,9 +619,6 @@
 
   // The network interface name e.g. wlan0, rmnet_data0.
   optional string iframe = 3;
-
-  // All the active subscription information.
-  repeated ActiveSubscriptionInfo active_subscription_info = 4;
 }
 
 message TelephonyEvent {
@@ -675,73 +672,99 @@
     // Carrier Key Change event.
     CARRIER_KEY_CHANGED = 14;
 
-    // Phone status change event.
-    PHONE_STATUS_CHANGED = 15;
-
     // Data switch event.
-    DATA_SWITCH = 16;
+    DATA_SWITCH = 15;
 
     // Network validate event.
-    NETWORK_VALIDATE = 17;
+    NETWORK_VALIDATE = 16;
 
     // On deman data switch event.
-    ON_DEMAND_DATA_SWITCH = 18;
+    ON_DEMAND_DATA_SWITCH = 17;
+
+    // SIM state change event.
+    SIM_STATE_CHANGED = 18;
+
+    // Active subscription info change event.
+    ACTIVE_SUBSCRIPTION_INFO_CHANGED = 19;
+
+    // Enabled modem change event.
+    ENABLED_MODEM_CHANGED = 20;
   }
 
   enum ApnType {
-      DEFAULT = 0;
-      MMS = 1;
-      SUPL = 2;
-      DUN = 3;
-      HIPRI = 4;
-      FOTA = 5;
-      IMS = 6;
-      CBS = 7;
-      IA = 8;
-      EMERGENCY = 9;
+    APN_TYPE_UNKNOWN = 0;
+
+    APN_TYPE_DEFAULT = 1;
+
+    APN_TYPE_MMS = 2;
+
+    APN_TYPE_SUPL = 3;
+
+    APN_TYPE_DUN = 4;
+
+    APN_TYPE_HIPRI = 5;
+
+    APN_TYPE_FOTA = 6;
+
+    APN_TYPE_IMS = 7;
+
+    APN_TYPE_CBS = 8;
+
+    APN_TYPE_IA = 9;
+
+    APN_TYPE_EMERGENCY = 10;
   }
 
   enum EventState {
-      START = 0;
-      END = 1;
+    EVENT_STATE_UNKNOWN = 0;
+
+    EVENT_STATE_START = 1;
+
+    EVENT_STATE_END = 2;
   }
 
   enum NetworkValidationState {
-      /** The network under validation is initial established. */
-      AVAILABLE = 0;
+    /** The network validation state is unknown. */
+    NETWORK_VALIDATION_STATE_UNKNOWN = 0;
 
-      /** The validation is failed. */
-      FAILED = 1;
+    /** The network under validation is initial established. */
+    NETWORK_VALIDATION_STATE_AVAILABLE = 1;
 
-      /** The validation is passed. */
-      PASSED = 2;
+    /** The validation is failed. */
+    NETWORK_VALIDATION_STATE_FAILED = 2;
+
+    /** The validation is passed. */
+    NETWORK_VALIDATION_STATE_PASSED = 3;
   }
 
   message DataSwitch {
-      enum Reason {
-          /** Data switch caused by user's manual switch. */
-          MANUAL = 0;
+    enum Reason {
+      /** Data switch caused by unknown reason. */
+      DATA_SWITCH_REASON_UNKNOWN = 0;
 
-          /** Data switch caused by incoming/outgoing call. */
-          IN_CALL = 1;
+      /** Data switch caused by user's manual switch. */
+      DATA_SWITCH_REASON_MANUAL = 1;
 
-          /** Data switch caused by CBRS switch. */
-          CBRS = 2;
-      }
+      /** Data switch caused by incoming/outgoing call. */
+      DATA_SWITCH_REASON_IN_CALL = 2;
 
-      /** The reason for data switch. */
-      optional Reason reason = 1;
+      /** Data switch caused by CBRS switch. */
+      DATA_SWITCH_REASON_CBRS = 3;
+    }
 
-      /** Current state of the data switch event. */
-      optional EventState state = 2;
+    /** The reason for data switch. */
+    optional Reason reason = 1;
+
+    /** Current state of the data switch event. */
+    optional EventState state = 2;
   }
 
   message OnDemandDataSwitch {
-      /** The apn associated with this event. */
-      optional ApnType apn = 1;
+    /** The apn associated with this event. */
+    optional ApnType apn = 1;
 
-      /** Current state of the on demand data switch event. */
-      optional EventState state = 2;
+    /** Current state of the on demand data switch event. */
+    optional EventState state = 2;
   }
 
   // Setup a packet data connection
@@ -1536,17 +1559,6 @@
     optional string mccmnc = 3;
   }
 
-  message PhoneStatus {
-      /** The sim state of each active slot. */
-      repeated SimState sim_state = 1;
-
-      /**
-       * The modem state represent by a bitmap, the i-th bit(LSB) indicates the i-th modem
-       * state(0 - disabled, 1 - enabled).
-       */
-      optional int32 enabled_modem_bitmap = 2;
-  }
-
   // Time when event happened on device, in milliseconds since epoch
   optional int64 timestamp_millis = 1;
 
@@ -1598,9 +1610,6 @@
   // Carrier key change
   optional CarrierKeyChange carrier_key_change = 17;
 
-  // Phone status
-  optional PhoneStatus phone_status = 18;
-
   // Data switch event
   optional DataSwitch data_switch = 19;
 
@@ -1609,31 +1618,41 @@
 
   // On demand data switch event
   optional OnDemandDataSwitch on_demand_data_switch = 21;
+
+  // Sim state for each slot.
+  repeated SimState sim_state = 22;
+
+  // The active subscription info for a specific slot.
+  optional ActiveSubscriptionInfo active_subscription_info = 23;
+
+  // The modem state represent by a bitmap, the i-th bit(LSB) indicates the i-th modem
+  // state (0 - disabled, 1 - enabled).
+  optional int32 enabled_modem_bitmap = 24;
 }
 
 message ActiveSubscriptionInfo {
-    /** The slot index which this subscription associated with. */
-    optional int32 slot_index = 1;
+  /** The slot index which this subscription is associated with. */
+  optional int32 slot_index = 1;
 
-    /** The Carrier id of this subscription. */
-    optional int32 carrier_id = 2;
+  /** The Carrier id of this subscription. -1 indicates unknown value. */
+  optional int32 carrier_id = 2;
 
-    /** whether subscription is opportunistic. */
-    optional bool is_opportunistic = 3;
+  /** whether subscription is opportunistic (0 - false, 1 - true, -1 - unknown). */
+  optional int32 is_opportunistic = 3;
 };
 
 enum SimState {
-    /**
-     * SIM card is inserted, but the state is unknown. Typically happened when the SIM is inserted
-     * but not loaded.
-     */
-    SIM_STATE_UNKNOWN = 0;
+  /**
+   * SIM card is inserted, but the state is unknown. Typically happened when the SIM is inserted
+   * but not loaded.
+   */
+  SIM_STATE_UNKNOWN = 0;
 
-    /** No SIM card is inserted in the slot. */
-    SIM_STATE_ABSENT = 1;
+  /** No SIM card is inserted in the slot. */
+  SIM_STATE_ABSENT = 1;
 
-    /** SIM card applications have been loaded. */
-    SIM_STATE_LOADED = 2;
+  /** SIM card applications have been loaded. */
+  SIM_STATE_LOADED = 2;
 };
 
 enum TimeInterval {
@@ -2001,12 +2020,6 @@
 
   // Indicating some call events are dropped
   optional bool events_dropped = 4;
-
-  // SIM state of the active slots
-  repeated SimState sim_states = 5;
-
-  // All the active subscription information.
-  repeated ActiveSubscriptionInfo active_subscription_info = 6;
 }
 
 message SmsSession {
@@ -2221,12 +2234,6 @@
 
   // Indicating some sms session events are dropped
   optional bool events_dropped = 4;
-
-  // SIM state of the active slots.
-  repeated SimState sim_state = 5;
-
-  // All the active subscription information.
-  repeated ActiveSubscriptionInfo active_subscription_info = 6;
 }
 
 // Power stats for modem
diff --git a/src/java/com/android/internal/telephony/CarrierResolver.java b/src/java/com/android/internal/telephony/CarrierResolver.java
index 9f96c67..60233f9 100644
--- a/src/java/com/android/internal/telephony/CarrierResolver.java
+++ b/src/java/com/android/internal/telephony/CarrierResolver.java
@@ -45,7 +45,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * CarrierResolver identifies the subscription carrier and returns a canonical carrier Id
@@ -71,15 +70,15 @@
     private List<CarrierMatchingRule> mCarrierMatchingRulesOnMccMnc = new ArrayList<>();
     // cached carrier Id
     private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
-    // cached precise carrier Id
-    private int mPreciseCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+    // cached specific carrier Id
+    private int mSpecificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
     // cached MNO carrier Id. mno carrier shares the same mccmnc as cid and can be solely
     // identified by mccmnc only. If there is no such mno carrier, mno carrier id equals to
     // the cid.
     private int mMnoCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
     // cached carrier name
     private String mCarrierName;
-    private String mPreciseCarrierName;
+    private String mSpecificCarrierName;
     // cached preferapn name
     private String mPreferApn;
     // cached service provider name. telephonyManager API returns empty string as default value.
@@ -350,7 +349,7 @@
     }
 
     private void updateCarrierIdAndName(int cid, String name,
-                                        int preciseCarrierId, String preciseCarrierName,
+                                        int specificCarrierId, String specificCarrierName,
                                         int mnoCid) {
         boolean update = false;
         if (!equals(name, mCarrierName, true)) {
@@ -391,34 +390,34 @@
         }
 
         update = false;
-        if (preciseCarrierId != mPreciseCarrierId) {
-            logd("[updatePreciseCarrierId] from:" + mPreciseCarrierId + " to:"
-                    + preciseCarrierId);
-            mPreciseCarrierId = preciseCarrierId;
+        if (specificCarrierId != mSpecificCarrierId) {
+            logd("[updateSpecificCarrierId] from:" + mSpecificCarrierId + " to:"
+                    + specificCarrierId);
+            mSpecificCarrierId = specificCarrierId;
             update = true;
         }
-        if (preciseCarrierName != mPreciseCarrierName) {
-            logd("[updatePreciseCarrierName] from:" + mPreciseCarrierName + " to:"
-                    + preciseCarrierName);
-            mPreciseCarrierName = preciseCarrierName;
+        if (specificCarrierName != mSpecificCarrierName) {
+            logd("[updateSpecificCarrierName] from:" + mSpecificCarrierName + " to:"
+                    + specificCarrierName);
+            mSpecificCarrierName = specificCarrierName;
             update = true;
         }
         if (update) {
-            mCarrierIdLocalLog.log("[updatePreciseCarrierIdAndName] cid:" + mPreciseCarrierId
-                    + " name:" + mPreciseCarrierName);
+            mCarrierIdLocalLog.log("[updateSpecificCarrierIdAndName] cid:"
+                    + mSpecificCarrierId + " name:" + mSpecificCarrierName);
             final Intent intent = new Intent(TelephonyManager
-                    .ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED);
-            intent.putExtra(TelephonyManager.EXTRA_PRECISE_CARRIER_ID, mPreciseCarrierId);
-            intent.putExtra(TelephonyManager.EXTRA_PRECISE_CARRIER_NAME, mPreciseCarrierName);
+                    .ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED);
+            intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID, mSpecificCarrierId);
+            intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_NAME, mSpecificCarrierName);
             intent.putExtra(TelephonyManager.EXTRA_SUBSCRIPTION_ID, mPhone.getSubId());
             mContext.sendBroadcast(intent);
 
-            // notify content observers for precise carrier id change event.
+            // notify content observers for specific carrier id change event.
             ContentValues cv = new ContentValues();
-            cv.put(CarrierId.PRECISE_CARRIER_ID, mPreciseCarrierId);
-            cv.put(CarrierId.PRECISE_CARRIER_ID_NAME, mPreciseCarrierName);
+            cv.put(CarrierId.SPECIFIC_CARRIER_ID, mSpecificCarrierId);
+            cv.put(CarrierId.SPECIFIC_CARRIER_ID_NAME, mSpecificCarrierName);
             mContext.getContentResolver().update(
-                    Telephony.CarrierId.getPreciseCarrierIdUriForSubscriptionId(mPhone.getSubId()),
+                    Telephony.CarrierId.getSpecificCarrierIdUriForSubscriptionId(mPhone.getSubId()),
                     cv, null, null);
         }
     }
@@ -742,8 +741,8 @@
                 maxRuleParent.mCid = maxRuleParent.mParentCid;
                 maxRuleParent.mName = getCarrierNameFromId(maxRuleParent.mCid);
             }
-            logd("[matchSubscriptionCarrier] precise cid: " + maxRule.mCid + " precise name: "
-                    + maxRule.mName +" cid: " + maxRuleParent.mCid
+            logd("[matchSubscriptionCarrier] specific cid: " + maxRule.mCid
+                    + " specific name: " + maxRule.mName +" cid: " + maxRuleParent.mCid
                     + " name: " + maxRuleParent.mName);
             updateCarrierIdAndName(maxRuleParent.mCid, maxRuleParent.mName,
                     maxRule.mCid, maxRule.mName,
@@ -783,25 +782,29 @@
     }
     /**
      * Returns fine-grained carrier id of the current subscription. Carrier ids with a valid parent
-     * id are precise carrier ids.
-     * The precise carrier id can be used to further differentiate a carrier by different
-     * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
-     * carrier id but can have multiple precise carrier id. e.g,
-     * {@link #getCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM, while
-     * {@link #getPreciseCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based on the
-     * current underlying network.
+     * id are specific carrier ids.
+     *
+     * A specific carrier ID can represent the fact that a carrier may be in effect an aggregation
+     * of other carriers (ie in an MVNO type scenario) where each of these specific carriers which
+     * are used to make up the actual carrier service may have different carrier configurations.
+     * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
+     * different carrier configuration for different service offering such as a prepaid plan.
+     * e.g, {@link #getCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM, while
+     * {@link #getSpecificCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based on the
+     * IMSI from the current subscription.
+     *
      * For carriers without any fine-grained carrier ids, return {@link #getCarrierId()}
      */
-    public int getPreciseCarrierId() {
-        return mPreciseCarrierId;
+    public int getSpecificCarrierId() {
+        return mSpecificCarrierId;
     }
 
     public String getCarrierName() {
         return mCarrierName;
     }
 
-    public String getPreciseCarrierName() {
-        return mPreciseCarrierName;
+    public String getSpecificCarrierName() {
+        return mSpecificCarrierName;
     }
 
     public int getMnoCarrierId() {
@@ -963,10 +966,10 @@
         ipw.decreaseIndent();
 
         ipw.println("mCarrierId: " + mCarrierId);
-        ipw.println("mPreciseCarrierId: " + mPreciseCarrierId);
+        ipw.println("mSpecificCarrierId: " + mSpecificCarrierId);
         ipw.println("mMnoCarrierId: " + mMnoCarrierId);
         ipw.println("mCarrierName: " + mCarrierName);
-        ipw.println("mPreciseCarrierName: " + mPreciseCarrierName);
+        ipw.println("mSpecificCarrierName: " + mSpecificCarrierName);
         ipw.println("carrier_list_version: " + getCarrierListVersion());
 
         ipw.println("mCarrierMatchingRules on mccmnc: "
diff --git a/src/java/com/android/internal/telephony/CellularNetworkValidator.java b/src/java/com/android/internal/telephony/CellularNetworkValidator.java
index 3e552fc..e88949b 100644
--- a/src/java/com/android/internal/telephony/CellularNetworkValidator.java
+++ b/src/java/com/android/internal/telephony/CellularNetworkValidator.java
@@ -25,6 +25,9 @@
 import android.telephony.SubscriptionManager;
 import android.util.Log;
 
+import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
+
 /**
  * This class will validate whether cellular network verified by Connectivity's
  * validation process. It listens request on a specific subId, sends a network request
@@ -186,6 +189,10 @@
                 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
                 mState = STATE_IDLE;
             }
+
+            TelephonyMetrics.getInstance().writeNetworkValidate(passed
+                    ? TelephonyEvent.NetworkValidationState.NETWORK_VALIDATION_STATE_PASSED
+                    : TelephonyEvent.NetworkValidationState.NETWORK_VALIDATION_STATE_FAILED);
         }
 
         mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -203,6 +210,10 @@
         @Override
         public void onAvailable(Network network) {
             logd("network onAvailable " + network);
+            if (ConnectivityNetworkCallback.this.mSubId == CellularNetworkValidator.this.mSubId) {
+                TelephonyMetrics.getInstance().writeNetworkValidate(
+                        TelephonyEvent.NetworkValidationState.NETWORK_VALIDATION_STATE_AVAILABLE);
+            }
         }
 
         @Override
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 6f139f6..d47e872 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -54,6 +54,7 @@
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.provider.Telephony;
+import android.telecom.TelecomManager;
 import android.telecom.VideoProfile;
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.CarrierConfigManager;
@@ -268,6 +269,8 @@
         mSettingsObserver.observe(
                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED),
                 EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE);
+
+        loadTtyMode();
         logd("GsmCdmaPhone: constructor: sub = " + mPhoneId);
     }
 
@@ -275,8 +278,17 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             Rlog.d(LOG_TAG, "mBroadcastReceiver: action " + intent.getAction());
-            if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
+            String action = intent.getAction();
+            if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) {
                 sendMessage(obtainMessage(EVENT_CARRIER_CONFIG_CHANGED));
+            } else if (TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED.equals(action)) {
+                int ttyMode = intent.getIntExtra(
+                        TelecomManager.EXTRA_CURRENT_TTY_MODE, TelecomManager.TTY_MODE_OFF);
+                updateTtyMode(ttyMode);
+            } else if (TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED.equals(action)) {
+                int newPreferredTtyMode = intent.getIntExtra(
+                        TelecomManager.EXTRA_TTY_PREFERRED_MODE, TelecomManager.TTY_MODE_OFF);
+                updateUiTtyMode(newPreferredTtyMode);
             }
         }
     };
@@ -327,8 +339,12 @@
 
         mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
         mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
-        mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(
-                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+        IntentFilter filter = new IntentFilter(
+                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
+        filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
+        filter.addAction(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
+        mContext.registerReceiver(mBroadcastReceiver, filter);
+
         mCDM = new CarrierKeyDownloadManager(this);
         mCIM = new CarrierInfoManager();
     }
@@ -1639,13 +1655,13 @@
     }
 
     @Override
-    public int getPreciseCarrierId() {
-        return mCarrierResolver.getPreciseCarrierId();
+    public int getSpecificCarrierId() {
+        return mCarrierResolver.getSpecificCarrierId();
     }
 
     @Override
-    public String getPreciseCarrierName() {
-        return mCarrierResolver.getPreciseCarrierName();
+    public String getSpecificCarrierName() {
+        return mCarrierResolver.getSpecificCarrierName();
     }
 
     @Override
@@ -3868,4 +3884,47 @@
         }
         return currentConfig;
     }
+
+    private void updateTtyMode(int ttyMode) {
+        logi(String.format("updateTtyMode ttyMode=%d", ttyMode));
+        setTTYMode(telecomModeToPhoneMode(ttyMode), null);
+    }
+    private void updateUiTtyMode(int ttyMode) {
+        logi(String.format("updateUiTtyMode ttyMode=%d", ttyMode));
+        setUiTTYMode(telecomModeToPhoneMode(ttyMode), null);
+    }
+
+    /**
+     * Given a telecom TTY mode, convert to a Telephony mode equivalent.
+     * @param telecomMode Telecom TTY mode.
+     * @return Telephony phone TTY mode.
+     */
+    private static int telecomModeToPhoneMode(int telecomMode) {
+        switch (telecomMode) {
+            // AT command only has 0 and 1, so mapping VCO
+            // and HCO to FULL
+            case TelecomManager.TTY_MODE_FULL:
+            case TelecomManager.TTY_MODE_VCO:
+            case TelecomManager.TTY_MODE_HCO:
+                return Phone.TTY_MODE_FULL;
+            default:
+                return Phone.TTY_MODE_OFF;
+        }
+    }
+
+    /**
+     * Load the current TTY mode in GsmCdmaPhone based on Telecom and UI settings.
+     */
+    private void loadTtyMode() {
+        int ttyMode = TelecomManager.TTY_MODE_OFF;
+        TelecomManager telecomManager = TelecomManager.from(mContext);
+        if (telecomManager != null) {
+            ttyMode = telecomManager.getCurrentTtyMode();
+        }
+        updateTtyMode(ttyMode);
+        //Get preferred TTY mode from settings as UI Tty mode is always user preferred Tty mode.
+        ttyMode = Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF);
+        updateUiTtyMode(ttyMode);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/IccProvider.java b/src/java/com/android/internal/telephony/IccProvider.java
index 76af170..0c0044d 100644
--- a/src/java/com/android/internal/telephony/IccProvider.java
+++ b/src/java/com/android/internal/telephony/IccProvider.java
@@ -17,24 +17,24 @@
 package com.android.internal.telephony;
 
 import android.content.ContentProvider;
-import android.content.UriMatcher;
 import android.content.ContentValues;
+import android.content.UriMatcher;
 import android.database.Cursor;
-import android.database.MergeCursor;
 import android.database.MatrixCursor;
+import android.database.MergeCursor;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.telephony.Rlog;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
-import android.telephony.Rlog;
-
-import java.util.List;
 
 import com.android.internal.telephony.uicc.AdnRecord;
 import com.android.internal.telephony.uicc.IccConstants;
 
+import java.util.List;
+
 
 /**
  * {@hide}
@@ -121,7 +121,8 @@
 
     private Cursor loadAllSimContacts(int efType) {
         Cursor [] result;
-        List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+        List<SubscriptionInfo> subInfoList = mSubscriptionManager
+                .getActiveSubscriptionInfoList(false);
 
         if ((subInfoList == null) || (subInfoList.size() == 0)) {
             result = new Cursor[0];
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index d64547e..8417121 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -3207,11 +3207,11 @@
         return TelephonyManager.UNKNOWN_CARRIER_ID;
     }
 
-    public int getPreciseCarrierId() {
+    public int getSpecificCarrierId() {
         return TelephonyManager.UNKNOWN_CARRIER_ID;
     }
 
-    public String getPreciseCarrierName() {
+    public String getSpecificCarrierName() {
         return null;
     }
 
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index 616e9fe..a191c47 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -46,11 +46,11 @@
     private static final int EVENT_SWITCH_DSDS_CONFIG_DONE = 100;
     private static final int EVENT_GET_MODEM_STATUS = 101;
     private static final int EVENT_GET_MODEM_STATUS_DONE = 102;
+    private static final int EVENT_GET_PHONE_CAPABILITY_DONE = 103;
 
     private static PhoneConfigurationManager sInstance = null;
     private final Context mContext;
     private PhoneCapability mStaticCapability;
-    private PhoneCapability mCurrentCapability;
     private final RadioConfig mRadioConfig;
     private final MainThreadHandler mHandler;
     private final Phone[] mPhones;
@@ -79,8 +79,8 @@
         mContext = context;
         // TODO: send commands to modem once interface is ready.
         TelephonyManager telephonyManager = new TelephonyManager(context);
-        mStaticCapability = PhoneConfigurationModels.DSDS_CAPABILITY;
-        mCurrentCapability = mStaticCapability;
+        //initialize with default, it'll get updated when RADIO is ON/AVAILABLE
+        mStaticCapability = getDefaultCapability();
         mRadioConfig = RadioConfig.getInstance(mContext);
         mHandler = new MainThreadHandler();
         mPhoneStatusMap = new HashMap<>();
@@ -99,6 +99,14 @@
         }
     }
 
+    private PhoneCapability getDefaultCapability() {
+        if (getPhoneCount() > 1) {
+            return PhoneConfigurationModels.DSDS_CAPABILITY;
+        } else {
+            return PhoneConfigurationModels.SSSS_CAPABILITY;
+        }
+    }
+
     /**
      * Static method to get instance.
      */
@@ -131,6 +139,7 @@
                     } else {
                         updatePhoneStatus(phone);
                     }
+                    getStaticPhoneCapability();
                     break;
                 case EVENT_SWITCH_DSDS_CONFIG_DONE:
                     ar = (AsyncResult) msg.obj;
@@ -152,6 +161,14 @@
                         log(msg.what + " failure. Not updating modem status." + ar.exception);
                     }
                     break;
+                case EVENT_GET_PHONE_CAPABILITY_DONE:
+                    ar = (AsyncResult) msg.obj;
+                    if (ar != null && ar.exception == null) {
+                        mStaticCapability = (PhoneCapability) ar.result;
+                        notifyCapabilityChanged();
+                    } else {
+                        log(msg.what + " failure. Not getting phone capability." + ar.exception);
+                    }
             }
         }
     }
@@ -196,7 +213,7 @@
     }
 
     /**
-     * method to call RIL getM
+     * method to call RIL getModemStatus
      */
     private void updatePhoneStatus(Phone phone) {
         Message callback = Message.obtain(
@@ -224,7 +241,13 @@
     /**
      * get static overall phone capabilities for all phones.
      */
-    public PhoneCapability getStaticPhoneCapability() {
+    public synchronized PhoneCapability getStaticPhoneCapability() {
+        if (getDefaultCapability().equals(mStaticCapability)) {
+            log("getStaticPhoneCapability: sending the request for getting PhoneCapability");
+            Message callback = Message.obtain(
+                    mHandler, EVENT_GET_PHONE_CAPABILITY_DONE);
+            mRadioConfig.getPhoneCapability(callback);
+        }
         return mStaticCapability;
     }
 
@@ -232,17 +255,17 @@
      * get configuration related status of each phone.
      */
     public PhoneCapability getCurrentPhoneCapability() {
-        return mCurrentCapability;
+        return getStaticPhoneCapability();
     }
 
     public int getNumberOfModemsWithSimultaneousDataConnections() {
-        return mCurrentCapability.maxActiveData;
+        return mStaticCapability.maxActiveData;
     }
 
     private void notifyCapabilityChanged() {
         PhoneNotifier notifier = new DefaultPhoneNotifier();
 
-        notifier.notifyPhoneCapabilityChanged(mCurrentCapability);
+        notifier.notifyPhoneCapabilityChanged(mStaticCapability);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationModels.java b/src/java/com/android/internal/telephony/PhoneConfigurationModels.java
index fb8cc5e..aca4955 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationModels.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationModels.java
@@ -40,7 +40,7 @@
         List<ModemInfo> logicalModemList = new ArrayList<>();
         logicalModemList.add(modemInfo1);
         logicalModemList.add(modemInfo2);
-        DSDS_CAPABILITY = new PhoneCapability(1, 2, 0, logicalModemList, false);
+        DSDS_CAPABILITY = new PhoneCapability(1, 2, 0, logicalModemList, true);
 
         logicalModemList = new ArrayList<>();
         logicalModemList.add(modemInfo1);
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 043de1c..065b201 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -27,7 +27,7 @@
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
-import android.telephony.DebugEventReporter;
+import android.telephony.AnomalyReporter;
 import android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
@@ -556,7 +556,7 @@
         pw.println("DebugEvents:");
         pw.increaseIndent();
         try {
-            DebugEventReporter.dump(fd, pw, args);
+            AnomalyReporter.dump(fd, pw, args);
         } catch (Exception e) {
             e.printStackTrace();
         }
diff --git a/src/java/com/android/internal/telephony/PhoneSwitcher.java b/src/java/com/android/internal/telephony/PhoneSwitcher.java
index aca9074..c3fba00 100644
--- a/src/java/com/android/internal/telephony/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/PhoneSwitcher.java
@@ -16,17 +16,24 @@
 
 package com.android.internal.telephony;
 
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
 import static android.telephony.PhoneStateListener.LISTEN_PRECISE_CALL_STATE;
 import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
 import static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER;
+import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
+import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
 import android.net.MatchAllNetworkSpecifier;
+import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkFactory;
 import android.net.NetworkRequest;
@@ -38,6 +45,7 @@
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.telephony.PhoneCapability;
 import android.telephony.PhoneStateListener;
 import android.telephony.PreciseCallState;
@@ -48,6 +56,10 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.dataconnection.DcRequest;
+import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.FileDescriptor;
@@ -65,8 +77,10 @@
  * the active phones.  Note we don't wait for data attach (which may not happen anyway).
  */
 public class PhoneSwitcher extends Handler {
-    private final static String LOG_TAG = "PhoneSwitcher";
-    private final static boolean VDBG = false;
+    private static final String LOG_TAG = "PhoneSwitcher";
+    private static final boolean VDBG = false;
+
+    private static final int DEFAULT_NETWORK_CHANGE_TIMEOUT_MS = 5000;
 
     private final List<DcRequest> mPrioritizedDcRequests = new ArrayList<DcRequest>();
     private final RegistrantList mActivePhoneRegistrants;
@@ -103,16 +117,19 @@
 
     private int mPhoneIdInCall = SubscriptionManager.INVALID_PHONE_INDEX;
 
+    private ISetOpportunisticDataCallback mSetOpptSubCallback;
+
     private static final int EVENT_DEFAULT_SUBSCRIPTION_CHANGED   = 101;
     private static final int EVENT_SUBSCRIPTION_CHANGED           = 102;
     private static final int EVENT_REQUEST_NETWORK                = 103;
     private static final int EVENT_RELEASE_NETWORK                = 104;
     private static final int EVENT_EMERGENCY_TOGGLE               = 105;
     private static final int EVENT_RADIO_CAPABILITY_CHANGED       = 106;
-    private static final int EVENT_PREFERRED_SUBSCRIPTION_CHANGED = 107;
+    private static final int EVENT_CHANGE_PREFERRED_SUBSCRIPTION  = 107;
     private static final int EVENT_RADIO_AVAILABLE                = 108;
     private static final int EVENT_PHONE_IN_CALL_CHANGED          = 109;
     private static final int EVENT_NETWORK_VALIDATION_DONE        = 110;
+    private static final int EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK = 111;
 
     // Depending on version of IRadioConfig, we need to send either RIL_REQUEST_ALLOW_DATA if it's
     // 1.0, or RIL_REQUEST_SET_PREFERRED_DATA if it's 1.1 or later. So internally mHalCommandToUse
@@ -129,6 +146,24 @@
     // Default timeout value of network validation in millisecond.
     private final static int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000;
 
+    private Boolean mHasRegisteredDefaultNetworkChangeCallback = false;
+
+    private ConnectivityManager mConnectivityManager;
+
+    private final ConnectivityManager.NetworkCallback mDefaultNetworkCallback =
+            new NetworkCallback() {
+                @Override
+                public void onAvailable(Network network) {
+                    if (mConnectivityManager.getNetworkCapabilities(network)
+                            .hasTransport(TRANSPORT_CELLULAR)) {
+                        logDataSwitchEvent(
+                                TelephonyEvent.EventState.EVENT_STATE_END,
+                                TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN);
+                    }
+                    removeDefaultNetworkChangeCallback();
+                }
+            };
+
     /**
      * Method to get singleton instance.
      */
@@ -150,6 +185,7 @@
         return sPhoneSwitcher;
     }
 
+    /** This constructor is only used for testing purpose. */
     @VisibleForTesting
     public PhoneSwitcher(int numPhones, Looper looper) {
         super(looper);
@@ -241,11 +277,14 @@
         } catch (RemoteException e) {
         }
 
+        mConnectivityManager =
+            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+
         mContext.registerReceiver(mDefaultDataChangedReceiver,
                 new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
 
         NetworkCapabilities netCap = new NetworkCapabilities();
-        netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+        netCap.addTransportType(TRANSPORT_CELLULAR);
         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
         netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
@@ -295,7 +334,10 @@
                 break;
             }
             case EVENT_DEFAULT_SUBSCRIPTION_CHANGED: {
+                logDataSwitchEvent(TelephonyEvent.EventState.EVENT_STATE_START,
+                        DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL);
                 onEvaluate(REQUESTS_UNCHANGED, "defaultChanged");
+                registerDefaultNetworkChangeCallback();
                 break;
             }
             case EVENT_REQUEST_NETWORK: {
@@ -314,8 +356,16 @@
                 resendRilCommands(msg);
                 break;
             }
-            case EVENT_PREFERRED_SUBSCRIPTION_CHANGED: {
-                onEvaluate(REQUESTS_UNCHANGED, "preferredDataSubscriptionIdChanged");
+            case EVENT_CHANGE_PREFERRED_SUBSCRIPTION: {
+                int subId = msg.arg1;
+                boolean needValidation = (msg.arg2 == 1);
+                ISetOpportunisticDataCallback callback =
+                        (ISetOpportunisticDataCallback) msg.obj;
+                if (SubscriptionManager.isUsableSubscriptionId(subId)) {
+                    setOpportunisticDataSubscription(subId, needValidation, callback);
+                } else {
+                    unsetOpportunisticDataSubscription(callback);
+                }
                 break;
             }
             case EVENT_RADIO_AVAILABLE: {
@@ -324,7 +374,10 @@
                 break;
             }
             case EVENT_PHONE_IN_CALL_CHANGED: {
+                logDataSwitchEvent(TelephonyEvent.EventState.EVENT_STATE_START,
+                        DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL);
                 onEvaluate(REQUESTS_UNCHANGED, "EVENT_PHONE_IN_CALL_CHANGED");
+                registerDefaultNetworkChangeCallback();
                 break;
             }
             case EVENT_NETWORK_VALIDATION_DONE: {
@@ -333,6 +386,10 @@
                 onValidationDone(subId, passed);
                 break;
             }
+            case EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK: {
+                removeDefaultNetworkChangeCallback();
+                break;
+            }
         }
     }
 
@@ -371,7 +428,8 @@
 
     private void onRequestNetwork(NetworkRequest networkRequest) {
         final DcRequest dcRequest = new DcRequest(networkRequest, mContext);
-        if (mPrioritizedDcRequests.contains(dcRequest) == false) {
+        if (!mPrioritizedDcRequests.contains(dcRequest)) {
+            collectRequestNetworkMetrics(networkRequest);
             mPrioritizedDcRequests.add(dcRequest);
             Collections.sort(mPrioritizedDcRequests);
             onEvaluate(REQUESTS_CHANGED, "netRequest");
@@ -383,6 +441,53 @@
 
         if (mPrioritizedDcRequests.remove(dcRequest)) {
             onEvaluate(REQUESTS_CHANGED, "netReleased");
+            collectReleaseNetworkMetrics(networkRequest);
+        }
+    }
+
+    private void removeDefaultNetworkChangeCallback() {
+        synchronized (mHasRegisteredDefaultNetworkChangeCallback) {
+            if (mHasRegisteredDefaultNetworkChangeCallback) {
+                mHasRegisteredDefaultNetworkChangeCallback = false;
+                removeMessages(EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK);
+                mConnectivityManager.unregisterNetworkCallback(mDefaultNetworkCallback);
+            }
+        }
+    }
+
+    private void registerDefaultNetworkChangeCallback() {
+        removeDefaultNetworkChangeCallback();
+
+        synchronized (mHasRegisteredDefaultNetworkChangeCallback) {
+            mHasRegisteredDefaultNetworkChangeCallback = true;
+            mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback);
+            sendMessageDelayed(
+                    obtainMessage(EVENT_REMOVE_DEFAULT_NETWORK_CHANGE_CALLBACK),
+                    DEFAULT_NETWORK_CHANGE_TIMEOUT_MS);
+        }
+    }
+
+    private void collectRequestNetworkMetrics(NetworkRequest networkRequest) {
+        // Request network for MMS will temporary disable the network on default data subscription,
+        // this only happen on multi-sim device.
+        if (mNumPhones > 1 && networkRequest.networkCapabilities.hasCapability(
+                NetworkCapabilities.NET_CAPABILITY_MMS)) {
+            OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
+            onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
+            onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_START;
+            TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch);
+        }
+    }
+
+    private void collectReleaseNetworkMetrics(NetworkRequest networkRequest) {
+        // Release network for MMS will recover the network on default data subscription, this only
+        // happen on multi-sim device.
+        if (mNumPhones > 1 && networkRequest.networkCapabilities.hasCapability(
+                NetworkCapabilities.NET_CAPABILITY_MMS)) {
+            OnDemandDataSwitch onDemandDataSwitch = new OnDemandDataSwitch();
+            onDemandDataSwitch.apn = TelephonyEvent.ApnType.APN_TYPE_MMS;
+            onDemandDataSwitch.state = TelephonyEvent.EventState.EVENT_STATE_END;
+            TelephonyMetrics.getInstance().writeOnDemandDataSwitch(onDemandDataSwitch);
         }
     }
 
@@ -494,6 +599,10 @@
                     activate(phoneId);
                 }
             }
+
+            notifyActiveDataSubIdChanged(mSubscriptionController.getSubIdUsingPhoneId(
+                    mPreferredDataPhoneId));
+
             // Notify all registrants.
             mActivePhoneRegistrants.notifyRegistrants();
         }
@@ -689,19 +798,35 @@
      * subscription. It has to be an active subscription, and PhoneSwitcher will try to validate
      * it first if needed.
      */
-    public void setOpportunisticDataSubscription(int subId) {
+    private void setOpportunisticDataSubscription(int subId, boolean needValidation,
+            ISetOpportunisticDataCallback callback) {
         if (!mSubscriptionController.isActiveSubId(subId)) {
             log("Can't switch data to inactive subId " + subId);
+            sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER);
+            return;
+        }
+
+        if (mValidator.isValidating()
+                && (!needValidation || subId != mValidator.getSubIdInValidation())) {
+            mValidator.stopValidation();
+        }
+
+        if (subId == mPreferredDataSubId) {
+            sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
             return;
         }
 
         // If validation feature is not supported, set it directly. Otherwise,
         // start validation on the subscription first.
-        if (!CellularNetworkValidator.isValidationFeatureSupported()) {
-            setPreferredDataSubscriptionId(subId);
-        } else {
+        if (CellularNetworkValidator.isValidationFeatureSupported() && needValidation) {
+            logDataSwitchEvent(TelephonyEvent.EventState.EVENT_STATE_START,
+                    DataSwitch.Reason.DATA_SWITCH_REASON_CBRS);
+            mSetOpptSubCallback = callback;
             mValidator.validate(subId, DEFAULT_VALIDATION_EXPIRATION_TIME,
                     false, mValidationCallback);
+        } else {
+            setPreferredSubscription(subId);
+            sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
         }
     }
 
@@ -709,32 +834,57 @@
      * Unset opportunistic data subscription. It's an indication to switch Internet data back
      * from opportunistic subscription to primary subscription.
      */
-    public void unsetOpportunisticDataSubscription() {
-        if (CellularNetworkValidator.isValidationFeatureSupported()
-                && mValidator.isValidating()) {
+    private void unsetOpportunisticDataSubscription(ISetOpportunisticDataCallback callback) {
+        if (mValidator.isValidating()) {
             mValidator.stopValidation();
         }
 
         // Set mPreferredDataSubId back to DEFAULT_SUBSCRIPTION_ID. This will trigger
         // data switch to mDefaultDataSubId.
-        setPreferredDataSubscriptionId(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+        setPreferredSubscription(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+        sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
+    }
+
+    private void sendSetOpptCallbackHelper(ISetOpportunisticDataCallback callback, int result) {
+        if (callback == null) return;
+        try {
+            callback.onComplete(result);
+        } catch (RemoteException exception) {
+            log("RemoteException " + exception);
+        }
+    }
+
+    /**
+     * Set opportunistic data subscription.
+     */
+    private void setPreferredSubscription(int subId) {
+        if (mPreferredDataSubId != subId) {
+            mPreferredDataSubId = subId;
+            logDataSwitchEvent(TelephonyEvent.EventState.EVENT_STATE_START,
+                    DataSwitch.Reason.DATA_SWITCH_REASON_CBRS);
+            onEvaluate(REQUESTS_UNCHANGED, "preferredDataSubscriptionIdChanged");
+            registerDefaultNetworkChangeCallback();
+        }
     }
 
     private void onValidationDone(int subId, boolean passed) {
         log("Network validation " + (passed ? "passed" : "failed")
                 + " on subId " + subId);
-        mValidator.stopValidation();
-        if (passed) setPreferredDataSubscriptionId(subId);
+        if (passed) setPreferredSubscription(subId);
+
+        // Trigger callback if needed
+        sendSetOpptCallbackHelper(mSetOpptSubCallback, passed ? SET_OPPORTUNISTIC_SUB_SUCCESS
+                : SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED);
+        mSetOpptSubCallback = null;
     }
 
     // TODO b/123598154: rename preferredDataSub to opportunisticSubId.
-    private void setPreferredDataSubscriptionId(int subId) {
-        if (mPreferredDataSubId != subId) {
-            log("setPreferredDataSubscriptionId subId changed to " + subId);
-            mPreferredDataSubId = subId;
-            Message msg = PhoneSwitcher.this.obtainMessage(EVENT_PREFERRED_SUBSCRIPTION_CHANGED);
-            msg.sendToTarget();
-        }
+    public void trySetPreferredSubscription(int subId, boolean needValidation,
+            ISetOpportunisticDataCallback callback) {
+        log("Try set preferred subscription to subId " + subId
+                + (needValidation ? " with " : " without ") + "validation");
+        PhoneSwitcher.this.obtainMessage(EVENT_CHANGE_PREFERRED_SUBSCRIPTION,
+                subId, needValidation ? 1 : 0, callback).sendToTarget();
     }
 
     private boolean isCallActive(Phone phone) {
@@ -751,11 +901,38 @@
                 ? HAL_COMMAND_PREFERRED_DATA : HAL_COMMAND_ALLOW_DATA;
     }
 
+    public int getPreferredDataSubscriptionId() {
+        return mPreferredDataSubId;
+    }
+
+    public int getPreferredDataPhoneId() {
+        return mPreferredDataPhoneId;
+    }
+
     private void log(String l) {
         Rlog.d(LOG_TAG, l);
         mLocalLog.log(l);
     }
 
+    private void logDataSwitchEvent(int state, int reason) {
+        DataSwitch dataSwitch = new DataSwitch();
+        dataSwitch.state = state;
+        dataSwitch.reason = reason;
+        TelephonyMetrics.getInstance().writeDataSwitch(dataSwitch);
+
+    }
+
+    private void notifyActiveDataSubIdChanged(int activeDataSubId) {
+        ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
+                "telephony.registry"));
+        try {
+            log("notifyActiveDataSubIdChanged to " + activeDataSubId);
+            tr.notifyActiveDataSubIdChanged(activeDataSubId);
+        } catch (RemoteException ex) {
+            // Should never happen because its always available.
+        }
+    }
+
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
         pw.println("PhoneSwitcher:");
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 03cb8b1..e18e3c1 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -5658,7 +5658,9 @@
             ArrayList<android.hardware.radio.V1_0.CellInfo> records) {
         ArrayList<CellInfo> response = new ArrayList<CellInfo>(records.size());
 
+        final long nanotime = SystemClock.elapsedRealtimeNanos();
         for (android.hardware.radio.V1_0.CellInfo record : records) {
+            record.timeStamp = nanotime;
             response.add(CellInfo.create(record));
         }
 
@@ -5675,7 +5677,9 @@
             ArrayList<android.hardware.radio.V1_2.CellInfo> records) {
         ArrayList<CellInfo> response = new ArrayList<CellInfo>(records.size());
 
+        final long nanotime = SystemClock.elapsedRealtimeNanos();
         for (android.hardware.radio.V1_2.CellInfo record : records) {
+            record.timeStamp = nanotime;
             response.add(CellInfo.create(record));
         }
         return response;
@@ -5691,8 +5695,9 @@
             ArrayList<android.hardware.radio.V1_4.CellInfo> records) {
         ArrayList<CellInfo> response = new ArrayList<CellInfo>(records.size());
 
+        final long nanotime = SystemClock.elapsedRealtimeNanos();
         for (android.hardware.radio.V1_4.CellInfo record : records) {
-            response.add(CellInfo.create(record));
+            response.add(CellInfo.create(record, nanotime));
         }
         return response;
     }
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index ab9afec..effab8f 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -324,7 +324,7 @@
      * Wrapper function for IRadioConfig.getPhoneCapability().
      */
     public void getPhoneCapability(Message result) {
-        IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
+        IRadioConfig radioConfigProxy = getRadioConfigProxy(null);
         if (radioConfigProxy == null || mRadioConfigVersion.less(RADIO_CONFIG_HAL_VERSION_1_1)) {
             if (result != null) {
                 AsyncResult.forMessage(result, null,
@@ -393,12 +393,16 @@
 
     static String requestToString(int request) {
         switch (request) {
+            case RIL_REQUEST_GET_PHONE_CAPABILITY:
+                return "GET_PHONE_CAPABILITY";
             case RIL_REQUEST_GET_SLOT_STATUS:
                 return "GET_SLOT_STATUS";
             case RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING:
                 return "SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING";
+            case RIL_REQUEST_SET_PREFERRED_DATA_MODEM:
+                return "SET_PREFERRED_DATA_MODEM";
             case RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG:
-                return "RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG";
+                return "SWITCH_DUAL_SIM_CONFIG";
             default:
                 return "<unknown request>";
         }
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
old mode 100644
new mode 100755
index fd0b011..562d2d7
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -422,6 +422,7 @@
     public static final int CS_NORMAL_ENABLED = 1005;     // Access Control blocks normal voice/sms service
     public static final int CS_EMERGENCY_ENABLED = 1006;  // Access Control blocks emergency call service
     public static final int CS_REJECT_CAUSE_ENABLED = 2001;     // Notify MM rejection cause
+    public static final int CS_REJECT_CAUSE_DISABLED = 2002;    // Cancel MM rejection cause
     /** Notification id. */
     public static final int PS_NOTIFICATION = 888;  // Id to update and cancel PS restricted
     public static final int CS_NOTIFICATION = 999;  // Id to update and cancel CS restricted
@@ -3873,6 +3874,8 @@
 
         Context context = mPhone.getContext();
 
+        boolean autoCancelCsRejectNotification = false;
+
         CarrierConfigManager configManager = (CarrierConfigManager)
                 context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         if (configManager != null) {
@@ -3886,6 +3889,8 @@
                     if (DBG) log("Voice/emergency call barred notification disabled");
                     return;
                 }
+                autoCancelCsRejectNotification = bundle.getBoolean(
+                        CarrierConfigManager.KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, false);
             }
         }
 
@@ -3946,8 +3951,12 @@
                 notificationId = CS_REJECT_CAUSE_NOTIFICATION;
                 int resId = selectResourceForRejectCode(mRejectCode, multipleSubscriptions);
                 if (0 == resId) {
-                    loge("setNotification: mRejectCode=" + mRejectCode + " is not handled.");
-                    return;
+                    if (autoCancelCsRejectNotification) {
+                        notifyType = CS_REJECT_CAUSE_DISABLED;
+                    } else {
+                        loge("setNotification: mRejectCode=" + mRejectCode + " is not handled.");
+                        return;
+                    }
                 } else {
                     icon = com.android.internal.R.drawable.stat_notify_mmcc_indication_icn;
                     // if using the single SIM resource, simNumber will be ignored
@@ -3978,7 +3987,8 @@
         NotificationManager notificationManager = (NotificationManager)
                 context.getSystemService(Context.NOTIFICATION_SERVICE);
 
-        if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
+        if (notifyType == PS_DISABLED || notifyType == CS_DISABLED
+                || notifyType == CS_REJECT_CAUSE_DISABLED) {
             // cancel previous post notification
             notificationManager.cancel(Integer.toString(mSubId), notificationId);
         } else {
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index f89ba4d..f8b58ff 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -92,7 +92,7 @@
 public class SubscriptionController extends ISub.Stub {
     static final String LOG_TAG = "SubscriptionController";
     static final boolean DBG = true;
-    static final boolean VDBG = false;
+    static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
     static final boolean DBG_CACHE = false;
     static final int MAX_LOCAL_LOG_LINES = 500; // TODO: Reduce to 100 when 17678050 is fixed
     private static final int DEPRECATED_SETTING = -1;
@@ -611,7 +611,7 @@
      */
     @Override
     public List<SubscriptionInfo> getAllSubInfoList(String callingPackage) {
-        if (DBG) logd("[getAllSubInfoList]+");
+        if (VDBG) logd("[getAllSubInfoList]+");
 
         // This API isn't public, so no need to provide a valid subscription ID - we're not worried
         // about carrier-privileged callers not having access.
@@ -627,9 +627,9 @@
             List<SubscriptionInfo> subList = null;
             subList = getSubInfo(null, null);
             if (subList != null) {
-                if (DBG) logd("[getAllSubInfoList]- " + subList.size() + " infos return");
+                if (VDBG) logd("[getAllSubInfoList]- " + subList.size() + " infos return");
             } else {
-                if (DBG) logd("[getAllSubInfoList]- no info return");
+                if (VDBG) logd("[getAllSubInfoList]- no info return");
             }
             return subList;
         } finally {
@@ -2268,12 +2268,30 @@
         return allSubs;
     }
 
+    private boolean isInvisibleSubscription(int subId) {
+        for (SubscriptionInfo info : mCacheOpportunisticSubInfoList) {
+            if (info.getSubscriptionId() == subId) {
+                return SubscriptionManager.isInvisibleSubscription(info);
+            }
+        }
+
+        return false;
+    }
+
+
     /**
      * @return the list of subId's that are active, is never null but the length maybe 0.
      */
     @Override
-    public int[] getActiveSubIdList() {
-        ArrayList<Integer> allSubs = getActiveSubIdArrayList();
+    public int[] getActiveSubIdList(boolean visibleOnly) {
+        List<Integer> allSubs = getActiveSubIdArrayList();
+
+        if (visibleOnly) {
+            // Grouped opportunistic subscriptions should be hidden.
+            allSubs = allSubs.stream().filter(subId -> isInvisibleSubscription(subId))
+                    .collect(Collectors.toList());
+        }
+
         int[] subIdArr = new int[allSubs.size()];
         int i = 0;
         for (int sub : allSubs) {
@@ -2690,16 +2708,14 @@
     }
 
     @Override
-    public void setPreferredDataSubscriptionId(int subId) {
+    public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+            ISetOpportunisticDataCallback callback) {
         enforceModifyPhoneState("setPreferredDataSubscriptionId");
         final long token = Binder.clearCallingIdentity();
 
         try {
-            if (SubscriptionManager.isUsableSubscriptionId(subId)) {
-                PhoneSwitcher.getInstance().setOpportunisticDataSubscription(subId);
-            } else {
-                PhoneSwitcher.getInstance().unsetOpportunisticDataSubscription();
-            }
+            PhoneSwitcher.getInstance().trySetPreferredSubscription(
+                    subId, needValidation, callback);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -2708,17 +2724,12 @@
     @Override
     public int getPreferredDataSubscriptionId() {
         enforceReadPrivilegedPhoneState("getPreferredDataSubscriptionId");
-        return mPreferredDataSubId;
-    }
+        final long token = Binder.clearCallingIdentity();
 
-    private void notifyPreferredDataSubIdChanged() {
-        ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
-                "telephony.registry"));
         try {
-            if (DBG) logd("notifyPreferredDataSubIdChanged:");
-            tr.notifyPreferredDataSubIdChanged(mPreferredDataSubId);
-        } catch (RemoteException ex) {
-            // Should never happen because its always available.
+            return PhoneSwitcher.getInstance().getPreferredDataSubscriptionId();
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
@@ -2778,6 +2789,8 @@
 
             refreshCachedActiveSubscriptionInfoList();
 
+            notifySubscriptionInfoChanged();
+
             return groupUUID;
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -2825,6 +2838,8 @@
 
             refreshCachedActiveSubscriptionInfoList();
 
+            notifySubscriptionInfoChanged();
+
             return result != 0;
         } finally {
             Binder.restoreCallingIdentity(identity);
diff --git a/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java b/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
index 96dabd4..77d8706 100644
--- a/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/AccessNetworksManager.java
@@ -25,6 +25,7 @@
 import android.content.ServiceConnection;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.Registrant;
 import android.os.RegistrantList;
@@ -55,7 +56,7 @@
  * It binds to the vendor's qualified networks service and actively monitors the qualified
  * networks changes.
  */
-public class AccessNetworksManager {
+public class AccessNetworksManager extends Handler {
     private static final String TAG = AccessNetworksManager.class.getSimpleName();
     private static final boolean DBG = false;
 
@@ -69,6 +70,8 @@
             ApnSetting.TYPE_EMERGENCY
     };
 
+    private static final int EVENT_BIND_QUALIFIED_NETWORKS_SERVICE = 1;
+
     private final Phone mPhone;
 
     private final CarrierConfigManager mCarrierConfigManager;
@@ -77,8 +80,7 @@
 
     private AccessNetworksManagerDeathRecipient mDeathRecipient;
 
-    // The bound qualified networks service component name
-    private ComponentName mBoundQualifiedNetworksServiceComponent;
+    private String mTargetBindingPackageName;
 
     private QualifiedNetworksServiceConnection mServiceConnection;
 
@@ -94,10 +96,11 @@
             if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)
                     && mPhone.getPhoneId() == intent.getIntExtra(
                     CarrierConfigManager.EXTRA_SLOT_INDEX, 0)) {
-                // When carrier config changes, we need to evaluate and see if we should unbind
-                // the existing service and bind to a new one.
-                if (DBG) log("Carrier config changed.");
-                bindQualifiedNetworksService();
+                // We should wait for carrier config changed event because the target binding
+                // package name can come from the carrier config. Note that we still get this event
+                // even when SIM is absent.
+                if (DBG) log("Carrier config changed. Try to bind qualified network service.");
+                sendEmptyMessage(EVENT_BIND_QUALIFIED_NETWORKS_SERVICE);
             }
         }
     };
@@ -107,7 +110,7 @@
      */
     public static class QualifiedNetworks {
         public final @ApnType int apnType;
-        // The qualified netowrks in preferred order. Each network is a AccessNetworkType.
+        // The qualified networks in preferred order. Each network is a AccessNetworkType.
         public final int[] qualifiedNetworks;
         public QualifiedNetworks(@ApnType int apnType, int[] qualifiedNetworks) {
             this.apnType = apnType;
@@ -134,15 +137,14 @@
         @Override
         public void binderDied() {
             // TODO: try to rebind the service.
-            loge("QualifiedNetworksService(" + mBoundQualifiedNetworksServiceComponent + ") died.");
+            loge("QualifiedNetworksService(" + mTargetBindingPackageName + ") died.");
         }
     }
 
     private final class QualifiedNetworksServiceConnection implements ServiceConnection {
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            if (DBG) log("onServiceConnected");
-            mBoundQualifiedNetworksServiceComponent = name;
+            if (DBG) log("onServiceConnected " + name);
             mIQualifiedNetworksService = IQualifiedNetworksService.Stub.asInterface(service);
             mDeathRecipient = new AccessNetworksManagerDeathRecipient();
 
@@ -157,8 +159,9 @@
         }
         @Override
         public void onServiceDisconnected(ComponentName name) {
-            if (DBG) log("onServiceDisconnected");
+            if (DBG) log("onServiceDisconnected " + name);
             mIQualifiedNetworksService.asBinder().unlinkToDeath(mDeathRecipient, 0);
+            mTargetBindingPackageName = null;
         }
     }
 
@@ -211,11 +214,22 @@
         intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
         phone.getContext().registerReceiverAsUser(mConfigChangedReceiver, UserHandle.ALL,
                 intentFilter, null, null);
+        sendEmptyMessage(EVENT_BIND_QUALIFIED_NETWORKS_SERVICE);
+    }
 
-        // Only binds to qualified network service in AP-assisted mode. For legacy mode,
-        // qualified networks service is not needed.
-        if (phone.getTransportManager() != null && !phone.getTransportManager().isInLegacyMode()) {
-            bindQualifiedNetworksService();
+    /**
+     * Handle message events
+     *
+     * @param msg The message to handle
+     */
+    @Override
+    public void handleMessage(Message msg) {
+        switch (msg.what) {
+            case EVENT_BIND_QUALIFIED_NETWORKS_SERVICE:
+                bindQualifiedNetworksService();
+                break;
+            default:
+                loge("Unhandled event " + msg.what);
         }
     }
 
@@ -232,13 +246,13 @@
             return;
         }
 
+        if (TextUtils.equals(packageName, mTargetBindingPackageName)) {
+            if (DBG) log("Service " + packageName + " already bound or being bound.");
+            return;
+        }
+
         if (mIQualifiedNetworksService != null
                 && mIQualifiedNetworksService.asBinder().isBinderAlive()) {
-            if (mBoundQualifiedNetworksServiceComponent.getPackageName().equals(packageName)) {
-                if (DBG) log("Service " + packageName + " already bound.");
-                return;
-            }
-
             // Remove the network availability updater and then unbind the service.
             try {
                 mIQualifiedNetworksService.removeNetworkAvailabilityUpdater(mPhone.getPhoneId());
@@ -258,7 +272,9 @@
                     mServiceConnection,
                     Context.BIND_AUTO_CREATE)) {
                 loge("Cannot bind to the qualified networks service.");
+                return;
             }
+            mTargetBindingPackageName = packageName;
         } catch (Exception e) {
             loge("Cannot bind to the qualified networks service. Exception: " + e);
         }
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
index a751bbc..c2162f7 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataConnection.java
@@ -44,6 +44,7 @@
 import android.provider.Telephony;
 import android.telephony.AccessNetworkConstants.TransportType;
 import android.telephony.DataFailCause;
+import android.telephony.NetworkRegistrationState;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
@@ -110,6 +111,9 @@
 
     private static final String NETWORK_TYPE = "MOBILE";
 
+    private static final String RAT_NAME_5G = "nr";
+    private static final String RAT_NAME_EVDO = "evdo";
+
     // The data connection providing default Internet connection will have a higher score of 50.
     // Other connections will have a slightly lower score of 45. The intention is other connections
     // will not cause ConnectivityService to tear down default internet connection. For example,
@@ -136,6 +140,8 @@
 
     private String[] mPcscfAddr;
 
+    private final String mTagSuffix;
+
     /**
      * Used internally for saving connecting parameters.
      */
@@ -321,9 +327,9 @@
         String transportType = (dataServiceManager.getTransportType() == TransportType.WWAN)
                 ? "C"   // Cellular
                 : "I";  // IWLAN
-        DataConnection dc = new DataConnection(phone,
-                "DC-" + transportType + "-" + mInstanceNumber.incrementAndGet(), id, dct,
-                dataServiceManager, failBringUpAll, dcc);
+        DataConnection dc = new DataConnection(phone, transportType + "-"
+                + mInstanceNumber.incrementAndGet(), id, dct, dataServiceManager, failBringUpAll,
+                dcc);
         dc.start();
         if (DBG) dc.log("Made " + dc.getName());
         return dc;
@@ -500,10 +506,11 @@
     }
 
     //***** Constructor (NOTE: uses dcc.getHandler() as its Handler)
-    private DataConnection(Phone phone, String name, int id,
+    private DataConnection(Phone phone, String tagSuffix, int id,
                            DcTracker dct, DataServiceManager dataServiceManager,
                            DcTesterFailBringUpAll failBringUpAll, DcController dcc) {
-        super(name, dcc.getHandler());
+        super("DC-" + tagSuffix, dcc.getHandler());
+        mTagSuffix = tagSuffix;
         setLogRecSize(300);
         setLogOnlyTransitions(true);
         if (DBG) log("DataConnection created");
@@ -882,17 +889,25 @@
         return true;
     }
 
+    /**
+     * TCP buffer size config based on the ril technology. There are 6 parameters
+     * read_min, read_default, read_max, write_min, write_default, write_max in the TCP buffer
+     * config string and they are separated by a comma. The unit of these parameters is byte.
+     */
     private static final String TCP_BUFFER_SIZES_GPRS = "4092,8760,48000,4096,8760,48000";
     private static final String TCP_BUFFER_SIZES_EDGE = "4093,26280,70800,4096,16384,70800";
     private static final String TCP_BUFFER_SIZES_UMTS = "58254,349525,1048576,58254,349525,1048576";
-    private static final String TCP_BUFFER_SIZES_1XRTT= "16384,32768,131072,4096,16384,102400";
+    private static final String TCP_BUFFER_SIZES_1XRTT = "16384,32768,131072,4096,16384,102400";
     private static final String TCP_BUFFER_SIZES_EVDO = "4094,87380,262144,4096,16384,262144";
-    private static final String TCP_BUFFER_SIZES_EHRPD= "131072,262144,1048576,4096,16384,524288";
-    private static final String TCP_BUFFER_SIZES_HSDPA= "61167,367002,1101005,8738,52429,262114";
+    private static final String TCP_BUFFER_SIZES_EHRPD = "131072,262144,1048576,4096,16384,524288";
+    private static final String TCP_BUFFER_SIZES_HSDPA = "61167,367002,1101005,8738,52429,262114";
     private static final String TCP_BUFFER_SIZES_HSPA = "40778,244668,734003,16777,100663,301990";
-    private static final String TCP_BUFFER_SIZES_LTE  =
+    private static final String TCP_BUFFER_SIZES_LTE =
             "524288,1048576,2097152,262144,524288,1048576";
-    private static final String TCP_BUFFER_SIZES_HSPAP= "122334,734003,2202010,32040,192239,576717";
+    private static final String TCP_BUFFER_SIZES_HSPAP =
+            "122334,734003,2202010,32040,192239,576717";
+    private static final String TCP_BUFFER_SIZES_NR =
+            "2097152,6291456,16777216,512000,2097152,8388608";
 
     private void updateTcpBufferSizes(int rilRat) {
         String sizes = null;
@@ -907,7 +922,13 @@
         if (rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 ||
                 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A ||
                 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B) {
-            ratName = "evdo";
+            ratName = RAT_NAME_EVDO;
+        }
+
+        // NR 5G Non-Standalone use LTE cell as the primary cell, the ril technology is LTE in this
+        // case. We use NR 5G TCP buffer size when connected to NR 5G Non-Standalone network.
+        if (rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_LTE && isNRConnected()) {
+            ratName = RAT_NAME_5G;
         }
 
         // in the form: "ratname:rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
@@ -955,7 +976,12 @@
                     break;
                 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE:
                 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA:
-                    sizes = TCP_BUFFER_SIZES_LTE;
+                    // Use NR 5G TCP buffer size when connected to NR 5G Non-Standalone network.
+                    if (isNRConnected()) {
+                        sizes = TCP_BUFFER_SIZES_NR;
+                    } else {
+                        sizes = TCP_BUFFER_SIZES_LTE;
+                    }
                     break;
                 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP:
                     sizes = TCP_BUFFER_SIZES_HSPAP;
@@ -1853,6 +1879,8 @@
                 if (dc != null) {
                     mNetworkAgent = dc.getNetworkAgent();
                     if (mNetworkAgent != null) {
+                        mNetworkAgent.setTransportType(mDataServiceManager.getTransportType());
+                        log("Transfer the network agent from " + dc.getName() + " successfully.");
                         mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities());
                         mNetworkAgent.sendLinkProperties(mLinkProperties);
                     } else {
@@ -1864,8 +1892,8 @@
             } else {
                 mScore = calculateScore();
                 mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
-                        "DcNetworkAgent", mNetworkInfo, getNetworkCapabilities(), mLinkProperties,
-                        mScore, misc);
+                        "DcNetworkAgent" + mTagSuffix, mNetworkInfo, getNetworkCapabilities(),
+                        mLinkProperties, mScore, misc);
             }
             if (mDataServiceManager.getTransportType() == TransportType.WWAN) {
                 mPhone.mCi.registerForNattKeepaliveStatus(
@@ -1897,14 +1925,7 @@
                 mPhone.mCi.unregisterForLceInfo(getHandler());
             }
             if (mNetworkAgent != null) {
-                // We do not want to update the network info if this is a handover. For all other
-                // cases we need to update connectivity service with the latest network info.
-                //
-                // For handover, the network agent is transferred to the other data connection.
-                if (mDisconnectParams == null
-                        || mDisconnectParams.mReleaseType != DcTracker.RELEASE_TYPE_HANDOVER) {
-                    mNetworkAgent.sendNetworkInfo(mNetworkInfo);
-                }
+                mNetworkAgent.sendNetworkInfo(mNetworkInfo);
                 mNetworkAgent = null;
             }
         }
@@ -2305,6 +2326,8 @@
 
     private class DcNetworkAgent extends NetworkAgent {
 
+        private final AtomicInteger mTransportType;
+
         private NetworkCapabilities mNetworkCapabilities;
 
         public final DcKeepaliveTracker keepaliveTracker = new DcKeepaliveTracker();
@@ -2314,6 +2337,11 @@
             super(l, c, TAG, ni, nc, lp, score, misc);
             mNetCapsLocalLog.log("New network agent created. capabilities=" + nc);
             mNetworkCapabilities = nc;
+            mTransportType = new AtomicInteger(mDataServiceManager.getTransportType());
+        }
+
+        public void setTransportType(int transportType) {
+            mTransportType.set(transportType);
         }
 
         @Override
@@ -2357,6 +2385,11 @@
 
         @Override
         public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
+            if (mTransportType.get() != mDataServiceManager.getTransportType()) {
+                log("sendNetworkCapabilities: Data connection has been handover to transport "
+                        + TransportType.toString(mTransportType.get()));
+                return;
+            }
             if (!networkCapabilities.equals(mNetworkCapabilities)) {
                 String logStr = "Changed from " + mNetworkCapabilities + " to "
                         + networkCapabilities + ", Data RAT="
@@ -2370,6 +2403,36 @@
         }
 
         @Override
+        public void sendLinkProperties(LinkProperties linkProperties) {
+            if (mTransportType.get() != mDataServiceManager.getTransportType()) {
+                log("sendLinkProperties: Data connection has been handover to transport "
+                        + TransportType.toString(mTransportType.get()));
+                return;
+            }
+            super.sendLinkProperties(linkProperties);
+        }
+
+        @Override
+        public void sendNetworkScore(int score) {
+            if (mTransportType.get() != mDataServiceManager.getTransportType()) {
+                log("sendNetworkScore: Data connection has been handover to transport "
+                        + TransportType.toString(mTransportType.get()));
+                return;
+            }
+            super.sendNetworkScore(score);
+        }
+
+        @Override
+        public void sendNetworkInfo(NetworkInfo networkInfo) {
+            if (mTransportType.get() != mDataServiceManager.getTransportType()) {
+                log("sendNetworkScore: Data connection has been handover to transport "
+                        + TransportType.toString(mTransportType.get()));
+                return;
+            }
+            super.sendNetworkInfo(networkInfo);
+        }
+
+        @Override
         protected void startSocketKeepalive(Message msg) {
             if (msg.obj instanceof NattKeepalivePacketData) {
                 DataConnection.this.obtainMessage(EVENT_KEEPALIVE_START_REQUEST,
@@ -2569,7 +2632,7 @@
      */
     public void tearDownAll(String reason, @ReleaseNetworkType int releaseType,
                             Message onCompletedMsg) {
-        if (DBG) log("tearDownAll: reason=" + reason + " onCompletedMsg=" + onCompletedMsg);
+        if (DBG) log("tearDownAll: reason=" + reason + ", releaseType=" + releaseType);
         sendMessage(DataConnection.EVENT_DISCONNECT_ALL,
                 new DisconnectParams(null, reason, releaseType, onCompletedMsg));
     }
@@ -2794,6 +2857,12 @@
         return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}";
     }
 
+    /** Check if the device is connected to NR 5G Non-Standalone network. */
+    private boolean isNRConnected() {
+        return mPhone.getServiceState().getNrStatus()
+                == NetworkRegistrationState.NR_STATUS_CONNECTED;
+    }
+
     private void dumpToLog() {
         dump(null, new PrintWriter(new StringWriter(0)) {
             @Override
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
index 72be25e..173f934 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DataServiceManager.java
@@ -60,13 +60,14 @@
  * Cellular data service, IWLAN data service).
  */
 public class DataServiceManager {
-    private static final String TAG = DataServiceManager.class.getSimpleName();
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     static final String DATA_CALL_RESPONSE = "data_call_response";
 
     private final Phone mPhone;
 
+    private final String mTag;
+
     private final CarrierConfigManager mCarrierConfigManager;
     private final AppOpsManager mAppOps;
     private final IPackageManager mPackageManager;
@@ -228,9 +229,11 @@
      * @param phone The phone object
      * @param transportType The transport type. Must be a
      *        {@link AccessNetworkConstants.TransportType}.
+     * @param tagSuffix Logging tag suffix
      */
-    public DataServiceManager(Phone phone, int transportType) {
+    public DataServiceManager(Phone phone, int transportType, String tagSuffix) {
         mPhone = phone;
+        mTag = "DSM" + tagSuffix;
         mTransportType = transportType;
         mBound = false;
         mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService(
@@ -580,11 +583,11 @@
     }
 
     private void log(String s) {
-        Rlog.d(TAG, s);
+        Rlog.d(mTag, s);
     }
 
     private void loge(String s) {
-        Rlog.e(TAG, s);
+        Rlog.e(mTag, s);
     }
 
 }
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcController.java b/src/java/com/android/internal/telephony/dataconnection/DcController.java
index f1790a3..391e264 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcController.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcController.java
@@ -121,9 +121,9 @@
     }
 
     public static DcController makeDcc(Phone phone, DcTracker dct,
-                                       DataServiceManager dataServiceManager, Handler handler) {
-        DcController dcc = new DcController("Dcc", phone, dct, dataServiceManager, handler);
-        return dcc;
+                                       DataServiceManager dataServiceManager, Handler handler,
+                                       String tagSuffix) {
+        return new DcController("Dcc" + tagSuffix, phone, dct, dataServiceManager, handler);
     }
 
     void dispose() {
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index db965f9..e900617 100755
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -17,6 +17,9 @@
 package com.android.internal.telephony.dataconnection;
 
 import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE_CA;
+import static android.telephony.TelephonyManager.NETWORK_TYPE_NR;
 
 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_DEFAULT;
 import static com.android.internal.telephony.RILConstants.DATA_PROFILE_INVALID;
@@ -75,6 +78,7 @@
 import android.telephony.TelephonyManager;
 import android.telephony.cdma.CdmaCellLocation;
 import android.telephony.data.ApnSetting;
+import android.telephony.data.ApnSetting.ApnType;
 import android.telephony.data.DataProfile;
 import android.telephony.gsm.GsmCellLocation;
 import android.text.TextUtils;
@@ -92,6 +96,7 @@
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.PhoneSwitcher;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.SettingsObserver;
 import com.android.internal.telephony.TelephonyIntents;
@@ -129,6 +134,25 @@
     private static final boolean VDBG_STALL = false; // STOPSHIP if true
     private static final boolean RADIO_TESTS = false;
 
+    /**
+     * These constants exist here because ConnectivityManager.TYPE_xxx constants are deprecated and
+     * new ones will not be added (for instance NETWORK_TYPE_MCX below).
+     * For backward compatibility, the values here need to be the same as
+     * ConnectivityManager.TYPE_xxx because networkAttributes overlay uses those values.
+     */
+    private static final int NETWORK_TYPE_DEFAULT = ConnectivityManager.TYPE_MOBILE;
+    private static final int NETWORK_TYPE_MMS = ConnectivityManager.TYPE_MOBILE_MMS;
+    private static final int NETWORK_TYPE_SUPL = ConnectivityManager.TYPE_MOBILE_SUPL;
+    private static final int NETWORK_TYPE_DUN = ConnectivityManager.TYPE_MOBILE_DUN;
+    private static final int NETWORK_TYPE_HIPRI = ConnectivityManager.TYPE_MOBILE_HIPRI;
+    private static final int NETWORK_TYPE_FOTA = ConnectivityManager.TYPE_MOBILE_FOTA;
+    private static final int NETWORK_TYPE_IMS = ConnectivityManager.TYPE_MOBILE_IMS;
+    private static final int NETWORK_TYPE_CBS = ConnectivityManager.TYPE_MOBILE_CBS;
+    private static final int NETWORK_TYPE_IA = ConnectivityManager.TYPE_MOBILE_IA;
+    private static final int NETWORK_TYPE_EMERGENCY = ConnectivityManager.TYPE_MOBILE_EMERGENCY;
+    private static final int NETWORK_TYPE_MCX = 1001;  // far away from ConnectivityManager.TYPE_xxx
+                                                       // constants as MCX isn't defined there.
+
     @IntDef(value = {
             REQUEST_TYPE_NORMAL,
             REQUEST_TYPE_HANDOVER,
@@ -559,7 +583,7 @@
 
     // When false we will not auto attach and manually attaching is required.
     private boolean mAutoAttachOnCreationConfig = false;
-    private AtomicBoolean mAutoAttachOnCreation = new AtomicBoolean(false);
+    private AtomicBoolean mAutoAttachEnabled = new AtomicBoolean(false);
 
     // State of screen
     // (TODO: Reconsider tying directly to screen, maybe this is
@@ -651,14 +675,14 @@
                 .createForSubscriptionId(phone.getSubId());
         // The 'C' in tag indicates cellular, and 'I' indicates IWLAN. This is to distinguish
         // between two DcTrackers, one for each.
-        String tag = "DCT-" + ((transportType == TransportType.WWAN) ? "C" : "I");
+        String tagSuffix = "-" + ((transportType == TransportType.WWAN) ? "C" : "I");
         if (mTelephonyManager.getPhoneCount() > 1) {
-            tag += "-" + mPhone.getPhoneId();
+            tagSuffix += "-" + mPhone.getPhoneId();
         }
-        mLogTag = tag;
+        mLogTag = "DCT" + tagSuffix;
 
         mTransportType = transportType;
-        mDataServiceManager = new DataServiceManager(phone, transportType);
+        mDataServiceManager = new DataServiceManager(phone, transportType, tagSuffix);
 
         mResolver = mPhone.getContext().getContentResolver();
         mUiccController = UiccController.getInstance();
@@ -683,7 +707,7 @@
         mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
 
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
-        mAutoAttachOnCreation.set(sp.getBoolean(Phone.DATA_DISABLED_ON_BOOT_KEY, false));
+        mAutoAttachEnabled.set(sp.getBoolean(Phone.DATA_DISABLED_ON_BOOT_KEY, false));
 
         mSubscriptionManager = SubscriptionManager.from(mPhone.getContext());
         mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
@@ -691,7 +715,7 @@
         HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread");
         dcHandlerThread.start();
         Handler dcHandler = new Handler(dcHandlerThread.getLooper());
-        mDcc = DcController.makeDcc(mPhone, this, mDataServiceManager, dcHandler);
+        mDcc = DcController.makeDcc(mPhone, this, mDataServiceManager, dcHandler, tagSuffix);
         mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler);
 
         mDataConnectionTracker = this;
@@ -974,39 +998,42 @@
             ApnContext apnContext;
 
             switch (networkConfig.type) {
-            case ConnectivityManager.TYPE_MOBILE:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_DEFAULT, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_MMS:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_MMS, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_SUPL:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_SUPL, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_DUN:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_DUN, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_HIPRI:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_HIPRI, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_FOTA:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_FOTA, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_IMS:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_IMS, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_CBS:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_CBS, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_IA:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_IA, networkConfig);
-                break;
-            case ConnectivityManager.TYPE_MOBILE_EMERGENCY:
-                apnContext = addApnContext(PhoneConstants.APN_TYPE_EMERGENCY, networkConfig);
-                break;
-            default:
-                log("initApnContexts: skipping unknown type=" + networkConfig.type);
-                continue;
+                case NETWORK_TYPE_DEFAULT:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_DEFAULT, networkConfig);
+                    break;
+                case NETWORK_TYPE_MMS:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_MMS, networkConfig);
+                    break;
+                case NETWORK_TYPE_SUPL:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_SUPL, networkConfig);
+                    break;
+                case NETWORK_TYPE_DUN:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_DUN, networkConfig);
+                    break;
+                case NETWORK_TYPE_HIPRI:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_HIPRI, networkConfig);
+                    break;
+                case NETWORK_TYPE_FOTA:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_FOTA, networkConfig);
+                    break;
+                case NETWORK_TYPE_IMS:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_IMS, networkConfig);
+                    break;
+                case NETWORK_TYPE_CBS:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_CBS, networkConfig);
+                    break;
+                case NETWORK_TYPE_IA:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_IA, networkConfig);
+                    break;
+                case NETWORK_TYPE_EMERGENCY:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_EMERGENCY, networkConfig);
+                    break;
+                case NETWORK_TYPE_MCX:
+                    apnContext = addApnContext(PhoneConstants.APN_TYPE_MCX, networkConfig);
+                    break;
+                default:
+                    log("initApnContexts: skipping unknown type=" + networkConfig.type);
+                    continue;
             }
             log("initApnContexts: apnContext=" + apnContext);
         }
@@ -1178,7 +1205,7 @@
             mPhone.notifyDataConnection();
         }
         if (mAutoAttachOnCreationConfig) {
-            mAutoAttachOnCreation.set(true);
+            mAutoAttachEnabled.set(true);
         }
         setupDataOnConnectableApns(Phone.REASON_DATA_ATTACHED, RetryFailures.ALWAYS);
     }
@@ -1277,7 +1304,7 @@
             reasons.add(DataDisallowedReasonType.IN_ECBM);
         }
 
-        if (!(attachedState || mAutoAttachOnCreation.get())) {
+        if (!(attachedState || mAutoAttachEnabled.get())) {
             reasons.add(DataDisallowedReasonType.NOT_ATTACHED);
         }
         if (!recordsLoaded) {
@@ -2152,8 +2179,8 @@
         }
     }
 
-    public boolean getAutoAttachOnCreation() {
-        return mAutoAttachOnCreation.get();
+    public boolean getAutoAttachEnabled() {
+        return mAutoAttachEnabled.get();
     }
 
     private void onRecordsLoadedOrSubIdChanged() {
@@ -2175,7 +2202,7 @@
         mAllApnSettings.clear();
         mAutoAttachOnCreationConfig = false;
         // Clear auto attach as modem is expected to do a new attach once SIM is ready
-        mAutoAttachOnCreation.set(false);
+        mAutoAttachEnabled.set(false);
         mOnSubscriptionsChangedListener.mPreviousSubId.set(
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
         // In no-sim case, we should still send the emergency APN to the modem, if there is any.
@@ -2259,7 +2286,7 @@
     }
 
     private void addRequestNetworkCompleteMsg(Message onCompleteMsg,
-                                              @ApnSetting.ApnType int apnType) {
+                                              @ApnType int apnType) {
         if (onCompleteMsg != null) {
             List<Message> messageList = mRequestNetworkCompletionMsgs.get(apnType);
             if (messageList == null) messageList = new ArrayList<>();
@@ -2279,13 +2306,13 @@
         message.sendToTarget();
     }
 
-    public void enableApn(@ApnSetting.ApnType int apnType, @RequestNetworkType int requestType,
+    public void enableApn(@ApnType int apnType, @RequestNetworkType int requestType,
                           Message onCompleteMsg) {
         sendMessage(obtainMessage(DctConstants.EVENT_ENABLE_APN, apnType, requestType,
                 onCompleteMsg));
     }
 
-    private void onEnableApn(@ApnSetting.ApnType int apnType, @RequestNetworkType int requestType,
+    private void onEnableApn(@ApnType int apnType, @RequestNetworkType int requestType,
                              Message onCompleteMsg) {
         ApnContext apnContext = mApnContextsByType.get(apnType);
         if (apnContext == null) {
@@ -2359,11 +2386,11 @@
         }
     }
 
-    public void disableApn(@ApnSetting.ApnType int apnType, @ReleaseNetworkType int releaseType) {
+    public void disableApn(@ApnType int apnType, @ReleaseNetworkType int releaseType) {
         sendMessage(obtainMessage(DctConstants.EVENT_DISABLE_APN, apnType, releaseType));
     }
 
-    private void onDisableApn(@ApnSetting.ApnType int apnType,
+    private void onDisableApn(@ApnType int apnType,
                               @ReleaseNetworkType int releaseType) {
         ApnContext apnContext = mApnContextsByType.get(apnType);
         if (apnContext == null) {
@@ -2637,7 +2664,7 @@
         mReregisterOnReconnectFailure = false;
 
         // Clear auto attach as modem is expected to do a new attach
-        mAutoAttachOnCreation.set(false);
+        mAutoAttachEnabled.set(false);
 
         if (mPhone.getSimulatedRadioControl() != null) {
             // Assume data is connected on the simulator
@@ -2649,7 +2676,7 @@
         }
     }
 
-    private void completeConnection(ApnContext apnContext) {
+    private void completeConnection(ApnContext apnContext, @RequestNetworkType int type) {
 
         if (DBG) log("completeConnection: successful, notify the world apnContext=" + apnContext);
 
@@ -2676,7 +2703,10 @@
                     mProvisioningSpinner));
         }
 
-        mPhone.notifyDataConnection(apnContext.getApnType());
+        // Notify data is connected except for handover case.
+        if (type != REQUEST_TYPE_HANDOVER) {
+            mPhone.notifyDataConnection(apnContext.getApnType());
+        }
         startNetStatPoll();
         startDataStallAlarm(DATA_STALL_NOT_SUSPECTED);
     }
@@ -2780,7 +2810,7 @@
                     // Complete the connection normally notifying the world we're connected.
                     // We do this if this isn't a special provisioning apn or if we've been
                     // told its time to provision.
-                    completeConnection(apnContext);
+                    completeConnection(apnContext, requestType);
                 } else {
                     // This is a provisioning APN that we're reporting as connected. Later
                     // when the user desires to upgrade this to a "default" connection,
@@ -3843,11 +3873,34 @@
         log("update(): Active DDS, register for all events now!");
         onUpdateIcc();
 
-        mAutoAttachOnCreation.set(false);
+        updateAutoAttachOnCreation();
 
         mPhone.updateCurrentCarrierInProvider();
     }
 
+    /**
+     * For non DDS phone, mAutoAttachEnabled should be true because it may be detached
+     * automatically from network only because it's idle for too long. In this case, we should
+     * try setting up data call even if it's not attached for 2G or 3G networks. And doing so will
+     * trigger PS attach if possible.
+     */
+    public void updateAutoAttachOnCreation() {
+        PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance();
+        ServiceState serviceState = mPhone.getServiceState();
+        if (PhoneSwitcher.getInstance() == null || serviceState == null) {
+            mAutoAttachEnabled.set(false);
+            return;
+        }
+
+        // If it's non DDS phone, and voice is registered on 2G or 3G network, we set
+        // mAutoAttachEnabled to true.
+        mAutoAttachEnabled.set(mPhone.getPhoneId() != phoneSwitcher.getPreferredDataPhoneId()
+                && serviceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
+                && serviceState.getVoiceNetworkType() != NETWORK_TYPE_LTE
+                && serviceState.getVoiceNetworkType() != NETWORK_TYPE_LTE_CA
+                && serviceState.getVoiceNetworkType() != NETWORK_TYPE_NR);
+    }
+
     private void notifyAllDataDisconnected() {
         sEnableFailFastRefCounter = 0;
         mFailFast = false;
@@ -3928,7 +3981,7 @@
         pw.println(" mNoRecvPollCount=" + mNoRecvPollCount);
         pw.println(" mResolver=" + mResolver);
         pw.println(" mReconnectIntent=" + mReconnectIntent);
-        pw.println(" mAutoAttachOnCreation=" + mAutoAttachOnCreation.get());
+        pw.println(" mAutoAttachEnabled=" + mAutoAttachEnabled.get());
         pw.println(" mIsScreenOn=" + mIsScreenOn);
         pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator);
         pw.println(" mDataServiceBound=" + mDataServiceBound);
diff --git a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
index cd64d1d..888c16a 100644
--- a/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/dataconnection/TelephonyNetworkFactory.java
@@ -219,6 +219,12 @@
 
     // apply or revoke requests if our active-ness changes
     private void onActivePhoneSwitch() {
+        // For non DDS phone, mAutoAttachOnCreation should be true because it may be detached
+        // automatically from network only because it's idle for too long. In this case, we should
+        // try setting up data call even if it's not attached. And doing so will trigger PS attach
+        // if possible.
+        mPhone.getDcTracker(TransportType.WWAN).updateAutoAttachOnCreation();
+
         for (HashMap.Entry<NetworkRequest, Integer> entry : mNetworkRequests.entrySet()) {
             NetworkRequest networkRequest = entry.getKey();
             boolean applied = entry.getValue() != TransportType.INVALID;
@@ -310,11 +316,12 @@
         log("onDataHandoverNeeded: apnType=" + ApnSetting.getApnTypeString(apnType)
                 + ", target transport=" + TransportType.toString(targetTransport));
         if (mTransportManager.getCurrentTransport(apnType) == targetTransport) {
-            log("apnType " + ApnSetting.getApnTypeString(apnType) + " is already on "
+            log("APN type " + ApnSetting.getApnTypeString(apnType) + " is already on "
                     + TransportType.toString(targetTransport));
             return;
         }
 
+        boolean handoverPending = false;
         for (HashMap.Entry<NetworkRequest, Integer> entry : mNetworkRequests.entrySet()) {
             NetworkRequest networkRequest = entry.getKey();
             int currentTransport = entry.getValue();
@@ -326,10 +333,20 @@
                         EVENT_DATA_HANDOVER_COMPLETED);
                 onCompleteMsg.getData().putParcelable(
                         DcTracker.DATA_COMPLETE_MSG_EXTRA_NETWORK_REQUEST, networkRequest);
+                // TODO: Need to handle the case that the request is there, but there is no actual
+                // data connections established.
                 requestNetworkInternal(networkRequest, DcTracker.REQUEST_TYPE_HANDOVER,
                         targetTransport, onCompleteMsg);
+                handoverPending = true;
             }
         }
+
+        if (!handoverPending) {
+            log("No handover request pending. Update the transport type to "
+                    + TransportType.toString(targetTransport) + " for APN type "
+                    + ApnSetting.getApnTypeString(apnType));
+            mTransportManager.setCurrentTransport(apnType, targetTransport);
+        }
     }
 
     private void onDataHandoverSetupCompleted(NetworkRequest networkRequest, boolean success,
diff --git a/src/java/com/android/internal/telephony/TransportManager.java b/src/java/com/android/internal/telephony/dataconnection/TransportManager.java
similarity index 97%
rename from src/java/com/android/internal/telephony/TransportManager.java
rename to src/java/com/android/internal/telephony/dataconnection/TransportManager.java
index aea1007..b04835b 100644
--- a/src/java/com/android/internal/telephony/TransportManager.java
+++ b/src/java/com/android/internal/telephony/dataconnection/TransportManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
@@ -104,7 +105,8 @@
     /** The available transports. Must be one or more of AccessNetworkConstants.TransportType.XXX */
     private final int[] mAvailableTransports;
 
-    private final AccessNetworksManager mAccessNetworksManager;
+    @Nullable
+    private AccessNetworksManager mAccessNetworksManager;
 
     /**
      * Available networks. The key is the APN type, and the value is the available network list in
@@ -138,7 +140,6 @@
 
     public TransportManager(Phone phone) {
         mPhone = phone;
-        mAccessNetworksManager = new AccessNetworksManager(phone);
         mCurrentAvailableNetworks = new ConcurrentHashMap<>();
         mCurrentTransports = new ConcurrentHashMap<>();
         mHandoverNeededEventRegistrants = new RegistrantList();
@@ -148,6 +149,7 @@
             // the IWLAN ones.
             mAvailableTransports = new int[]{TransportType.WWAN};
         } else {
+            mAccessNetworksManager = new AccessNetworksManager(phone);
             mAccessNetworksManager.registerForQualifiedNetworksChanged(this,
                     EVENT_QUALIFIED_NETWORKS_CHANGED);
             mAvailableTransports = new int[]{TransportType.WWAN, TransportType.WLAN};
@@ -333,7 +335,9 @@
         pw.println("mCurrentTransports=" + mCurrentTransports);
         pw.println("isInLegacy=" + isInLegacyMode());
         pw.println("IWLAN operation mode=" + mPhone.mCi.getIwlanOperationMode());
-        mAccessNetworksManager.dump(fd, pw, args);
+        if (mAccessNetworksManager != null) {
+            mAccessNetworksManager.dump(fd, pw, args);
+        }
         pw.decreaseIndent();
         pw.flush();
     }
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index 4d1edd0..083f9ee 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -578,6 +578,7 @@
         try {
             latch.await();
         } catch (InterruptedException e) {
+            Log.e(TAG, "blockingGetEuiccInfoFromEuiccService got InterruptedException e: " + e);
             Thread.currentThread().interrupt();
         }
         return resultRef.get();
@@ -1162,7 +1163,8 @@
     // Checks whether the caller can manage the active embedded subscription on the SIM with the
     // given cardId.
     private boolean canManageActiveSubscriptionOnTargetSim(int cardId, String callingPackage) {
-        List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+        List<SubscriptionInfo> subInfoList = mSubscriptionManager
+                .getActiveSubscriptionInfoList(/* userVisibleonly */false);
         if (subInfoList == null || subInfoList.size() == 0) {
             // No active subscription on any SIM.
             return false;
@@ -1189,7 +1191,8 @@
     // For a single-active subscription phone, checks whether the caller can manage any active
     // embedded subscription.
     private boolean canManageSubscriptionOnTargetSim(int cardId, String callingPackage) {
-        List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+        List<SubscriptionInfo> subInfoList = mSubscriptionManager
+                .getActiveSubscriptionInfoList(/* userVisibleonly */false);
         // No active subscription on any SIM.
         if (subInfoList == null || subInfoList.size() == 0) {
             return false;
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 477b77f..5cb0429 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -3276,6 +3276,7 @@
                 ImsPhoneConnection oldConnection = findConnection(callInfo.first);
                 if (oldConnection == null) {
                     sendCallStartFailedDisconnect(callInfo.first, callInfo.second);
+                    break;
                 }
                 mForegroundCall.detach(oldConnection);
                 removeConnection(oldConnection);
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java b/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java
index 56db4ba..8a97579 100644
--- a/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyEventBuilder.java
@@ -19,6 +19,7 @@
 import static com.android.internal.telephony.nano.TelephonyProto.ImsCapabilities;
 import static com.android.internal.telephony.nano.TelephonyProto.ImsConnectionState;
 import static com.android.internal.telephony.nano.TelephonyProto.RilDataCall;
+import static com.android.internal.telephony.nano.TelephonyProto.SimState;
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierIdMatching;
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierKeyChange;
@@ -30,10 +31,16 @@
 import static com.android.internal.telephony.nano.TelephonyProto.TelephonySettings;
 
 import android.os.SystemClock;
+import android.telephony.TelephonyManager;
+import android.util.SparseArray;
 
-import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.PhoneStatus;
+import com.android.internal.telephony.nano.TelephonyProto.ActiveSubscriptionInfo;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.Type;
 
+import java.util.Arrays;
+
 public class TelephonyEventBuilder {
     private final TelephonyEvent mEvent = new TelephonyEvent();
 
@@ -41,6 +48,11 @@
         return mEvent;
     }
 
+    /** The event is not related to any phone id. */
+    public TelephonyEventBuilder() {
+        this(-1 /* phoneId */);
+    }
+
     public TelephonyEventBuilder(int phoneId) {
         this(SystemClock.elapsedRealtime(), phoneId);
     }
@@ -137,12 +149,53 @@
         return this;
     }
 
-    /**
-     * Set and build phone status changed event.
-     */
-    public TelephonyEventBuilder setPhoneStatusChange(PhoneStatus phoneStatus) {
-        mEvent.type = Type.PHONE_STATUS_CHANGED;
-        mEvent.phoneStatus = phoneStatus;
+    /** Set and build SIM state change event. */
+    public TelephonyEventBuilder setSimStateChange(SparseArray<Integer> simStates) {
+        int phoneCount = TelephonyManager.getDefault().getPhoneCount();
+        mEvent.simState = new int[phoneCount];
+        Arrays.fill(mEvent.simState, SimState.SIM_STATE_UNKNOWN);
+        mEvent.type = Type.SIM_STATE_CHANGED;
+        for (int i = 0; i < simStates.size(); i++) {
+            int key = simStates.keyAt(i);
+            if (0 <= key && key < phoneCount) {
+                mEvent.simState[key] = simStates.get(key);
+            }
+        }
+        return this;
+    }
+
+    /** Set and build subscription info change event. */
+    public TelephonyEventBuilder setActiveSubscriptionInfoChange(ActiveSubscriptionInfo info) {
+        mEvent.type = Type.ACTIVE_SUBSCRIPTION_INFO_CHANGED;
+        mEvent.activeSubscriptionInfo = info;
+        return this;
+    }
+
+    /** Set and build enabled modem bitmap change event. */
+    public TelephonyEventBuilder setEnabledModemBitmap(int enabledModemBitmap) {
+        mEvent.type = Type.ENABLED_MODEM_CHANGED;
+        mEvent.enabledModemBitmap = enabledModemBitmap;
+        return this;
+    }
+
+    /** Set and build data switch event. */
+    public TelephonyEventBuilder setDataSwitch(DataSwitch dataSwitch) {
+        mEvent.type = TelephonyEvent.Type.DATA_SWITCH;
+        mEvent.dataSwitch = dataSwitch;
+        return this;
+    }
+
+    /** Set and build network validation event. */
+    public TelephonyEventBuilder setNetworkValidate(int networkValidationState) {
+        mEvent.type = TelephonyEvent.Type.NETWORK_VALIDATE;
+        mEvent.networkValidationState = networkValidationState;
+        return this;
+    }
+
+    /** Set and build on demand data switch event. */
+    public TelephonyEventBuilder setOnDemandDataSwitch(OnDemandDataSwitch onDemandDataSwitch) {
+        mEvent.type = TelephonyEvent.Type.ON_DEMAND_DATA_SWITCH;
+        mEvent.onDemandDataSwitch = onDemandDataSwitch;
         return this;
     }
 }
diff --git a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
index fa7f18c..9c103be 100644
--- a/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
+++ b/src/java/com/android/internal/telephony/metrics/TelephonyMetrics.java
@@ -86,8 +86,9 @@
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierIdMatching;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierIdMatchingResult;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.CarrierKeyChange;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.ModemRestart;
-import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.PhoneStatus;
+import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.OnDemandDataSwitch;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilDeactivateDataCall.DeactivateReason;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.RilSetupDataCall;
@@ -97,6 +98,7 @@
 import com.android.internal.telephony.nano.TelephonyProto.TelephonyServiceState;
 import com.android.internal.telephony.nano.TelephonyProto.TelephonySettings;
 import com.android.internal.telephony.nano.TelephonyProto.TimeInterval;
+import com.android.internal.telephony.protobuf.nano.MessageNano;
 import com.android.internal.util.IndentingPrintWriter;
 
 import java.io.FileDescriptor;
@@ -598,7 +600,18 @@
             addTelephonyEvent(event);
         }
 
-        writePhoneStatusChangedEvent();
+        for (int i = 0; i < mLastActiveSubscriptionInfos.size(); i++) {
+            final int key = mLastActiveSubscriptionInfos.keyAt(i);
+            TelephonyEvent event = new TelephonyEventBuilder(mStartElapsedTimeMs, key)
+                    .setActiveSubscriptionInfoChange(mLastActiveSubscriptionInfos.get(key)).build();
+            addTelephonyEvent(event);
+        }
+
+        addTelephonyEvent(new TelephonyEventBuilder(mStartElapsedTimeMs, -1 /* phoneId */)
+                .setSimStateChange(mLastSimState).build());
+
+        addTelephonyEvent(new TelephonyEventBuilder(mStartElapsedTimeMs, -1 /* phoneId */)
+                .setEnabledModemBitmap(mLastEnabledModemBitmap).build());
     }
 
     /**
@@ -655,6 +668,22 @@
         log.endTime = new TelephonyProto.Time();
         log.endTime.systemTimestampMillis = System.currentTimeMillis();
         log.endTime.elapsedTimestampMillis = SystemClock.elapsedRealtime();
+
+        // Log the last active subscription information.
+        int phoneCount = TelephonyManager.getDefault().getPhoneCount();
+        ActiveSubscriptionInfo[] activeSubscriptionInfo =
+                new ActiveSubscriptionInfo[phoneCount];
+        for (int i = 0; i < mLastActiveSubscriptionInfos.size(); i++) {
+            int key = mLastActiveSubscriptionInfos.keyAt(i);
+            activeSubscriptionInfo[key] = mLastActiveSubscriptionInfos.get(key);
+        }
+        for (int i = 0; i < phoneCount; i++) {
+            if (activeSubscriptionInfo[i] == null) {
+                activeSubscriptionInfo[i] = makeInvalidSubscriptionInfo(i);
+            }
+        }
+        log.lastActiveSubscriptionInfo = activeSubscriptionInfo;
+
         return log;
     }
 
@@ -664,19 +693,37 @@
         Integer lastSimState = mLastSimState.get(phoneId);
         if (lastSimState == null || !lastSimState.equals(state)) {
             mLastSimState.put(phoneId, state);
-            writePhoneStatusChangedEvent();
+            addTelephonyEvent(new TelephonyEventBuilder().setSimStateChange(mLastSimState).build());
         }
     }
 
     /** Update active subscription info list. */
     public void updateActiveSubscriptionInfoList(List<SubscriptionInfo> subInfos) {
-        mLastActiveSubscriptionInfos.clear();
+        List<Integer> inActivePhoneList = new ArrayList<>();
+        for (int i = 0; i < mLastActiveSubscriptionInfos.size(); i++) {
+            inActivePhoneList.add(mLastActiveSubscriptionInfos.keyAt(i));
+        }
+
         for (SubscriptionInfo info : subInfos) {
             int phoneId = SubscriptionManager.getPhoneId(info.getSubscriptionId());
+            inActivePhoneList.removeIf(value -> value.equals(phoneId));
             ActiveSubscriptionInfo activeSubscriptionInfo = new ActiveSubscriptionInfo();
-            activeSubscriptionInfo.isOpportunistic = info.isOpportunistic();
+            activeSubscriptionInfo.slotIndex = phoneId;
+            activeSubscriptionInfo.isOpportunistic = info.isOpportunistic() ? 1 : 0;
             activeSubscriptionInfo.carrierId = info.getCarrierId();
-            mLastActiveSubscriptionInfos.put(phoneId, activeSubscriptionInfo);
+            if (!MessageNano.messageNanoEquals(
+                    mLastActiveSubscriptionInfos.get(phoneId), activeSubscriptionInfo)) {
+                addTelephonyEvent(new TelephonyEventBuilder(phoneId)
+                        .setActiveSubscriptionInfoChange(activeSubscriptionInfo).build());
+
+                mLastActiveSubscriptionInfos.put(phoneId, activeSubscriptionInfo);
+            }
+        }
+
+        for (int phoneId : inActivePhoneList) {
+            mLastActiveSubscriptionInfos.remove(phoneId);
+            addTelephonyEvent(new TelephonyEventBuilder(phoneId)
+                    .setActiveSubscriptionInfoChange(makeInvalidSubscriptionInfo(phoneId)).build());
         }
     }
 
@@ -684,28 +731,16 @@
     public void updateEnabledModemBitmap(int enabledModemBitmap) {
         if (mLastEnabledModemBitmap == enabledModemBitmap) return;
         mLastEnabledModemBitmap = enabledModemBitmap;
-        writePhoneStatusChangedEvent();
+        addTelephonyEvent(new TelephonyEventBuilder()
+                .setEnabledModemBitmap(mLastEnabledModemBitmap).build());
     }
 
-    /** Write the event of phone status changed. */
-    public void writePhoneStatusChangedEvent() {
-        int phoneCount = TelephonyManager.getDefault().getPhoneCount();
-        PhoneStatus phoneStatus = new PhoneStatus();
-        phoneStatus.enabledModemBitmap = mLastEnabledModemBitmap;
-        phoneStatus.simState = new int[phoneCount];
-        Arrays.fill(phoneStatus.simState, SimState.SIM_STATE_ABSENT);
-        for (int i = 0; i < mLastSimState.size(); i++) {
-            int phoneId = mLastSimState.keyAt(i);
-            if (SubscriptionManager.isValidPhoneId(phoneId)) {
-                phoneStatus.simState[phoneId] = mLastSimState.get(phoneId);
-            }
-        }
-
-        // Phone status is not associated with any phone id, so set the phone id to -1 for the phone
-        // status changed event.
-        addTelephonyEvent(new TelephonyEventBuilder(-1 /* phoneId */)
-                .setPhoneStatusChange(phoneStatus)
-                .build());
+    private static ActiveSubscriptionInfo makeInvalidSubscriptionInfo(int phoneId) {
+        ActiveSubscriptionInfo invalidSubscriptionInfo = new ActiveSubscriptionInfo();
+        invalidSubscriptionInfo.slotIndex = phoneId;
+        invalidSubscriptionInfo.carrierId = -1;
+        invalidSubscriptionInfo.isOpportunistic = -1;
+        return invalidSubscriptionInfo;
     }
 
     /**
@@ -1709,6 +1744,32 @@
     }
 
     /**
+     * Write network validation event.
+     * @param networkValidationState the network validation state.
+     */
+    public void writeNetworkValidate(int networkValidationState) {
+        addTelephonyEvent(
+                new TelephonyEventBuilder().setNetworkValidate(networkValidationState).build());
+    }
+
+    /**
+     * Write data switch event.
+     * @param dataSwitch the reason and state of data switch.
+     */
+    public void writeDataSwitch(DataSwitch dataSwitch) {
+        addTelephonyEvent(new TelephonyEventBuilder().setDataSwitch(dataSwitch).build());
+    }
+
+    /**
+     * Write on demand data switch event.
+     * @param onDemandDataSwitch the apn and state of on demand data switch.
+     */
+    public void writeOnDemandDataSwitch(OnDemandDataSwitch onDemandDataSwitch) {
+        addTelephonyEvent(
+                new TelephonyEventBuilder().setOnDemandDataSwitch(onDemandDataSwitch).build());
+    }
+
+    /**
      * Write phone state changed event
      *
      * @param phoneId Phone id
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
index 6a57469..2604959 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierResolverTest.java
@@ -177,27 +177,27 @@
         mCarrierResolver.sendEmptyMessage(SIM_LOAD_EVENT);
         waitForMs(200);
         assertEquals(CID_ATT, mCarrierResolver.getCarrierId());
-        assertEquals(CID_ATT, mCarrierResolver.getPreciseCarrierId());
+        assertEquals(CID_ATT, mCarrierResolver.getSpecificCarrierId());
 
         doReturn(GID_TRACFONE).when(mPhone).getGroupIdLevel1();
         mCarrierResolver.sendEmptyMessage(SIM_LOAD_EVENT);
         waitForMs(200);
         assertEquals(CID_TRACFONE, mCarrierResolver.getCarrierId());
-        assertEquals(CID_TRACFONE_ATT, mCarrierResolver.getPreciseCarrierId());
+        assertEquals(CID_TRACFONE_ATT, mCarrierResolver.getSpecificCarrierId());
 
         doReturn(MCCMNC_TRACFONE_TMO).when(mTelephonyManager)
                 .getSimOperatorNumericForPhone(eq(phoneId));
         mCarrierResolver.sendEmptyMessage(SIM_LOAD_EVENT);
         waitForMs(200);
         assertEquals(CID_TRACFONE, mCarrierResolver.getCarrierId());
-        assertEquals(CID_TRACFONE_TMO, mCarrierResolver.getPreciseCarrierId());
+        assertEquals(CID_TRACFONE_TMO, mCarrierResolver.getSpecificCarrierId());
 
         doReturn(MCCMNC_O2).when(mTelephonyManager)
                 .getSimOperatorNumericForPhone(eq(phoneId));
         mCarrierResolver.sendEmptyMessage(SIM_LOAD_EVENT);
         waitForMs(200);
         assertEquals(CID_O2, mCarrierResolver.getCarrierId());
-        assertEquals(CID_O2, mCarrierResolver.getPreciseCarrierId());
+        assertEquals(CID_O2, mCarrierResolver.getSpecificCarrierId());
 
         doReturn(MCCMNC_O2).when(mTelephonyManager)
                 .getSimOperatorNumericForPhone(eq(phoneId));
@@ -205,7 +205,7 @@
         mCarrierResolver.sendEmptyMessage(SIM_LOAD_EVENT);
         waitForMs(200);
         assertEquals(CID_O2, mCarrierResolver.getCarrierId());
-        assertEquals(CID_O2_PREPAID, mCarrierResolver.getPreciseCarrierId());
+        assertEquals(CID_O2_PREPAID, mCarrierResolver.getSpecificCarrierId());
     }
 
     @Test
@@ -223,6 +223,7 @@
         waitForMs(200);
         assertEquals(CID_UNKNOWN, mCarrierResolver.getCarrierId());
         assertNull(mCarrierResolver.getCarrierName());
+        assertNull(mCarrierResolver.getCarrierName());
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityNrTest.java b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityNrTest.java
index e6e8590..ed7fc1c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CellIdentityNrTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CellIdentityNrTest.java
@@ -45,7 +45,7 @@
 
         // THEN the get method should return correct value
         assertThat(cellIdentityNr.getType()).isEqualTo(CellInfo.TYPE_NR);
-        assertThat(cellIdentityNr.getChannelNumber()).isEqualTo(NRARFCN);
+        assertThat(cellIdentityNr.getNrarfcn()).isEqualTo(NRARFCN);
         assertThat(cellIdentityNr.getPci()).isEqualTo(PCI);
         assertThat(cellIdentityNr.getTac()).isEqualTo(TAC);
         assertThat(cellIdentityNr.getOperatorAlphaLong()).isEqualTo(ALPHAL);
@@ -95,7 +95,7 @@
         // THEN the new object is equal to the old one
         assertThat(anotherCellIdentityNr).isEqualTo(anotherCellIdentityNr);
         assertThat(anotherCellIdentityNr.getType()).isEqualTo(CellInfo.TYPE_NR);
-        assertThat(anotherCellIdentityNr.getChannelNumber()).isEqualTo(NRARFCN);
+        assertThat(anotherCellIdentityNr.getNrarfcn()).isEqualTo(NRARFCN);
         assertThat(anotherCellIdentityNr.getPci()).isEqualTo(PCI);
         assertThat(anotherCellIdentityNr.getTac()).isEqualTo(TAC);
         assertThat(anotherCellIdentityNr.getOperatorAlphaLong()).isEqualTo(ALPHAL);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
index 7746bd5..d5f400b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSwitcherTest.java
@@ -386,13 +386,14 @@
         assertTrue(mDataAllowed[0]);
 
         // Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
-        mPhoneSwitcher.setOpportunisticDataSubscription(2);
+        mPhoneSwitcher.trySetPreferredSubscription(2, false, null);
         waitABit();
         assertFalse(mDataAllowed[0]);
         assertTrue(mDataAllowed[1]);
 
         // Unset preferred sub should make default data sub (phone 0 / sub 1) activated again.
-        mPhoneSwitcher.unsetOpportunisticDataSubscription();
+        mPhoneSwitcher.trySetPreferredSubscription(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                false, null);
         waitABit();
         assertTrue(mDataAllowed[0]);
         assertFalse(mDataAllowed[1]);
@@ -441,7 +442,7 @@
         assertTrue(mPhoneSwitcher.shouldApplyNetworkRequest(mmsRequest, 1));
 
         // Set sub 2 as preferred sub should make phone 1 preferredDataModem
-        mPhoneSwitcher.setOpportunisticDataSubscription(2);
+        mPhoneSwitcher.trySetPreferredSubscription(2, false, null);
         waitABit();
         verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
@@ -454,7 +455,8 @@
         clearInvocations(mActivePhoneSwitchHandler);
 
         // Unset preferred sub should make phone0 preferredDataModem again.
-        mPhoneSwitcher.unsetOpportunisticDataSubscription();
+        mPhoneSwitcher.trySetPreferredSubscription(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                false, null);
         waitABit();
         verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
         verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
@@ -640,7 +642,13 @@
         doReturn(mDefaultDataSub).when(mSubscriptionController).getDefaultDataSubId();
         doAnswer(invocation -> {
             int phoneId = (int) invocation.getArguments()[0];
-            return mSlotIndexToSubId[phoneId][0];
+            if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
+                return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+            } else if (phoneId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
+                return mSlotIndexToSubId[0][0];
+            } else {
+                return mSlotIndexToSubId[phoneId][0];
+            }
         }).when(mSubscriptionController).getSubIdUsingPhoneId(anyInt());
 
         doAnswer(invocation -> {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index dfc2a0b..206ebea 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -151,6 +151,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 
 public class RILTest extends TelephonyTest {
 
@@ -212,7 +213,7 @@
     private static final int RSSI_ASU = 24;
     private static final int SYSTEM_ID = 65533;
     private static final int TAC = 65535;
-    private static final int TIME_ADVANCE = 4;
+    private static final int TIMING_ADVANCE = 4;
     private static final long TIMESTAMP = 215924934;
     private static final int UARFCN = 690;
     private static final int TYPE_CDMA = 2;
@@ -1099,7 +1100,7 @@
         lte.signalStrengthLte.rsrq = -RSRQ;
         lte.signalStrengthLte.rssnr = RSSNR;
         lte.signalStrengthLte.cqi = CQI;
-        lte.signalStrengthLte.timingAdvance = TIME_ADVANCE;
+        lte.signalStrengthLte.timingAdvance = TIMING_ADVANCE;
         android.hardware.radio.V1_0.CellInfo record = new android.hardware.radio.V1_0.CellInfo();
         record.cellInfoType = TYPE_LTE;
         record.registered = false;
@@ -1120,7 +1121,7 @@
         CellIdentityLte cil = new CellIdentityLte(CI, PCI, TAC, EARFCN, Integer.MAX_VALUE, MCC_STR,
                 MNC_STR, EMPTY_ALPHA_LONG, EMPTY_ALPHA_SHORT);
         CellSignalStrengthLte css = new CellSignalStrengthLte(
-                RSSI, RSRP, RSRQ, RSSNR, CQI, TIME_ADVANCE);
+                RSSI, RSRP, RSRQ, RSSNR, CQI, TIMING_ADVANCE);
         expected.setCellIdentity(cil);
         expected.setCellSignalStrength(css);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_UNKNOWN);
@@ -1140,7 +1141,7 @@
         cellinfo.cellIdentityGsm.mnc = MNC_STR;
         cellinfo.signalStrengthGsm.signalStrength = RSSI_ASU;
         cellinfo.signalStrengthGsm.bitErrorRate = BIT_ERROR_RATE;
-        cellinfo.signalStrengthGsm.timingAdvance = TIME_ADVANCE;
+        cellinfo.signalStrengthGsm.timingAdvance = TIMING_ADVANCE;
         android.hardware.radio.V1_0.CellInfo record = new android.hardware.radio.V1_0.CellInfo();
         record.cellInfoType = TYPE_GSM;
         record.registered = false;
@@ -1161,7 +1162,7 @@
         CellIdentityGsm ci = new CellIdentityGsm(
                 LAC, CID, ARFCN, BSIC, MCC_STR, MNC_STR, EMPTY_ALPHA_LONG, EMPTY_ALPHA_SHORT);
         CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
-                RSSI, BIT_ERROR_RATE, TIME_ADVANCE);
+                RSSI, BIT_ERROR_RATE, TIMING_ADVANCE);
         expected.setCellIdentity(ci);
         expected.setCellSignalStrength(cs);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_UNKNOWN);
@@ -1305,7 +1306,7 @@
         CellIdentityLte cil = new CellIdentityLte(
                 CI, PCI, TAC, EARFCN, BANDWIDTH, MCC_STR, MNC_STR, ALPHA_LONG, ALPHA_SHORT);
         CellSignalStrengthLte css = new CellSignalStrengthLte(
-                RSSI, RSRP, RSRQ, RSSNR, CQI, TIME_ADVANCE);
+                RSSI, RSRP, RSRQ, RSSNR, CQI, TIMING_ADVANCE);
         expected.setCellIdentity(cil);
         expected.setCellSignalStrength(css);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
@@ -1326,7 +1327,7 @@
         CellIdentityLte cil = new CellIdentityLte(CI, PCI, TAC, EARFCN, BANDWIDTH, MCC_STR, MNC_STR,
                 EMPTY_ALPHA_LONG, EMPTY_ALPHA_SHORT);
         CellSignalStrengthLte css = new CellSignalStrengthLte(
-                RSSI, RSRP, RSRQ, RSSNR, CQI, TIME_ADVANCE);
+                RSSI, RSRP, RSRQ, RSSNR, CQI, TIMING_ADVANCE);
         expected.setCellIdentity(cil);
         expected.setCellSignalStrength(css);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
@@ -1349,7 +1350,7 @@
         CellIdentityLte cil = new CellIdentityLte(
                 CI, PCI, TAC, EARFCN, BANDWIDTH, null, null, ALPHA_LONG, ALPHA_SHORT);
         CellSignalStrengthLte css = new CellSignalStrengthLte(
-                RSSI, RSRP, RSRQ, RSSNR, CQI, TIME_ADVANCE);
+                RSSI, RSRP, RSRQ, RSSNR, CQI, TIMING_ADVANCE);
         expected.setCellIdentity(cil);
         expected.setCellSignalStrength(css);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
@@ -1369,7 +1370,7 @@
         CellIdentityGsm ci = new CellIdentityGsm(
                 LAC, CID, ARFCN, BSIC, MCC_STR, MNC_STR, ALPHA_LONG, ALPHA_SHORT);
         CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
-                RSSI, BIT_ERROR_RATE, TIME_ADVANCE);
+                RSSI, BIT_ERROR_RATE, TIMING_ADVANCE);
         expected.setCellIdentity(ci);
         expected.setCellSignalStrength(cs);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
@@ -1390,7 +1391,7 @@
         CellIdentityGsm ci = new CellIdentityGsm(
                 LAC, CID, ARFCN, BSIC, MCC_STR, MNC_STR, EMPTY_ALPHA_LONG, EMPTY_ALPHA_SHORT);
         CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
-                RSSI, BIT_ERROR_RATE, TIME_ADVANCE);
+                RSSI, BIT_ERROR_RATE, TIMING_ADVANCE);
         expected.setCellIdentity(ci);
         expected.setCellSignalStrength(cs);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
@@ -1413,7 +1414,7 @@
         CellIdentityGsm ci = new CellIdentityGsm(
                 LAC, CID, ARFCN, BSIC, null, null, ALPHA_LONG, ALPHA_SHORT);
         CellSignalStrengthGsm cs = new CellSignalStrengthGsm(
-                RSSI, BIT_ERROR_RATE, TIME_ADVANCE);
+                RSSI, BIT_ERROR_RATE, TIMING_ADVANCE);
         expected.setCellIdentity(ci);
         expected.setCellConnectionStatus(CellInfo.CONNECTION_NONE);
         expected.setCellSignalStrength(cs);
@@ -1603,24 +1604,89 @@
         assertEquals("100:foo", request.getWorkSourceClientId());
     }
 
-    private ArrayList<CellInfo> getCellInfoListForLTE(
-            String mcc, String mnc, String alphaLong, String alphaShort) {
-        android.hardware.radio.V1_2.CellInfoLte lte = new android.hardware.radio.V1_2.CellInfoLte();
+    @Test
+    public void testCellInfoTimestamp_1_4() {
+        ArrayList<android.hardware.radio.V1_4.CellInfo> records =
+                new ArrayList<android.hardware.radio.V1_4.CellInfo>();
+
+        for (int i = 0; i < 5 /* arbitrary */; i++) {
+            android.hardware.radio.V1_4.CellInfo record =
+                    new android.hardware.radio.V1_4.CellInfo();
+            record.info = new android.hardware.radio.V1_4.CellInfo.Info();
+            record.info.lte(new android.hardware.radio.V1_4.CellInfoLte());
+            initializeCellInfoLte_1_2(record.info.lte().base);
+            record.info.lte().base.cellIdentityLte.base.ci += i; // make them marginally unique
+
+            records.add(record);
+        }
+        List<CellInfo> cil = RIL.convertHalCellInfoList_1_4(records);
+
+        // Check that all timestamps are set to a valid number and are equal
+        final long ts = cil.get(0).getTimeStamp();
+        for (CellInfo ci : cil) {
+            assertTrue(ci.getTimeStamp() > 0 && ci.getTimeStamp() != Long.MAX_VALUE);
+            assertEquals(ci.getTimeStamp(), ts);
+        }
+    }
+
+    @Test
+    public void testCellInfoTimestamp_1_2() {
+        ArrayList<android.hardware.radio.V1_2.CellInfo> records =
+                new ArrayList<android.hardware.radio.V1_2.CellInfo>();
+
+        for (int i = 0; i < 5 /* arbitrary */; i++) {
+            android.hardware.radio.V1_2.CellInfo record =
+                    new android.hardware.radio.V1_2.CellInfo();
+            record.cellInfoType = TYPE_LTE;
+            record.timeStamp = Long.MAX_VALUE;
+            record.registered = false;
+            record.timeStampType = RIL_TIMESTAMP_TYPE_OEM_RIL;
+            record.lte.add(new android.hardware.radio.V1_2.CellInfoLte());
+            initializeCellInfoLte_1_2(record.lte.get(0));
+            record.lte.get(0).cellIdentityLte.base.ci += i; // make them marginally unique
+
+            records.add(record);
+        }
+        List<CellInfo> cil = RIL.convertHalCellInfoList_1_2(records);
+
+        // Check that all timestamps are set to a valid number and are equal
+        final long ts = cil.get(0).getTimeStamp();
+        for (CellInfo ci : cil) {
+            assertTrue(ci.getTimeStamp() > 0 && ci.getTimeStamp() != Long.MAX_VALUE);
+            assertEquals(ci.getTimeStamp(), ts);
+        }
+    }
+
+    private static void initializeCellInfoLte_1_2(android.hardware.radio.V1_2.CellInfoLte lte) {
         lte.cellIdentityLte.base.ci = CI;
         lte.cellIdentityLte.base.pci = PCI;
         lte.cellIdentityLte.base.tac = TAC;
         lte.cellIdentityLte.base.earfcn = EARFCN;
         lte.cellIdentityLte.bandwidth = BANDWIDTH;
-        lte.cellIdentityLte.base.mcc = mcc;
-        lte.cellIdentityLte.base.mnc = mnc;
-        lte.cellIdentityLte.operatorNames.alphaLong = alphaLong;
-        lte.cellIdentityLte.operatorNames.alphaShort = alphaShort;
         lte.signalStrengthLte.signalStrength = RSSI_ASU;
         lte.signalStrengthLte.rsrp = -RSRP;
         lte.signalStrengthLte.rsrq = -RSRQ;
         lte.signalStrengthLte.rssnr = RSSNR;
         lte.signalStrengthLte.cqi = CQI;
-        lte.signalStrengthLte.timingAdvance = TIME_ADVANCE;
+        lte.signalStrengthLte.timingAdvance = TIMING_ADVANCE;
+
+        lte.cellIdentityLte.operatorNames.alphaLong = ALPHA_LONG;
+        lte.cellIdentityLte.operatorNames.alphaShort = ALPHA_SHORT;
+        lte.cellIdentityLte.base.mcc = MCC_STR;
+        lte.cellIdentityLte.base.mnc = MNC_STR;
+    }
+
+    private ArrayList<CellInfo> getCellInfoListForLTE(
+            String mcc, String mnc, String alphaLong, String alphaShort) {
+        android.hardware.radio.V1_2.CellInfoLte lte = new android.hardware.radio.V1_2.CellInfoLte();
+
+        initializeCellInfoLte_1_2(lte);
+        // Override the defaults for test-specific purposes
+        lte.cellIdentityLte.operatorNames.alphaLong = alphaLong;
+        lte.cellIdentityLte.operatorNames.alphaShort = alphaShort;
+        lte.cellIdentityLte.base.mcc = mcc;
+        lte.cellIdentityLte.base.mnc = mnc;
+
         android.hardware.radio.V1_2.CellInfo record = new android.hardware.radio.V1_2.CellInfo();
         record.cellInfoType = TYPE_LTE;
         record.registered = false;
@@ -1648,7 +1714,7 @@
         cellinfo.cellIdentityGsm.operatorNames.alphaShort = alphaShort;
         cellinfo.signalStrengthGsm.signalStrength = RSSI_ASU;
         cellinfo.signalStrengthGsm.bitErrorRate = BIT_ERROR_RATE;
-        cellinfo.signalStrengthGsm.timingAdvance = TIME_ADVANCE;
+        cellinfo.signalStrengthGsm.timingAdvance = TIMING_ADVANCE;
         android.hardware.radio.V1_2.CellInfo record = new android.hardware.radio.V1_2.CellInfo();
         record.cellInfoType = TYPE_GSM;
         record.registered = false;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
index 38ebf4e..0a683b0 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionControllerTest.java
@@ -148,7 +148,7 @@
 
         testInsertSim();
         /* Get SUB ID */
-        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList();
+        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false);
         assertTrue(subIds != null && subIds.length != 0);
         int subID = subIds[0];
 
@@ -189,7 +189,7 @@
         testInsertSim();
 
         /* Get SUB ID */
-        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList();
+        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false);
         assertTrue(subIds != null && subIds.length != 0);
         int subID = subIds[0];
 
@@ -300,7 +300,7 @@
     @SmallTest
     public void testMigrateImsSettings() throws Exception {
         testInsertSim();
-        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList();
+        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false);
         assertTrue(subIds != null && subIds.length != 0);
         int subID = subIds[0];
 
@@ -554,7 +554,7 @@
         /* insert some sims */
         testInsertMultipleRemoteSims();
         assertEquals(1, mSubscriptionControllerUT.getDefaultSubId());
-        int[] subIdsArray = mSubscriptionControllerUT.getActiveSubIdList();
+        int[] subIdsArray = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false);
         assertTrue(subIdsArray.length > 0);
         int len = subIdsArray.length;
 
@@ -564,7 +564,7 @@
 
         assertTrue(result > 0);
         // now check the number of subs left. should be one less than earlier
-        int[] newSubIdsArray = mSubscriptionControllerUT.getActiveSubIdList();
+        int[] newSubIdsArray = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false);
         assertTrue(newSubIdsArray.length > 0);
         assertEquals(len - 1, newSubIdsArray.length);
 
@@ -802,8 +802,8 @@
         mSubscriptionControllerUT.addSubInfoRecord("123", 1);   // sub 1
         mSubscriptionControllerUT.addSubInfoRecord("456", 0);   // sub 2
 
+        int[] subIds = mSubscriptionControllerUT.getActiveSubIdList(/*visibleOnly*/false);
         // Make sure the return sub ids are sorted by slot index
-        assertTrue("active sub ids = " + mSubscriptionControllerUT.getActiveSubIdList(),
-                Arrays.equals(mSubscriptionControllerUT.getActiveSubIdList(), new int[]{2, 1}));
+        assertTrue("active sub ids = " + subIds, Arrays.equals(subIds, new int[]{2, 1}));
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
index c804cd0..52a0cb1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
@@ -151,7 +151,8 @@
         ((MockContentResolver) mContext.getContentResolver()).addProvider(
                 SubscriptionManager.CONTENT_URI.getAuthority(),
                 new FakeSubscriptionContentProvider());
-        doReturn(new int[]{}).when(mSubscriptionController).getActiveSubIdList();
+        doReturn(new int[]{}).when(mSubscriptionController)
+                .getActiveSubIdList(/*visibleOnly*/false);
         mIccRecord = mUiccProfile.getIccRecords();
 
         mSubscriptionInfoUpdaterHandlerThread = new SubscriptionInfoUpdaterHandlerThread(TAG);
@@ -170,7 +171,8 @@
     public void testSimAbsent() throws Exception {
         doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController)
                 .getSubInfoUsingSlotIndexPrivileged(eq(FAKE_SUB_ID_1), anyBoolean());
-        doReturn(new int[]{FAKE_SUB_ID_1}).when(mSubscriptionController).getActiveSubIdList();
+        doReturn(new int[]{FAKE_SUB_ID_1}).when(mSubscriptionController)
+                .getActiveSubIdList(/*visibleOnly*/false);
         mUpdater.updateInternalIccState(
                 IccCardConstants.INTENT_VALUE_ICC_ABSENT, null, FAKE_SUB_ID_1);
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 35bab98..b708b1e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -15,8 +15,8 @@
  */
 package com.android.internal.telephony;
 
+import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 import static android.telephony.PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE;
-import static android.telephony.PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE;
 import static android.telephony.PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED;
 
 import static org.junit.Assert.assertEquals;
@@ -44,7 +44,7 @@
     private PhoneStateListener mPhoneStateListener;
     private TelephonyRegistry mTelephonyRegistry;
     private PhoneCapability mPhoneCapability;
-    private int mPreferredSubId;
+    private int mActiveSubId;
     private int mSrvccState = -1;
 
     public class PhoneStateListenerWrapper extends PhoneStateListener {
@@ -60,8 +60,8 @@
             setReady(true);
         }
         @Override
-        public void onPreferredDataSubIdChanged(int preferredSubId) {
-            mPreferredSubId = preferredSubId;
+        public void onActiveDataSubscriptionIdChanged(int activeSubId) {
+            mActiveSubId = activeSubId;
             setReady(true);
         }
     }
@@ -121,23 +121,23 @@
 
 
     @Test @SmallTest
-    public void testPreferredDataSubChanged() {
+    public void testActiveDataSubChanged() {
         // mTelephonyRegistry.listen with notifyNow = true should trigger callback immediately.
         setReady(false);
-        int preferredSubId = 0;
-        mTelephonyRegistry.notifyPreferredDataSubIdChanged(preferredSubId);
+        int activeSubId = 0;
+        mTelephonyRegistry.notifyActiveDataSubIdChanged(activeSubId);
         mTelephonyRegistry.listen(mContext.getOpPackageName(),
                 mPhoneStateListener.callback,
-                LISTEN_PREFERRED_DATA_SUBID_CHANGE, true);
+                LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE, true);
         waitUntilReady();
-        assertEquals(preferredSubId, mPreferredSubId);
+        assertEquals(activeSubId, mActiveSubId);
 
         // notifyPhoneCapabilityChanged with a new capability. Callback should be triggered.
         setReady(false);
-        mPreferredSubId = 1;
-        mTelephonyRegistry.notifyPreferredDataSubIdChanged(preferredSubId);
+        mActiveSubId = 1;
+        mTelephonyRegistry.notifyActiveDataSubIdChanged(activeSubId);
         waitUntilReady();
-        assertEquals(preferredSubId, mPreferredSubId);
+        assertEquals(activeSubId, mActiveSubId);
     }
 
     /**
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
index 6289e31..9aafb25 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java
@@ -254,8 +254,8 @@
         public void onLooperPrepared() {
             Handler h = new Handler();
 
-            DataServiceManager manager = new DataServiceManager(mPhone, TransportType.WWAN);
-            mDcc = DcController.makeDcc(mPhone, mDcTracker, manager, h);
+            DataServiceManager manager = new DataServiceManager(mPhone, TransportType.WWAN, "");
+            mDcc = DcController.makeDcc(mPhone, mDcTracker, manager, h, "");
             mDcc.start();
             mDc = DataConnection.makeDataConnection(mPhone, 0, mDcTracker, manager,
                     mDcTesterFailBringUpAll, mDcc);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java
index 27d1839..b7b49fd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcControllerTest.java
@@ -85,7 +85,7 @@
         @Override
         public void onLooperPrepared() {
             mHandler = new Handler();
-            mDcc = DcController.makeDcc(mPhone, mDcTracker, mDataServiceManager, mHandler);
+            mDcc = DcController.makeDcc(mPhone, mDcTracker, mDataServiceManager, mHandler, "");
             mDcc.start();
             setReady(true);
         }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
index 29fc9fa..e220d30 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java
@@ -878,10 +878,10 @@
 
         verifyDataConnected(FAKE_APN1);
 
-        assertTrue(mDct.getAutoAttachOnCreation());
+        assertTrue(mDct.getAutoAttachEnabled());
         mDct.update();
         // The auto attach flag should be reset after update
-        assertFalse(mDct.getAutoAttachOnCreation());
+        assertFalse(mDct.getAutoAttachEnabled());
 
         verify(mSST, times(1)).registerForDataConnectionDetached(eq(TransportType.WWAN), eq(mDct),
                 intArgumentCaptor.capture(), eq(null));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
index e14931c..a4b3b58 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -983,7 +983,7 @@
                 false, "", false, false, 0, 0, 0);
         when(mSubscriptionManager.canManageSubscription(subInfo, PACKAGE_NAME)).thenReturn(
                 hasPrivileges);
-        when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(
+        when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
                 Collections.singletonList(subInfo));
     }
 
@@ -1011,7 +1011,7 @@
         when(mSubscriptionManager.canManageSubscription(subInfo2, PACKAGE_NAME)).thenReturn(
                 hasPrivileges);
         ArrayList<SubscriptionInfo> subInfos = new ArrayList<>(Arrays.asList(subInfo1, subInfo2));
-        when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subInfos);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(subInfos);
     }
 
     private void prepareOperationSubscription(boolean hasPrivileges) throws Exception {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
index dff75b0..294c5bb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsManagerTest.java
@@ -61,10 +61,14 @@
     private static final boolean VT_IMS_ENABLE_DEFAULT_VAL = true;
     private static final boolean WFC_IMS_EDITABLE_VAL = true;
     private static final boolean WFC_IMS_NOT_EDITABLE_VAL = false;
+    private static final boolean WFC_IMS_ROAMING_EDITABLE_VAL = true;
+    private static final boolean WFC_IMS_ROAMING_NOT_EDITABLE_VAL = false;
     private static final int WFC_IMS_MODE_DEFAULT_VAL =
             ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED;
     private static final int WFC_IMS_ROAMING_MODE_DEFAULT_VAL =
             ImsConfig.WfcModeFeatureValueConstants.WIFI_PREFERRED;
+    private static final boolean WFC_USE_HOME_MODE_FOR_ROAMING_VAL = true;
+    private static final boolean WFC_NOT_USE_HOME_MODE_FOR_ROAMING_VAL = false;
 
     PersistableBundle mBundle;
     @Mock IBinder mBinder;
@@ -107,6 +111,8 @@
                 ENHANCED_4G_MODE_EDITABLE);
         mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL,
                 WFC_IMS_EDITABLE_VAL);
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL,
+                WFC_IMS_ROAMING_EDITABLE_VAL);
         mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL,
                 WFC_IMS_ENABLE_DEFAULT_VAL);
         mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_ENABLED_BOOL,
@@ -118,6 +124,9 @@
         mBundle.putBoolean(CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL,
                 ENHANCED_4G_MODE_DEFAULT_VAL);
         mBundle.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, true);
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL,
+                WFC_NOT_USE_HOME_MODE_FOR_ROAMING_VAL);
     }
 
     @Test @SmallTest
@@ -653,6 +662,98 @@
                 eq(WFC_IMS_MODE_DEFAULT_VAL));
     }
 
+    /**
+     * Tests the operation of getWfcMode when the configuration to use the home network mode when
+     * roaming for WFC is false. First, it checks that the user setting for WFC_IMS_ROAMING_MODE is
+     * returned when WFC roaming is set to editable. Then, it switches the WFC roaming mode to not
+     * editable and ensures that the default WFC roaming mode is returned.
+     *
+     * Preconditions:
+     *  - CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = false
+     */
+    @Test @SmallTest
+    public void getWfcMode_useWfcHomeModeConfigFalse_shouldUseWfcRoamingMode() {
+        // Set some values that are different than the defaults for WFC mode.
+        doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY))
+                .when(mSubscriptionController).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_MODE),
+                anyString());
+        doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED))
+                .when(mSubscriptionController).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+                anyString());
+
+        ImsManager imsManager = getImsManagerAndInitProvisionedValues();
+
+        // Check that use the WFC roaming network mode.
+        assertEquals(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED,
+                imsManager.getWfcMode(true));
+        verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+                anyString());
+
+        // Set WFC roaming network mode to not editable.
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_ROAMING_MODE_BOOL,
+                WFC_IMS_ROAMING_NOT_EDITABLE_VAL);
+
+        // Check that use the default WFC roaming network mode.
+        assertEquals(WFC_IMS_ROAMING_MODE_DEFAULT_VAL, imsManager.getWfcMode(true));
+        verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+                anyString());
+    }
+
+    /**
+     * Tests the operation of getWfcMode when the configuration to use the home network mode when
+     * roaming for WFC is true independent of whether or not the WFC roaming mode is editable.
+     *
+     * Preconditions:
+     *  - CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = true
+     */
+    @Test @SmallTest
+    public void getWfcMode_useWfcHomeModeConfigTrue_shouldUseWfcHomeMode() {
+        // Set some values that are different than the defaults for WFC mode.
+        doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY))
+                .when(mSubscriptionController).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_MODE),
+                anyString());
+        doReturn(String.valueOf(ImsConfig.WfcModeFeatureValueConstants.CELLULAR_PREFERRED))
+                .when(mSubscriptionController).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_ROAMING_MODE),
+                anyString());
+
+        // Set to use WFC home network mode in roaming network.
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL,
+                WFC_USE_HOME_MODE_FOR_ROAMING_VAL);
+
+        ImsManager imsManager = getImsManagerAndInitProvisionedValues();
+
+        // Check that use the WFC home network mode.
+        assertEquals(ImsConfig.WfcModeFeatureValueConstants.WIFI_ONLY, imsManager.getWfcMode(true));
+        verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_MODE),
+                anyString());
+
+        // Set WFC home network mode to not editable.
+        mBundle.putBoolean(CarrierConfigManager.KEY_EDITABLE_WFC_MODE_BOOL,
+                WFC_IMS_NOT_EDITABLE_VAL);
+
+        // Check that use the default WFC home network mode.
+        assertEquals(WFC_IMS_MODE_DEFAULT_VAL, imsManager.getWfcMode(true));
+        verify(mSubscriptionController, times(1)).getSubscriptionProperty(
+                anyInt(),
+                eq(SubscriptionManager.WFC_IMS_MODE),
+                anyString());
+    }
+
     private ImsManager getImsManagerAndInitProvisionedValues() {
         when(mImsConfigImplBaseMock.getConfigInt(anyInt()))
                 .thenAnswer(invocation ->  {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/MmTelFeatureConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/MmTelFeatureConnectionTest.java
index 0acb694..26afbe3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/MmTelFeatureConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/MmTelFeatureConnectionTest.java
@@ -19,6 +19,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
@@ -193,7 +194,7 @@
 
         // Simulate subscriptions changed, where testSub1 is no longer active
         doReturn(createSubscriptionInfoList(new int[] {testSub2, testSub3}))
-                .when(mSubscriptionManager).getActiveSubscriptionInfoList();
+                .when(mSubscriptionManager).getActiveSubscriptionInfoList(anyBoolean());
         mCallbackManagerUT.mSubChangedListener.onSubscriptionsChanged();
         assertFalse(mCallbackManagerUT.doesCallbackExist(testCallback1));
         // verify that the subscription changed listener is not removed, since we still have a
@@ -220,7 +221,7 @@
 
         // Simulate subscriptions changed, where testSub1 is no longer active
         doReturn(createSubscriptionInfoList(new int[] {testSub2}))
-                .when(mSubscriptionManager).getActiveSubscriptionInfoList();
+                .when(mSubscriptionManager).getActiveSubscriptionInfoList(anyBoolean());
         mCallbackManagerUT.mSubChangedListener.onSubscriptionsChanged();
         assertFalse(mCallbackManagerUT.doesCallbackExist(testCallback1));
         // verify that the subscription listener is removed, since the only active callback has been
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionControllerMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionControllerMock.java
index 411ed1d..2007dca 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionControllerMock.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/mocks/SubscriptionControllerMock.java
@@ -259,7 +259,7 @@
         throw new RuntimeException("not implemented");
     }
     @Override
-    public int[] getActiveSubIdList() {
+    public int[] getActiveSubIdList(boolean visibleOnly) {
         throw new RuntimeException("not implemented");
     }
     @Override
diff --git a/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java b/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
index 984b583..412cc1b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/mocks/TelephonyRegistryMock.java
@@ -427,12 +427,12 @@
     }
 
     @Override
-    public void notifyRadioPowerStateChanged(int state) {
+    public void notifyActiveDataSubIdChanged(int subId) {
         throw new RuntimeException("Not implemented");
     }
 
     @Override
-    public void notifyPreferredDataSubIdChanged(int subId) {
+    public void notifyRadioPowerStateChanged(int state) {
         throw new RuntimeException("Not implemented");
     }