Merge "Fix crash when MultipathPolicyTracker cannot get IMSI"
diff --git a/core/api/current.txt b/core/api/current.txt
index 0610446..4036c98 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -25209,6 +25209,7 @@
 
   public final class Ikev2VpnProfile extends android.net.PlatformVpnProfile {
     method @NonNull public java.util.List<java.lang.String> getAllowedAlgorithms();
+    method @Nullable public android.net.ipsec.ike.IkeTunnelConnectionParams getIkeTunnelConnectionParams();
     method public int getMaxMtu();
     method @Nullable public String getPassword();
     method @Nullable public byte[] getPresharedKey();
@@ -25503,11 +25504,13 @@
 
   public class VpnManager {
     method public void deleteProvisionedVpnProfile();
+    method @Nullable public android.net.VpnProfileState getProvisionedVpnProfileState();
     method @Nullable public android.content.Intent provisionVpnProfile(@NonNull android.net.PlatformVpnProfile);
     method @Deprecated public void startProvisionedVpnProfile();
     method @NonNull public String startProvisionedVpnProfileSession();
     method public void stopProvisionedVpnProfile();
     field public static final String ACTION_VPN_MANAGER_EVENT = "android.net.action.VPN_MANAGER_EVENT";
+    field public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED = "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";
     field public static final String CATEGORY_EVENT_DEACTIVATED_BY_USER = "android.net.category.EVENT_DEACTIVATED_BY_USER";
     field public static final String CATEGORY_EVENT_IKE_ERROR = "android.net.category.EVENT_IKE_ERROR";
     field public static final String CATEGORY_EVENT_NETWORK_ERROR = "android.net.category.EVENT_NETWORK_ERROR";
@@ -25524,6 +25527,22 @@
     field public static final String EXTRA_UNDERLYING_LINK_PROPERTIES = "android.net.extra.UNDERLYING_LINK_PROPERTIES";
     field public static final String EXTRA_UNDERLYING_NETWORK = "android.net.extra.UNDERLYING_NETWORK";
     field public static final String EXTRA_UNDERLYING_NETWORK_CAPABILITIES = "android.net.extra.UNDERLYING_NETWORK_CAPABILITIES";
+    field public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";
+  }
+
+  public final class VpnProfileState implements android.os.Parcelable {
+    ctor public VpnProfileState(int, @Nullable String, boolean, boolean);
+    method public int describeContents();
+    method @Nullable public String getSessionId();
+    method public int getState();
+    method public boolean isAlwaysOn();
+    method public boolean isLockdownEnabled();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnProfileState> CREATOR;
+    field public static final int STATE_CONNECTED = 2; // 0x2
+    field public static final int STATE_CONNECTING = 1; // 0x1
+    field public static final int STATE_DISCONNECTED = 0; // 0x0
+    field public static final int STATE_FAILED = 3; // 0x3
   }
 
   public class VpnService extends android.app.Service {
@@ -41403,7 +41422,8 @@
     method public void setSubscriptionOverrideCongested(int, boolean, @NonNull int[], long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, long);
     method public void setSubscriptionOverrideUnmetered(int, boolean, @NonNull int[], long);
-    method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>);
+    method @Deprecated public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>);
+    method public void setSubscriptionPlans(int, @NonNull java.util.List<android.telephony.SubscriptionPlan>, long);
     method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, @NonNull android.app.PendingIntent);
     field public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
     field public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 6145886..cbfd86e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -11594,7 +11594,7 @@
   }
 
   public class TelephonyManager {
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addCarrierPrivilegesListener(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
     method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) @WorkerThread public void bootstrapAuthenticationRequest(int, @NonNull android.net.Uri, @NonNull android.telephony.gba.UaSecurityProtocolIdentifier, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.BootstrapAuthenticationCallback);
     method @Deprecated @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void call(String, String);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telephony.PinResult changeIccLockPin(@NonNull String, @NonNull String);
@@ -11639,7 +11639,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
     method public int getMaxNumberOfSimultaneouslyActiveSims();
     method public static long getMaxNumberVerificationTimeoutMillis();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
@@ -11647,10 +11647,13 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int, int);
     method public int getSimCardState();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Collection<android.telephony.UiccSlotMapping> getSimSlotMapping();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
@@ -11687,7 +11690,8 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyOtaEmergencyNumberDbInstalled();
     method @RequiresPermission(android.Manifest.permission.REBOOT) public int prepareForUnattendedReboot();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerCarrierPrivilegesCallback(int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeCarrierPrivilegesListener(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesListener);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void reportDefaultNetworkStatus(boolean);
     method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestModemActivityInfo(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.telephony.ModemActivityInfo,android.telephony.TelephonyManager.ModemActivityInfoException>);
@@ -11737,6 +11741,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterCarrierPrivilegesCallback(@NonNull android.telephony.TelephonyManager.CarrierPrivilegesCallback);
     method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
     method public void updateServiceLocation();
     field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
@@ -11841,8 +11846,13 @@
     field public static final int RESULT_SUCCESS = 0; // 0x0
   }
 
-  public static interface TelephonyManager.CarrierPrivilegesListener {
-    method public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
+  public static interface TelephonyManager.CarrierPrivilegesCallback {
+    method public void onCarrierPrivilegesChanged(@NonNull java.util.Set<java.lang.String>, @NonNull java.util.Set<java.lang.Integer>);
+    method public default void onCarrierServiceChanged(@Nullable String, int);
+  }
+
+  @Deprecated public static interface TelephonyManager.CarrierPrivilegesListener {
+    method @Deprecated public void onCarrierPrivilegesChanged(@NonNull java.util.List<java.lang.String>, @NonNull int[]);
   }
 
   public static class TelephonyManager.ModemActivityInfoException extends java.lang.Exception {
diff --git a/core/java/android/content/pm/SHORTCUT_OWNERS b/core/java/android/content/pm/SHORTCUT_OWNERS
index 3688d5a..f8bba473 100644
--- a/core/java/android/content/pm/SHORTCUT_OWNERS
+++ b/core/java/android/content/pm/SHORTCUT_OWNERS
@@ -1,7 +1,6 @@
 set noparent
 
+pinyaoting@google.com
+sunnygoyal@google.com
 omakoto@google.com
 yamasani@google.com
-sunnygoyal@google.com
-mett@google.com
-pinyaoting@google.com
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 6284f56..dc24106 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -72,9 +72,9 @@
     SubscriptionPlan getSubscriptionPlan(in NetworkTemplate template);
     void notifyStatsProviderWarningOrLimitReached();
     SubscriptionPlan[] getSubscriptionPlans(int subId, String callingPackage);
-    void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, String callingPackage);
+    void setSubscriptionPlans(int subId, in SubscriptionPlan[] plans, long expirationDurationMillis, String callingPackage);
     String getSubscriptionPlansOwner(int subId);
-    void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes, long timeoutMillis, String callingPackage);
+    void setSubscriptionOverride(int subId, int overrideMask, int overrideValue, in int[] networkTypes, long expirationDurationMillis, String callingPackage);
 
     void factoryReset(String subscriber);
 
diff --git a/core/java/android/net/IVpnManager.aidl b/core/java/android/net/IVpnManager.aidl
index 070efa3..b4647ca 100644
--- a/core/java/android/net/IVpnManager.aidl
+++ b/core/java/android/net/IVpnManager.aidl
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.net.Network;
+import android.net.VpnProfileState;
 
 import com.android.internal.net.LegacyVpnInfo;
 import com.android.internal.net.VpnConfig;
@@ -40,6 +41,7 @@
     void deleteVpnProfile(String packageName);
     String startVpnProfile(String packageName);
     void stopVpnProfile(String packageName);
+    VpnProfileState getProvisionedVpnProfileState(String packageName);
 
     /** Always-on VPN APIs */
     boolean isAlwaysOnVpnPackageSupported(int userId, String packageName);
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 0fd3e03..3abe83b 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -142,6 +142,7 @@
     private final boolean mIsMetered; // Defaults in builder
     private final int mMaxMtu; // Defaults in builder
     private final boolean mIsRestrictedToTestNetworks;
+    @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams;
 
     private Ikev2VpnProfile(
             int type,
@@ -160,7 +161,8 @@
             int maxMtu,
             boolean restrictToTestNetworks,
             boolean excludeLocalRoutes,
-            boolean requiresInternetValidation) {
+            boolean requiresInternetValidation,
+            @Nullable IkeTunnelConnectionParams ikeTunConnParams) {
         super(type, excludeLocalRoutes, requiresInternetValidation);
 
         checkNotNull(serverAddr, MISSING_PARAM_MSG_TMPL, "Server address");
@@ -190,6 +192,8 @@
         mMaxMtu = maxMtu;
         mIsRestrictedToTestNetworks = restrictToTestNetworks;
 
+        mIkeTunConnParams = ikeTunConnParams;
+
         validate();
     }
 
@@ -375,6 +379,12 @@
         return mMaxMtu;
     }
 
+    /** Retrieves the ikeTunnelConnectionParams contains IKEv2 configurations, if any was set. */
+    @Nullable
+    public IkeTunnelConnectionParams getIkeTunnelConnectionParams() {
+        return mIkeTunConnParams;
+    }
+
     /**
      * Returns whether or not this VPN profile is restricted to test networks.
      *
@@ -403,7 +413,8 @@
                 mMaxMtu,
                 mIsRestrictedToTestNetworks,
                 mExcludeLocalRoutes,
-                mRequiresInternetValidation);
+                mRequiresInternetValidation,
+                mIkeTunConnParams);
     }
 
     @Override
@@ -429,7 +440,8 @@
                 && mMaxMtu == other.mMaxMtu
                 && mIsRestrictedToTestNetworks == other.mIsRestrictedToTestNetworks
                 && mExcludeLocalRoutes == other.mExcludeLocalRoutes
-                && mRequiresInternetValidation == other.mRequiresInternetValidation;
+                && mRequiresInternetValidation == other.mRequiresInternetValidation
+                && Objects.equals(mIkeTunConnParams, other.mIkeTunConnParams);
     }
 
     /**
@@ -504,6 +516,7 @@
     @NonNull
     public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile)
             throws GeneralSecurityException {
+        // TODO: Build the VpnProfile from mIkeTunConnParams if it exists.
         final Builder builder = new Builder(profile.server, profile.ipsecIdentifier);
         builder.setProxy(profile.proxy);
         builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
@@ -788,7 +801,7 @@
         private int mMaxMtu = PlatformVpnProfile.MAX_MTU_DEFAULT;
         private boolean mIsRestrictedToTestNetworks = false;
         private boolean mExcludeLocalRoutes = false;
-        @Nullable private IkeTunnelConnectionParams mIkeTunConnParams;
+        @Nullable private final IkeTunnelConnectionParams mIkeTunConnParams;
 
         /**
          * Creates a new builder with the basic parameters of an IKEv2/IPsec VPN.
@@ -803,6 +816,8 @@
 
             mServerAddr = serverAddr;
             mUserIdentity = identity;
+
+            mIkeTunConnParams = null;
         }
 
         /**
@@ -1135,7 +1150,8 @@
                     mMaxMtu,
                     mIsRestrictedToTestNetworks,
                     mExcludeLocalRoutes,
-                    mRequiresInternetValidation);
+                    mRequiresInternetValidation,
+                    mIkeTunConnParams);
         }
     }
 }
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index 341d98f..43ae4fc 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -484,8 +484,8 @@
      * @param networkTypes the network types this override applies to. If no
      *            network types are specified, override values will be ignored.
      *            {@see TelephonyManager#getAllNetworkTypes()}
-     * @param timeoutMillis the timeout after which the requested override will
-     *            be automatically cleared, or {@code 0} to leave in the
+     * @param expirationDurationMillis the duration after which the requested override
+     *            will be automatically cleared, or {@code 0} to leave in the
      *            requested state until explicitly cleared, or the next reboot,
      *            whichever happens first
      * @param callingPackage the name of the package making the call.
@@ -493,11 +493,11 @@
      */
     public void setSubscriptionOverride(int subId, @SubscriptionOverrideMask int overrideMask,
             @SubscriptionOverrideMask int overrideValue,
-            @NonNull @Annotation.NetworkType int[] networkTypes, long timeoutMillis,
+            @NonNull @Annotation.NetworkType int[] networkTypes, long expirationDurationMillis,
             @NonNull String callingPackage) {
         try {
             mService.setSubscriptionOverride(subId, overrideMask, overrideValue, networkTypes,
-                    timeoutMillis, callingPackage);
+                    expirationDurationMillis, callingPackage);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -508,13 +508,16 @@
      *
      * @param subId the subscriber this relationship applies to.
      * @param plans the list of plans.
+     * @param expirationDurationMillis the duration after which the subscription plans
+     *            will be automatically cleared, or {@code 0} to leave the plans until
+     *            explicitly cleared, or the next reboot, whichever happens first
      * @param callingPackage the name of the package making the call
      * @hide
      */
     public void setSubscriptionPlans(int subId, @NonNull SubscriptionPlan[] plans,
-            @NonNull String callingPackage) {
+            long expirationDurationMillis, @NonNull String callingPackage) {
         try {
-            mService.setSubscriptionPlans(subId, plans, callingPackage);
+            mService.setSubscriptionPlans(subId, plans, expirationDurationMillis, callingPackage);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -525,9 +528,11 @@
      *
      * @param subId the subscriber to get the subscription plans for.
      * @param callingPackage the name of the package making the call.
+     * @return the active {@link SubscriptionPlan}s for the given subscription id, or
+     *         {@code null} if not found.
      * @hide
      */
-    @NonNull
+    @Nullable
     public SubscriptionPlan[] getSubscriptionPlans(int subId, @NonNull String callingPackage) {
         try {
             return mService.getSubscriptionPlans(subId, callingPackage);
@@ -540,7 +545,7 @@
      * Get subscription plan for the given networkTemplate.
      *
      * @param template the networkTemplate to get the subscription plan for.
-     * @return the active {@link SubscriptionPlan} for the given template, or
+     * @return the active {@link SubscriptionPlan}s for the given template, or
      *         {@code null} if not found.
      * @hide
      */
diff --git a/core/java/android/net/SntpClient.java b/core/java/android/net/SntpClient.java
index 0eb4cf3..b05f7cf 100644
--- a/core/java/android/net/SntpClient.java
+++ b/core/java/android/net/SntpClient.java
@@ -60,7 +60,7 @@
     private static final int TRANSMIT_TIME_OFFSET = 40;
     private static final int NTP_PACKET_SIZE = 48;
 
-    private static final int NTP_PORT = 123;
+    public static final int STANDARD_NTP_PORT = 123;
     private static final int NTP_MODE_CLIENT = 3;
     private static final int NTP_MODE_SERVER = 4;
     private static final int NTP_MODE_BROADCAST = 5;
@@ -108,18 +108,21 @@
      * Sends an SNTP request to the given host and processes the response.
      *
      * @param host host name of the server.
+     * @param port port of the server.
      * @param timeout network timeout in milliseconds. the timeout doesn't include the DNS lookup
      *                time, and it applies to each individual query to the resolved addresses of
      *                the NTP server.
      * @param network network over which to send the request.
      * @return true if the transaction was successful.
      */
-    public boolean requestTime(String host, int timeout, Network network) {
+    public boolean requestTime(String host, int port, int timeout, Network network) {
         final Network networkForResolv = network.getPrivateDnsBypassingCopy();
         try {
             final InetAddress[] addresses = networkForResolv.getAllByName(host);
             for (int i = 0; i < addresses.length; i++) {
-                if (requestTime(addresses[i], NTP_PORT, timeout, networkForResolv)) return true;
+                if (requestTime(addresses[i], port, timeout, networkForResolv)) {
+                    return true;
+                }
             }
         } catch (UnknownHostException e) {
             Log.w(TAG, "Unknown host: " + host);
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index c51444c..ae7d91f 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -161,6 +161,23 @@
             "android.net.category.EVENT_DEACTIVATED_BY_USER";
 
     /**
+     * The always-on state of this VPN was changed
+     *
+     * <p>This may be the result of a user changing VPN settings, or a Device Policy Manager app
+     * having changed the VPN policy.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED =
+            "android.net.category.EVENT_ALWAYS_ON_STATE_CHANGED";
+
+    /**
+     * The VpnProfileState at the time that this event occurred.
+     *
+     * <p>This extra may be null if the VPN was revoked by the user, or the profile was deleted.
+     */
+    public static final String EXTRA_VPN_PROFILE_STATE = "android.net.extra.VPN_PROFILE_STATE";
+
+    /**
      * The key of the session that experienced this event, as a {@code String}.
      *
      * This is the same key that was returned by {@link #startProvisionedVpnProfileSession}.
@@ -403,6 +420,21 @@
     }
 
     /**
+     * Retrieve the VpnProfileState for the profile provisioned by the calling package.
+     *
+     * @return the VpnProfileState with current information, or null if there was no profile
+     *         provisioned by the calling package.
+     */
+    @Nullable
+    public VpnProfileState getProvisionedVpnProfileState() {
+        try {
+            return mService.getProvisionedVpnProfileState(mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Resets all VPN settings back to factory defaults.
      * @hide
      */
diff --git a/core/java/android/net/VpnProfileState.aidl b/core/java/android/net/VpnProfileState.aidl
new file mode 100644
index 0000000..add6386e
--- /dev/null
+++ b/core/java/android/net/VpnProfileState.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable VpnProfileState;
\ No newline at end of file
diff --git a/core/java/android/net/VpnProfileState.java b/core/java/android/net/VpnProfileState.java
new file mode 100644
index 0000000..c69ea1a
--- /dev/null
+++ b/core/java/android/net/VpnProfileState.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Describe the state of VPN.
+ */
+public final class VpnProfileState implements Parcelable {
+    /** The VPN has not been started, or some other VPN is active. */
+    public static final int STATE_DISCONNECTED = 0;
+    /** The VPN is attempting to connect, potentially after a failure. */
+    public static final int STATE_CONNECTING = 1;
+    /** The VPN was established successfully. */
+    public static final int STATE_CONNECTED = 2;
+    /** A non-recoverable error has occurred, and will not be retried. */
+    public static final int STATE_FAILED = 3;
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"STATE_"}, value = {
+            STATE_CONNECTED,
+            STATE_CONNECTING,
+            STATE_DISCONNECTED,
+            STATE_FAILED,
+    })
+    public @interface State {}
+
+    @State private final int mState;
+    private final String mSessionKey;
+    private final boolean mAlwaysOn;
+    private final boolean mLockdown;
+
+    public VpnProfileState(@State int state, @Nullable String sessionKey, boolean alwaysOn,
+            boolean lockdown) {
+        mState = state;
+        mSessionKey = sessionKey;
+        mAlwaysOn = alwaysOn;
+        mLockdown = lockdown;
+    }
+
+    /**
+     * Returns the state of the Platform VPN
+     *
+     * <p>This state represents the internal connection state of the VPN. This state may diverge
+     * from the VPN Network's state during error and recovery handling.
+     */
+    @State public int getState() {
+        return mState;
+    }
+
+    /**
+     * Retrieves the Session Key
+     *
+     * <p>The session key is an ephemeral key uniquely identifying the session for a Platform VPN.
+     * The lifetime of this key is tied to the lifetime of the VPN session. In other words,
+     * reprovisioning of the VPN profile, restarting of the device, or manually restarting the
+     * platform VPN session will result in a new VPN session, and a new key.
+     *
+     * @return the unique key for the platform VPN session, or null if it is not running.
+     */
+    @Nullable
+    public String getSessionId() {
+        return mSessionKey;
+    }
+
+    /**
+     * Returns the always-on status of the PlatformVpnProfile.
+     *
+     * <p>If the PlatformVpnProfile is set to be running in always-on mode, the system will ensure
+     * that the profile is always started, and restarting it when necessary (e.g. after reboot).
+     *
+     * <p>Always-on can be set by an appropriately privileged user via the Settings VPN menus, or by
+     * the Device Policy Manager app programmatically.
+     *
+     * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
+     */
+    public boolean isAlwaysOn() {
+        return mAlwaysOn;
+    }
+
+    /**
+     * Returns the lockdown mode status of the PlatformVpnProfile.
+     *
+     * <p>In lockdown mode, the system will ensure that apps are not allowed to bypass the VPN,
+     * including during startup or failure of the VPN.
+     *
+     * <p>Lockdown mode can be set by an appropriately privileged user via the Settings VPN menus,
+     * or by the Device Policy Manager app programmatically.
+     *
+     * See DevicePolicyManager#setAlwaysOnVpnPackage(ComponentName, String, boolean, Set)
+     */
+    public boolean isLockdownEnabled() {
+        return mLockdown;
+    }
+
+    /**
+     * Implement the Parcelable interface
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Implement the Parcelable interface
+     */
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        out.writeInt(mState);
+        out.writeString(mSessionKey);
+        out.writeBoolean(mAlwaysOn);
+        out.writeBoolean(mLockdown);
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<VpnProfileState> CREATOR =
+            new Parcelable.Creator<VpnProfileState>() {
+                public VpnProfileState createFromParcel(Parcel in) {
+                    return new VpnProfileState(in);
+                }
+
+                public VpnProfileState[] newArray(int size) {
+                    return new VpnProfileState[size];
+                }
+            };
+
+    private VpnProfileState(Parcel in) {
+        mState = in.readInt();
+        mSessionKey = in.readString();
+        mAlwaysOn = in.readBoolean();
+        mLockdown = in.readBoolean();
+    }
+}
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 5bf1b04..ef33543 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -125,7 +125,6 @@
     boolean isUserKeyUnlocked(int userId) = 65;
     void prepareUserStorage(in String volumeUuid, int userId, int serialNumber, int flags) = 66;
     void destroyUserStorage(in String volumeUuid, int userId, int flags) = 67;
-    boolean isConvertibleToFBE() = 68;
     void addUserKeyAuth(int userId, int serialNumber, in byte[] secret) = 70;
     void fixateNewestUserKeyAuth(int userId) = 71;
     void fstrim(int flags, IVoldTaskListener listener) = 72;
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 0d5ef34..5b59b21 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -1425,25 +1425,6 @@
         public static final String KEY_TYPE = "key_type";
 
         /**
-         * MVNO type:
-         * {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
-         * <P> Type: TEXT </P>
-         */
-        public static final String MVNO_TYPE = "mvno_type";
-
-        /**
-         * MVNO data.
-         * Use the following examples.
-         * <ul>
-         *     <li>SPN: A MOBILE, BEN NL, ...</li>
-         *     <li>IMSI: 302720x94, 2060188, ...</li>
-         *     <li>GID: 4E, 33, ...</li>
-         * </ul>
-         * <P> Type: TEXT </P>
-         */
-        public static final String MVNO_MATCH_DATA = "mvno_match_data";
-
-        /**
          * The carrier public key that is used for the IMSI encryption.
          * <P> Type: TEXT </P>
          */
@@ -1470,6 +1451,11 @@
         public static final String LAST_MODIFIED = "last_modified";
 
         /**
+         * Carrier ID of the operetor.
+         * <P> Type: TEXT </P>
+         */
+        public static final String CARRIER_ID = "carrier_id";
+        /**
          * The {@code content://} style URL for this table.
          */
         @NonNull
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index aebc5e8..01a037a 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -140,6 +140,10 @@
 
     /** An in-memory config override for use during tests. */
     @Nullable
+    private Integer mPortForTests;
+
+    /** An in-memory config override for use during tests. */
+    @Nullable
     private Duration mTimeoutForTests;
 
     // Declared volatile and accessed outside of synchronized blocks to avoid blocking reads during
@@ -163,9 +167,11 @@
      * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
      * test value, i.e. so the normal value will be used next time.
      */
-    public void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+    public void setServerConfigForTests(
+            @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) {
         synchronized (this) {
             mHostnameForTests = hostname;
+            mPortForTests = port;
             mTimeoutForTests = timeout;
         }
     }
@@ -195,8 +201,9 @@
             if (LOGD) Log.d(TAG, "forceRefresh() from cache miss");
             final SntpClient client = new SntpClient();
             final String serverName = connectionInfo.getServer();
+            final int port = connectionInfo.getPort();
             final int timeoutMillis = connectionInfo.getTimeoutMillis();
-            if (client.requestTime(serverName, timeoutMillis, network)) {
+            if (client.requestTime(serverName, port, timeoutMillis, network)) {
                 long ntpCertainty = client.getRoundTripTime() / 2;
                 mTimeResult = new TimeResult(
                         client.getNtpTime(), client.getNtpTimeReference(), ntpCertainty);
@@ -297,10 +304,12 @@
     private static class NtpConnectionInfo {
 
         @NonNull private final String mServer;
+        private final int mPort;
         private final int mTimeoutMillis;
 
-        NtpConnectionInfo(@NonNull String server, int timeoutMillis) {
+        NtpConnectionInfo(@NonNull String server, int port, int timeoutMillis) {
             mServer = Objects.requireNonNull(server);
+            mPort = port;
             mTimeoutMillis = timeoutMillis;
         }
 
@@ -309,6 +318,11 @@
             return mServer;
         }
 
+        @NonNull
+        public int getPort() {
+            return mPort;
+        }
+
         int getTimeoutMillis() {
             return mTimeoutMillis;
         }
@@ -317,6 +331,7 @@
         public String toString() {
             return "NtpConnectionInfo{"
                     + "mServer='" + mServer + '\''
+                    + ", mPort='" + mPort + '\''
                     + ", mTimeoutMillis=" + mTimeoutMillis
                     + '}';
         }
@@ -341,6 +356,13 @@
             }
         }
 
+        final Integer port;
+        if (mPortForTests != null) {
+            port = mPortForTests;
+        } else {
+            port = SntpClient.STANDARD_NTP_PORT;
+        }
+
         final int timeoutMillis;
         if (mTimeoutForTests != null) {
             timeoutMillis = (int) mTimeoutForTests.toMillis();
@@ -350,7 +372,8 @@
             timeoutMillis = Settings.Global.getInt(
                     resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
         }
-        return TextUtils.isEmpty(hostname) ? null : new NtpConnectionInfo(hostname, timeoutMillis);
+        return TextUtils.isEmpty(hostname) ? null :
+            new NtpConnectionInfo(hostname, port, timeoutMillis);
     }
 
     /** Prints debug information. */
diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS
index e6c911e..3833976 100644
--- a/core/java/com/android/internal/app/OWNERS
+++ b/core/java/com/android/internal/app/OWNERS
@@ -9,3 +9,6 @@
 per-file *Assist* = file:/core/java/android/service/voice/OWNERS
 per-file *Hotword* = file:/core/java/android/service/voice/OWNERS
 per-file *Voice* = file:/core/java/android/service/voice/OWNERS
+
+# System language settings
+per-file *Locale* = file:platform/packages/apps/Settings:/src/com/android/settings/localepicker/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/net/SntpClientTest.java b/core/tests/coretests/src/android/net/SntpClientTest.java
index b400b9b..1299d7f 100644
--- a/core/tests/coretests/src/android/net/SntpClientTest.java
+++ b/core/tests/coretests/src/android/net/SntpClientTest.java
@@ -293,7 +293,8 @@
 
     @Test
     public void testDnsResolutionFailure() throws Exception {
-        assertFalse(mClient.requestTime("ntp.server.doesnotexist.example", 5000, mNetwork));
+        assertFalse(mClient.requestTime("ntp.server.doesnotexist.example",
+                SntpClient.STANDARD_NTP_PORT, 5000, mNetwork));
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
index b89e8bc..625f52a 100644
--- a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -232,7 +232,7 @@
         assertThat(entry3.handlerClassName).isEqualTo(
                 "com.android.internal.os.LooperStatsTest$TestHandlerSecond");
         assertThat(entry3.messageName).startsWith(
-                "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda4");
+                "com.android.internal.os.LooperStatsTest$$ExternalSyntheticLambda");
         assertThat(entry3.messageCount).isEqualTo(1);
         assertThat(entry3.recordedMessageCount).isEqualTo(1);
         assertThat(entry3.exceptionCount).isEqualTo(0);
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c9abee2..e608a74 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -292,6 +292,8 @@
         <!-- Needed for test only -->
         <permission name="android.permission.BATTERY_PREDICTION"/>
         <permission name="android.permission.BATTERY_STATS"/>
+        <!-- BLUETOOTH_PRIVILEGED is needed for test only -->
+        <permission name="android.permission.BLUETOOTH_PRIVILEGED"/>
         <permission name="android.permission.BIND_APPWIDGET"/>
         <permission name="android.permission.CHANGE_APP_IDLE_STATE"/>
         <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE"/>
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
index ec56d61..ad1405a 100644
--- a/media/java/android/media/MediaActionSound.java
+++ b/media/java/android/media/MediaActionSound.java
@@ -25,7 +25,8 @@
 
 /**
  * <p>A class for producing sounds that match those produced by various actions
- * taken by the media and camera APIs.  </p>
+ * taken by the media and camera APIs. It is recommended to call methods in this class
+ * in a background thread since it relies on binder calls.</p>
  *
  * <p>This class is recommended for use with the {@link android.hardware.camera2} API, since the
  * camera2 API does not play any sounds on its own for any capture or video recording actions.</p>
@@ -109,7 +110,7 @@
 
     /**
      * <p>Returns true if the application must play the shutter sound in accordance
-     * to certain regional restrictions. </p>
+     * to certain regional restrictions.</p>
      *
      * <p>If this method returns true, applications are strongly recommended to use
      * MediaActionSound.play(SHUTTER_CLICK) or START_VIDEO_RECORDING whenever it captures
diff --git a/packages/DynamicSystemInstallationService/Android.bp b/packages/DynamicSystemInstallationService/Android.bp
index ad86f46..b8f54b3 100644
--- a/packages/DynamicSystemInstallationService/Android.bp
+++ b/packages/DynamicSystemInstallationService/Android.bp
@@ -22,6 +22,9 @@
     defaults: ["platform_app_defaults"],
 
     srcs: ["src/**/*.java"],
+    static_libs: [
+        "DynamicSystemInstallationService-logtags",
+    ],
     resource_dirs: ["res"],
 
     certificate: "platform",
@@ -32,3 +35,8 @@
         enabled: false,
     },
 }
+
+java_library {
+    name: "DynamicSystemInstallationService-logtags",
+    srcs: ["src/**/*.logtags"],
+}
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index f8cb5d3..02128d4 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -58,6 +58,7 @@
 import android.os.image.DynamicSystemClient;
 import android.os.image.DynamicSystemManager;
 import android.text.TextUtils;
+import android.util.EventLog;
 import android.util.Log;
 import android.widget.Toast;
 
@@ -104,6 +105,36 @@
     private static final int NOTIFICATION_ID = 1;
 
     /*
+     * Event log tags
+     */
+    private static final int EVENT_DSU_PROGRESS_UPDATE = 120000;
+    private static final int EVENT_DSU_INSTALL_COMPLETE = 120001;
+    private static final int EVENT_DSU_INSTALL_FAILED = 120002;
+
+    protected static void logEventProgressUpdate(
+            String partition,
+            long installedSize,
+            long partitionSize,
+            int partitionNumber,
+            int totalPartitionNumber) {
+        EventLog.writeEvent(
+                EVENT_DSU_PROGRESS_UPDATE,
+                partition,
+                installedSize,
+                partitionSize,
+                partitionNumber,
+                totalPartitionNumber);
+    }
+
+    protected static void logEventComplete() {
+        EventLog.writeEvent(EVENT_DSU_INSTALL_COMPLETE);
+    }
+
+    protected static void logEventFailed(String cause) {
+        EventLog.writeEvent(EVENT_DSU_INSTALL_FAILED, cause);
+    }
+
+    /*
      * IPC
      */
     /** Keeps track of all current registered clients. */
@@ -132,15 +163,10 @@
     private DynamicSystemManager mDynSystem;
     private NotificationManager mNM;
 
-    private int mNumInstalledPartitions;
-
-    private String mCurrentPartitionName;
-    private long mCurrentPartitionSize;
-    private long mCurrentPartitionInstalledSize;
-
     // This is for testing only now
     private boolean mEnableWhenCompleted;
 
+    private InstallationAsyncTask.Progress mInstallTaskProgress;
     private InstallationAsyncTask mInstallTask;
 
 
@@ -203,17 +229,21 @@
 
     @Override
     public void onProgressUpdate(InstallationAsyncTask.Progress progress) {
-        mCurrentPartitionName = progress.partitionName;
-        mCurrentPartitionSize = progress.partitionSize;
-        mCurrentPartitionInstalledSize = progress.installedSize;
-        mNumInstalledPartitions = progress.numInstalledPartitions;
+        logEventProgressUpdate(
+                progress.partitionName,
+                progress.installedSize,
+                progress.partitionSize,
+                progress.partitionNumber,
+                progress.totalPartitionNumber);
 
+        mInstallTaskProgress = progress;
         postStatus(STATUS_IN_PROGRESS, CAUSE_NOT_SPECIFIED, null);
     }
 
     @Override
     public void onResult(int result, Throwable detail) {
         if (result == RESULT_OK) {
+            logEventComplete();
             postStatus(STATUS_READY, CAUSE_INSTALL_COMPLETED, null);
 
             // For testing: enable DSU and restart the device when install completed
@@ -223,6 +253,12 @@
             return;
         }
 
+        if (result == RESULT_CANCELLED) {
+            logEventFailed("Dynamic System installation task is canceled by the user.");
+        } else {
+            logEventFailed("error: " + detail);
+        }
+
         boolean removeNotification = false;
         switch (result) {
             case RESULT_CANCELLED:
@@ -251,16 +287,20 @@
     private void executeInstallCommand(Intent intent) {
         if (!verifyRequest(intent)) {
             Log.e(TAG, "Verification failed. Did you use VerificationActivity?");
+            logEventFailed("VerificationActivity");
             return;
         }
 
         if (mInstallTask != null) {
             Log.e(TAG, "There is already an installation task running");
+            logEventFailed("There is already an ongoing installation task.");
             return;
         }
 
         if (isInDynamicSystem()) {
             Log.e(TAG, "We are already running in DynamicSystem");
+            logEventFailed(
+                    "Cannot start a Dynamic System installation task within a Dynamic System.");
             return;
         }
 
@@ -445,19 +485,22 @@
             case STATUS_IN_PROGRESS:
                 builder.setContentText(getString(R.string.notification_install_inprogress));
 
-                int max = 1024;
-                int progress = 0;
+                if (mInstallTaskProgress != null) {
+                    int max = 1024;
+                    int progress = 0;
 
-                int currentMax = max >> (mNumInstalledPartitions + 1);
-                progress = max - currentMax * 2;
+                    int currentMax = max >> mInstallTaskProgress.partitionNumber;
+                    progress = max - currentMax * 2;
 
-                long currentProgress = (mCurrentPartitionInstalledSize >> 20) * currentMax
-                        / Math.max(mCurrentPartitionSize >> 20, 1);
+                    long currentProgress =
+                            (mInstallTaskProgress.installedSize >> 20)
+                                    * currentMax
+                                    / Math.max(mInstallTaskProgress.partitionSize >> 20, 1);
 
-                progress += (int) currentProgress;
+                    progress += (int) currentProgress;
 
-                builder.setProgress(max, progress, false);
-
+                    builder.setProgress(max, progress, false);
+                }
                 builder.addAction(new Notification.Action.Builder(
                         null, getString(R.string.notification_action_cancel),
                         createPendingIntent(ACTION_CANCEL_INSTALL)).build());
@@ -563,13 +606,13 @@
 
         StringBuilder msg = new StringBuilder();
         msg.append("status: " + statusString + ", cause: " + causeString);
-        if (status == STATUS_IN_PROGRESS) {
+        if (status == STATUS_IN_PROGRESS && mInstallTaskProgress != null) {
             msg.append(
                     String.format(
                             ", partition name: %s, progress: %d/%d",
-                            mCurrentPartitionName,
-                            mCurrentPartitionInstalledSize,
-                            mCurrentPartitionSize));
+                            mInstallTaskProgress.partitionName,
+                            mInstallTaskProgress.installedSize,
+                            mInstallTaskProgress.partitionSize));
         }
         if (detail != null) {
             msg.append(", detail: " + detail);
@@ -594,7 +637,10 @@
         Bundle bundle = new Bundle();
 
         // TODO: send more info to the clients
-        bundle.putLong(DynamicSystemClient.KEY_INSTALLED_SIZE, mCurrentPartitionInstalledSize);
+        if (mInstallTaskProgress != null) {
+            bundle.putLong(
+                    DynamicSystemClient.KEY_INSTALLED_SIZE, mInstallTaskProgress.installedSize);
+        }
 
         if (detail != null) {
             bundle.putSerializable(DynamicSystemClient.KEY_EXCEPTION_DETAIL,
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
new file mode 100644
index 0000000..eae9de9
--- /dev/null
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/EventLogTags.logtags
@@ -0,0 +1,7 @@
+# See system/logging/logcat/event.logtags for a description of the format of this file.
+
+option java_package com.android.dynsystem
+
+120000 dsu_progress_update (partition|3),(installed_size|2|5),(partition_size|2|5),(partition_number|1|5),(total_partition_number|1|5)
+120001 dsu_install_complete
+120002 dsu_install_failed (cause|3)
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index f18d426..998aeeab 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -23,9 +23,11 @@
 import android.os.Build;
 import android.os.MemoryFile;
 import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
 import android.os.image.DynamicSystemManager;
 import android.service.persistentdata.PersistentDataBlockManager;
 import android.util.Log;
+import android.util.Range;
 import android.webkit.URLUtil;
 
 import org.json.JSONException;
@@ -44,11 +46,16 @@
 import java.util.zip.ZipFile;
 import java.util.zip.ZipInputStream;
 
-class InstallationAsyncTask extends AsyncTask<String, InstallationAsyncTask.Progress, Throwable> {
+class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
 
     private static final String TAG = "InstallationAsyncTask";
 
-    private static final int READ_BUFFER_SIZE = 1 << 13;
+    private static final int MIN_SHARED_MEMORY_SIZE = 8 << 10; // 8KiB
+    private static final int MAX_SHARED_MEMORY_SIZE = 1024 << 10; // 1MiB
+    private static final int DEFAULT_SHARED_MEMORY_SIZE = 64 << 10; // 64KiB
+    private static final String SHARED_MEMORY_SIZE_PROP =
+            "dynamic_system.data_transfer.shared_memory.size";
+
     private static final long MIN_PROGRESS_TO_PUBLISH = 1 << 27;
 
     private static final List<String> UNSUPPORTED_PARTITIONS =
@@ -106,14 +113,22 @@
 
     static class Progress {
         public final String partitionName;
+        public final long installedSize;
         public final long partitionSize;
-        public final int numInstalledPartitions;
-        public long installedSize;
+        public final int partitionNumber;
+        public final int totalPartitionNumber;
 
-        Progress(String partitionName, long partitionSize, int numInstalledPartitions) {
+        Progress(
+                String partitionName,
+                long installedSize,
+                long partitionSize,
+                int partitionNumber,
+                int totalPartitionNumber) {
             this.partitionName = partitionName;
+            this.installedSize = installedSize;
             this.partitionSize = partitionSize;
-            this.numInstalledPartitions = numInstalledPartitions;
+            this.partitionNumber = partitionNumber;
+            this.totalPartitionNumber = totalPartitionNumber;
         }
     }
 
@@ -123,6 +138,7 @@
         void onResult(int resultCode, Throwable detail);
     }
 
+    private final int mSharedMemorySize;
     private final String mUrl;
     private final String mDsuSlot;
     private final String mPublicKey;
@@ -139,7 +155,10 @@
     private boolean mIsZip;
     private boolean mIsCompleted;
 
-    private int mNumInstalledPartitions;
+    private String mPartitionName;
+    private long mPartitionSize;
+    private int mPartitionNumber;
+    private int mTotalPartitionNumber;
 
     private InputStream mStream;
     private ZipFile mZipFile;
@@ -153,6 +172,11 @@
             Context context,
             DynamicSystemManager dynSystem,
             ProgressListener listener) {
+        mSharedMemorySize =
+                Range.create(MIN_SHARED_MEMORY_SIZE, MAX_SHARED_MEMORY_SIZE)
+                        .clamp(
+                                SystemProperties.getInt(
+                                        SHARED_MEMORY_SIZE_PROP, DEFAULT_SHARED_MEMORY_SIZE));
         mUrl = url;
         mDsuSlot = dsuSlot;
         mPublicKey = publicKey;
@@ -175,11 +199,15 @@
     protected Throwable doInBackground(String... voids) {
         Log.d(TAG, "Start doInBackground(), URL: " + mUrl);
 
+        final boolean wantScratchPartition = Build.IS_DEBUGGABLE;
         try {
             // call DynamicSystemManager to cleanup stuff
             mDynSystem.remove();
 
             verifyAndPrepare();
+            if (wantScratchPartition) {
+                ++mTotalPartitionNumber;
+            }
 
             mDynSystem.startInstallation(mDsuSlot);
 
@@ -198,7 +226,7 @@
                 return null;
             }
 
-            if (Build.IS_DEBUGGABLE) {
+            if (wantScratchPartition) {
                 // If host is debuggable, then install a scratch partition so that we can do
                 // adb remount in the guest system.
                 try {
@@ -262,9 +290,14 @@
     }
 
     @Override
-    protected void onProgressUpdate(Progress... values) {
-        Progress progress = values[0];
-        mListener.onProgressUpdate(progress);
+    protected void onProgressUpdate(Long... installedSize) {
+        mListener.onProgressUpdate(
+                new Progress(
+                        mPartitionName,
+                        installedSize[0],
+                        mPartitionSize,
+                        mPartitionNumber,
+                        mTotalPartitionNumber));
     }
 
     private void verifyAndPrepare() throws Exception {
@@ -281,12 +314,16 @@
             throw new UnsupportedFormatException(
                 String.format(Locale.US, "Unsupported file format: %s", mUrl));
         }
+        // At least two partitions, {system, userdata}
+        mTotalPartitionNumber = 2;
 
         if (mIsNetworkUrl) {
             mStream = new URL(mUrl).openStream();
         } else if (URLUtil.isFileUrl(mUrl)) {
             if (mIsZip) {
                 mZipFile = new ZipFile(new File(new URL(mUrl).toURI()));
+                // {*.img in zip} + {userdata}
+                mTotalPartitionNumber = calculateNumberOfImagesInLocalZip(mZipFile) + 1;
             } else {
                 mStream = new URL(mUrl).openStream();
             }
@@ -333,9 +370,13 @@
             }
         };
 
-        thread.start();
-        Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++);
+        mPartitionName = partitionName;
+        mPartitionSize = partitionSize;
+        ++mPartitionNumber;
+        publishProgress(/* installedSize = */ 0L);
 
+        long prevInstalledSize = 0;
+        thread.start();
         while (thread.isAlive()) {
             if (isCancelled()) {
                 return;
@@ -343,9 +384,9 @@
 
             final long installedSize = mDynSystem.getInstallationProgress().bytes_processed;
 
-            if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) {
-                progress.installedSize = installedSize;
-                publishProgress(progress);
+            if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+                publishProgress(installedSize);
+                prevInstalledSize = installedSize;
             }
 
             try {
@@ -392,14 +433,42 @@
         installImage("system", mSystemSize, new GZIPInputStream(mStream));
     }
 
+    private boolean shouldInstallEntry(String name) {
+        if (!name.endsWith(".img")) {
+            return false;
+        }
+        String partitionName = name.substring(0, name.length() - 4);
+        if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
+            return false;
+        }
+        return true;
+    }
+
+    private int calculateNumberOfImagesInLocalZip(ZipFile zipFile) {
+        int total = 0;
+        Enumeration<? extends ZipEntry> entries = zipFile.entries();
+        while (entries.hasMoreElements()) {
+            ZipEntry entry = entries.nextElement();
+            if (shouldInstallEntry(entry.getName())) {
+                ++total;
+            }
+        }
+        return total;
+    }
+
     private void installStreamingZipUpdate() throws IOException, ImageValidationException {
         Log.d(TAG, "To install a streaming ZIP update");
 
         ZipInputStream zis = new ZipInputStream(mStream);
-        ZipEntry zipEntry = null;
+        ZipEntry entry = null;
 
-        while ((zipEntry = zis.getNextEntry()) != null) {
-            installImageFromAnEntry(zipEntry, zis);
+        while ((entry = zis.getNextEntry()) != null) {
+            String name = entry.getName();
+            if (shouldInstallEntry(name)) {
+                installImageFromAnEntry(entry, zis);
+            } else {
+                Log.d(TAG, name + " installation is not supported, skip it.");
+            }
 
             if (isCancelled()) {
                 break;
@@ -414,7 +483,12 @@
 
         while (entries.hasMoreElements()) {
             ZipEntry entry = entries.nextElement();
-            installImageFromAnEntry(entry, mZipFile.getInputStream(entry));
+            String name = entry.getName();
+            if (shouldInstallEntry(name)) {
+                installImageFromAnEntry(entry, mZipFile.getInputStream(entry));
+            } else {
+                Log.d(TAG, name + " installation is not supported, skip it.");
+            }
 
             if (isCancelled()) {
                 break;
@@ -422,28 +496,16 @@
         }
     }
 
-    private boolean installImageFromAnEntry(ZipEntry entry, InputStream is)
+    private void installImageFromAnEntry(ZipEntry entry, InputStream is)
             throws IOException, ImageValidationException {
         String name = entry.getName();
 
         Log.d(TAG, "ZipEntry: " + name);
 
-        if (!name.endsWith(".img")) {
-            return false;
-        }
-
         String partitionName = name.substring(0, name.length() - 4);
-
-        if (UNSUPPORTED_PARTITIONS.contains(partitionName)) {
-            Log.d(TAG, name + " installation is not supported, skip it.");
-            return false;
-        }
-
         long uncompressedSize = entry.getSize();
 
         installImage(partitionName, uncompressedSize, is);
-
-        return true;
     }
 
     private void installImage(String partitionName, long uncompressedSize, InputStream is)
@@ -492,18 +554,22 @@
 
         Log.d(TAG, "Start installing: " + partitionName);
 
-        MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, READ_BUFFER_SIZE);
+        MemoryFile memoryFile = new MemoryFile("dsu_" + partitionName, mSharedMemorySize);
         ParcelFileDescriptor pfd = new ParcelFileDescriptor(memoryFile.getFileDescriptor());
 
-        mInstallationSession.setAshmem(pfd, READ_BUFFER_SIZE);
+        mInstallationSession.setAshmem(pfd, memoryFile.length());
 
-        Progress progress = new Progress(partitionName, partitionSize, mNumInstalledPartitions++);
+        mPartitionName = partitionName;
+        mPartitionSize = partitionSize;
+        ++mPartitionNumber;
+        publishProgress(/* installedSize = */ 0L);
 
+        long prevInstalledSize = 0;
         long installedSize = 0;
-        byte[] bytes = new byte[READ_BUFFER_SIZE];
+        byte[] bytes = new byte[memoryFile.length()];
         int numBytesRead;
 
-        while ((numBytesRead = sis.read(bytes, 0, READ_BUFFER_SIZE)) != -1) {
+        while ((numBytesRead = sis.read(bytes, 0, bytes.length)) != -1) {
             if (isCancelled()) {
                 return;
             }
@@ -516,9 +582,9 @@
 
             installedSize += numBytesRead;
 
-            if (installedSize > progress.installedSize + MIN_PROGRESS_TO_PUBLISH) {
-                progress.installedSize = installedSize;
-                publishProgress(progress);
+            if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+                publishProgress(installedSize);
+                prevInstalledSize = installedSize;
             }
         }
 
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
index 4117d0f..7d23266 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/SparseInputStream.java
@@ -133,36 +133,32 @@
         return mLeft == 0;
     }
 
-    /**
-     * It overrides the InputStream.read(byte[] buf)
-     */
-    public int read(byte[] buf) throws IOException {
+    @Override
+    public int read(byte[] buf, int off, int len) throws IOException {
         if (!mIsSparse) {
-            return mIn.read(buf);
+            return mIn.read(buf, off, len);
         }
         if (prepareChunk()) return -1;
         int n = -1;
         switch (mCur.mChunkType) {
             case SparseChunk.RAW:
-                n = mIn.read(buf, 0, (int) min(mLeft, buf.length));
+                n = mIn.read(buf, off, (int) min(mLeft, len));
                 mLeft -= n;
                 return n;
             case SparseChunk.DONTCARE:
-                n = (int) min(mLeft, buf.length);
-                Arrays.fill(buf, 0, n - 1, (byte) 0);
+                n = (int) min(mLeft, len);
+                Arrays.fill(buf, off, off + n, (byte) 0);
                 mLeft -= n;
                 return n;
             case SparseChunk.FILL:
                 // The FILL type is rarely used, so use a simple implmentation.
-                return super.read(buf);
+                return super.read(buf, off, len);
             default:
                 throw new IOException("Unsupported Chunk:" + mCur.toString());
         }
     }
 
-    /**
-     * It overrides the InputStream.read()
-     */
+    @Override
     public int read() throws IOException {
         if (!mIsSparse) {
             return mIn.read();
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a56c490..534e41c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1038,23 +1038,6 @@
     <!-- Developer settings: text for the WebView provider selection toast shown if an invalid provider was chosen (i.e. the setting list was stale). [CHAR LIMIT=NONE] -->
     <string name="select_webview_provider_toast_text">This choice is no longer valid. Try again.</string>
 
-    <!-- Developer settings screen, convert userdata to file encryption option name -->
-    <string name="convert_to_file_encryption">Convert to file encryption</string>
-    <!-- Developer settings screen, convert userdata to file encryption summary when option is available -->
-    <string name="convert_to_file_encryption_enabled">Convert\u2026</string>
-    <!-- Developer settings screen, convert userdata to file encryption summary when option is already done -->
-    <string name="convert_to_file_encryption_done">Already file encrypted</string>
-    <!-- Title used on dialog with final prompt for converting to file encryption -->
-    <string name="title_convert_fbe">Converting to file based encryption</string>
-    <!-- Warning displayed on dialog with final prompt for converting to file encryption -->
-    <string name="convert_to_fbe_warning">
-        Convert data partition to file based encryption.\n
-        !!Warning!! This will erase all your data.\n
-        This feature is alpha, and may not work correctly.\n
-        Press \'Wipe and convert\u2026\' to continue.</string>
-    <!-- Button on dialog that triggers convertion to file encryption -->
-    <string name="button_convert_fbe">Wipe and convert\u2026</string>
-
     <!-- Name of feature to change color setting for the display [CHAR LIMIT=60] -->
     <string name="picture_color_mode">Picture color mode</string>
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8f2ac9f..feee4a1 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -121,6 +121,8 @@
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
     <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
+    <!-- BLUETOOTH_PRIVILEGED is needed for testing purposes only. -->
+    <uses-permission android:name="android.permission.BLUETOOTH_PRIVILEGED" />
     <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
     <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
     <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e00b941..6f46b70 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -664,4 +664,17 @@
     <!-- Flag to enable privacy dot views, it shall be true for normal case -->
     <bool name="config_enablePrivacyDot">true</bool>
 
+    <!-- Icons that don't show in a collapsed non-keyguard statusbar -->
+    <string-array name="config_collapsed_statusbar_icon_blocklist" translatable="false">
+        <item>@*android:string/status_bar_volume</item>
+        <item>@*android:string/status_bar_alarm_clock</item>
+        <item>@*android:string/status_bar_call_strength</item>
+    </string-array>
+
+    <!-- Icons that don't show in a collapsed statusbar on keyguard -->
+    <string-array name="config_keyguard_statusbar_icon_blocklist" translatable="false">
+        <item>@*android:string/status_bar_volume</item>
+        <item>@*android:string/status_bar_alarm_clock</item>
+        <item>@*android:string/status_bar_call_strength</item>
+    </string-array>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index e7d5724..810b95b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -263,10 +263,8 @@
         );
 
         Resources r = getResources();
-        mBlockedIcons = Collections.unmodifiableList(Arrays.asList(
-                r.getString(com.android.internal.R.string.status_bar_volume),
-                r.getString(com.android.internal.R.string.status_bar_alarm_clock),
-                r.getString(com.android.internal.R.string.status_bar_call_strength)));
+        mBlockedIcons = Arrays.asList(r.getStringArray(
+                R.array.config_keyguard_statusbar_icon_blocklist));
         mNotificationsHeaderCollideDistance = r.getDimensionPixelSize(
                 R.dimen.header_notifications_collide_distance);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index d6ba6f3..2670ed8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -69,6 +69,7 @@
 import org.jetbrains.annotations.NotNull;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import javax.inject.Inject;
@@ -190,9 +191,8 @@
         }
         mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons), mFeatureFlags);
         mDarkIconManager.setShouldLog(true);
-        mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_volume));
-        mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_alarm_clock));
-        mBlockedIcons.add(getString(com.android.internal.R.string.status_bar_call_strength));
+        mBlockedIcons = Arrays.asList(getResources().getStringArray(
+                R.array.config_collapsed_statusbar_icon_blocklist));
         mDarkIconManager.setBlockList(mBlockedIcons);
         mStatusBarIconController.addIconGroup(mDarkIconManager);
         mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 3f712dd..3801c24 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -2260,10 +2260,12 @@
     ACCOUNTS_WORK_PROFILE_SETTINGS = 401;
 
     // Settings -> Dev options -> Convert to file encryption
-    CONVERT_FBE = 402;
+    // DEPRECATED: this setting was removed in Android T.
+    CONVERT_FBE = 402 [deprecated=true];
 
     // Settings -> Dev options -> Convert to file encryption -> WIPE AND CONVERT...
-    CONVERT_FBE_CONFIRM = 403;
+    // DEPRECATED: this setting was removed in Android T.
+    CONVERT_FBE_CONFIRM = 403 [deprecated=true];
 
     // Settings -> Dev options -> Running services
     RUNNING_SERVICES = 404;
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 186ff62..2015dc9 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -196,13 +196,15 @@
      * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
      * test value, i.e. so the normal value will be used next time.
      */
-    void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+    void setServerConfigForTests(
+            @Nullable String hostname, @Nullable Integer port, @Nullable Duration timeout) {
         mContext.enforceCallingPermission(
                 android.Manifest.permission.SET_TIME, "set NTP server config for tests");
 
         mLocalLog.log("Setting server config for tests: hostname=" + hostname
+                + ", port=" + port
                 + ", timeout=" + timeout);
-        mTime.setServerConfigForTests(hostname, timeout);
+        mTime.setServerConfigForTests(hostname, port, timeout);
     }
 
     private void onPollNetworkTime(int event) {
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
index 464af01..d7504ce 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
@@ -46,6 +46,7 @@
      */
     private static final String SHELL_COMMAND_SET_SERVER_CONFIG = "set_server_config";
     private static final String SET_SERVER_CONFIG_HOSTNAME_ARG = "--hostname";
+    private static final String SET_SERVER_CONFIG_PORT_ARG = "--port";
     private static final String SET_SERVER_CONFIG_TIMEOUT_ARG = "--timeout_millis";
 
     @NonNull
@@ -87,6 +88,7 @@
 
     private int runSetServerConfig() {
         String hostname = null;
+        Integer port = null;
         Duration timeout = null;
         String opt;
         while ((opt = getNextArg()) != null) {
@@ -95,6 +97,10 @@
                     hostname = getNextArgRequired();
                     break;
                 }
+                case SET_SERVER_CONFIG_PORT_ARG: {
+                    port = Integer.parseInt(getNextArgRequired());
+                    break;
+                }
                 case SET_SERVER_CONFIG_TIMEOUT_ARG: {
                     timeout = Duration.ofMillis(Integer.parseInt(getNextArgRequired()));
                     break;
@@ -104,7 +110,7 @@
                 }
             }
         }
-        mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout);
+        mNetworkTimeUpdateService.setServerConfigForTests(hostname, port, timeout);
         return 0;
     }
 
@@ -120,8 +126,9 @@
         pw.printf("    Refreshes the latest time. Prints whether it was successful.\n");
         pw.printf("  %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);
         pw.printf("    Sets the NTP server config for tests. The config is not persisted.\n");
-        pw.printf("      Options: [%s <hostname>] [%s <millis>]\n",
-                SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_TIMEOUT_ARG);
+        pw.printf("      Options: [%s <hostname>] [%s <port>] [%s <millis>]\n",
+                SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_PORT_ARG,
+                SET_SERVER_CONFIG_TIMEOUT_ARG);
         pw.printf("      Each key/value is optional and must be specified to override the\n");
         pw.printf("      normal value, not specifying a key causes it to reset to the original.\n");
         pw.println();
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 9c8cb8c..9f32888 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -3072,23 +3072,6 @@
     }
 
     /**
-     * Is userdata convertible to file based encryption?
-     * @return non zero for convertible
-     */
-    @Override
-    public boolean isConvertibleToFBE() throws RemoteException {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.CRYPT_KEEPER,
-            "no permission to access the crypt keeper");
-
-        try {
-            return mVold.isConvertibleToFbe();
-        } catch (Exception e) {
-            Slog.wtf(TAG, e);
-            return false;
-        }
-    }
-
-    /**
      * Check whether the device supports filesystem checkpointing.
      *
      * @return true if the device supports filesystem checkpointing, false otherwise.
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 811f2f5..382359a 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2009,10 +2009,8 @@
             return;
         }
 
-        ApnSetting apnSetting = preciseState.getApnSetting();
-
         synchronized (mRecords) {
-            if (validatePhoneId(phoneId)) {
+            if (validatePhoneId(phoneId) && preciseState.getApnSetting() != null) {
                 Pair<Integer, ApnSetting> key = Pair.create(preciseState.getTransportType(),
                         preciseState.getApnSetting());
                 PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId)
diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java
index 7b8cce5..c1d8e7b 100644
--- a/services/core/java/com/android/server/VpnManagerService.java
+++ b/services/core/java/com/android/server/VpnManagerService.java
@@ -37,6 +37,7 @@
 import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
 import android.net.VpnManager;
+import android.net.VpnProfileState;
 import android.net.VpnService;
 import android.net.util.NetdService;
 import android.os.Binder;
@@ -374,6 +375,24 @@
     }
 
     /**
+     * Retrieve the VpnProfileState for the profile provisioned by the given package.
+     *
+     * @return the VpnProfileState with current information, or null if there was no profile
+     *         provisioned by the given package.
+     * @hide
+     */
+    @Override
+    @Nullable
+    public VpnProfileState getProvisionedVpnProfileState(@NonNull String packageName) {
+        final int callingUid = Binder.getCallingUid();
+        verifyCallingUidAndPackage(packageName, callingUid);
+        final int user = UserHandle.getUserId(callingUid);
+        synchronized (mVpns) {
+            return mVpns.get(user).getProvisionedVpnProfileState(packageName);
+        }
+    }
+
+    /**
      * Start legacy VPN, controlling native daemons as needed. Creates a
      * secondary thread to perform connection work, returning quickly.
      *
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 956f34f..96ea6db 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -547,7 +547,6 @@
                 uids.clear();
                 uids.put(uidRec.getUid(), uidRec);
                 updateUidsLSP(uids, SystemClock.elapsedRealtime());
-                mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(uids);
             }
         }
 
@@ -1268,8 +1267,6 @@
             }
         }
 
-        mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
-
         return mService.mAppProfiler.updateLowMemStateLSP(numCached, numEmpty, numTrimming);
     }
 
@@ -1304,6 +1301,11 @@
 
     @GuardedBy({"mService", "mProcLock"})
     private void updateUidsLSP(ActiveUids activeUids, final long nowElapsed) {
+        // This compares previously set procstate to the current procstate in regards to whether
+        // or not the app's network access will be blocked. So, this needs to be called before
+        // we update the UidRecord's procstate by calling {@link UidRecord#setSetProcState}.
+        mProcessList.incrementProcStateSeqAndNotifyAppsLOSP(activeUids);
+
         ArrayList<UidRecord> becameIdle = mTmpBecameIdle;
         becameIdle.clear();
 
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c0df095..a6da4a6 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -75,6 +75,7 @@
 import android.net.UidRangeParcel;
 import android.net.UnderlyingNetworkInfo;
 import android.net.VpnManager;
+import android.net.VpnProfileState;
 import android.net.VpnService;
 import android.net.VpnTransportInfo;
 import android.net.ipsec.ike.ChildSessionCallback;
@@ -3438,6 +3439,45 @@
         }
     }
 
+    private @VpnProfileState.State int getStateFromLegacyState(int legacyState) {
+        switch (legacyState) {
+            case LegacyVpnInfo.STATE_CONNECTING:
+                return VpnProfileState.STATE_CONNECTING;
+            case LegacyVpnInfo.STATE_CONNECTED:
+                return VpnProfileState.STATE_CONNECTED;
+            case LegacyVpnInfo.STATE_DISCONNECTED:
+                return VpnProfileState.STATE_DISCONNECTED;
+            case LegacyVpnInfo.STATE_FAILED:
+                return VpnProfileState.STATE_FAILED;
+            default:
+                Log.wtf(TAG, "Unhandled state " + legacyState
+                        + ", treat it as STATE_DISCONNECTED");
+                return VpnProfileState.STATE_DISCONNECTED;
+        }
+    }
+
+    private VpnProfileState makeVpnProfileState() {
+        // TODO: mSessionKey will be moved to Ikev2VpnRunner once aosp/2007077 is merged, so after
+        //  merging aosp/2007077, here should check Ikev2VpnRunner is null or not. Session key will
+        //  be null if Ikev2VpnRunner is null.
+        return new VpnProfileState(getStateFromLegacyState(mLegacyState), mSessionKey, mAlwaysOn,
+                mLockdown);
+    }
+
+    /**
+     * Retrieve the VpnProfileState for the profile provisioned by the given package.
+     *
+     * @return the VpnProfileState with current information, or null if there was no profile
+     *         provisioned by the given package.
+     */
+    @Nullable
+    public synchronized VpnProfileState getProvisionedVpnProfileState(
+            @NonNull String packageName) {
+        requireNonNull(packageName, "No package name provided");
+        enforceNotRestrictedUser();
+        return isCurrentIkev2VpnLocked(packageName) ? makeVpnProfileState() : null;
+    }
+
     /**
      * Proxy to allow testing
      *
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 71cc361..470aa0e 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -118,9 +118,7 @@
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
 import static com.android.internal.util.XmlUtils.readStringAttribute;
-import static com.android.internal.util.XmlUtils.readThisIntArrayXml;
 import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
-import static com.android.internal.util.XmlUtils.writeIntArrayXml;
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
 import static com.android.internal.util.XmlUtils.writeStringAttribute;
@@ -243,7 +241,6 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.StatLogger;
-import com.android.internal.util.XmlUtils;
 import com.android.net.module.util.NetworkIdentityUtils;
 import com.android.net.module.util.NetworkStatsUtils;
 import com.android.net.module.util.PermissionUtils;
@@ -257,8 +254,6 @@
 
 import libcore.io.IoUtils;
 
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -334,7 +329,8 @@
     private static final int VERSION_ADDED_CYCLE = 11;
     private static final int VERSION_ADDED_NETWORK_TYPES = 12;
     private static final int VERSION_SUPPORTED_CARRIER_USAGE = 13;
-    private static final int VERSION_LATEST = VERSION_SUPPORTED_CARRIER_USAGE;
+    private static final int VERSION_REMOVED_SUBSCRIPTION_PLANS = 14;
+    private static final int VERSION_LATEST = VERSION_REMOVED_SUBSCRIPTION_PLANS;
 
     @VisibleForTesting
     public static final int TYPE_WARNING = SystemMessage.NOTE_NET_WARNING;
@@ -347,7 +343,6 @@
 
     private static final String TAG_POLICY_LIST = "policy-list";
     private static final String TAG_NETWORK_POLICY = "network-policy";
-    private static final String TAG_SUBSCRIPTION_PLAN = "subscription-plan";
     private static final String TAG_UID_POLICY = "uid-policy";
     private static final String TAG_APP_POLICY = "app-policy";
     private static final String TAG_WHITELIST = "whitelist";
@@ -426,6 +421,13 @@
      * obj = oldBlockedReasons
      */
     private static final int MSG_BLOCKED_REASON_CHANGED = 21;
+    /**
+     * Message to indicate that subscription plans expired and should be cleared.
+     * arg1 = subId
+     * arg2 = setSubscriptionPlans call ID
+     * obj = callingPackage
+     */
+    private static final int MSG_CLEAR_SUBSCRIPTION_PLANS = 22;
 
     private static final int UID_MSG_STATE_CHANGED = 100;
     private static final int UID_MSG_GONE = 101;
@@ -492,6 +494,12 @@
     /** Map from subId to package name that owns subscription plans. */
     @GuardedBy("mNetworkPoliciesSecondLock")
     final SparseArray<String> mSubscriptionPlansOwner = new SparseArray<>();
+    /** Map from subId to the ID of the clear plans request. */
+    @GuardedBy("mNetworkPoliciesSecondLock")
+    final SparseIntArray mSetSubscriptionPlansIds = new SparseIntArray();
+    /** Atomic integer to generate a new ID for each clear plans request. */
+    @GuardedBy("mNetworkPoliciesSecondLock")
+    int mSetSubscriptionPlansIdCounter = 0;
 
     /** Map from subId to daily opportunistic quota. */
     @GuardedBy("mNetworkPoliciesSecondLock")
@@ -2553,56 +2561,6 @@
                                     warningBytes, limitBytes, lastWarningSnooze,
                                     lastLimitSnooze, metered, inferred));
                         }
-
-                    } else if (TAG_SUBSCRIPTION_PLAN.equals(tag)) {
-                        final String start = readStringAttribute(in, ATTR_CYCLE_START);
-                        final String end = readStringAttribute(in, ATTR_CYCLE_END);
-                        final String period = readStringAttribute(in, ATTR_CYCLE_PERIOD);
-                        final SubscriptionPlan.Builder builder = new SubscriptionPlan.Builder(
-                                RecurrenceRule.convertZonedDateTime(start),
-                                RecurrenceRule.convertZonedDateTime(end),
-                                RecurrenceRule.convertPeriod(period));
-                        builder.setTitle(readStringAttribute(in, ATTR_TITLE));
-                        builder.setSummary(readStringAttribute(in, ATTR_SUMMARY));
-
-                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES,
-                                SubscriptionPlan.BYTES_UNKNOWN);
-                        final int limitBehavior = readIntAttribute(in, ATTR_LIMIT_BEHAVIOR,
-                                SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN);
-                        if (limitBytes != SubscriptionPlan.BYTES_UNKNOWN
-                                && limitBehavior != SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN) {
-                            builder.setDataLimit(limitBytes, limitBehavior);
-                        }
-
-                        final long usageBytes = readLongAttribute(in, ATTR_USAGE_BYTES,
-                                SubscriptionPlan.BYTES_UNKNOWN);
-                        final long usageTime = readLongAttribute(in, ATTR_USAGE_TIME,
-                                SubscriptionPlan.TIME_UNKNOWN);
-                        if (usageBytes != SubscriptionPlan.BYTES_UNKNOWN
-                                && usageTime != SubscriptionPlan.TIME_UNKNOWN) {
-                            builder.setDataUsage(usageBytes, usageTime);
-                        }
-
-                        final int subId = readIntAttribute(in, ATTR_SUB_ID);
-                        final String ownerPackage = readStringAttribute(in, ATTR_OWNER_PACKAGE);
-
-                        if (version >= VERSION_ADDED_NETWORK_TYPES) {
-                            final int depth = in.getDepth();
-                            while (XmlUtils.nextElementWithin(in, depth)) {
-                                if (TAG_XML_UTILS_INT_ARRAY.equals(in.getName())
-                                        && ATTR_NETWORK_TYPES.equals(
-                                                readStringAttribute(in, ATTR_XML_UTILS_NAME))) {
-                                    final int[] networkTypes =
-                                            readThisIntArrayXml(in, TAG_XML_UTILS_INT_ARRAY, null);
-                                    builder.setNetworkTypes(networkTypes);
-                                }
-                            }
-                        }
-
-                        final SubscriptionPlan plan = builder.build();
-                        mSubscriptionPlans.put(subId, ArrayUtils.appendElement(
-                                SubscriptionPlan.class, mSubscriptionPlans.get(subId), plan));
-                        mSubscriptionPlansOwner.put(subId, ownerPackage);
                     } else if (TAG_UID_POLICY.equals(tag)) {
                         final int uid = readIntAttribute(in, ATTR_UID);
                         final int policy = readIntAttribute(in, ATTR_POLICY);
@@ -2793,38 +2751,6 @@
                 out.endTag(null, TAG_NETWORK_POLICY);
             }
 
-            // write all known subscription plans
-            for (int i = 0; i < mSubscriptionPlans.size(); i++) {
-                final int subId = mSubscriptionPlans.keyAt(i);
-                if (subId == INVALID_SUBSCRIPTION_ID) continue;
-                final String ownerPackage = mSubscriptionPlansOwner.get(subId);
-                final SubscriptionPlan[] plans = mSubscriptionPlans.valueAt(i);
-                if (ArrayUtils.isEmpty(plans)) continue;
-
-                for (SubscriptionPlan plan : plans) {
-                    out.startTag(null, TAG_SUBSCRIPTION_PLAN);
-                    writeIntAttribute(out, ATTR_SUB_ID, subId);
-                    writeStringAttribute(out, ATTR_OWNER_PACKAGE, ownerPackage);
-                    final RecurrenceRule cycleRule = plan.getCycleRule();
-                    writeStringAttribute(out, ATTR_CYCLE_START,
-                            RecurrenceRule.convertZonedDateTime(cycleRule.start));
-                    writeStringAttribute(out, ATTR_CYCLE_END,
-                            RecurrenceRule.convertZonedDateTime(cycleRule.end));
-                    writeStringAttribute(out, ATTR_CYCLE_PERIOD,
-                            RecurrenceRule.convertPeriod(cycleRule.period));
-                    writeStringAttribute(out, ATTR_TITLE, plan.getTitle());
-                    writeStringAttribute(out, ATTR_SUMMARY, plan.getSummary());
-                    writeLongAttribute(out, ATTR_LIMIT_BYTES, plan.getDataLimitBytes());
-                    writeIntAttribute(out, ATTR_LIMIT_BEHAVIOR, plan.getDataLimitBehavior());
-                    writeLongAttribute(out, ATTR_USAGE_BYTES, plan.getDataUsageBytes());
-                    writeLongAttribute(out, ATTR_USAGE_TIME, plan.getDataUsageTime());
-                    try {
-                        writeIntArrayXml(plan.getNetworkTypes(), ATTR_NETWORK_TYPES, out);
-                    } catch (XmlPullParserException ignored) { }
-                    out.endTag(null, TAG_SUBSCRIPTION_PLAN);
-                }
-            }
-
             // write all known uid policies
             for (int i = 0; i < mUidPolicy.size(); i++) {
                 final int uid = mUidPolicy.keyAt(i);
@@ -3698,7 +3624,8 @@
     }
 
     @Override
-    public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage) {
+    public void setSubscriptionPlans(int subId, SubscriptionPlan[] plans,
+            long expirationDurationMillis, String callingPackage) {
         enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
         enforceSubscriptionPlanValidity(plans);
 
@@ -3708,34 +3635,47 @@
 
         final long token = Binder.clearCallingIdentity();
         try {
-            synchronized (mUidRulesFirstLock) {
-                synchronized (mNetworkPoliciesSecondLock) {
-                    mSubscriptionPlans.put(subId, plans);
-                    mSubscriptionPlansOwner.put(subId, callingPackage);
-
-                    final String subscriberId = mSubIdToSubscriberId.get(subId, null);
-                    if (subscriberId != null) {
-                        ensureActiveCarrierPolicyAL(subId, subscriberId);
-                        maybeUpdateCarrierPolicyCycleAL(subId, subscriberId);
-                    } else {
-                        Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
-                    }
-
-                    handleNetworkPoliciesUpdateAL(true);
-                }
-            }
-
-            final Intent intent = new Intent(SubscriptionManager.ACTION_SUBSCRIPTION_PLANS_CHANGED);
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-            intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
-            mContext.sendBroadcast(intent, android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
-            mHandler.sendMessage(
-                    mHandler.obtainMessage(MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
+            setSubscriptionPlansInternal(subId, plans, expirationDurationMillis, callingPackage);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
+    private void setSubscriptionPlansInternal(int subId, SubscriptionPlan[] plans,
+            long expirationDurationMillis, String callingPackage) {
+        synchronized (mUidRulesFirstLock) {
+            synchronized (mNetworkPoliciesSecondLock) {
+                mSubscriptionPlans.put(subId, plans);
+                mSubscriptionPlansOwner.put(subId, callingPackage);
+
+                final String subscriberId = mSubIdToSubscriberId.get(subId, null);
+                if (subscriberId != null) {
+                    ensureActiveCarrierPolicyAL(subId, subscriberId);
+                    maybeUpdateCarrierPolicyCycleAL(subId, subscriberId);
+                } else {
+                    Slog.wtf(TAG, "Missing subscriberId for subId " + subId);
+                }
+
+                handleNetworkPoliciesUpdateAL(true);
+
+                final Intent intent = new Intent(
+                        SubscriptionManager.ACTION_SUBSCRIPTION_PLANS_CHANGED);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
+                mContext.sendBroadcast(intent,
+                        android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS);
+                mHandler.sendMessage(mHandler.obtainMessage(
+                        MSG_SUBSCRIPTION_PLANS_CHANGED, subId, 0, plans));
+                final int setPlansId = mSetSubscriptionPlansIdCounter++;
+                mSetSubscriptionPlansIds.put(subId, setPlansId);
+                if (expirationDurationMillis > 0) {
+                    mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_SUBSCRIPTION_PLANS,
+                            subId, setPlansId, callingPackage), expirationDurationMillis);
+                }
+            }
+        }
+    }
+
     /**
      * Only visible for testing purposes. This doesn't give any access to
      * existing plans; it simply lets the debug package define new plans.
@@ -3758,7 +3698,7 @@
 
     @Override
     public void setSubscriptionOverride(int subId, int overrideMask, int overrideValue,
-            int[] networkTypes, long timeoutMillis, String callingPackage) {
+            int[] networkTypes, long expirationDurationMillis, String callingPackage) {
         enforceSubscriptionPlanAccess(subId, Binder.getCallingUid(), callingPackage);
 
         final ArraySet<Integer> allNetworksSet = new ArraySet<>();
@@ -3796,10 +3736,10 @@
             args.arg3 = overrideValue;
             args.arg4 = applicableNetworks.toArray();
             mHandler.sendMessage(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args));
-            if (timeoutMillis > 0) {
+            if (expirationDurationMillis > 0) {
                 args.arg3 = 0;
                 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SUBSCRIPTION_OVERRIDE, args),
-                        timeoutMillis);
+                        expirationDurationMillis);
             }
         }
     }
@@ -5214,6 +5154,22 @@
                     mListeners.finishBroadcast();
                     return true;
                 }
+                case MSG_CLEAR_SUBSCRIPTION_PLANS: {
+                    synchronized (mUidRulesFirstLock) {
+                        synchronized (mNetworkPoliciesSecondLock) {
+                            int subId = msg.arg1;
+                            if (msg.arg2 == mSetSubscriptionPlansIds.get(subId)) {
+                                if (LOGD) Slog.d(TAG, "Clearing expired subscription plans.");
+                                setSubscriptionPlansInternal(subId, new SubscriptionPlan[]{},
+                                        0 /* expirationDurationMillis */,
+                                        (String) msg.obj /* callingPackage */);
+                            } else {
+                                if (LOGD) Slog.d(TAG, "Ignoring stale CLEAR_SUBSCRIPTION_PLANS.");
+                            }
+                        }
+                    }
+                    return true;
+                }
                 case MSG_BLOCKED_REASON_CHANGED: {
                     final int uid = msg.arg1;
                     final int newBlockedReasons = msg.arg2;
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 1393d39..f865a50 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -2238,7 +2238,7 @@
 
     private void setSubscriptionPlans(int subId, SubscriptionPlan[] plans, String callingPackage)
             throws InterruptedException {
-        mService.setSubscriptionPlans(subId, plans, callingPackage);
+        mService.setSubscriptionPlans(subId, plans, 0, callingPackage);
         // setSubscriptionPlans() triggers async events, wait for those to be completed before
         // moving forward as they could interfere with the tests later.
         postMsgAndWaitForCompletion();
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index e88106c..86b98f1 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -127,7 +127,9 @@
             ApnSetting.TYPE_EMERGENCY,
             ApnSetting.TYPE_MCX,
             ApnSetting.TYPE_XCAP,
-            // ApnSetting.TYPE_ENTERPRISE
+            ApnSetting.TYPE_BIP,
+            ApnSetting.TYPE_VSIM,
+            ApnSetting.TYPE_ENTERPRISE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApnType {
@@ -707,6 +709,9 @@
             NetworkCapabilities.NET_CAPABILITY_VSIM,
             NetworkCapabilities.NET_CAPABILITY_BIP,
             NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT,
+            NetworkCapabilities.NET_CAPABILITY_MMTEL,
+            NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY,
+            NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH
     })
     public @interface NetCapability { }
 
@@ -721,4 +726,16 @@
             NetworkAgent.VALIDATION_STATUS_NOT_VALID
     })
     public @interface ValidationStatus {}
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "NET_CAPABILITY_ENTERPRISE_SUB_LEVEL" }, value = {
+            NetworkCapabilities.NET_ENTERPRISE_ID_1,
+            NetworkCapabilities.NET_ENTERPRISE_ID_2,
+            NetworkCapabilities.NET_ENTERPRISE_ID_3,
+            NetworkCapabilities.NET_ENTERPRISE_ID_4,
+            NetworkCapabilities.NET_ENTERPRISE_ID_5
+    })
+
+    public @interface EnterpriseId {}
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 4a5a137..ee646d9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5641,6 +5641,13 @@
             "telephony_data_handover_retry_rules_string_array";
 
     /**
+     * Indicates whether delay tearing down IMS data network until voice call ends.
+     * @hide
+     */
+    public static final String KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL =
+            "delay_ims_tear_down_until_call_end_bool";
+
+    /**
      * The patterns of missed incoming call sms. This is the regular expression used for
      * matching the missed incoming call's date, time, and caller id. The pattern should match
      * fields for at least month, day, hour, and minute. Year is optional although it is encouraged.
@@ -6458,6 +6465,7 @@
                 KEY_TELEPHONY_DATA_HANDOVER_RETRY_RULES_STRING_ARRAY, new String[] {
                         "retry_interval=1000|2000|4000|8000|16000, maximum_retries=5"
                 });
+        sDefaults.putBoolean(KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL, false);
         sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
         sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
         sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
@@ -6469,7 +6477,7 @@
         sDefaults.putBoolean(KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL, true);
         sDefaults.putBoolean(KEY_HIDE_ENABLE_2G, false);
         sDefaults.putStringArray(KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY,
-                new String[]{"ia", "default", "mms", "dun"});
+                new String[]{"ia", "default"});
         sDefaults.putBoolean(KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL, false);
         sDefaults.putBoolean(KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL, false);
         sDefaults.putBoolean(KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL, true);
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 56bf303..3a3b363 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1083,6 +1083,13 @@
      */
     public static final int REQUEST_NOT_SUPPORTED = 0x1000A;
 
+    /**
+     * An internal setup data error initiated by telephony that no retry should be performed.
+     *
+     * @hide
+     */
+    public static final int NO_RETRY_FAILURE = 0x1000B;
+
     private static final Map<Integer, String> sFailCauseMap;
     static {
         sFailCauseMap = new HashMap<>();
@@ -1515,6 +1522,8 @@
         sFailCauseMap.put(DUPLICATE_CID, "DUPLICATE_CID");
         sFailCauseMap.put(NO_DEFAULT_DATA, "NO_DEFAULT_DATA");
         sFailCauseMap.put(SERVICE_TEMPORARILY_UNAVAILABLE, "SERVICE_TEMPORARILY_UNAVAILABLE");
+        sFailCauseMap.put(REQUEST_NOT_SUPPORTED, "REQUEST_NOT_SUPPORTED");
+        sFailCauseMap.put(NO_RETRY_FAILURE, "NO_RETRY_FAILURE");
     }
 
     private DataFailCause() {
@@ -1565,6 +1574,7 @@
     }
 
     /** @hide */
+    // TODO: Migrated to DataConfigManager
     public static boolean isPermanentFailure(@NonNull Context context,
                                              @DataFailureCause int failCause,
                                              int subId) {
@@ -1621,6 +1631,7 @@
                     };
                 }
 
+                permanentFailureSet.add(NO_RETRY_FAILURE);
                 sPermanentFailureCache.put(subId, permanentFailureSet);
             }
 
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index 957f683..1d7c18f 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -22,6 +22,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.Objects;
 
 
@@ -76,7 +78,8 @@
     /**
      * @hide
      */
-    DataSpecificRegistrationInfo(
+    @VisibleForTesting
+    public DataSpecificRegistrationInfo(
             int maxDataCalls, boolean isDcNrRestricted, boolean isNrAvailable,
             boolean isEnDcAvailable, @Nullable VopsSupportInfo vops) {
         this.maxDataCalls = maxDataCalls;
@@ -186,7 +189,7 @@
     /**
      * @return The VOPS (Voice over Packet Switched) support information.
      *
-     * The instance of {@link LTEVopsSupportInfo}, or {@link NrVopsSupportInfo},
+     * The instance of {@link LteVopsSupportInfo}, or {@link NrVopsSupportInfo},
      * null if there is there is no VOPS support information available.
      */
     @Nullable
diff --git a/telephony/java/android/telephony/ImsiEncryptionInfo.java b/telephony/java/android/telephony/ImsiEncryptionInfo.java
index 4978692..82333a4 100644
--- a/telephony/java/android/telephony/ImsiEncryptionInfo.java
+++ b/telephony/java/android/telephony/ImsiEncryptionInfo.java
@@ -46,16 +46,17 @@
     private final int keyType;
     //Date-Time in UTC when the key will expire.
     private final Date expirationTime;
+    private final int carrierId;
 
     /** @hide */
     public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
-                              byte[] key, Date expirationTime) {
-        this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime);
+            byte[] key, Date expirationTime, int carrierId) {
+        this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime, carrierId);
     }
 
     /** @hide */
     public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
-                              PublicKey publicKey, Date expirationTime) {
+            PublicKey publicKey, Date expirationTime, int carrierId) {
         // todo need to validate that ImsiEncryptionInfo is being created with the correct params.
         //      Including validating that the public key is in "X.509" format. This will be done in
         //      a subsequent CL.
@@ -65,6 +66,7 @@
         this.publicKey = publicKey;
         this.keyIdentifier = keyIdentifier;
         this.expirationTime = expirationTime;
+        this.carrierId = carrierId;
     }
 
     /** @hide */
@@ -78,6 +80,7 @@
         keyIdentifier = in.readString();
         keyType = in.readInt();
         expirationTime = new Date(in.readLong());
+        carrierId = in.readInt();
     }
 
     /** @hide */
@@ -90,6 +93,11 @@
         return this.mcc;
     }
 
+    /** @hide */
+    public int getCarrierId() {
+        return carrierId;
+    }
+
     /**
      * Returns key identifier, a string that helps the authentication server to locate the
      * private key to decrypt the permanent identity, or {@code null} when uavailable.
@@ -157,6 +165,7 @@
         dest.writeString(keyIdentifier);
         dest.writeInt(keyType);
         dest.writeLong(expirationTime.getTime());
+        dest.writeInt(carrierId);
     }
 
     @Override
@@ -164,10 +173,11 @@
         return "[ImsiEncryptionInfo "
                 + "mcc=" + mcc
                 + " mnc=" + mnc
-                + " publicKey=" + publicKey
+                + ", publicKey=" + publicKey
                 + ", keyIdentifier=" + keyIdentifier
                 + ", keyType=" + keyType
                 + ", expirationTime=" + expirationTime
+                + ", carrier_id=" + carrierId
                 + "]";
     }
 }
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 6a80766..1a5a5ae 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -242,13 +242,16 @@
      * @param cellIdentity The identity representing a unique cell or wifi AP. Set to null if the
      * information is not available.
      * @param rplmn the registered plmn or the last plmn for attempted registration if reg failed.
+     * @param voiceSpecificInfo Voice specific registration information.
+     * @param dataSpecificInfo Data specific registration information.
      */
     private NetworkRegistrationInfo(@Domain int domain, @TransportType int transportType,
-                                   @RegistrationState int registrationState,
-                                   @NetworkType int accessNetworkTechnology, int rejectCause,
-                                   boolean emergencyOnly,
-                                   @Nullable @ServiceType List<Integer> availableServices,
-                                   @Nullable CellIdentity cellIdentity, @Nullable String rplmn) {
+            @RegistrationState int registrationState,
+            @NetworkType int accessNetworkTechnology, int rejectCause,
+            boolean emergencyOnly, @Nullable @ServiceType List<Integer> availableServices,
+            @Nullable CellIdentity cellIdentity, @Nullable String rplmn,
+            @Nullable VoiceSpecificRegistrationInfo voiceSpecificInfo,
+            @Nullable DataSpecificRegistrationInfo dataSpecificInfo) {
         mDomain = domain;
         mTransportType = transportType;
         mRegistrationState = registrationState;
@@ -262,6 +265,10 @@
         mEmergencyOnly = emergencyOnly;
         mNrState = NR_STATE_NONE;
         mRplmn = rplmn;
+        mVoiceSpecificInfo = voiceSpecificInfo;
+        mDataSpecificInfo = dataSpecificInfo;
+
+        updateNrState();
     }
 
     /**
@@ -276,10 +283,9 @@
                                    boolean cssSupported, int roamingIndicator, int systemIsInPrl,
                                    int defaultRoamingIndicator) {
         this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
-                emergencyOnly, availableServices, cellIdentity, rplmn);
-
-        mVoiceSpecificInfo = new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
-                systemIsInPrl, defaultRoamingIndicator);
+                emergencyOnly, availableServices, cellIdentity, rplmn,
+                new VoiceSpecificRegistrationInfo(cssSupported, roamingIndicator,
+                        systemIsInPrl, defaultRoamingIndicator), null);
     }
 
     /**
@@ -295,11 +301,9 @@
                                    boolean isNrAvailable, boolean isEndcAvailable,
                                    @Nullable VopsSupportInfo vopsSupportInfo) {
         this(domain, transportType, registrationState, accessNetworkTechnology, rejectCause,
-                emergencyOnly, availableServices, cellIdentity, rplmn);
-        mDataSpecificInfo = new DataSpecificRegistrationInfo(
-                maxDataCalls, isDcNrRestricted, isNrAvailable,
-                isEndcAvailable, vopsSupportInfo);
-        updateNrState();
+                emergencyOnly, availableServices, cellIdentity, rplmn, null,
+                new DataSpecificRegistrationInfo(maxDataCalls, isDcNrRestricted, isNrAvailable,
+                        isEndcAvailable, vopsSupportInfo));
     }
 
     private NetworkRegistrationInfo(Parcel source) {
@@ -804,6 +808,12 @@
         @NonNull
         private String mRplmn = "";
 
+        @Nullable
+        private DataSpecificRegistrationInfo mDataSpecificRegistrationInfo;
+
+        @Nullable
+        private VoiceSpecificRegistrationInfo mVoiceSpecificRegistrationInfo;
+
         /**
          * Default constructor for Builder.
          */
@@ -930,6 +940,30 @@
         }
 
         /**
+         * Set voice specific registration information.
+         *
+         * @param info The voice specific registration information.
+         * @return The builder.
+         * @hide
+         */
+        public @NonNull Builder setVoiceSpecificInfo(@NonNull VoiceSpecificRegistrationInfo info) {
+            mVoiceSpecificRegistrationInfo = info;
+            return this;
+        }
+
+        /**
+         * Set data specific registration information.
+         *
+         * @param info The data specific registration information.
+         * @return The builder.
+         * @hide
+         */
+        public @NonNull Builder setDataSpecificInfo(@NonNull DataSpecificRegistrationInfo info) {
+            mDataSpecificRegistrationInfo = info;
+            return this;
+        }
+
+        /**
          * Build the NetworkRegistrationInfo.
          * @return the NetworkRegistrationInfo object.
          * @hide
@@ -938,7 +972,8 @@
         public @NonNull NetworkRegistrationInfo build() {
             return new NetworkRegistrationInfo(mDomain, mTransportType, mRegistrationState,
                     mAccessNetworkTechnology, mRejectCause, mEmergencyOnly, mAvailableServices,
-                    mCellIdentity, mRplmn);
+                    mCellIdentity, mRplmn, mVoiceSpecificRegistrationInfo,
+                    mDataSpecificRegistrationInfo);
         }
     }
 }
diff --git a/telephony/java/android/telephony/PcoData.java b/telephony/java/android/telephony/PcoData.java
index bcfbcf8b..39e4f2f 100644
--- a/telephony/java/android/telephony/PcoData.java
+++ b/telephony/java/android/telephony/PcoData.java
@@ -19,6 +19,9 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 /**
  * Contains Carrier-specific (and opaque) Protocol configuration Option
  * Data.  In general this is only passed on to carrier-specific applications
@@ -84,4 +87,22 @@
         return "PcoData(" + cid + ", " + bearerProto + ", " + pcoId + ", contents[" +
                 contents.length + "])";
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        PcoData pcoData = (PcoData) o;
+        return cid == pcoData.cid
+                && pcoId == pcoData.pcoId
+                && Objects.equals(bearerProto, pcoData.bearerProto)
+                && Arrays.equals(contents, pcoData.contents);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Objects.hash(cid, bearerProto, pcoId);
+        result = 31 * result + Arrays.hashCode(contents);
+        return result;
+    }
 }
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index 95448c7..d91134e 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -23,12 +23,15 @@
 import android.os.Parcelable;
 import android.telephony.Annotation.NetworkType;
 
+import com.android.telephony.Rlog;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Arrays;
 import java.util.Objects;
 
 public final class PhysicalChannelConfig implements Parcelable {
+    static final String TAG = "PhysicalChannelConfig";
 
     // TODO(b/72993578) consolidate these enums in a central location.
     /** @hide */
@@ -568,19 +571,21 @@
 
         public @NonNull Builder setNetworkType(@NetworkType int networkType) {
             if (!TelephonyManager.isNetworkTypeValid(networkType)) {
-                throw new IllegalArgumentException("Network type: " + networkType + " is invalid.");
+                Rlog.e(TAG, "Builder.setNetworkType: Network type " + networkType + " is invalid.");
+            } else {
+                mNetworkType = networkType;
             }
-            mNetworkType = networkType;
             return this;
         }
 
         public @NonNull Builder setFrequencyRange(int frequencyRange) {
             if (!ServiceState.isFrequencyRangeValid(frequencyRange)
                     && frequencyRange != ServiceState.FREQUENCY_RANGE_UNKNOWN) {
-                throw new IllegalArgumentException("Frequency range: " + frequencyRange +
-                        " is invalid.");
+                Rlog.e(TAG, "Builder.setFrequencyRange: Frequency range " + frequencyRange
+                        + " is invalid.");
+            } else {
+                mFrequencyRange = frequencyRange;
             }
-            mFrequencyRange = frequencyRange;
             return this;
         }
 
@@ -596,19 +601,21 @@
 
         public @NonNull Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
             if (cellBandwidthDownlinkKhz < CELL_BANDWIDTH_UNKNOWN) {
-                throw new IllegalArgumentException("Cell downlink bandwidth(kHz): " +
-                        cellBandwidthDownlinkKhz + " is invalid.");
+                Rlog.e(TAG, "Builder.setCellBandwidthDownlinkKhz: Cell downlink bandwidth(kHz) "
+                        + cellBandwidthDownlinkKhz + " is invalid.");
+            } else {
+                mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
             }
-            mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
             return this;
         }
 
         public @NonNull Builder setCellBandwidthUplinkKhz(int cellBandwidthUplinkKhz) {
             if (cellBandwidthUplinkKhz < CELL_BANDWIDTH_UNKNOWN) {
-                throw new IllegalArgumentException("Cell uplink bandwidth(kHz): "+
-                        cellBandwidthUplinkKhz +" is invalid.");
+                Rlog.e(TAG, "Builder.setCellBandwidthUplinkKhz: Cell uplink bandwidth(kHz) "
+                        + cellBandwidthUplinkKhz + " is invalid.");
+            } else {
+                mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
             }
-            mCellBandwidthUplinkKhz = cellBandwidthUplinkKhz;
             return this;
         }
 
@@ -625,19 +632,20 @@
 
         public @NonNull Builder setPhysicalCellId(int physicalCellId) {
             if (physicalCellId > PHYSICAL_CELL_ID_MAXIMUM_VALUE) {
-                throw new IllegalArgumentException("Physical cell Id: " + physicalCellId +
-                        " is over limit.");
+                Rlog.e(TAG, "Builder.setPhysicalCellId: Physical cell ID " + physicalCellId
+                        + " is over limit.");
+            } else {
+                mPhysicalCellId = physicalCellId;
             }
-            mPhysicalCellId = physicalCellId;
             return this;
         }
 
         public @NonNull Builder setBand(int band) {
             if (band <= BAND_UNKNOWN) {
-                throw new IllegalArgumentException("Band: " + band +
-                        " is invalid.");
+                Rlog.e(TAG, "Builder.setBand: Band " + band + " is invalid.");
+            } else {
+                mBand = band;
             }
-            mBand = band;
             return this;
         }
     }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 9fd2ae4..753935a 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1205,7 +1205,15 @@
         }
     }
 
-    private void init() {
+    /**
+     * Initialize the service state. Set everything to the default value.
+     *
+     * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+     * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+     * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+     * {@link NetworkRegistrationInfo}.
+     */
+    private void init(boolean legacyMode) {
         if (DBG) Rlog.d(LOG_TAG, "init");
         mVoiceRegState = STATE_OUT_OF_SERVICE;
         mDataRegState = STATE_OUT_OF_SERVICE;
@@ -1237,6 +1245,13 @@
                     .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                     .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
                     .build());
+            if (!legacyMode) {
+                addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+                        .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                        .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
+                        .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+                        .build());
+            }
         }
         mOperatorAlphaLongRaw = null;
         mOperatorAlphaShortRaw = null;
@@ -1245,15 +1260,32 @@
     }
 
     public void setStateOutOfService() {
-        init();
+        init(true);
     }
 
     public void setStateOff() {
-        init();
+        init(true);
         mVoiceRegState = STATE_POWER_OFF;
         mDataRegState = STATE_POWER_OFF;
     }
 
+    /**
+     * Set the service state to out-of-service
+     *
+     * @param legacyMode {@code true} if the device is on IWLAN legacy mode, where IWLAN is
+     * considered as a RAT on WWAN {@link NetworkRegistrationInfo}. {@code false} if the device
+     * is on AP-assisted mode, where IWLAN should be reported through WLAN.
+     * @param powerOff {@code true} if this is a power off case (i.e. Airplane mode on).
+     * @hide
+     */
+    public void setOutOfService(boolean legacyMode, boolean powerOff) {
+        init(legacyMode);
+        if (powerOff) {
+            mVoiceRegState = STATE_POWER_OFF;
+            mDataRegState = STATE_POWER_OFF;
+        }
+    }
+
     public void setState(int state) {
         setVoiceRegState(state);
         if (DBG) Rlog.e(LOG_TAG, "[ServiceState] setState deprecated use setVoiceRegState()");
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c6c797e..4b8b590 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2792,10 +2792,43 @@
      *             outlined above.
      * @throws IllegalArgumentException if plans don't meet the requirements
      *             defined in {@link SubscriptionPlan}.
+     * @deprecated use {@link #setSubscriptionPlans(int, List, long)} instead.
      */
+    @Deprecated
     public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
+        setSubscriptionPlans(subId, plans, 0);
+    }
+
+    /**
+     * Set the description of the billing relationship plan between a carrier
+     * and a specific subscriber.
+     * <p>
+     * This method is only accessible to the following narrow set of apps:
+     * <ul>
+     * <li>The carrier app for this subscriberId, as determined by
+     * {@link TelephonyManager#hasCarrierPrivileges()}.
+     * <li>The carrier app explicitly delegated access through
+     * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+     * </ul>
+     *
+     * @param subId the subscriber this relationship applies to. An empty list
+     *            may be sent to clear any existing plans.
+     * @param plans the list of plans. The first plan is always the primary and
+     *            most important plan. Any additional plans are secondary and
+     *            may not be displayed or used by decision making logic.
+     * @param expirationDurationMillis the duration after which the subscription plans
+     *            will be automatically cleared, or {@code 0} to leave the plans until
+     *            explicitly cleared, or the next reboot, whichever happens first.
+     * @throws SecurityException if the caller doesn't meet the requirements
+     *             outlined above.
+     * @throws IllegalArgumentException if plans don't meet the requirements
+     *             defined in {@link SubscriptionPlan}.
+     */
+    public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans,
+            @DurationMillisLong long expirationDurationMillis) {
         getNetworkPolicyManager().setSubscriptionPlans(subId,
-                plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName());
+                plans.toArray(new SubscriptionPlan[0]), expirationDurationMillis,
+                mContext.getOpPackageName());
     }
 
     /**
@@ -2814,17 +2847,17 @@
      * @param subId the subscriber this override applies to.
      * @param overrideUnmetered set if the billing relationship should be
      *            considered unmetered.
-     * @param timeoutMillis the timeout after which the requested override will
-     *            be automatically cleared, or {@code 0} to leave in the
+     * @param expirationDurationMillis the duration after which the requested override
+     *            will be automatically cleared, or {@code 0} to leave in the
      *            requested state until explicitly cleared, or the next reboot,
      *            whichever happens first.
      * @throws SecurityException if the caller doesn't meet the requirements
      *            outlined above.
      */
     public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
-            @DurationMillisLong long timeoutMillis) {
+            @DurationMillisLong long expirationDurationMillis) {
         setSubscriptionOverrideUnmetered(subId, overrideUnmetered,
-                TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+                TelephonyManager.getAllNetworkTypes(), expirationDurationMillis);
     }
 
     /**
@@ -2846,8 +2879,8 @@
      * @param networkTypes the network types this override applies to. If no
      *            network types are specified, override values will be ignored.
      *            {@see TelephonyManager#getAllNetworkTypes()}
-     * @param timeoutMillis the timeout after which the requested override will
-     *            be automatically cleared, or {@code 0} to leave in the
+     * @param expirationDurationMillis the duration after which the requested override
+     *            will be automatically cleared, or {@code 0} to leave in the
      *            requested state until explicitly cleared, or the next reboot,
      *            whichever happens first.
      * @throws SecurityException if the caller doesn't meet the requirements
@@ -2855,10 +2888,10 @@
      */
     public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
             @NonNull @Annotation.NetworkType int[] networkTypes,
-            @DurationMillisLong long timeoutMillis) {
+            @DurationMillisLong long expirationDurationMillis) {
         final int overrideValue = overrideUnmetered ? SUBSCRIPTION_OVERRIDE_UNMETERED : 0;
         getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_UNMETERED,
-                overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
+                overrideValue, networkTypes, expirationDurationMillis, mContext.getOpPackageName());
     }
 
     /**
@@ -2878,17 +2911,17 @@
      * @param subId the subscriber this override applies to.
      * @param overrideCongested set if the subscription should be considered
      *            congested.
-     * @param timeoutMillis the timeout after which the requested override will
-     *            be automatically cleared, or {@code 0} to leave in the
+     * @param expirationDurationMillis the duration after which the requested override
+     *            will be automatically cleared, or {@code 0} to leave in the
      *            requested state until explicitly cleared, or the next reboot,
      *            whichever happens first.
      * @throws SecurityException if the caller doesn't meet the requirements
      *            outlined above.
      */
     public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
-            @DurationMillisLong long timeoutMillis) {
+            @DurationMillisLong long expirationDurationMillis) {
         setSubscriptionOverrideCongested(subId, overrideCongested,
-                TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+                TelephonyManager.getAllNetworkTypes(), expirationDurationMillis);
     }
 
     /**
@@ -2911,8 +2944,8 @@
      * @param networkTypes the network types this override applies to. If no
      *            network types are specified, override values will be ignored.
      *            {@see TelephonyManager#getAllNetworkTypes()}
-     * @param timeoutMillis the timeout after which the requested override will
-     *            be automatically cleared, or {@code 0} to leave in the
+     * @param expirationDurationMillis the duration after which the requested override
+     *            will be automatically cleared, or {@code 0} to leave in the
      *            requested state until explicitly cleared, or the next reboot,
      *            whichever happens first.
      * @throws SecurityException if the caller doesn't meet the requirements
@@ -2920,10 +2953,10 @@
      */
     public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
             @NonNull @Annotation.NetworkType int[] networkTypes,
-            @DurationMillisLong long timeoutMillis) {
+            @DurationMillisLong long expirationDurationMillis) {
         final int overrideValue = overrideCongested ? SUBSCRIPTION_OVERRIDE_CONGESTED : 0;
         getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_CONGESTED,
-                overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
+                overrideValue, networkTypes, expirationDurationMillis, mContext.getOpPackageName());
     }
 
     /**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 63ff232..8c8e203 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -140,6 +140,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
@@ -3475,15 +3476,39 @@
      * @see #SIM_STATE_PRESENT
      *
      * @hide
+     * @deprecated instead use {@link #getSimCardState(int, int)}
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @Deprecated
     public @SimState int getSimCardState(int physicalSlotIndex) {
-        int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex));
+        int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, DEFAULT_PORT_INDEX));
         return getSimCardStateFromSimState(simState);
     }
 
     /**
+     * Returns a constant indicating the state of the device SIM card in a physical slot and
+     * port index.
+     *
+     * @param physicalSlotIndex physical slot index
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     *                  Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_ABSENT
+     * @see #SIM_STATE_CARD_IO_ERROR
+     * @see #SIM_STATE_CARD_RESTRICTED
+     * @see #SIM_STATE_PRESENT
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimState int getSimCardState(int physicalSlotIndex, int portIndex) {
+        int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, portIndex));
+        return getSimCardStateFromSimState(simState);
+    }
+    /**
      * Converts SIM state to SIM card state.
      * @param simState
      * @return SIM card state
@@ -3503,13 +3528,19 @@
     /**
      * Converts a physical slot index to logical slot index.
      * @param physicalSlotIndex physical slot index
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     *                  Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
      * @return logical slot index
      */
-    private int getLogicalSlotIndex(int physicalSlotIndex) {
+    private int getLogicalSlotIndex(int physicalSlotIndex, int portIndex) {
         UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
         if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length
                 && slotInfos[physicalSlotIndex] != null) {
-            return slotInfos[physicalSlotIndex].getLogicalSlotIdx();
+            for (UiccPortInfo portInfo : slotInfos[physicalSlotIndex].getPorts()) {
+                if (portInfo.getPortIndex() == portIndex) {
+                    return portInfo.getLogicalSlotIndex();
+                }
+            }
         }
 
         return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
@@ -3549,12 +3580,42 @@
      * @see #SIM_STATE_LOADED
      *
      * @hide
+     * @deprecated instead use {@link #getSimApplicationState(int, int)}
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @Deprecated
     public @SimState int getSimApplicationState(int physicalSlotIndex) {
         int simState =
-                SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex));
+                SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+                        DEFAULT_PORT_INDEX));
+        return getSimApplicationStateFromSimState(simState);
+    }
+
+    /**
+     * Returns a constant indicating the state of the card applications on the device SIM card in
+     * a physical slot.
+     *
+     * @param physicalSlotIndex physical slot index
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     *                  Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_PIN_REQUIRED
+     * @see #SIM_STATE_PUK_REQUIRED
+     * @see #SIM_STATE_NETWORK_LOCKED
+     * @see #SIM_STATE_NOT_READY
+     * @see #SIM_STATE_PERM_DISABLED
+     * @see #SIM_STATE_LOADED
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimState int getSimApplicationState(int physicalSlotIndex, int portIndex) {
+        int simState =
+                SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+                        portIndex));
         return getSimApplicationStateFromSimState(simState);
     }
 
@@ -4153,18 +4214,21 @@
      * should be {@link #getPhoneCount()} if success, otherwise return an empty map.
      *
      * @hide
+     * @deprecated use {@link #getSimSlotMapping()} instead.
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @NonNull
+    @Deprecated
     public Map<Integer, Integer> getLogicalToPhysicalSlotMapping() {
         Map<Integer, Integer> slotMapping = new HashMap<>();
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                int[] slotMappingArray = telephony.getSlotsMapping(mContext.getOpPackageName());
-                for (int i = 0; i < slotMappingArray.length; i++) {
-                    slotMapping.put(i, slotMappingArray[i]);
+                List<UiccSlotMapping> simSlotsMapping = telephony.getSlotsMapping(
+                        mContext.getOpPackageName());
+                for (UiccSlotMapping slotMap : simSlotsMapping) {
+                    slotMapping.put(slotMap.getLogicalSlotIndex(), slotMap.getPhysicalSlotIndex());
                 }
             }
         } catch (RemoteException e) {
@@ -4173,6 +4237,33 @@
         return slotMapping;
     }
 
+    /**
+     * Get the mapping from logical slots to physical sim slots and port indexes. Initially the
+     * logical slot index was mapped to physical slot index, but with support for multi-enabled
+     * profile(MEP) logical slot is now mapped to port index.
+     *
+     * @return a collection of {@link UiccSlotMapping} which indicates the mapping from logical
+     *         slots to ports and physical slots.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @NonNull
+    public Collection<UiccSlotMapping> getSimSlotMapping() {
+        List<UiccSlotMapping> slotMap = new ArrayList<>();
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                slotMap = telephony.getSlotsMapping(mContext.getOpPackageName());
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+        return slotMap;
+    }
     //
     //
     // Subscriber Info
@@ -16138,6 +16229,8 @@
      * Callback to listen for when the set of packages with carrier privileges for a SIM changes.
      *
      * @hide
+     * @deprecated Use {@link CarrierPrivilegesCallback} instead. This API will be removed soon
+     * prior to API finalization.
      */
     @SystemApi
     public interface CarrierPrivilegesListener {
@@ -16158,6 +16251,54 @@
     }
 
     /**
+     * Callbacks to listen for when the set of packages with carrier privileges for a SIM changes.
+     *
+     * <p>Of note, when multiple callbacks are registered, they may be triggered one after another.
+     * The ordering of them is not guaranteed and thus should not be depend on.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface CarrierPrivilegesCallback {
+        /**
+         * Called when the set of packages with carrier privileges has changed.
+         *
+         * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+         * switch and the same set of packages remains privileged after the switch.
+         *
+         * <p>At registration, the callback will receive the current set of privileged packages.
+         *
+         * @param privilegedPackageNames The updated set of package names that have carrier
+         *                               privileges
+         * @param privilegedUids         The updated set of UIDs that have carrier privileges
+         */
+        void onCarrierPrivilegesChanged(
+                @NonNull Set<String> privilegedPackageNames, @NonNull Set<Integer> privilegedUids);
+
+        /**
+         * Called when the {@link CarrierService} for the current user profile has changed.
+         *
+         * <p>This method does nothing by default. Clients that are interested in the carrier
+         * service change should override this method to get package name and UID info.
+         *
+         * <p>At registration, the callback will receive the current carrier service info.
+         *
+         * <p>Of note, this callback will <b>not</b> be fired if a carrier triggers a SIM profile
+         * switch and the same carrier service remains after switch.
+         *
+         * @param carrierServicePackageName package name of the {@link CarrierService}. May be
+         *                                  {@code null} when no carrier service is detected.
+         * @param carrierServiceUid         UID of the {@link CarrierService}. May be
+         *                                  {@link android.os.Process#INVALID_UID} if no carrier
+         *                                  service is detected.
+         */
+        default void onCarrierServiceChanged(
+                @Nullable String carrierServicePackageName, int carrierServiceUid) {
+            // do nothing by default
+        }
+    }
+
+    /**
      * Registers a {@link CarrierPrivilegesListener} on the given {@code logicalSlotIndex} to
      * receive callbacks when the set of packages with carrier privileges changes. The callback will
      * immediately be called with the latest state.
@@ -16166,7 +16307,10 @@
      * @param executor The executor where {@code listener} will be invoked
      * @param listener The callback to register
      * @hide
+     * @deprecated Use {@link #registerCarrierPrivilegesCallback} instead. This API will be
+     * removed prior to API finalization.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void addCarrierPrivilegesListener(
@@ -16190,7 +16334,10 @@
      * Unregisters an existing {@link CarrierPrivilegesListener}.
      *
      * @hide
+     * @deprecated Use {@link #unregisterCarrierPrivilegesCallback} instead. This API will be
+     * removed prior to API finalization.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public void removeCarrierPrivilegesListener(@NonNull CarrierPrivilegesListener listener) {
@@ -16205,4 +16352,36 @@
         }
         mTelephonyRegistryMgr.removeCarrierPrivilegesListener(listener);
     }
+
+    /**
+     * Registers a {@link CarrierPrivilegesCallback} on the given {@code logicalSlotIndex} to
+     * receive callbacks when the set of packages with carrier privileges changes. The callback will
+     * immediately be called with the latest state.
+     *
+     * @param logicalSlotIndex The SIM slot to listen on
+     * @param executor The executor where {@code callback} will be invoked
+     * @param callback The callback to register
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void registerCarrierPrivilegesCallback(
+            int logicalSlotIndex,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull CarrierPrivilegesCallback callback) {
+        // TODO(b/216549778): cherry-pick implementation once merge conflict is resolved
+        throw new UnsupportedOperationException("Not implemented, yet");
+    }
+
+    /**
+     * Unregisters an existing {@link CarrierPrivilegesCallback}.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public void unregisterCarrierPrivilegesCallback(@NonNull CarrierPrivilegesCallback callback) {
+        // TODO(b/216549778): cherry-pick implementation once merge conflict is resolved
+        throw new UnsupportedOperationException("Not implemented, yet");
+    }
 }
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index f854020..281b018 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1272,24 +1272,34 @@
      */
     public boolean similar(ApnSetting other) {
         return (!this.canHandleType(TYPE_DUN)
-            && !other.canHandleType(TYPE_DUN)
-            && Objects.equals(this.mApnName, other.mApnName)
-            && !typeSameAny(this, other)
-            && xorEqualsString(this.mProxyAddress, other.mProxyAddress)
-            && xorEqualsInt(this.mProxyPort, other.mProxyPort)
-            && xorEquals(this.mProtocol, other.mProtocol)
-            && xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
-            && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
-            && Objects.equals(this.mProfileId, other.mProfileId)
-            && Objects.equals(this.mMvnoType, other.mMvnoType)
-            && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
-            && xorEquals(this.mMmsc, other.mMmsc)
-            && xorEqualsString(this.mMmsProxyAddress, other.mMmsProxyAddress)
-            && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
-            && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
-            && Objects.equals(mApnSetId, other.mApnSetId)
-            && Objects.equals(mCarrierId, other.mCarrierId)
-            && Objects.equals(mSkip464Xlat, other.mSkip464Xlat);
+                && !other.canHandleType(TYPE_DUN)
+                && Objects.equals(this.mApnName, other.mApnName)
+                && xorEqualsString(this.mProxyAddress, other.mProxyAddress)
+                && xorEqualsInt(this.mProxyPort, other.mProxyPort)
+                && xorEquals(this.mMmsc, other.mMmsc)
+                && xorEqualsString(this.mMmsProxyAddress, other.mMmsProxyAddress)
+                && xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
+                && xorEqualsString(this.mUser, other.mUser)
+                && xorEqualsString(this.mPassword, other.mPassword)
+                && xorEqualsInt(this.mAuthType, other.mAuthType)
+                && !typeSameAny(this, other)
+                && Objects.equals(this.mOperatorNumeric, other.mOperatorNumeric)
+                && Objects.equals(this.mProtocol, other.mProtocol)
+                && Objects.equals(this.mRoamingProtocol, other.mRoamingProtocol)
+                && xorEqualsInt(this.mMtuV4, other.mMtuV4)
+                && xorEqualsInt(this.mMtuV6, other.mMtuV6)
+                && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
+                && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
+                && Objects.equals(this.mLingeringNetworkTypeBitmask,
+                other.mLingeringNetworkTypeBitmask)
+                && Objects.equals(this.mProfileId, other.mProfileId)
+                && Objects.equals(this.mPersistent, other.mPersistent)
+                && Objects.equals(this.mMvnoType, other.mMvnoType)
+                && Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
+                && Objects.equals(this.mApnSetId, other.mApnSetId)
+                && Objects.equals(this.mCarrierId, other.mCarrierId)
+                && Objects.equals(this.mSkip464Xlat, other.mSkip464Xlat)
+                && Objects.equals(this.mAlwaysOn, other.mAlwaysOn);
     }
 
     // Equal or one is null.
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index ec04c1a..0b361dc 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -26,10 +26,10 @@
 import android.net.NetworkCapabilities;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.Annotation.ApnType;
 import android.telephony.Annotation.NetCapability;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyManager.NetworkTypeBitMask;
+import android.telephony.data.ApnSetting.ApnType;
 import android.telephony.data.ApnSetting.AuthType;
 import android.text.TextUtils;
 
@@ -245,8 +245,7 @@
      * @return The supported APN types bitmask.
      * @deprecated Use {@link #getApnSetting()} and {@link ApnSetting#getApnTypeBitmask()} instead.
      */
-    @Deprecated
-    public @ApnType int getSupportedApnTypesBitmask() {
+    @Deprecated public @ApnType int getSupportedApnTypesBitmask() {
         if (mApnSetting != null) {
             return mApnSetting.getApnTypeBitmask();
         }
@@ -425,6 +424,12 @@
                 return ApnSetting.TYPE_MCX;
             case NetworkCapabilities.NET_CAPABILITY_IA:
                 return ApnSetting.TYPE_IA;
+            case NetworkCapabilities.NET_CAPABILITY_BIP:
+                return ApnSetting.TYPE_BIP;
+            case NetworkCapabilities.NET_CAPABILITY_VSIM:
+                return ApnSetting.TYPE_VSIM;
+            case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE:
+                return ApnSetting.TYPE_ENTERPRISE;
             default:
                 return ApnSetting.TYPE_NONE;
         }
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 13d8c7b..ec73471 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -253,8 +253,10 @@
                 return "RESULT_ERROR_BUSY";
             case RESULT_ERROR_ILLEGAL_STATE:
                 return "RESULT_ERROR_ILLEGAL_STATE";
+            case RESULT_ERROR_TEMPORARILY_UNAVAILABLE:
+                return "RESULT_ERROR_TEMPORARILY_UNAVAILABLE";
             default:
-                return "Missing case for result code=" + resultCode;
+                return "Unknown(" + resultCode + ")";
         }
     }
 
diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java
index 2178fc1..66dcf8f 100644
--- a/telephony/java/android/telephony/data/TrafficDescriptor.java
+++ b/telephony/java/android/telephony/data/TrafficDescriptor.java
@@ -21,8 +21,13 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.Arrays;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
 import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for UE Route Selection
@@ -31,24 +36,215 @@
  * not specify the end point to be used for the data call.
  */
 public final class TrafficDescriptor implements Parcelable {
+    /**
+     * The OS/App id
+     *
+     * @hide
+     */
+    public static final class OsAppId {
+        /**
+         * OSId for "Android", using UUID version 5 with namespace ISO OSI.
+         * Prepended to the OsAppId in TrafficDescriptor to use for URSP matching.
+         */
+        public static final UUID ANDROID_OS_ID =
+                UUID.fromString("97a498e3-fc92-5c94-8986-0333d06e4e47");
+
+        /**
+         * Allowed app ids.
+         */
+        // The following app ids are the only apps id Android supports. OEMs or vendors are
+        // prohibited to modify/extend the allowed list, especially passing the real package name to
+        // the network.
+        private static final Set<String> ALLOWED_APP_IDS = Set.of(
+                "ENTERPRISE", "PRIORITIZE_LATENCY", "PRIORITIZE_BANDWIDTH", "CBS"
+        );
+
+        /** OS id in UUID format. */
+        private final @NonNull UUID mOsId;
+
+        /**
+         * App id in string format. Note that Android will not allow use specific app id. This must
+         * be a category/capability identifier.
+         */
+        private final @NonNull String mAppId;
+
+        /**
+         * The differentiator when multiple traffic descriptor has the same OS and app id. Must be
+         * greater than 1.
+         */
+        private final int mDifferentiator;
+
+        /**
+         * Constructor
+         *
+         * @param osId OS id in UUID format.
+         * @param appId App id in string format. Note that Android will not allow use specific app
+         * id. This must be a category/capability identifier.
+         */
+        public OsAppId(@NonNull UUID osId, @NonNull String appId) {
+            this(osId, appId, 1);
+        }
+
+        /**
+         * Constructor
+         *
+         * @param osId OS id in UUID format.
+         * @param appId App id in string format. Note that Android will not allow use specific app
+         * id. This must be a category/capability identifier.
+         * @param differentiator The differentiator when multiple traffic descriptor has the same
+         * OS and app id. Must be greater than 0.
+         */
+        public OsAppId(@NonNull UUID osId, @NonNull String appId, int differentiator) {
+            Objects.requireNonNull(osId);
+            Objects.requireNonNull(appId);
+            if (differentiator < 1) {
+                throw new IllegalArgumentException("Invalid differentiator " + differentiator);
+            }
+
+            mOsId = osId;
+            mAppId = appId;
+            mDifferentiator = differentiator;
+        }
+
+        /**
+         * Constructor from raw byte array.
+         *
+         * @param rawOsAppId The raw OS/App id.
+         */
+        public OsAppId(@NonNull byte[] rawOsAppId) {
+            try {
+                ByteBuffer bb = ByteBuffer.wrap(rawOsAppId);
+                // OS id is the first 16 bytes.
+                mOsId = new UUID(bb.getLong(), bb.getLong());
+                // App id length is 1 byte.
+                int appIdLen = bb.get();
+                // The remaining is the app id + differentiator.
+                byte[] appIdAndDifferentiator = new byte[appIdLen];
+                bb.get(appIdAndDifferentiator, 0, appIdLen);
+                // Extract trailing numbers, for example, "ENTERPRISE", "ENTERPRISE3".
+                String appIdAndDifferentiatorStr = new String(appIdAndDifferentiator);
+                Pattern pattern = Pattern.compile("[^0-9]+([0-9]+)$");
+                Matcher matcher = pattern.matcher(new String(appIdAndDifferentiator));
+                if (matcher.find()) {
+                    mDifferentiator = Integer.parseInt(matcher.group(1));
+                    mAppId = appIdAndDifferentiatorStr.replace(matcher.group(1), "");
+                } else {
+                    mDifferentiator = 1;
+                    mAppId = appIdAndDifferentiatorStr;
+                }
+            } catch (Exception e) {
+                throw new IllegalArgumentException("Failed to decode " + (rawOsAppId != null
+                        ? new BigInteger(1, rawOsAppId).toString(16) : null));
+            }
+        }
+
+        /**
+         * @return The OS id in UUID format.
+         */
+        public @NonNull UUID getOsId() {
+            return mOsId;
+        }
+
+        /**
+         * @return App id in string format. Note that Android will not allow use specific app id.
+         * This must be a category/capability identifier.
+         */
+        public @NonNull String getAppId() {
+            return mAppId;
+        }
+
+        /**
+         * @return The differentiator when multiple traffic descriptor has the same OS and app id.
+         * Must be greater than 1.
+         */
+        public int getDifferentiator() {
+            return mDifferentiator;
+        }
+
+        /**
+         * @return OS/App id in raw byte format.
+         */
+        public @NonNull byte[] getBytes() {
+            byte[] osAppId = (mAppId + (mDifferentiator > 1 ? mDifferentiator : "")).getBytes();
+            // 16 bytes for UUID, 1 byte for length of osAppId, and up to 255 bytes for osAppId
+            ByteBuffer bb = ByteBuffer.allocate(16 + 1 + osAppId.length);
+            bb.putLong(mOsId.getMostSignificantBits());
+            bb.putLong(mOsId.getLeastSignificantBits());
+            bb.put((byte) osAppId.length);
+            bb.put(osAppId);
+            return bb.array();
+        }
+
+        @Override
+        public String toString() {
+            return "[OsAppId: OS=" + mOsId + ", App=" + mAppId + ", differentiator="
+                    + mDifferentiator + ", raw="
+                    + new BigInteger(1, getBytes()).toString(16) + "]";
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            OsAppId osAppId = (OsAppId) o;
+            return mDifferentiator == osAppId.mDifferentiator && mOsId.equals(osAppId.mOsId)
+                    && mAppId.equals(osAppId.mAppId);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mOsId, mAppId, mDifferentiator);
+        }
+    }
+
     private final String mDnn;
-    private final byte[] mOsAppId;
+    private final OsAppId mOsAppId;
 
     private TrafficDescriptor(@NonNull Parcel in) {
         mDnn = in.readString();
-        mOsAppId = in.createByteArray();
+        byte[] osAppIdBytes = in.createByteArray();
+        OsAppId osAppId = null;
+        if (osAppIdBytes != null) {
+            osAppId = new OsAppId(osAppIdBytes);
+        }
+        mOsAppId = osAppId;
+
+        enforceAllowedIds();
     }
 
     /**
      * Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2
      * @param dnn optional DNN, which must be used for traffic matching, if present
-     * @param osAppId OsId + osAppId of the traffic descriptor
+     * @param osAppIdRawBytes Raw bytes of OsId + osAppId of the traffic descriptor
      *
      * @hide
      */
-    public TrafficDescriptor(String dnn, byte[] osAppId) {
+    public TrafficDescriptor(String dnn, @Nullable byte[] osAppIdRawBytes) {
         mDnn = dnn;
+        OsAppId osAppId = null;
+        if (osAppIdRawBytes != null) {
+            osAppId = new OsAppId(osAppIdRawBytes);
+        }
         mOsAppId = osAppId;
+
+        enforceAllowedIds();
+    }
+
+    /**
+     * Enforce the OS id and app id are in the allowed list.
+     *
+     * @throws IllegalArgumentException if ids are not allowed.
+     */
+    private void enforceAllowedIds() {
+        if (mOsAppId != null && !mOsAppId.getOsId().equals(OsAppId.ANDROID_OS_ID)) {
+            throw new IllegalArgumentException("OS id " + mOsAppId.getOsId() + " does not match "
+                    + OsAppId.ANDROID_OS_ID);
+        }
+
+        if (mOsAppId != null && !OsAppId.ALLOWED_APP_IDS.contains(mOsAppId.getAppId())) {
+            throw new IllegalArgumentException("Illegal app id " + mOsAppId.getAppId()
+                    + ". Only allowing one of the following " + OsAppId.ALLOWED_APP_IDS);
+        }
     }
 
     /**
@@ -61,13 +257,13 @@
     }
 
     /**
-     * OsAppId is the app id as defined in 3GPP TS 24.526 Section 5.2, and it identifies a traffic
-     * category. It includes the OS Id component of the field as defined in the specs.
-     * @return the OS App ID of this traffic descriptor if one is included by the network, null
-     * otherwise.
+     * OsAppId identifies a broader traffic category. Although it names Os/App id, it only includes
+     * OS version with a general/broader category id used as app id.
+     *
+     * @return The id in byte format. {@code null} if not available.
      */
     public @Nullable byte[] getOsAppId() {
-        return mOsAppId;
+        return mOsAppId != null ? mOsAppId.getBytes() : null;
     }
 
     @Override
@@ -77,13 +273,13 @@
 
     @NonNull @Override
     public String toString() {
-        return "TrafficDescriptor={mDnn=" + mDnn + ", mOsAppId=" + mOsAppId + "}";
+        return "TrafficDescriptor={mDnn=" + mDnn + ", " + mOsAppId + "}";
     }
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeString(mDnn);
-        dest.writeByteArray(mOsAppId);
+        dest.writeByteArray(mOsAppId != null ? mOsAppId.getBytes() : null);
     }
 
     public static final @NonNull Parcelable.Creator<TrafficDescriptor> CREATOR =
@@ -104,7 +300,7 @@
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         TrafficDescriptor that = (TrafficDescriptor) o;
-        return Objects.equals(mDnn, that.mDnn) && Arrays.equals(mOsAppId, that.mOsAppId);
+        return Objects.equals(mDnn, that.mDnn) && Objects.equals(mOsAppId, that.mOsAppId);
     }
 
     @Override
@@ -148,7 +344,7 @@
         }
 
         /**
-         * Set the OS App ID (including OS Id as defind in the specs).
+         * Set the OS App ID (including OS Id as defined in the specs).
          *
          * @return The same instance of the builder.
          */
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 683bb92..82d64ab 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -618,9 +618,9 @@
 
         ITelephony iTelephony = getITelephony();
         if (iTelephony == null) {
-            throw new RuntimeException("Could not find Telephony Service.");
+            Log.w("ImsMmTelManager", "Could not find Telephony Service.");
+            return;
         }
-
         try {
             iTelephony.unregisterMmTelCapabilityCallback(mSubId, c.getBinder());
         } catch (RemoteException e) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 0ac7cf9..e1da407 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2153,9 +2153,9 @@
              String callingFeatureId);
 
     /**
-     * Get the mapping from logical slots to physical slots.
+     * Get the mapping from logical slots to port index.
      */
-    int[] getSlotsMapping(String callingPackage);
+    List<UiccSlotMapping> getSlotsMapping(String callingPackage);
 
     /**
      * Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown
diff --git a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
index 35f1e58..644d450 100644
--- a/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
+++ b/tests/BandwidthTests/src/com/android/tests/bandwidthenforcement/BandwidthEnforcementTestService.java
@@ -24,6 +24,8 @@
 import android.os.Environment;
 import android.util.Log;
 
+import libcore.io.Streams;
+
 import java.io.BufferedWriter;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -37,8 +39,6 @@
 import java.net.URL;
 import java.util.Random;
 
-import libcore.io.Streams;
-
 /*
  * Test Service that tries to connect to the web via different methods and outputs the results to
  * the log and a output file.
@@ -146,7 +146,7 @@
         final ConnectivityManager mCM = context.getSystemService(ConnectivityManager.class);
         final Network network = mCM.getActiveNetwork();
 
-        if (client.requestTime("0.pool.ntp.org", 10000, network)) {
+        if (client.requestTime("0.pool.ntp.org", SntpClient.STANDARD_NTP_PORT, 10000, network)) {
             return true;
         }
         return false;
diff --git a/tests/SoundTriggerTestApp/OWNERS b/tests/SoundTriggerTestApp/OWNERS
index 816bc6b..9db19a3 100644
--- a/tests/SoundTriggerTestApp/OWNERS
+++ b/tests/SoundTriggerTestApp/OWNERS
@@ -1 +1,2 @@
 include /core/java/android/media/soundtrigger/OWNERS
+mdooley@google.com