Merge "Import translations. DO NOT MERGE" into stage-aosp-master
diff --git a/api/current.txt b/api/current.txt
index 2648394..514f608 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -29160,7 +29160,7 @@
     method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int);
     method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int);
     method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier);
-    method @NonNull public android.net.NetworkCapabilities setOwnerUid(int);
+    method public void setOwnerUid(int);
     method @NonNull public android.net.NetworkCapabilities setSignalStrength(int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
@@ -43685,7 +43685,7 @@
     field public static final int DIRECTION_INCOMING = 0; // 0x0
     field public static final int DIRECTION_OUTGOING = 1; // 0x1
     field public static final int DIRECTION_UNKNOWN = -1; // 0xffffffff
-    field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200
+    field public static final int PROPERTY_ASSISTED_DIALING = 512; // 0x200
     field public static final int PROPERTY_CONFERENCE = 1; // 0x1
     field public static final int PROPERTY_EMERGENCY_CALLBACK_MODE = 4; // 0x4
     field public static final int PROPERTY_ENTERPRISE_CALL = 32; // 0x20
@@ -43774,7 +43774,8 @@
     method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
     method public final int getConnectionCapabilities();
     method public final int getConnectionProperties();
-    method public final long getConnectionTime();
+    method public final long getConnectionStartElapsedRealtimeMillis();
+    method @IntRange(from=0) public final long getConnectionTime();
     method public final java.util.List<android.telecom.Connection> getConnections();
     method public final android.telecom.DisconnectCause getDisconnectCause();
     method public final android.os.Bundle getExtras();
@@ -43804,8 +43805,9 @@
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConnectionCapabilities(int);
     method public final void setConnectionProperties(int);
-    method public final void setConnectionStartElapsedRealTime(long);
-    method public final void setConnectionTime(long);
+    method @Deprecated public final void setConnectionStartElapsedRealTime(long);
+    method public final void setConnectionStartElapsedRealtimeMillis(long);
+    method public final void setConnectionTime(@IntRange(from=0) long);
     method public final void setDialing();
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setExtras(@Nullable android.os.Bundle);
@@ -43965,7 +43967,7 @@
     field public static final String EXTRA_IS_RTT_AUDIO_PRESENT = "android.telecom.extra.IS_RTT_AUDIO_PRESENT";
     field public static final String EXTRA_LAST_FORWARDED_NUMBER = "android.telecom.extra.LAST_FORWARDED_NUMBER";
     field public static final String EXTRA_SIP_INVITE = "android.telecom.extra.SIP_INVITE";
-    field public static final int PROPERTY_ASSISTED_DIALING_USED = 512; // 0x200
+    field public static final int PROPERTY_ASSISTED_DIALING = 512; // 0x200
     field public static final int PROPERTY_HAS_CDMA_VOICE_PRIVACY = 32; // 0x20
     field public static final int PROPERTY_HIGH_DEF_AUDIO = 4; // 0x4
     field public static final int PROPERTY_IS_EXTERNAL_CALL = 16; // 0x10
@@ -45043,7 +45045,7 @@
     method @NonNull public abstract android.telephony.CellIdentity getCellIdentity();
     method @NonNull public abstract android.telephony.CellSignalStrength getCellSignalStrength();
     method @Deprecated public long getTimeStamp();
-    method public long getTimestampNanos();
+    method public long getTimestampMillis();
     method public boolean isRegistered();
     field public static final int CONNECTION_NONE = 0; // 0x0
     field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
@@ -45549,7 +45551,7 @@
     method @Deprecated public int getGsmBitErrorRate();
     method @Deprecated public int getGsmSignalStrength();
     method public int getLevel();
-    method public long getTimestampNanos();
+    method public long getTimestampMillis();
     method @Deprecated public boolean isGsm();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SignalStrength> CREATOR;
diff --git a/api/system-current.txt b/api/system-current.txt
index 2d1f228..469f367 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4368,7 +4368,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     method public void logEvent(int, @NonNull String);
-    method public void reevaluateNetwork();
+    method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork();
     method public void useNetwork();
     field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
@@ -4649,9 +4649,7 @@
     method @Nullable public String getSSID();
     method @NonNull public int[] getTransportTypes();
     method public boolean satisfiedByNetworkCapabilities(@Nullable android.net.NetworkCapabilities);
-    method @NonNull public android.net.NetworkCapabilities setAdministratorUids(@NonNull java.util.List<java.lang.Integer>);
-    method @NonNull public android.net.NetworkCapabilities setRequestorPackageName(@NonNull String);
-    method @NonNull public android.net.NetworkCapabilities setRequestorUid(int);
+    method public void setAdministratorUids(@NonNull java.util.List<java.lang.Integer>);
     method @NonNull public android.net.NetworkCapabilities setSSID(@Nullable String);
     method @NonNull public android.net.NetworkCapabilities setTransportInfo(@NonNull android.net.TransportInfo);
     field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
@@ -4703,8 +4701,6 @@
   }
 
   public class NetworkRequest implements android.os.Parcelable {
-    method @Nullable public String getRequestorPackageName();
-    method public int getRequestorUid();
     method public boolean satisfiedBy(@Nullable android.net.NetworkCapabilities);
   }
 
@@ -4739,6 +4735,7 @@
   }
 
   public abstract class NetworkSpecifier {
+    method public void assertValidFromUid(int);
     method @Nullable public android.net.NetworkSpecifier redact();
     method public abstract boolean satisfiedBy(@Nullable android.net.NetworkSpecifier);
   }
@@ -8256,27 +8253,26 @@
   public abstract class Conference extends android.telecom.Conferenceable {
     method @Deprecated public final android.telecom.AudioState getAudioState();
     method @Deprecated public final long getConnectTimeMillis();
-    method public final long getConnectionStartElapsedRealTime();
     method public android.telecom.Connection getPrimaryConnection();
     method @NonNull public final String getTelecomCallId();
     method @Deprecated public void onAudioStateChanged(android.telecom.AudioState);
-    method public final void setAddress(@NonNull android.net.Uri, int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setAddress(@NonNull android.net.Uri, int);
     method public final void setCallerDisplayName(@NonNull String, int);
-    method public void setConferenceState(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setConferenceState(boolean);
     method @Deprecated public final void setConnectTimeMillis(long);
   }
 
   public abstract class Connection extends android.telecom.Conferenceable {
     method @Deprecated public final android.telecom.AudioState getAudioState();
-    method public final long getConnectElapsedTimeMillis();
-    method public final long getConnectTimeMillis();
+    method @IntRange(from=0) public final long getConnectTimeMillis();
+    method public final long getConnectionStartElapsedRealtimeMillis();
     method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
     method @Nullable public final String getTelecomCallId();
     method @Deprecated public void onAudioStateChanged(android.telecom.AudioState);
     method public final void resetConnectionTime();
     method public void setCallDirection(int);
-    method public final void setConnectTimeMillis(long);
-    method public final void setConnectionStartElapsedRealTime(long);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectionStartElapsedRealtimeMillis(long);
     method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
     method public void setTelecomCallId(@NonNull String);
     field public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 2097152; // 0x200000
@@ -8428,7 +8424,7 @@
   }
 
   public static class PhoneAccount.Builder {
-    method @NonNull public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String);
   }
 
   public class PhoneAccountSuggestionService extends android.app.Service {
@@ -8503,7 +8499,7 @@
     method public int getCallState();
     method public android.telecom.PhoneAccountHandle getConnectionManager();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCurrentTtyMode();
-    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
     method @Deprecated public android.content.ComponentName getDefaultPhoneApp();
     method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsSupportingScheme(String);
diff --git a/api/test-current.txt b/api/test-current.txt
index a806b64..b3e80a9 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1398,7 +1398,7 @@
 
   public class CaptivePortal implements android.os.Parcelable {
     method public void logEvent(int, @NonNull String);
-    method public void reevaluateNetwork();
+    method @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void reevaluateNetwork();
     method public void useNetwork();
     field public static final int APP_REQUEST_REEVALUATION_REQUIRED = 100; // 0x64
     field public static final int APP_RETURN_DISMISSED = 0; // 0x0
@@ -3005,23 +3005,22 @@
   }
 
   public abstract class Conference extends android.telecom.Conferenceable {
-    method public final long getConnectionStartElapsedRealTime();
     method public android.telecom.Connection getPrimaryConnection();
     method @NonNull public final String getTelecomCallId();
-    method public final void setAddress(@NonNull android.net.Uri, int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setAddress(@NonNull android.net.Uri, int);
     method public final void setCallerDisplayName(@NonNull String, int);
-    method public void setConferenceState(boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setConferenceState(boolean);
   }
 
   public abstract class Connection extends android.telecom.Conferenceable {
-    method public final long getConnectElapsedTimeMillis();
-    method public final long getConnectTimeMillis();
+    method @IntRange(from=0) public final long getConnectTimeMillis();
+    method public final long getConnectionStartElapsedRealtimeMillis();
     method @Nullable public android.telecom.PhoneAccountHandle getPhoneAccountHandle();
     method @Nullable public final String getTelecomCallId();
     method public final void resetConnectionTime();
     method public void setCallDirection(int);
-    method public final void setConnectTimeMillis(long);
-    method public final void setConnectionStartElapsedRealTime(long);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectTimeMillis(@IntRange(from=0) long);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public final void setConnectionStartElapsedRealtimeMillis(long);
     method public void setPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
     method public void setTelecomCallId(@NonNull String);
     field public static final int CAPABILITY_CONFERENCE_HAS_NO_CHILDREN = 2097152; // 0x200000
@@ -3053,7 +3052,7 @@
   }
 
   public static class PhoneAccount.Builder {
-    method @NonNull public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telecom.PhoneAccount.Builder setGroupId(@NonNull String);
   }
 
   public class PhoneAccountSuggestionService extends android.app.Service {
@@ -3067,7 +3066,7 @@
   public class TelecomManager {
     method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts(boolean);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCurrentTtyMode();
-    method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDefaultDialerPackage(int);
+    method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDefaultDialerPackage(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean isInEmergencyCall();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUserSelectedOutgoingPhoneAccount(@Nullable android.telecom.PhoneAccountHandle);
     field public static final int TTY_MODE_FULL = 1; // 0x1
diff --git a/core/java/android/app/role/RoleManager.java b/core/java/android/app/role/RoleManager.java
index b9cda6c..2eb9459 100644
--- a/core/java/android/app/role/RoleManager.java
+++ b/core/java/android/app/role/RoleManager.java
@@ -89,6 +89,7 @@
      * The name of the dialer role.
      *
      * @see Intent#ACTION_DIAL
+     * @see android.telecom.InCallService
      */
     public static final String ROLE_DIALER = "android.app.role.DIALER";
 
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index fb35b4b..8afeb30 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -15,7 +15,9 @@
  */
 package android.net;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.IBinder;
@@ -23,6 +25,8 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
 /**
  * A class allowing apps handling the {@link ConnectivityManager#ACTION_CAPTIVE_PORTAL_SIGN_IN}
  * activity to indicate to the system different outcomes of captive portal sign in.  This class is
@@ -76,6 +80,17 @@
     private final IBinder mBinder;
 
     /** @hide */
+    @IntDef(value = {
+        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
+        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_DISMISSED,
+        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_UNWANTED,
+        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_WANTED_AS_IS,
+        MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR,
+    })
+    public @interface EventId {
+    }
+
+    /** @hide */
     public CaptivePortal(@NonNull IBinder binder) {
         mBinder = binder;
     }
@@ -153,6 +168,7 @@
      */
     @SystemApi
     @TestApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
     public void reevaluateNetwork() {
         try {
             ICaptivePortal.Stub.asInterface(mBinder).appRequest(APP_REQUEST_REEVALUATION_REQUIRED);
@@ -168,7 +184,7 @@
      */
     @SystemApi
     @TestApi
-    public void logEvent(int eventId, @NonNull String packageName) {
+    public void logEvent(@EventId int eventId, @NonNull String packageName) {
         try {
             ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
         } catch (RemoteException e) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index f24de88..94eda01 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3747,7 +3747,6 @@
         checkCallbackNotNull(callback);
         Preconditions.checkArgument(action == REQUEST || need != null, "null NetworkCapabilities");
         final NetworkRequest request;
-        final String callingPackageName = mContext.getOpPackageName();
         try {
             synchronized(sCallbacks) {
                 if (callback.networkRequest != null
@@ -3759,11 +3758,10 @@
                 Messenger messenger = new Messenger(handler);
                 Binder binder = new Binder();
                 if (action == LISTEN) {
-                    request = mService.listenForNetwork(
-                            need, messenger, binder, callingPackageName);
+                    request = mService.listenForNetwork(need, messenger, binder);
                 } else {
                     request = mService.requestNetwork(
-                            need, messenger, timeoutMs, binder, legacyType, callingPackageName);
+                            need, messenger, timeoutMs, binder, legacyType);
                 }
                 if (request != null) {
                     sCallbacks.put(request, callback);
@@ -4036,10 +4034,8 @@
             @NonNull PendingIntent operation) {
         printStackTrace();
         checkPendingIntentNotNull(operation);
-        final String callingPackageName = mContext.getOpPackageName();
         try {
-            mService.pendingRequestForNetwork(
-                    request.networkCapabilities, operation, callingPackageName);
+            mService.pendingRequestForNetwork(request.networkCapabilities, operation);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
@@ -4151,10 +4147,8 @@
             @NonNull PendingIntent operation) {
         printStackTrace();
         checkPendingIntentNotNull(operation);
-        final String callingPackageName = mContext.getOpPackageName();
         try {
-            mService.pendingListenForNetwork(
-                    request.networkCapabilities, operation, callingPackageName);
+            mService.pendingListenForNetwork(request.networkCapabilities, operation);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 3a55461..c871c45 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -166,19 +166,18 @@
             in int factorySerialNumber);
 
     NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
-            in Messenger messenger, int timeoutSec, in IBinder binder, int legacy,
-            String callingPackageName);
+            in Messenger messenger, int timeoutSec, in IBinder binder, int legacy);
 
     NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities,
-            in PendingIntent operation, String callingPackageName);
+            in PendingIntent operation);
 
     void releasePendingNetworkRequest(in PendingIntent operation);
 
     NetworkRequest listenForNetwork(in NetworkCapabilities networkCapabilities,
-            in Messenger messenger, in IBinder binder, String callingPackageName);
+            in Messenger messenger, in IBinder binder);
 
     void pendingListenForNetwork(in NetworkCapabilities networkCapabilities,
-            in PendingIntent operation, String callingPackageName);
+            in PendingIntent operation);
 
     void releaseNetworkRequest(in NetworkRequest networkRequest);
 
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index 09ec6c3..d83715c 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -51,7 +51,7 @@
  *
  * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create
  * transport mode security associations and apply them to individual sockets. Applications looking
- * to create a VPN should use {@link VpnService}.
+ * to create an IPsec VPN should use {@link VpnManager} and {@link Ikev2VpnProfile}.
  *
  * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
  *     Internet Protocol</a>
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index ef4a9e5..38f7390 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -27,7 +27,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Process;
-import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
@@ -64,16 +63,6 @@
     // Set to true when private DNS is broken.
     private boolean mPrivateDnsBroken;
 
-    /**
-     * Uid of the app making the request.
-     */
-    private int mRequestorUid;
-
-    /**
-     * Package name of the app making the request.
-     */
-    private String mRequestorPackageName;
-
     public NetworkCapabilities() {
         clearAll();
         mNetworkCapabilities = DEFAULT_CAPABILITIES;
@@ -100,8 +89,6 @@
         mOwnerUid = Process.INVALID_UID;
         mSSID = null;
         mPrivateDnsBroken = false;
-        mRequestorUid = Process.INVALID_UID;
-        mRequestorPackageName = null;
     }
 
     /**
@@ -122,8 +109,6 @@
         mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
         mSSID = nc.mSSID;
         mPrivateDnsBroken = nc.mPrivateDnsBroken;
-        mRequestorUid = nc.mRequestorUid;
-        mRequestorPackageName = nc.mRequestorPackageName;
     }
 
     /**
@@ -825,7 +810,7 @@
     }
 
     /**
-     * UID of the app that owns this network, or Process#INVALID_UID if none/unknown.
+     * UID of the app that owns this network, or INVALID_UID if none/unknown.
      *
      * <p>This field keeps track of the UID of the app that created this network and is in charge of
      * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running
@@ -836,9 +821,8 @@
     /**
      * Set the UID of the owner app.
      */
-    public @NonNull NetworkCapabilities setOwnerUid(final int uid) {
+    public void setOwnerUid(final int uid) {
         mOwnerUid = uid;
-        return this;
     }
 
     /**
@@ -881,11 +865,9 @@
      * @hide
      */
     @SystemApi
-    public @NonNull NetworkCapabilities setAdministratorUids(
-            @NonNull final List<Integer> administratorUids) {
+    public void setAdministratorUids(@NonNull final List<Integer> administratorUids) {
         mAdministratorUids.clear();
         mAdministratorUids.addAll(administratorUids);
-        return this;
     }
 
     /**
@@ -1403,7 +1385,6 @@
         combineSignalStrength(nc);
         combineUids(nc);
         combineSSIDs(nc);
-        combineRequestor(nc);
     }
 
     /**
@@ -1423,8 +1404,7 @@
                 && satisfiedBySpecifier(nc)
                 && (onlyImmutable || satisfiedBySignalStrength(nc))
                 && (onlyImmutable || satisfiedByUids(nc))
-                && (onlyImmutable || satisfiedBySSID(nc)))
-                && (onlyImmutable || satisfiedByRequestor(nc));
+                && (onlyImmutable || satisfiedBySSID(nc)));
     }
 
     /**
@@ -1508,7 +1488,7 @@
     public boolean equals(@Nullable Object obj) {
         if (obj == null || (obj instanceof NetworkCapabilities == false)) return false;
         NetworkCapabilities that = (NetworkCapabilities) obj;
-        return equalsNetCapabilities(that)
+        return (equalsNetCapabilities(that)
                 && equalsTransportTypes(that)
                 && equalsLinkBandwidths(that)
                 && equalsSignalStrength(that)
@@ -1516,8 +1496,7 @@
                 && equalsTransportInfo(that)
                 && equalsUids(that)
                 && equalsSSID(that)
-                && equalsPrivateDnsBroken(that)
-                && equalsRequestor(that);
+                && equalsPrivateDnsBroken(that));
     }
 
     @Override
@@ -1535,9 +1514,7 @@
                 + Objects.hashCode(mUids) * 31
                 + Objects.hashCode(mSSID) * 37
                 + Objects.hashCode(mTransportInfo) * 41
-                + Objects.hashCode(mPrivateDnsBroken) * 43
-                + Objects.hashCode(mRequestorUid) * 47
-                + Objects.hashCode(mRequestorPackageName) * 53;
+                + Objects.hashCode(mPrivateDnsBroken) * 43;
     }
 
     @Override
@@ -1560,8 +1537,6 @@
         dest.writeBoolean(mPrivateDnsBroken);
         dest.writeList(mAdministratorUids);
         dest.writeInt(mOwnerUid);
-        dest.writeInt(mRequestorUid);
-        dest.writeString(mRequestorPackageName);
     }
 
     public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1584,8 +1559,6 @@
                 netCap.mPrivateDnsBroken = in.readBoolean();
                 netCap.setAdministratorUids(in.readArrayList(null));
                 netCap.mOwnerUid = in.readInt();
-                netCap.mRequestorUid = in.readInt();
-                netCap.mRequestorPackageName = in.readString();
                 return netCap;
             }
             @Override
@@ -1651,9 +1624,6 @@
             sb.append(" Private DNS is broken");
         }
 
-        sb.append(" RequestorUid: ").append(mRequestorUid);
-        sb.append(" RequestorPackageName: ").append(mRequestorPackageName);
-
         sb.append("]");
         return sb.toString();
     }
@@ -1662,7 +1632,6 @@
     private interface NameOf {
         String nameOf(int value);
     }
-
     /**
      * @hide
      */
@@ -1830,120 +1799,4 @@
     private boolean equalsPrivateDnsBroken(NetworkCapabilities nc) {
         return mPrivateDnsBroken == nc.mPrivateDnsBroken;
     }
-
-    /**
-     * Set the uid of the app making the request.
-     *
-     * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in
-     * via the public {@link ConnectivityManager} API's will have this field overwritten.
-     *
-     * @param uid UID of the app.
-     * @hide
-     */
-    @SystemApi
-    public @NonNull NetworkCapabilities setRequestorUid(int uid) {
-        mRequestorUid = uid;
-        return this;
-    }
-
-    /**
-     * @return the uid of the app making the request.
-     *
-     * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest}
-     * object was not obtained from {@link ConnectivityManager}.
-     * @hide
-     */
-    public int getRequestorUid() {
-        return mRequestorUid;
-    }
-
-    /**
-     * Set the package name of the app making the request.
-     *
-     * Note: This works only for {@link NetworkAgent} instances. Any capabilities passed in
-     * via the public {@link ConnectivityManager} API's will have this field overwritten.
-     *
-     * @param packageName package name of the app.
-     * @hide
-     */
-    @SystemApi
-    public @NonNull NetworkCapabilities setRequestorPackageName(@NonNull String packageName) {
-        mRequestorPackageName = packageName;
-        return this;
-    }
-
-    /**
-     * @return the package name of the app making the request.
-     *
-     * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained
-     * from {@link ConnectivityManager}.
-     * @hide
-     */
-    @Nullable
-    public String getRequestorPackageName() {
-        return mRequestorPackageName;
-    }
-
-    /**
-     * Set the uid and package name of the app making the request.
-     *
-     * Note: This is intended to be only invoked from within connectivitiy service.
-     *
-     * @param uid UID of the app.
-     * @param packageName package name of the app.
-     * @hide
-     */
-    public @NonNull NetworkCapabilities setRequestorUidAndPackageName(
-            int uid, @NonNull String packageName) {
-        return setRequestorUid(uid).setRequestorPackageName(packageName);
-    }
-
-    /**
-     * Test whether the passed NetworkCapabilities satisfies the requestor restrictions of this
-     * capabilities.
-     *
-     * This method is called on the NetworkCapabilities embedded in a request with the
-     * capabilities of an available network. If the available network, sets a specific
-     * requestor (by uid and optionally package name), then this will only match a request from the
-     * same app. If either of the capabilities have an unset uid or package name, then it matches
-     * everything.
-     * <p>
-     * nc is assumed nonnull. Else, NPE.
-     */
-    private boolean satisfiedByRequestor(NetworkCapabilities nc) {
-        // No uid set, matches everything.
-        if (mRequestorUid == Process.INVALID_UID || nc.mRequestorUid == Process.INVALID_UID) {
-            return true;
-        }
-        // uids don't match.
-        if (mRequestorUid != nc.mRequestorUid) return false;
-        // No package names set, matches everything
-        if (null == nc.mRequestorPackageName || null == mRequestorPackageName) return true;
-        // check for package name match.
-        return TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName);
-    }
-
-    /**
-     * Combine requestor info of the capabilities.
-     * <p>
-     * This is only legal if either the requestor info of this object is reset, or both info are
-     * equal.
-     * nc is assumed nonnull.
-     */
-    private void combineRequestor(@NonNull NetworkCapabilities nc) {
-        if (mRequestorUid != Process.INVALID_UID && mRequestorUid != nc.mOwnerUid) {
-            throw new IllegalStateException("Can't combine two uids");
-        }
-        if (mRequestorPackageName != null
-                && !mRequestorPackageName.equals(nc.mRequestorPackageName)) {
-            throw new IllegalStateException("Can't combine two package names");
-        }
-        setRequestorUid(nc.mRequestorUid);
-        setRequestorPackageName(nc.mRequestorPackageName);
-    }
-
-    private boolean equalsRequestor(NetworkCapabilities nc) {
-        return mRequestorUid == nc.mRequestorUid
-                && TextUtils.equals(mRequestorPackageName, nc.mRequestorPackageName);
-    }
 }
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index b0bf64e..ee4379a 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -380,7 +380,6 @@
         dest.writeInt(requestId);
         dest.writeString(type.name());
     }
-
     public static final @android.annotation.NonNull Creator<NetworkRequest> CREATOR =
         new Creator<NetworkRequest>() {
             public NetworkRequest createFromParcel(Parcel in) {
@@ -495,31 +494,6 @@
         return networkCapabilities.getNetworkSpecifier();
     }
 
-    /**
-     * @return the uid of the app making the request.
-     *
-     * Note: This could return {@link Process#INVALID_UID} if the {@link NetworkRequest} object was
-     * not obtained from {@link ConnectivityManager}.
-     * @hide
-     */
-    @SystemApi
-    public int getRequestorUid() {
-        return networkCapabilities.getRequestorUid();
-    }
-
-    /**
-     * @return the package name of the app making the request.
-     *
-     * Note: This could return {@code null} if the {@link NetworkRequest} object was not obtained
-     * from {@link ConnectivityManager}.
-     * @hide
-     */
-    @SystemApi
-    @Nullable
-    public String getRequestorPackageName() {
-        return networkCapabilities.getRequestorPackageName();
-    }
-
     public String toString() {
         return "NetworkRequest [ " + type + " id=" + requestId +
                 (legacyType != ConnectivityManager.TYPE_NONE ? ", legacyType=" + legacyType : "") +
diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java
index 2dd0c4e..cf31d21 100644
--- a/core/java/android/net/NetworkSpecifier.java
+++ b/core/java/android/net/NetworkSpecifier.java
@@ -39,6 +39,23 @@
 
     /**
      * Optional method which can be overridden by concrete implementations of NetworkSpecifier to
+     * check a self-reported UID. A concrete implementation may contain a UID which would be self-
+     * reported by the caller (since NetworkSpecifier implementations should be non-mutable). This
+     * function is called by ConnectivityService and is passed the actual UID of the caller -
+     * allowing the verification of the self-reported UID. In cases of mismatch the implementation
+     * should throw a SecurityException.
+     *
+     * @param requestorUid The UID of the requestor as obtained from its binder.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void assertValidFromUid(int requestorUid) {
+        // empty
+    }
+
+    /**
+     * Optional method which can be overridden by concrete implementations of NetworkSpecifier to
      * perform any redaction of information from the NetworkSpecifier, e.g. if it contains
      * sensitive information. The default implementation simply returns the object itself - i.e.
      * no information is redacted. A concrete implementation may return a modified (copy) of the
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 7b799e2..c82c288 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -548,32 +548,32 @@
         final int startIndex = getIndexAfter(end);
         for (int i = startIndex; i >= 0; i--) {
             final long curStart = bucketStart[i];
-            final long curEnd = curStart + bucketDuration;
+            long curEnd = curStart + bucketDuration;
 
             // bucket is older than request; we're finished
             if (curEnd <= start) break;
             // bucket is newer than request; keep looking
             if (curStart >= end) continue;
 
-            // include full value for active buckets, otherwise only fractional
-            final boolean activeBucket = curStart < now && curEnd > now;
-            final long overlap;
-            if (activeBucket) {
-                overlap = bucketDuration;
-            } else {
-                final long overlapEnd = curEnd < end ? curEnd : end;
-                final long overlapStart = curStart > start ? curStart : start;
-                overlap = overlapEnd - overlapStart;
-            }
+            // the active bucket is shorter then a normal completed bucket
+            if (curEnd > now) curEnd = now;
+            // usually this is simply bucketDuration
+            final long bucketSpan = curEnd - curStart;
+            // prevent division by zero
+            if (bucketSpan <= 0) continue;
+
+            final long overlapEnd = curEnd < end ? curEnd : end;
+            final long overlapStart = curStart > start ? curStart : start;
+            final long overlap = overlapEnd - overlapStart;
             if (overlap <= 0) continue;
 
             // integer math each time is faster than floating point
-            if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketDuration;
-            if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
-            if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
-            if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketDuration;
-            if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketDuration;
-            if (operations != null) entry.operations += operations[i] * overlap / bucketDuration;
+            if (activeTime != null) entry.activeTime += activeTime[i] * overlap / bucketSpan;
+            if (rxBytes != null) entry.rxBytes += rxBytes[i] * overlap / bucketSpan;
+            if (rxPackets != null) entry.rxPackets += rxPackets[i] * overlap / bucketSpan;
+            if (txBytes != null) entry.txBytes += txBytes[i] * overlap / bucketSpan;
+            if (txPackets != null) entry.txPackets += txPackets[i] * overlap / bucketSpan;
+            if (operations != null) entry.operations += operations[i] * overlap / bucketSpan;
         }
         return entry;
     }
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 25584f1..c5c26b0 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -175,11 +175,7 @@
     }
 
     /**
-     * Set whether tracing is enabled in this process.  Tracing is disabled shortly after Zygote
-     * initializes and re-enabled after processes fork from Zygote.  This is done because Zygote
-     * has no way to be notified about changes to the tracing tags, and if Zygote ever reads and
-     * caches the tracing tags, forked processes will inherit those stale tags.
-     *
+     * Set whether tracing is enabled in this process.
      * @hide
      */
     public static void setTracingEnabled(boolean enabled, int debugFlags) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c1c74dc..bcb6c0f 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -261,10 +261,8 @@
         int pid = nativeForkAndSpecialize(
                 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                 fdsToIgnore, startChildZygote, instructionSet, appDataDir);
-        // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
             Zygote.disableExecuteOnly(targetSdkVersion);
-            Trace.setTracingEnabled(true, runtimeFlags);
 
             // Note that this event ends at the end of handleChildProc,
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -309,9 +307,6 @@
         nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
                 niceName, startChildZygote, instructionSet, appDataDir);
 
-        // Enable tracing as soon as possible for the child process.
-        Trace.setTracingEnabled(true, runtimeFlags);
-
         // Note that this event ends at the end of handleChildProc.
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
 
@@ -367,11 +362,6 @@
                 uid, gid, gids, runtimeFlags, rlimits,
                 permittedCapabilities, effectiveCapabilities);
 
-        // Enable tracing as soon as we enter the system_server.
-        if (pid == 0) {
-            Trace.setTracingEnabled(true, runtimeFlags);
-        }
-
         // Set the Java Language thread priority to the default value for new apps.
         Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
 
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 348262e..1b81a06 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -908,10 +908,6 @@
             bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
 
             bootTimingsTraceLog.traceEnd(); // ZygoteInit
-            // Disable tracing so that forked processes do not inherit stale tracing tags from
-            // Zygote.
-            Trace.setTracingEnabled(false, 0);
-
 
             Zygote.initNativeState(isPrimaryZygote);
 
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredential.java b/identity/java/android/security/identity/CredstoreIdentityCredential.java
index c520331..7c0af6d 100644
--- a/identity/java/android/security/identity/CredstoreIdentityCredential.java
+++ b/identity/java/android/security/identity/CredstoreIdentityCredential.java
@@ -152,8 +152,8 @@
             derivedKey = Util.computeHkdf("HmacSha256", sharedSecret, salt, info, 32);
             mReaderSecretKey = new SecretKeySpec(derivedKey, "AES");
 
-            mEphemeralCounter = 0;
-            mReadersExpectedEphemeralCounter = 0;
+            mEphemeralCounter = 1;
+            mReadersExpectedEphemeralCounter = 1;
 
         } catch (NoSuchAlgorithmException e) {
             throw new RuntimeException("Error performing key agreement", e);
diff --git a/packages/CarrierDefaultApp/res/values-fa/strings.xml b/packages/CarrierDefaultApp/res/values-fa/strings.xml
index 70ad837..37a3de8 100644
--- a/packages/CarrierDefaultApp/res/values-fa/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-fa/strings.xml
@@ -10,7 +10,7 @@
     <!-- no translation found for no_data_notification_detail (3112125343857014825) -->
     <skip />
     <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"بدون اتصال داده دستگاه همراه"</string>
-    <string name="no_mobile_data_connection" msgid="544980465184147010">"‏افزودن طرح داده یا رومینگ ازطریق %s"</string>
+    <string name="no_mobile_data_connection" msgid="544980465184147010">"‏افزودن طرح داده یا فراگردی ازطریق %s"</string>
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"وضعیت داده تلفن همراه"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"ورود به سیستم شبکه تلفن همراه"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"شبکه‌ای که می‌خواهید به آن بپیوندید مشکلات امنیتی دارد."</string>
diff --git a/packages/CarrierDefaultApp/res/values-in/strings.xml b/packages/CarrierDefaultApp/res/values-in/strings.xml
index 01a9c60..f48d31f 100644
--- a/packages/CarrierDefaultApp/res/values-in/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-in/strings.xml
@@ -5,7 +5,7 @@
     <string name="android_system_label" msgid="2797790869522345065">"Operator Seluler"</string>
     <string name="portal_notification_id" msgid="5155057562457079297">"Data seluler telah habis"</string>
     <string name="no_data_notification_id" msgid="668400731803969521">"Data seluler telah dinonaktifkan"</string>
-    <string name="portal_notification_detail" msgid="2295729385924660881">"Tap untuk membuka situs web %s"</string>
+    <string name="portal_notification_detail" msgid="2295729385924660881">"Ketuk untuk membuka situs web %s"</string>
     <string name="no_data_notification_detail" msgid="3112125343857014825">"Hubungi penyedia layanan %s"</string>
     <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"Tidak ada sambungan data seluler"</string>
     <string name="no_mobile_data_connection" msgid="544980465184147010">"Tambahkan paket data atau roaming melalui %s"</string>
diff --git a/packages/CarrierDefaultApp/res/values-ky/strings.xml b/packages/CarrierDefaultApp/res/values-ky/strings.xml
index 066e8f6..199476f 100644
--- a/packages/CarrierDefaultApp/res/values-ky/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-ky/strings.xml
@@ -12,6 +12,6 @@
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"Мобилдик Интернеттин абалы"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"Мобилдик тармакка кирүү"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"Кошулайын деген тармагыңызда коопсуздук көйгөйлөрү бар."</string>
-    <string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, каттоо эсебине кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
+    <string name="ssl_error_example" msgid="6188711843183058764">"Мисалы, аккаунтка кирүү баракчасы көрсөтүлгөн уюмга таандык эмес болушу мүмкүн."</string>
     <string name="ssl_error_continue" msgid="1138548463994095584">"Баары бир серепчи аркылуу улантуу"</string>
 </resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
index 0ad921a..0623cb3 100644
--- a/packages/CompanionDeviceManager/res/values-ca/strings.xml
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4470785958457506021">"Aplicació Gestor de dispositius complementaris"</string>
+    <string name="app_label" msgid="4470785958457506021">"Gestor de dispositius complementaris"</string>
     <string name="chooser_title" msgid="4958797271463138976">"Enllaça amb &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt;"</string>
     <string name="confirmation_title" msgid="5683126664999349196">"Enllaça &lt;strong&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/strong&gt; amb &lt;strong&gt;<xliff:g id="DEVICE_NAME">%2$s</xliff:g>&lt;/strong&gt;"</string>
 </resources>
diff --git a/packages/FusedLocation/res/values-or/strings.xml b/packages/FusedLocation/res/values-or/strings.xml
index b95bc37..b50e63d 100644
--- a/packages/FusedLocation/res/values-or/strings.xml
+++ b/packages/FusedLocation/res/values-or/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="5379477904423203699">"ଫ୍ୟୁଜ୍‍ଡ୍‍ ଲୋକେଶନ୍‍"</string>
+    <string name="app_label" msgid="5379477904423203699">"ଫ୍ୟୁଜ୍‍ଡ୍‍ ଲୋକେସନ୍‍"</string>
 </resources>
diff --git a/packages/InputDevices/res/values-ar/strings.xml b/packages/InputDevices/res/values-ar/strings.xml
index bc23b7a..b161c9a 100644
--- a/packages/InputDevices/res/values-ar/strings.xml
+++ b/packages/InputDevices/res/values-ar/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="8016145283189546017">"أجهزة إدخال بيانات"</string>
+    <string name="app_label" msgid="8016145283189546017">"أجهزة إدخال البيانات"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"‏لوحة مفاتيح Android"</string>
     <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"الإنجليزية (المملكة المتحدة)"</string>
     <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"الإنجليزية (الولايات المتحدة)"</string>
diff --git a/packages/InputDevices/res/values-el/strings.xml b/packages/InputDevices/res/values-el/strings.xml
index 05de3b7..b9d65c5 100644
--- a/packages/InputDevices/res/values-el/strings.xml
+++ b/packages/InputDevices/res/values-el/strings.xml
@@ -8,7 +8,7 @@
     <string name="keyboard_layout_english_us_intl" msgid="3705168594034233583">"Αγγλικά (ΗΠΑ), τύπου International"</string>
     <string name="keyboard_layout_english_us_colemak_label" msgid="4194969610343455380">"Αγγλικά (ΗΠΑ), τύπου Colemak"</string>
     <string name="keyboard_layout_english_us_dvorak_label" msgid="793528923171145202">"Αγγλικά (ΗΠΑ), τύπου Dvorak"</string>
-    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Αγγλικά (ΗΠΑ), στυλ Workman"</string>
+    <string name="keyboard_layout_english_us_workman_label" msgid="2944541595262173111">"Αγγλικά (ΗΠΑ), στιλ Workman"</string>
     <string name="keyboard_layout_german_label" msgid="8451565865467909999">"Γερμανικά"</string>
     <string name="keyboard_layout_french_label" msgid="813450119589383723">"Γαλλικά"</string>
     <string name="keyboard_layout_french_ca_label" msgid="365352601060604832">"Γαλλικά (Καναδά)"</string>
diff --git a/packages/InputDevices/res/values-hy/strings.xml b/packages/InputDevices/res/values-hy/strings.xml
index c7523e3..64ddf7a 100644
--- a/packages/InputDevices/res/values-hy/strings.xml
+++ b/packages/InputDevices/res/values-hy/strings.xml
@@ -40,7 +40,7 @@
     <string name="keyboard_layout_hebrew" msgid="7241473985890173812">"Եբրայերեն"</string>
     <string name="keyboard_layout_lithuanian" msgid="6943110873053106534">"Լիտվերեն"</string>
     <string name="keyboard_layout_spanish_latin" msgid="5690539836069535697">"Իսպաներեն (Լատինական)"</string>
-    <string name="keyboard_layout_latvian" msgid="4405417142306250595">"լատիշերեն"</string>
+    <string name="keyboard_layout_latvian" msgid="4405417142306250595">"լատվիերեն"</string>
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"պարսկերեն"</string>
     <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"ադրբեջաներեն"</string>
     <string name="keyboard_layout_polish" msgid="1121588624094925325">"լեհերեն"</string>
diff --git a/packages/InputDevices/res/values-pa/strings.xml b/packages/InputDevices/res/values-pa/strings.xml
index 1a977f4..a5ac9be 100644
--- a/packages/InputDevices/res/values-pa/strings.xml
+++ b/packages/InputDevices/res/values-pa/strings.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="8016145283189546017">"ਇਨਪੁਟ ਡਿਵਾਈਸਾਂ"</string>
+    <string name="app_label" msgid="8016145283189546017">"ਇਨਪੁੱਟ ਡੀਵਾਈਸਾਂ"</string>
     <string name="keyboard_layouts_label" msgid="6688773268302087545">"Android ਕੀ-ਬੋਰਡ"</string>
     <string name="keyboard_layout_english_uk_label" msgid="6664258463319999632">"ਅੰਗ੍ਰੇਜ਼ੀ (ਯੂਕੇ)"</string>
     <string name="keyboard_layout_english_us_label" msgid="8994890249649106291">"ਅੰਗ੍ਰੇਜੀ (ਅਮ੍ਰੀਕਾ)"</string>
diff --git a/packages/InputDevices/res/values-pl/strings.xml b/packages/InputDevices/res/values-pl/strings.xml
index 831e4b4..a54757a 100644
--- a/packages/InputDevices/res/values-pl/strings.xml
+++ b/packages/InputDevices/res/values-pl/strings.xml
@@ -43,5 +43,5 @@
     <string name="keyboard_layout_latvian" msgid="4405417142306250595">"łotewski"</string>
     <string name="keyboard_layout_persian" msgid="3920643161015888527">"Perski"</string>
     <string name="keyboard_layout_azerbaijani" msgid="7315895417176467567">"Azerski"</string>
-    <string name="keyboard_layout_polish" msgid="1121588624094925325">"polski"</string>
+    <string name="keyboard_layout_polish" msgid="1121588624094925325">"Polski"</string>
 </resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ar/strings.xml b/packages/MtpDocumentsProvider/res/values-ar/strings.xml
index 284a860..66adf32 100644
--- a/packages/MtpDocumentsProvider/res/values-ar/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-ar/strings.xml
@@ -17,9 +17,9 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="6271216747302322594">"‏مضيف بروتوكول نقل الوسائط (MTP)"</string>
-    <string name="downloads_app_label" msgid="7120690641874849726">"التنزيلات"</string>
+    <string name="downloads_app_label" msgid="7120690641874849726">"عمليات التنزيل"</string>
     <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
     <string name="accessing_notification_title" msgid="3030133609230917944">"جارٍ الوصول إلى الملفات من <xliff:g id="DEVICE_MODEL">%1$s</xliff:g>"</string>
     <string name="error_busy_device" msgid="3997316850357386589">"الجهاز الآخر مشغول، ولا يمكنك نقل الملفات إلا بعد أن يصبح متاحًا."</string>
-    <string name="error_locked_device" msgid="7557872102188356147">"لم يتم العثور على ملفات، وربما يكون الجهاز الآخر في وضع القفل. إذا كان الأمر كذلك، فعليك إلغاء قفله وإعادة المحاولة."</string>
+    <string name="error_locked_device" msgid="7557872102188356147">"لم يتم العثور على ملفات، وربما يكون الجهاز الآخر في وضع القفل. إذا كان الأمر كذلك، فعليك فتح قفله وإعادة المحاولة."</string>
 </resources>
diff --git a/packages/MtpDocumentsProvider/res/values-hi/strings.xml b/packages/MtpDocumentsProvider/res/values-hi/strings.xml
index bbd0ae7..e469fc0 100644
--- a/packages/MtpDocumentsProvider/res/values-hi/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-hi/strings.xml
@@ -19,7 +19,7 @@
     <string name="app_label" msgid="6271216747302322594">"MTP होस्ट"</string>
     <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string>
     <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
-    <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> से फ़ाइलें एक्सेस कर रहा है"</string>
+    <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> से फ़ाइलें ऐक्सेस कर रहा है"</string>
     <string name="error_busy_device" msgid="3997316850357386589">"दूसरा डिवाइस व्यस्त है. आप उसके उपलब्ध हो जाने तक फ़ाइलें ट्रांसफ़र नहीं कर सकते."</string>
     <string name="error_locked_device" msgid="7557872102188356147">"कोई फ़ाइल नहीं मिली. हो सकता है कि दूसरा डिवाइस लॉक हो. अगर ऐसा है, तो उसे अनलॉक करें और दोबारा कोशिश करें."</string>
 </resources>
diff --git a/packages/MtpDocumentsProvider/res/values-ja/strings.xml b/packages/MtpDocumentsProvider/res/values-ja/strings.xml
index 4ae59f5..72ab33d 100644
--- a/packages/MtpDocumentsProvider/res/values-ja/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-ja/strings.xml
@@ -20,6 +20,6 @@
     <string name="downloads_app_label" msgid="7120690641874849726">"ダウンロード"</string>
     <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
     <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> からファイルにアクセスしています"</string>
-    <string name="error_busy_device" msgid="3997316850357386589">"接続先の端末は使用中のため、利用できるようになるまでファイルを転送できません。"</string>
-    <string name="error_locked_device" msgid="7557872102188356147">"ファイルが見つかりません。接続先の端末がロックされている可能性があります。その場合は、ロックを解除してからもう一度お試しください。"</string>
+    <string name="error_busy_device" msgid="3997316850357386589">"接続先のデバイスは使用中のため、利用できるようになるまでファイルを転送できません。"</string>
+    <string name="error_locked_device" msgid="7557872102188356147">"ファイルが見つかりません。接続先のデバイスがロックされている可能性があります。その場合は、ロックを解除してからもう一度お試しください。"</string>
 </resources>
diff --git a/packages/MtpDocumentsProvider/res/values-mr/strings.xml b/packages/MtpDocumentsProvider/res/values-mr/strings.xml
index d581e10..983112c 100644
--- a/packages/MtpDocumentsProvider/res/values-mr/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values-mr/strings.xml
@@ -20,6 +20,6 @@
     <string name="downloads_app_label" msgid="7120690641874849726">"डाउनलोड"</string>
     <string name="root_name" msgid="5819495383921089536">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> <xliff:g id="STORAGE_NAME">%2$s</xliff:g>"</string>
     <string name="accessing_notification_title" msgid="3030133609230917944">"<xliff:g id="DEVICE_MODEL">%1$s</xliff:g> मधून फायलींंमध्ये प्रवेश करत आहे"</string>
-    <string name="error_busy_device" msgid="3997316850357386589">"दुसरे डिव्हाइस व्यस्त आहे. ते उपलब्‍ध होईपर्यंत तुम्ही फायली ट्रांसफर करू शकत नाही."</string>
+    <string name="error_busy_device" msgid="3997316850357386589">"दुसरे डिव्हाइस व्यस्त आहे. ते उपलब्‍ध होईपर्यंत तुम्ही फायली ट्रान्सफर करू शकत नाही."</string>
     <string name="error_locked_device" msgid="7557872102188356147">"कोणत्याही फायली आढळल्या नाहीत. दुसरे डिव्हाइस कदाचित बंद असू शकते. तसे असल्यास, ते अनलॉक करा आणि पुन्हा प्रयत्न करा."</string>
 </resources>
diff --git a/packages/PrintSpooler/res/values-ja/donottranslate.xml b/packages/PrintSpooler/res/values-ja/donottranslate.xml
index d334ddd..6a0f768 100644
--- a/packages/PrintSpooler/res/values-ja/donottranslate.xml
+++ b/packages/PrintSpooler/res/values-ja/donottranslate.xml
@@ -16,7 +16,7 @@
 
 <resources>
 
-    <string name="mediasize_default">JIS_B5</string>
+    <string name="mediasize_default">ISO_A4</string>
     <string name="mediasize_standard">@string/mediasize_standard_japan</string>
 
 </resources>
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
index 6514688..f5c9664 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
@@ -25,7 +25,7 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Objects;
 
@@ -83,7 +83,7 @@
      * @hide
      */
     public TetheredClient addAddresses(@NonNull TetheredClient other) {
-        final HashSet<AddressInfo> newAddresses = new HashSet<>(
+        final LinkedHashSet<AddressInfo> newAddresses = new LinkedHashSet<>(
                 mAddresses.size() + other.mAddresses.size());
         newAddresses.addAll(mAddresses);
         newAddresses.addAll(other.mAddresses);
diff --git a/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt b/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt
index 83c19ec..d85389a 100644
--- a/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt
+++ b/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt
@@ -75,7 +75,7 @@
         assertNotEquals(makeTestClient(), TetheredClient(
                 TEST_MACADDR,
                 listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
-                TETHERING_BLUETOOTH))
+                TETHERING_USB))
     }
 
     @Test
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 83d25f7..e2b8ad9 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -606,7 +606,7 @@
 
     private Set<String> mWolSupportedInterfaces;
 
-    private final TelephonyManager mTelephonyManager;
+    private TelephonyManager mTelephonyManager;
     private final AppOpsManager mAppOpsManager;
 
     private final LocationPermissionChecker mLocationPermissionChecker;
@@ -1166,7 +1166,6 @@
             int transportType, NetworkRequest.Type type) {
         final NetworkCapabilities netCap = new NetworkCapabilities();
         netCap.addCapability(NET_CAPABILITY_INTERNET);
-        netCap.setRequestorUidAndPackageName(Process.myUid(), mContext.getPackageName());
         if (transportType > -1) {
             netCap.addTransportType(transportType);
         }
@@ -1697,12 +1696,10 @@
         return newLp;
     }
 
-    private void restrictRequestUidsForCallerAndSetRequestorInfo(NetworkCapabilities nc,
-            int callerUid, String callerPackageName) {
+    private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
         if (!checkSettingsPermission()) {
-            nc.setSingleUid(callerUid);
+            nc.setSingleUid(Binder.getCallingUid());
         }
-        nc.setRequestorUidAndPackageName(callerUid, callerPackageName);
         nc.setAdministratorUids(Collections.EMPTY_LIST);
 
         // Clear owner UID; this can never come from an app.
@@ -3742,6 +3739,7 @@
             if (nm == null) return;
 
             if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) {
+                checkNetworkStackPermission();
                 nm.forceReevaluation(Binder.getCallingUid());
             }
         }
@@ -5307,7 +5305,7 @@
     // This checks that the passed capabilities either do not request a
     // specific SSID/SignalStrength, or the calling app has permission to do so.
     private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc,
-            int callerPid, int callerUid, String callerPackageName) {
+            int callerPid, int callerUid) {
         if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) {
             throw new SecurityException("Insufficient permissions to request a specific SSID");
         }
@@ -5317,7 +5315,6 @@
             throw new SecurityException(
                     "Insufficient permissions to request a specific signal strength");
         }
-        mAppOpsManager.checkPackage(callerUid, callerPackageName);
     }
 
     private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
@@ -5364,6 +5361,7 @@
             return;
         }
         MatchAllNetworkSpecifier.checkNotMatchAllNetworkSpecifier(ns);
+        ns.assertValidFromUid(Binder.getCallingUid());
     }
 
     private void ensureValid(NetworkCapabilities nc) {
@@ -5375,9 +5373,7 @@
 
     @Override
     public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
-            Messenger messenger, int timeoutMs, IBinder binder, int legacyType,
-            @NonNull String callingPackageName) {
-        final int callingUid = Binder.getCallingUid();
+            Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
         final NetworkRequest.Type type = (networkCapabilities == null)
                 ? NetworkRequest.Type.TRACK_DEFAULT
                 : NetworkRequest.Type.REQUEST;
@@ -5385,7 +5381,7 @@
         // the default network request. This allows callers to keep track of
         // the system default network.
         if (type == NetworkRequest.Type.TRACK_DEFAULT) {
-            networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
+            networkCapabilities = createDefaultNetworkCapabilitiesForUid(Binder.getCallingUid());
             enforceAccessPermission();
         } else {
             networkCapabilities = new NetworkCapabilities(networkCapabilities);
@@ -5397,14 +5393,13 @@
         }
         ensureRequestableCapabilities(networkCapabilities);
         ensureSufficientPermissionsForRequest(networkCapabilities,
-                Binder.getCallingPid(), callingUid, callingPackageName);
+                Binder.getCallingPid(), Binder.getCallingUid());
         // Set the UID range for this request to the single UID of the requester, or to an empty
         // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
         // This will overwrite any allowed UIDs in the requested capabilities. Though there
         // are no visible methods to set the UIDs, an app could use reflection to try and get
         // networks for other apps so it's essential that the UIDs are overwritten.
-        restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
-                callingUid, callingPackageName);
+        restrictRequestUidsForCaller(networkCapabilities);
 
         if (timeoutMs < 0) {
             throw new IllegalArgumentException("Bad timeout specified");
@@ -5479,18 +5474,16 @@
 
     @Override
     public NetworkRequest pendingRequestForNetwork(NetworkCapabilities networkCapabilities,
-            PendingIntent operation, @NonNull String callingPackageName) {
+            PendingIntent operation) {
         checkNotNull(operation, "PendingIntent cannot be null.");
-        final int callingUid = Binder.getCallingUid();
         networkCapabilities = new NetworkCapabilities(networkCapabilities);
         enforceNetworkRequestPermissions(networkCapabilities);
         enforceMeteredApnPolicy(networkCapabilities);
         ensureRequestableCapabilities(networkCapabilities);
         ensureSufficientPermissionsForRequest(networkCapabilities,
-                Binder.getCallingPid(), callingUid, callingPackageName);
+                Binder.getCallingPid(), Binder.getCallingUid());
         ensureValidNetworkSpecifier(networkCapabilities);
-        restrictRequestUidsForCallerAndSetRequestorInfo(networkCapabilities,
-                callingUid, callingPackageName);
+        restrictRequestUidsForCaller(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
@@ -5538,16 +5531,15 @@
 
     @Override
     public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
-            Messenger messenger, IBinder binder, @NonNull String callingPackageName) {
-        final int callingUid = Binder.getCallingUid();
+            Messenger messenger, IBinder binder) {
         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
             enforceAccessPermission();
         }
 
         NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
         ensureSufficientPermissionsForRequest(networkCapabilities,
-                Binder.getCallingPid(), callingUid, callingPackageName);
-        restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
+                Binder.getCallingPid(), Binder.getCallingUid());
+        restrictRequestUidsForCaller(nc);
         // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
         // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
         // onLost and onAvailable callbacks when networks move in and out of the background.
@@ -5567,17 +5559,17 @@
 
     @Override
     public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
-            PendingIntent operation, @NonNull String callingPackageName) {
+            PendingIntent operation) {
         checkNotNull(operation, "PendingIntent cannot be null.");
-        final int callingUid = Binder.getCallingUid();
         if (!hasWifiNetworkListenPermission(networkCapabilities)) {
             enforceAccessPermission();
         }
         ensureValid(networkCapabilities);
         ensureSufficientPermissionsForRequest(networkCapabilities,
-                Binder.getCallingPid(), callingUid, callingPackageName);
+                Binder.getCallingPid(), Binder.getCallingUid());
+
         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
-        restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
+        restrictRequestUidsForCaller(nc);
 
         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
@@ -7856,13 +7848,12 @@
             throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated."
                     + " Please use NetworkCapabilities instead.");
         }
-        final int callingUid = Binder.getCallingUid();
-        mAppOpsManager.checkPackage(callingUid, callingPackageName);
+        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName);
 
         // This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
         // and administrator uids to be safe.
         final NetworkCapabilities nc = new NetworkCapabilities(request.networkCapabilities);
-        restrictRequestUidsForCallerAndSetRequestorInfo(nc, callingUid, callingPackageName);
+        restrictRequestUidsForCaller(nc);
 
         final NetworkRequest requestWithId =
                 new NetworkRequest(
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index a629b3f..98ac4cb 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -1557,16 +1557,16 @@
         }
 
         checkNotNull(callingPackage, "Null calling package cannot create IpSec tunnels");
-        switch (getAppOpsManager().noteOp(TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
-            case AppOpsManager.MODE_DEFAULT:
-                mContext.enforceCallingOrSelfPermission(
-                        android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
-                break;
-            case AppOpsManager.MODE_ALLOWED:
-                return;
-            default:
-                throw new SecurityException("Request to ignore AppOps for non-legacy API");
+
+        // OP_MANAGE_IPSEC_TUNNELS will return MODE_ERRORED by default, including for the system
+        // server. If the appop is not granted, require that the caller has the MANAGE_IPSEC_TUNNELS
+        // permission or is the System Server.
+        if (AppOpsManager.MODE_ALLOWED == getAppOpsManager().noteOpNoThrow(
+                TUNNEL_OP, Binder.getCallingUid(), callingPackage)) {
+            return;
         }
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.MANAGE_IPSEC_TUNNELS, "IpSecService");
     }
 
     private void createOrUpdateTransform(
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index b41e60b..068d6fc 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -124,6 +124,7 @@
 import android.util.MathUtils;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
+import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -243,6 +244,7 @@
     // AudioHandler messages
     private static final int MSG_SET_DEVICE_VOLUME = 0;
     private static final int MSG_PERSIST_VOLUME = 1;
+    private static final int MSG_PERSIST_VOLUME_GROUP = 2;
     private static final int MSG_PERSIST_RINGER_MODE = 3;
     private static final int MSG_AUDIO_SERVER_DIED = 4;
     private static final int MSG_PLAY_SOUND_EFFECT = 5;
@@ -761,6 +763,10 @@
         mSettingsObserver = new SettingsObserver();
         createStreamStates();
 
+        // must be called after createStreamStates() as it uses MUSIC volume as default if no
+        // persistent data
+        initVolumeGroupStates();
+
         // mSafeUsbMediaVolumeIndex must be initialized after createStreamStates() because it
         // relies on audio policy having correct ranges for volume indexes.
         mSafeUsbMediaVolumeIndex = getSafeUsbMediaVolumeIndex();
@@ -995,6 +1001,9 @@
             streamState.applyAllVolumes();
         }
 
+        // Restore audio volume groups
+        restoreVolumeGroups();
+
         // Restore mono mode
         updateMasterMono(mContentResolver);
 
@@ -2112,20 +2121,20 @@
                                             String callingPackage) {
         enforceModifyAudioRoutingPermission();
         Preconditions.checkNotNull(attr, "attr must not be null");
-        // @todo not hold the caller context, post message
-        int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
-        final int device = getDeviceForStream(stream);
-
-        int oldIndex = AudioSystem.getVolumeIndexForAttributes(attr, device);
-
-        AudioSystem.setVolumeIndexForAttributes(attr, index, device);
-
         final int volumeGroup = getVolumeGroupIdForAttributes(attr);
-        final AudioVolumeGroup avg = getAudioVolumeGroupById(volumeGroup);
-        if (avg == null) {
+        if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
+            Log.e(TAG, ": no volume group found for attributes " + attr.toString());
             return;
         }
-        for (final int groupedStream : avg.getLegacyStreamTypes()) {
+        final VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
+
+        sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_GROUP_VOL, attr, vgs.name(),
+                index/*val1*/, flags/*val2*/, callingPackage));
+
+        vgs.setVolumeIndex(index, flags);
+
+        // For legacy reason, propagate to all streams associated to this volume group
+        for (final int groupedStream : vgs.getLegacyStreamTypes()) {
             setStreamVolume(groupedStream, index, flags, callingPackage, callingPackage,
                             Binder.getCallingUid());
         }
@@ -2147,10 +2156,12 @@
     public int getVolumeIndexForAttributes(@NonNull AudioAttributes attr) {
         enforceModifyAudioRoutingPermission();
         Preconditions.checkNotNull(attr, "attr must not be null");
-        int stream = AudioProductStrategy.getLegacyStreamTypeForStrategyWithAudioAttributes(attr);
-        final int device = getDeviceForStream(stream);
-
-        return AudioSystem.getVolumeIndexForAttributes(attr, device);
+        final int volumeGroup = getVolumeGroupIdForAttributes(attr);
+        if (sVolumeGroupStates.indexOfKey(volumeGroup) < 0) {
+            throw new IllegalArgumentException("No volume group for attributes " + attr);
+        }
+        final VolumeGroupState vgs = sVolumeGroupStates.get(volumeGroup);
+        return vgs.getVolumeIndex();
     }
 
     /** @see AudioManager#getMaxVolumeIndexForAttributes(attr) */
@@ -3550,6 +3561,8 @@
                 enforceSafeMediaVolume(TAG);
             }
         }
+
+        readVolumeGroupsSettings();
     }
 
     /** @see AudioManager#setSpeakerphoneOn(boolean) */
@@ -4438,6 +4451,310 @@
     ///////////////////////////////////////////////////////////////////////////
     // Inner classes
     ///////////////////////////////////////////////////////////////////////////
+    /**
+     * Key is the AudioManager VolumeGroupId
+     * Value is the VolumeGroupState
+     */
+    private static final SparseArray<VolumeGroupState> sVolumeGroupStates = new SparseArray<>();
+
+    private void initVolumeGroupStates() {
+        for (final AudioVolumeGroup avg : getAudioVolumeGroups()) {
+            try {
+                // if no valid attributes, this volume group is not controllable, throw exception
+                ensureValidAttributes(avg);
+            } catch (IllegalArgumentException e) {
+                // Volume Groups without attributes are not controllable through set/get volume
+                // using attributes. Do not append them.
+                Log.d(TAG, "volume group " + avg.name() + " for internal policy needs");
+                continue;
+            }
+            sVolumeGroupStates.append(avg.getId(), new VolumeGroupState(avg));
+        }
+        for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+            final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+            vgs.applyAllVolumes();
+        }
+    }
+
+    private void ensureValidAttributes(AudioVolumeGroup avg) {
+        boolean hasAtLeastOneValidAudioAttributes = avg.getAudioAttributes().stream()
+                .anyMatch(aa -> !aa.equals(AudioProductStrategy.sDefaultAttributes));
+        if (!hasAtLeastOneValidAudioAttributes) {
+            throw new IllegalArgumentException("Volume Group " + avg.name()
+                    + " has no valid audio attributes");
+        }
+    }
+
+    private void readVolumeGroupsSettings() {
+        Log.v(TAG, "readVolumeGroupsSettings");
+        for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+            final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+            vgs.readSettings();
+            vgs.applyAllVolumes();
+        }
+    }
+
+    // Called upon crash of AudioServer
+    private void restoreVolumeGroups() {
+        Log.v(TAG, "restoreVolumeGroups");
+        for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+            final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+            vgs.applyAllVolumes();
+        }
+    }
+
+    private void dumpVolumeGroups(PrintWriter pw) {
+        pw.println("\nVolume Groups (device: index)");
+        for (int i = 0; i < sVolumeGroupStates.size(); i++) {
+            final VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
+            vgs.dump(pw);
+            pw.println("");
+        }
+    }
+
+    // NOTE: Locking order for synchronized objects related to volume management:
+    //  1     mSettingsLock
+    //  2       VolumeGroupState.class
+    private class VolumeGroupState {
+        private final AudioVolumeGroup mAudioVolumeGroup;
+        private final SparseIntArray mIndexMap = new SparseIntArray(8);
+        private int mIndexMin;
+        private int mIndexMax;
+        private int mLegacyStreamType = AudioSystem.STREAM_DEFAULT;
+        private int mPublicStreamType = AudioSystem.STREAM_MUSIC;
+        private AudioAttributes mAudioAttributes = AudioProductStrategy.sDefaultAttributes;
+
+        // No API in AudioSystem to get a device from strategy or from attributes.
+        // Need a valid public stream type to use current API getDeviceForStream
+        private int getDeviceForVolume() {
+            return getDeviceForStream(mPublicStreamType);
+        }
+
+        private VolumeGroupState(AudioVolumeGroup avg) {
+            mAudioVolumeGroup = avg;
+            Log.v(TAG, "VolumeGroupState for " + avg.toString());
+            for (final AudioAttributes aa : avg.getAudioAttributes()) {
+                if (!aa.equals(AudioProductStrategy.sDefaultAttributes)) {
+                    mAudioAttributes = aa;
+                    break;
+                }
+            }
+            final int[] streamTypes = mAudioVolumeGroup.getLegacyStreamTypes();
+            if (streamTypes.length != 0) {
+                // Uses already initialized MIN / MAX if a stream type is attached to group
+                mLegacyStreamType = streamTypes[0];
+                for (final int streamType : streamTypes) {
+                    if (streamType != AudioSystem.STREAM_DEFAULT
+                            && streamType < AudioSystem.getNumStreamTypes()) {
+                        mPublicStreamType = streamType;
+                        break;
+                    }
+                }
+                mIndexMin = MIN_STREAM_VOLUME[mPublicStreamType];
+                mIndexMax = MAX_STREAM_VOLUME[mPublicStreamType];
+            } else if (!avg.getAudioAttributes().isEmpty()) {
+                mIndexMin = AudioSystem.getMinVolumeIndexForAttributes(mAudioAttributes);
+                mIndexMax = AudioSystem.getMaxVolumeIndexForAttributes(mAudioAttributes);
+            } else {
+                Log.e(TAG, "volume group: " + mAudioVolumeGroup.name()
+                        + " has neither valid attributes nor valid stream types assigned");
+                return;
+            }
+            // Load volume indexes from data base
+            readSettings();
+        }
+
+        public @NonNull int[] getLegacyStreamTypes() {
+            return mAudioVolumeGroup.getLegacyStreamTypes();
+        }
+
+        public String name() {
+            return mAudioVolumeGroup.name();
+        }
+
+        public int getVolumeIndex() {
+            return getIndex(getDeviceForVolume());
+        }
+
+        public void setVolumeIndex(int index, int flags) {
+            if (mUseFixedVolume) {
+                return;
+            }
+            setVolumeIndex(index, getDeviceForVolume(), flags);
+        }
+
+        private void setVolumeIndex(int index, int device, int flags) {
+            // Set the volume index
+            setVolumeIndexInt(index, device, flags);
+
+            // Update local cache
+            mIndexMap.put(device, index);
+
+            // update data base - post a persist volume group msg
+            sendMsg(mAudioHandler,
+                    MSG_PERSIST_VOLUME_GROUP,
+                    SENDMSG_QUEUE,
+                    device,
+                    0,
+                    this,
+                    PERSIST_DELAY);
+        }
+
+        private void setVolumeIndexInt(int index, int device, int flags) {
+            // Set the volume index
+            AudioSystem.setVolumeIndexForAttributes(mAudioAttributes, index, device);
+        }
+
+        public int getIndex(int device) {
+            synchronized (VolumeGroupState.class) {
+                int index = mIndexMap.get(device, -1);
+                // there is always an entry for AudioSystem.DEVICE_OUT_DEFAULT
+                return (index != -1) ? index : mIndexMap.get(AudioSystem.DEVICE_OUT_DEFAULT);
+            }
+        }
+
+        public boolean hasIndexForDevice(int device) {
+            synchronized (VolumeGroupState.class) {
+                return (mIndexMap.get(device, -1) != -1);
+            }
+        }
+
+        public int getMaxIndex() {
+            return mIndexMax;
+        }
+
+        public int getMinIndex() {
+            return mIndexMin;
+        }
+
+        public void applyAllVolumes() {
+            synchronized (VolumeGroupState.class) {
+                if (mLegacyStreamType != AudioSystem.STREAM_DEFAULT) {
+                    // No-op to avoid regression with stream based volume management
+                    return;
+                }
+                // apply device specific volumes first
+                int index;
+                for (int i = 0; i < mIndexMap.size(); i++) {
+                    final int device = mIndexMap.keyAt(i);
+                    if (device != AudioSystem.DEVICE_OUT_DEFAULT) {
+                        index = mIndexMap.valueAt(i);
+                        Log.v(TAG, "applyAllVolumes: restore index " + index + " for group "
+                                + mAudioVolumeGroup.name() + " and device "
+                                + AudioSystem.getOutputDeviceName(device));
+                        setVolumeIndexInt(index, device, 0 /*flags*/);
+                    }
+                }
+                // apply default volume last: by convention , default device volume will be used
+                index = getIndex(AudioSystem.DEVICE_OUT_DEFAULT);
+                Log.v(TAG, "applyAllVolumes: restore default device index " + index + " for group "
+                        + mAudioVolumeGroup.name());
+                setVolumeIndexInt(index, AudioSystem.DEVICE_OUT_DEFAULT, 0 /*flags*/);
+            }
+        }
+
+        private void persistVolumeGroup(int device) {
+            if (mUseFixedVolume) {
+                return;
+            }
+            Log.v(TAG, "persistVolumeGroup: storing index " + getIndex(device) + " for group "
+                    + mAudioVolumeGroup.name() + " and device "
+                    + AudioSystem.getOutputDeviceName(device));
+            boolean success = Settings.System.putIntForUser(mContentResolver,
+                    getSettingNameForDevice(device),
+                    getIndex(device),
+                    UserHandle.USER_CURRENT);
+            if (!success) {
+                Log.e(TAG, "persistVolumeGroup failed for group " +  mAudioVolumeGroup.name());
+            }
+        }
+
+        public void readSettings() {
+            synchronized (VolumeGroupState.class) {
+                // First clear previously loaded (previous user?) settings
+                mIndexMap.clear();
+                // force maximum volume on all streams if fixed volume property is set
+                if (mUseFixedVolume) {
+                    mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax);
+                    return;
+                }
+                for (int device : AudioSystem.DEVICE_OUT_ALL_SET) {
+                    // retrieve current volume for device
+                    // if no volume stored for current volume group and device, use default volume
+                    // if default device, continue otherwise
+                    int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT)
+                            ? AudioSystem.DEFAULT_STREAM_VOLUME[mPublicStreamType] : -1;
+                    int index;
+                    String name = getSettingNameForDevice(device);
+                    index = Settings.System.getIntForUser(
+                            mContentResolver, name, defaultIndex, UserHandle.USER_CURRENT);
+                    if (index == -1) {
+                        Log.e(TAG, "readSettings: No index stored for group "
+                                + mAudioVolumeGroup.name() + ", device " + name);
+                        continue;
+                    }
+                    Log.v(TAG, "readSettings: found stored index " + getValidIndex(index)
+                             + " for group " + mAudioVolumeGroup.name() + ", device: " + name);
+                    mIndexMap.put(device, getValidIndex(index));
+                }
+            }
+        }
+
+        private int getValidIndex(int index) {
+            if (index < mIndexMin) {
+                return mIndexMin;
+            } else if (mUseFixedVolume || index > mIndexMax) {
+                return mIndexMax;
+            }
+            return index;
+        }
+
+        public @NonNull String getSettingNameForDevice(int device) {
+            final String suffix = AudioSystem.getOutputDeviceName(device);
+            if (suffix.isEmpty()) {
+                return mAudioVolumeGroup.name();
+            }
+            return mAudioVolumeGroup.name() + "_" + AudioSystem.getOutputDeviceName(device);
+        }
+
+        private void dump(PrintWriter pw) {
+            pw.println("- VOLUME GROUP " + mAudioVolumeGroup.name() + ":");
+            pw.print("   Min: ");
+            pw.println(mIndexMin);
+            pw.print("   Max: ");
+            pw.println(mIndexMax);
+            pw.print("   Current: ");
+            for (int i = 0; i < mIndexMap.size(); i++) {
+                if (i > 0) {
+                    pw.print(", ");
+                }
+                final int device = mIndexMap.keyAt(i);
+                pw.print(Integer.toHexString(device));
+                final String deviceName = device == AudioSystem.DEVICE_OUT_DEFAULT ? "default"
+                        : AudioSystem.getOutputDeviceName(device);
+                if (!deviceName.isEmpty()) {
+                    pw.print(" (");
+                    pw.print(deviceName);
+                    pw.print(")");
+                }
+                pw.print(": ");
+                pw.print(mIndexMap.valueAt(i));
+            }
+            pw.println();
+            pw.print("   Devices: ");
+            int n = 0;
+            final int devices = getDeviceForVolume();
+            for (int device : AudioSystem.DEVICE_OUT_ALL_SET) {
+                if ((devices & device) == device) {
+                    if (n++ > 0) {
+                        pw.print(", ");
+                    }
+                    pw.print(AudioSystem.getOutputDeviceName(device));
+                }
+            }
+        }
+    }
+
 
     // NOTE: Locking order for synchronized objects related to volume or ringer mode management:
     //  1 mScoclient OR mSafeMediaVolumeState
@@ -5082,6 +5399,11 @@
                     persistVolume((VolumeStreamState) msg.obj, msg.arg1);
                     break;
 
+                case MSG_PERSIST_VOLUME_GROUP:
+                    final VolumeGroupState vgs = (VolumeGroupState) msg.obj;
+                    vgs.persistVolumeGroup(msg.arg1);
+                    break;
+
                 case MSG_PERSIST_RINGER_MODE:
                     // note that the value persisted is the current ringer mode, not the
                     // value of ringer mode as of the time the request was made to persist
@@ -6129,6 +6451,7 @@
         }
         mMediaFocusControl.dump(pw);
         dumpStreamStates(pw);
+        dumpVolumeGroups(pw);
         dumpRingerMode(pw);
         pw.println("\nAudio routes:");
         pw.print("  mMainType=0x"); pw.println(Integer.toHexString(
diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java
index fcd8701..add620e 100644
--- a/services/core/java/com/android/server/audio/AudioServiceEvents.java
+++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java
@@ -16,6 +16,7 @@
 
 package com.android.server.audio;
 
+import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioSystem;
 
@@ -97,12 +98,15 @@
         static final int VOL_ADJUST_VOL_UID = 5;
         static final int VOL_VOICE_ACTIVITY_HEARING_AID = 6;
         static final int VOL_MODE_CHANGE_HEARING_AID = 7;
+        static final int VOL_SET_GROUP_VOL = 8;
 
         final int mOp;
         final int mStream;
         final int mVal1;
         final int mVal2;
         final String mCaller;
+        final String mGroupName;
+        final AudioAttributes mAudioAttributes;
 
         /** used for VOL_ADJUST_VOL_UID,
          *           VOL_ADJUST_SUGG_VOL,
@@ -114,6 +118,8 @@
             mVal1 = val1;
             mVal2 = val2;
             mCaller = caller;
+            mGroupName = null;
+            mAudioAttributes = null;
         }
 
         /** used for VOL_SET_HEARING_AID_VOL*/
@@ -124,6 +130,8 @@
             // unused
             mStream = -1;
             mCaller = null;
+            mGroupName = null;
+            mAudioAttributes = null;
         }
 
         /** used for VOL_SET_AVRCP_VOL */
@@ -134,6 +142,8 @@
             mVal2 = 0;
             mStream = -1;
             mCaller = null;
+            mGroupName = null;
+            mAudioAttributes = null;
         }
 
         /** used for VOL_VOICE_ACTIVITY_HEARING_AID */
@@ -144,6 +154,8 @@
             mVal2 = voiceActive ? 1 : 0;
             // unused
             mCaller = null;
+            mGroupName = null;
+            mAudioAttributes = null;
         }
 
         /** used for VOL_MODE_CHANGE_HEARING_AID */
@@ -154,6 +166,19 @@
             mVal2 = mode;
             // unused
             mCaller = null;
+            mGroupName = null;
+            mAudioAttributes = null;
+        }
+
+        /** used for VOL_SET_GROUP_VOL */
+        VolumeEvent(int op, AudioAttributes aa, String group, int index, int flags, String caller) {
+            mOp = op;
+            mStream = -1;
+            mVal1 = index;
+            mVal2 = flags;
+            mCaller = caller;
+            mGroupName = group;
+            mAudioAttributes = aa;
         }
 
         @Override
@@ -208,6 +233,14 @@
                             .append(") causes setting HEARING_AID volume to idx:").append(mVal1)
                             .append(" stream:").append(AudioSystem.streamToString(mStream))
                             .toString();
+                case VOL_SET_GROUP_VOL:
+                    return new StringBuilder("setVolumeIndexForAttributes(attr:")
+                            .append(mAudioAttributes.toString())
+                            .append(" group: ").append(mGroupName)
+                            .append(" index:").append(mVal1)
+                            .append(" flags:0x").append(Integer.toHexString(mVal2))
+                            .append(") from ").append(mCaller)
+                            .toString();
                 default: return new StringBuilder("FIXME invalid op:").append(mOp).toString();
             }
         }
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index 2eec419..8687f35 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -17,6 +17,7 @@
 package com.android.server.compat;
 
 import android.annotation.Nullable;
+import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
 import android.content.pm.ApplicationInfo;
 
@@ -39,6 +40,13 @@
 public final class CompatChange extends CompatibilityChangeInfo {
 
     /**
+     * A change ID to be used only in the CTS test for this SystemApi
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = 1234) // Needs to be > test APK targetSdkVersion.
+    private static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id.
+
+    /**
      * Callback listener for when compat changes are updated for a package.
      * See {@link #registerListener(ChangeListener)} for more details.
      */
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 9956022..7f6dc55 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -48,8 +48,12 @@
 import android.content.pm.UserInfo;
 import android.net.ConnectivityManager;
 import android.net.INetworkManagementEventObserver;
+import android.net.Ikev2VpnProfile;
 import android.net.IpPrefix;
 import android.net.IpSecManager;
+import android.net.IpSecManager.IpSecTunnelInterface;
+import android.net.IpSecManager.UdpEncapsulationSocket;
+import android.net.IpSecTransform;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.LocalSocket;
@@ -65,6 +69,12 @@
 import android.net.UidRange;
 import android.net.VpnManager;
 import android.net.VpnService;
+import android.net.ipsec.ike.ChildSessionCallback;
+import android.net.ipsec.ike.ChildSessionConfiguration;
+import android.net.ipsec.ike.ChildSessionParams;
+import android.net.ipsec.ike.IkeSession;
+import android.net.ipsec.ike.IkeSessionCallback;
+import android.net.ipsec.ike.IkeSessionParams;
 import android.os.Binder;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
@@ -113,6 +123,7 @@
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -122,6 +133,9 @@
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicInteger;
 
 /**
@@ -176,14 +190,14 @@
 
     private final Context mContext;
     private final NetworkInfo mNetworkInfo;
-    private String mPackage;
+    @VisibleForTesting protected String mPackage;
     private int mOwnerUID;
     private boolean mIsPackageTargetingAtLeastQ;
     private String mInterface;
     private Connection mConnection;
 
     /** Tracks the runners for all VPN types managed by the platform (eg. LegacyVpn, PlatformVpn) */
-    private VpnRunner mVpnRunner;
+    @VisibleForTesting protected VpnRunner mVpnRunner;
 
     private PendingIntent mStatusIntent;
     private volatile boolean mEnableTeardown = true;
@@ -196,6 +210,7 @@
     @VisibleForTesting
     protected final NetworkCapabilities mNetworkCapabilities;
     private final SystemServices mSystemServices;
+    private final Ikev2SessionCreator mIkev2SessionCreator;
 
     /**
      * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
@@ -238,17 +253,20 @@
 
     public Vpn(Looper looper, Context context, INetworkManagementService netService,
             @UserIdInt int userHandle) {
-        this(looper, context, netService, userHandle, new SystemServices(context));
+        this(looper, context, netService, userHandle,
+                new SystemServices(context), new Ikev2SessionCreator());
     }
 
     @VisibleForTesting
     protected Vpn(Looper looper, Context context, INetworkManagementService netService,
-            int userHandle, SystemServices systemServices) {
+            int userHandle, SystemServices systemServices,
+            Ikev2SessionCreator ikev2SessionCreator) {
         mContext = context;
         mNetd = netService;
         mUserHandle = userHandle;
         mLooper = looper;
         mSystemServices = systemServices;
+        mIkev2SessionCreator = ikev2SessionCreator;
 
         mPackage = VpnConfig.LEGACY_VPN;
         mOwnerUID = getAppUid(mPackage, mUserHandle);
@@ -749,8 +767,9 @@
 
     private boolean isCurrentPreparedPackage(String packageName) {
         // We can't just check that packageName matches mPackage, because if the app was uninstalled
-        // and reinstalled it will no longer be prepared. Instead check the UID.
-        return getAppUid(packageName, mUserHandle) == mOwnerUID;
+        // and reinstalled it will no longer be prepared. Similarly if there is a shared UID, the
+        // calling package may not be the same as the prepared package. Check both UID and package.
+        return getAppUid(packageName, mUserHandle) == mOwnerUID && mPackage.equals(packageName);
     }
 
     /** Prepare the VPN for the given package. Does not perform permission checks. */
@@ -975,7 +994,11 @@
         }
         lp.setDomains(buffer.toString().trim());
 
-        // TODO: Stop setting the MTU in jniCreate and set it here.
+        if (mConfig.mtu > 0) {
+            lp.setMtu(mConfig.mtu);
+        }
+
+        // TODO: Stop setting the MTU in jniCreate
 
         return lp;
     }
@@ -2000,30 +2023,369 @@
         protected abstract void exit();
     }
 
-    private class IkeV2VpnRunner extends VpnRunner {
-        private static final String TAG = "IkeV2VpnRunner";
+    interface IkeV2VpnRunnerCallback {
+        void onDefaultNetworkChanged(@NonNull Network network);
 
-        private final IpSecManager mIpSecManager;
-        private final VpnProfile mProfile;
+        void onChildOpened(
+                @NonNull Network network, @NonNull ChildSessionConfiguration childConfig);
 
-        IkeV2VpnRunner(VpnProfile profile) {
+        void onChildTransformCreated(
+                @NonNull Network network, @NonNull IpSecTransform transform, int direction);
+
+        void onSessionLost(@NonNull Network network);
+    }
+
+    /**
+     * Internal class managing IKEv2/IPsec VPN connectivity
+     *
+     * <p>The IKEv2 VPN will listen to, and run based on the lifecycle of Android's default Network.
+     * As a new default is selected, old IKE sessions will be torn down, and a new one will be
+     * started.
+     *
+     * <p>This class uses locking minimally - the Vpn instance lock is only ever held when fields of
+     * the outer class are modified. As such, care must be taken to ensure that no calls are added
+     * that might modify the outer class' state without acquiring a lock.
+     *
+     * <p>The overall structure of the Ikev2VpnRunner is as follows:
+     *
+     * <ol>
+     *   <li>Upon startup, a NetworkRequest is registered with ConnectivityManager. This is called
+     *       any time a new default network is selected
+     *   <li>When a new default is connected, an IKE session is started on that Network. If there
+     *       were any existing IKE sessions on other Networks, they are torn down before starting
+     *       the new IKE session
+     *   <li>Upon establishment, the onChildTransformCreated() callback is called twice, one for
+     *       each direction, and finally onChildOpened() is called
+     *   <li>Upon the onChildOpened() call, the VPN is fully set up.
+     *   <li>Subsequent Network changes result in new onDefaultNetworkChanged() callbacks. See (2).
+     * </ol>
+     */
+    class IkeV2VpnRunner extends VpnRunner implements IkeV2VpnRunnerCallback {
+        @NonNull private static final String TAG = "IkeV2VpnRunner";
+
+        @NonNull private final IpSecManager mIpSecManager;
+        @NonNull private final Ikev2VpnProfile mProfile;
+        @NonNull private final ConnectivityManager.NetworkCallback mNetworkCallback;
+
+        /**
+         * Executor upon which ALL callbacks must be run.
+         *
+         * <p>This executor MUST be a single threaded executor, in order to ensure the consistency
+         * of the mutable Ikev2VpnRunner fields. The Ikev2VpnRunner is built mostly lock-free by
+         * virtue of everything being serialized on this executor.
+         */
+        @NonNull private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+
+        /** Signal to ensure shutdown is honored even if a new Network is connected. */
+        private boolean mIsRunning = true;
+
+        @Nullable private UdpEncapsulationSocket mEncapSocket;
+        @Nullable private IpSecTunnelInterface mTunnelIface;
+        @Nullable private IkeSession mSession;
+        @Nullable private Network mActiveNetwork;
+
+        IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) {
             super(TAG);
             mProfile = profile;
-
-            // TODO: move this to startVpnRunnerPrivileged()
-            mConfig = new VpnConfig();
-            mIpSecManager = mContext.getSystemService(IpSecManager.class);
+            mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
+            mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this);
         }
 
         @Override
         public void run() {
-            // TODO: Build IKE config, start IKE session
+            // Explicitly use only the network that ConnectivityService thinks is the "best." In
+            // other words, only ever use the currently selected default network. This does mean
+            // that in both onLost() and onConnected(), any old sessions MUST be torn down. This
+            // does NOT include VPNs.
+            final ConnectivityManager cm = ConnectivityManager.from(mContext);
+            cm.requestNetwork(cm.getDefaultRequest(), mNetworkCallback);
+        }
+
+        private boolean isActiveNetwork(@Nullable Network network) {
+            return Objects.equals(mActiveNetwork, network) && mIsRunning;
+        }
+
+        /**
+         * Called when an IKE Child session has been opened, signalling completion of the startup.
+         *
+         * <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor
+         * thread in order to ensure consistency of the Ikev2VpnRunner fields.
+         */
+        public void onChildOpened(
+                @NonNull Network network, @NonNull ChildSessionConfiguration childConfig) {
+            if (!isActiveNetwork(network)) {
+                Log.d(TAG, "onOpened called for obsolete network " + network);
+
+                // Do nothing; this signals that either: (1) a new/better Network was found,
+                // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
+                // IKE session was already shut down (exited, or an error was encountered somewhere
+                // else). In both cases, all resources and sessions are torn down via
+                // resetIkeState().
+                return;
+            }
+
+            try {
+                final String interfaceName = mTunnelIface.getInterfaceName();
+                final int maxMtu = mProfile.getMaxMtu();
+                final List<LinkAddress> internalAddresses = childConfig.getInternalAddresses();
+
+                final Collection<RouteInfo> newRoutes = VpnIkev2Utils.getRoutesFromTrafficSelectors(
+                        childConfig.getOutboundTrafficSelectors());
+                for (final LinkAddress address : internalAddresses) {
+                    mTunnelIface.addAddress(address.getAddress(), address.getPrefixLength());
+                }
+
+                final NetworkAgent networkAgent;
+                final LinkProperties lp;
+
+                synchronized (Vpn.this) {
+                    mInterface = interfaceName;
+                    mConfig.mtu = maxMtu;
+                    mConfig.interfaze = mInterface;
+
+                    mConfig.addresses.clear();
+                    mConfig.addresses.addAll(internalAddresses);
+
+                    mConfig.routes.clear();
+                    mConfig.routes.addAll(newRoutes);
+
+                    // TODO: Add DNS servers from negotiation
+
+                    networkAgent = mNetworkAgent;
+
+                    // The below must be done atomically with the mConfig update, otherwise
+                    // isRunningLocked() will be racy.
+                    if (networkAgent == null) {
+                        if (isSettingsVpnLocked()) {
+                            prepareStatusIntent();
+                        }
+                        agentConnect();
+                        return; // Link properties are already sent.
+                    }
+
+                    lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked
+                }
+
+                networkAgent.sendLinkProperties(lp);
+            } catch (Exception e) {
+                Log.d(TAG, "Error in ChildOpened for network " + network, e);
+                onSessionLost(network);
+            }
+        }
+
+        /**
+         * Called when an IPsec transform has been created, and should be applied.
+         *
+         * <p>This method is called multiple times over the lifetime of an IkeSession (or default
+         * network), and is MUST always be called on the mExecutor thread in order to ensure
+         * consistency of the Ikev2VpnRunner fields.
+         */
+        public void onChildTransformCreated(
+                @NonNull Network network, @NonNull IpSecTransform transform, int direction) {
+            if (!isActiveNetwork(network)) {
+                Log.d(TAG, "ChildTransformCreated for obsolete network " + network);
+
+                // Do nothing; this signals that either: (1) a new/better Network was found,
+                // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
+                // IKE session was already shut down (exited, or an error was encountered somewhere
+                // else). In both cases, all resources and sessions are torn down via
+                // resetIkeState().
+                return;
+            }
+
+            try {
+                // Transforms do not need to be persisted; the IkeSession will keep
+                // them alive for us
+                mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform);
+            } catch (IOException e) {
+                Log.d(TAG, "Transform application failed for network " + network, e);
+                onSessionLost(network);
+            }
+        }
+
+        /**
+         * Called when a new default network is connected.
+         *
+         * <p>The Ikev2VpnRunner will unconditionally switch to the new network, killing the old IKE
+         * state in the process, and starting a new IkeSession instance.
+         *
+         * <p>This method is called multiple times over the lifetime of the Ikev2VpnRunner, and is
+         * called on the ConnectivityService thread. Thus, the actual work MUST be proxied to the
+         * mExecutor thread in order to ensure consistency of the Ikev2VpnRunner fields.
+         */
+        public void onDefaultNetworkChanged(@NonNull Network network) {
+            Log.d(TAG, "Starting IKEv2/IPsec session on new network: " + network);
+
+            // Proxy to the Ikev2VpnRunner (single-thread) executor to ensure consistency in lieu
+            // of locking.
+            mExecutor.execute(() -> {
+                try {
+                    if (!mIsRunning) {
+                        Log.d(TAG, "onDefaultNetworkChanged after exit");
+                        return; // VPN has been shut down.
+                    }
+
+                    // Without MOBIKE, we have no way to seamlessly migrate. Close on old
+                    // (non-default) network, and start the new one.
+                    resetIkeState();
+                    mActiveNetwork = network;
+
+                    // TODO(b/149356682): Update this based on new IKE API
+                    mEncapSocket = mIpSecManager.openUdpEncapsulationSocket();
+
+                    // TODO(b/149356682): Update this based on new IKE API
+                    final IkeSessionParams ikeSessionParams =
+                            VpnIkev2Utils.buildIkeSessionParams(mProfile, mEncapSocket);
+                    final ChildSessionParams childSessionParams =
+                            VpnIkev2Utils.buildChildSessionParams();
+
+                    // TODO: Remove the need for adding two unused addresses with
+                    // IPsec tunnels.
+                    mTunnelIface =
+                            mIpSecManager.createIpSecTunnelInterface(
+                                    ikeSessionParams.getServerAddress() /* unused */,
+                                    ikeSessionParams.getServerAddress() /* unused */,
+                                    network);
+                    mNetd.setInterfaceUp(mTunnelIface.getInterfaceName());
+
+                    // Socket must be bound to prevent network switches from causing
+                    // the IKE teardown to fail/timeout.
+                    // TODO(b/149356682): Update this based on new IKE API
+                    network.bindSocket(mEncapSocket.getFileDescriptor());
+
+                    mSession = mIkev2SessionCreator.createIkeSession(
+                            mContext,
+                            ikeSessionParams,
+                            childSessionParams,
+                            mExecutor,
+                            new VpnIkev2Utils.IkeSessionCallbackImpl(
+                                    TAG, IkeV2VpnRunner.this, network),
+                            new VpnIkev2Utils.ChildSessionCallbackImpl(
+                                    TAG, IkeV2VpnRunner.this, network));
+                    Log.d(TAG, "Ike Session started for network " + network);
+                } catch (Exception e) {
+                    Log.i(TAG, "Setup failed for network " + network + ". Aborting", e);
+                    onSessionLost(network);
+                }
+            });
+        }
+
+        /**
+         * Handles loss of a session
+         *
+         * <p>The loss of a session might be due to an onLost() call, the IKE session getting torn
+         * down for any reason, or an error in updating state (transform application, VPN setup)
+         *
+         * <p>This method MUST always be called on the mExecutor thread in order to ensure
+         * consistency of the Ikev2VpnRunner fields.
+         */
+        public void onSessionLost(@NonNull Network network) {
+            if (!isActiveNetwork(network)) {
+                Log.d(TAG, "onSessionLost() called for obsolete network " + network);
+
+                // Do nothing; this signals that either: (1) a new/better Network was found,
+                // and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
+                // IKE session was already shut down (exited, or an error was encountered somewhere
+                // else). In both cases, all resources and sessions are torn down via
+                // onSessionLost() and resetIkeState().
+                return;
+            }
+
+            mActiveNetwork = null;
+
+            // Close all obsolete state, but keep VPN alive incase a usable network comes up.
+            // (Mirrors VpnService behavior)
+            Log.d(TAG, "Resetting state for network: " + network);
+
+            synchronized (Vpn.this) {
+                // Since this method handles non-fatal errors only, set mInterface to null to
+                // prevent the NetworkManagementEventObserver from killing this VPN based on the
+                // interface going down (which we expect).
+                mInterface = null;
+                mConfig.interfaze = null;
+
+                // Set as unroutable to prevent traffic leaking while the interface is down.
+                if (mConfig != null && mConfig.routes != null) {
+                    final List<RouteInfo> oldRoutes = new ArrayList<>(mConfig.routes);
+
+                    mConfig.routes.clear();
+                    for (final RouteInfo route : oldRoutes) {
+                        mConfig.routes.add(new RouteInfo(route.getDestination(), RTN_UNREACHABLE));
+                    }
+                    if (mNetworkAgent != null) {
+                        mNetworkAgent.sendLinkProperties(makeLinkProperties());
+                    }
+                }
+            }
+
+            resetIkeState();
+        }
+
+        /**
+         * Cleans up all IKE state
+         *
+         * <p>This method MUST always be called on the mExecutor thread in order to ensure
+         * consistency of the Ikev2VpnRunner fields.
+         */
+        private void resetIkeState() {
+            if (mTunnelIface != null) {
+                // No need to call setInterfaceDown(); the IpSecInterface is being fully torn down.
+                mTunnelIface.close();
+                mTunnelIface = null;
+            }
+            if (mSession != null) {
+                mSession.kill(); // Kill here to make sure all resources are released immediately
+                mSession = null;
+            }
+
+            // TODO(b/149356682): Update this based on new IKE API
+            if (mEncapSocket != null) {
+                try {
+                    mEncapSocket.close();
+                } catch (IOException e) {
+                    Log.e(TAG, "Failed to close encap socket", e);
+                }
+                mEncapSocket = null;
+            }
+        }
+
+        /**
+         * Triggers cleanup of outer class' state
+         *
+         * <p>Can be called from any thread, as it does not mutate state in the Ikev2VpnRunner.
+         */
+        private void cleanupVpnState() {
+            synchronized (Vpn.this) {
+                agentDisconnect();
+            }
+        }
+
+        /**
+         * Cleans up all Ikev2VpnRunner internal state
+         *
+         * <p>This method MUST always be called on the mExecutor thread in order to ensure
+         * consistency of the Ikev2VpnRunner fields.
+         */
+        private void shutdownVpnRunner() {
+            mActiveNetwork = null;
+            mIsRunning = false;
+
+            resetIkeState();
+
+            final ConnectivityManager cm = ConnectivityManager.from(mContext);
+            cm.unregisterNetworkCallback(mNetworkCallback);
+
+            mExecutor.shutdown();
         }
 
         @Override
         public void exit() {
-            // TODO: Teardown IKE session & any resources.
-            agentDisconnect();
+            // Cleanup outer class' state immediately, otherwise race conditions may ensue.
+            cleanupVpnState();
+
+            mExecutor.execute(() -> {
+                shutdownVpnRunner();
+            });
         }
     }
 
@@ -2484,12 +2846,46 @@
                         throw new IllegalArgumentException("No profile found for " + packageName);
                     }
 
-                    startVpnProfilePrivileged(profile);
+                    startVpnProfilePrivileged(profile, packageName);
                 });
     }
 
-    private void startVpnProfilePrivileged(@NonNull VpnProfile profile) {
-        // TODO: Start PlatformVpnRunner
+    private void startVpnProfilePrivileged(
+            @NonNull VpnProfile profile, @NonNull String packageName) {
+        // Ensure that no other previous instance is running.
+        if (mVpnRunner != null) {
+            mVpnRunner.exit();
+            mVpnRunner = null;
+        }
+        updateState(DetailedState.CONNECTING, "startPlatformVpn");
+
+        try {
+            // Build basic config
+            mConfig = new VpnConfig();
+            mConfig.user = packageName;
+            mConfig.isMetered = profile.isMetered;
+            mConfig.startTime = SystemClock.elapsedRealtime();
+            mConfig.proxyInfo = profile.proxy;
+
+            switch (profile.type) {
+                case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
+                case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
+                case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
+                    mVpnRunner = new IkeV2VpnRunner(Ikev2VpnProfile.fromVpnProfile(profile));
+                    mVpnRunner.start();
+                    break;
+                default:
+                    updateState(DetailedState.FAILED, "Invalid platform VPN type");
+                    Log.d(TAG, "Unknown VPN profile type: " + profile.type);
+                    break;
+            }
+        } catch (IOException | GeneralSecurityException e) {
+            // Reset mConfig
+            mConfig = null;
+
+            updateState(DetailedState.FAILED, "VPN startup failed");
+            throw new IllegalArgumentException("VPN startup failed", e);
+        }
     }
 
     /**
@@ -2503,13 +2899,37 @@
     public synchronized void stopVpnProfile(@NonNull String packageName) {
         checkNotNull(packageName, "No package name provided");
 
-        // To stop the VPN profile, the caller must be the current prepared package. Otherwise,
-        // the app is not prepared, and we can just return.
-        if (!isCurrentPreparedPackage(packageName)) {
-            // TODO: Also check to make sure that the running VPN is a VPN profile.
+        // To stop the VPN profile, the caller must be the current prepared package and must be
+        // running an Ikev2VpnProfile.
+        if (!isCurrentPreparedPackage(packageName) && mVpnRunner instanceof IkeV2VpnRunner) {
             return;
         }
 
         prepareInternal(VpnConfig.LEGACY_VPN);
     }
+
+    /**
+     * Proxy to allow testing
+     *
+     * @hide
+     */
+    @VisibleForTesting
+    public static class Ikev2SessionCreator {
+        /** Creates a IKE session */
+        public IkeSession createIkeSession(
+                @NonNull Context context,
+                @NonNull IkeSessionParams ikeSessionParams,
+                @NonNull ChildSessionParams firstChildSessionParams,
+                @NonNull Executor userCbExecutor,
+                @NonNull IkeSessionCallback ikeSessionCallback,
+                @NonNull ChildSessionCallback firstChildSessionCallback) {
+            return new IkeSession(
+                    context,
+                    ikeSessionParams,
+                    firstChildSessionParams,
+                    userCbExecutor,
+                    ikeSessionCallback,
+                    firstChildSessionCallback);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
new file mode 100644
index 0000000..33fc32b
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import static android.net.ConnectivityManager.NetworkCallback;
+import static android.net.ipsec.ike.SaProposal.DH_GROUP_1024_BIT_MODP;
+import static android.net.ipsec.ike.SaProposal.DH_GROUP_2048_BIT_MODP;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
+import static android.net.ipsec.ike.SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
+import static android.net.ipsec.ike.SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256;
+import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_128;
+import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_192;
+import static android.net.ipsec.ike.SaProposal.KEY_LEN_AES_256;
+import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
+import static android.net.ipsec.ike.SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1;
+
+import android.annotation.NonNull;
+import android.net.Ikev2VpnProfile;
+import android.net.InetAddresses;
+import android.net.IpPrefix;
+import android.net.IpSecManager.UdpEncapsulationSocket;
+import android.net.IpSecTransform;
+import android.net.Network;
+import android.net.RouteInfo;
+import android.net.eap.EapSessionConfig;
+import android.net.ipsec.ike.ChildSaProposal;
+import android.net.ipsec.ike.ChildSessionCallback;
+import android.net.ipsec.ike.ChildSessionConfiguration;
+import android.net.ipsec.ike.ChildSessionParams;
+import android.net.ipsec.ike.IkeFqdnIdentification;
+import android.net.ipsec.ike.IkeIdentification;
+import android.net.ipsec.ike.IkeIpv4AddrIdentification;
+import android.net.ipsec.ike.IkeIpv6AddrIdentification;
+import android.net.ipsec.ike.IkeKeyIdIdentification;
+import android.net.ipsec.ike.IkeRfc822AddrIdentification;
+import android.net.ipsec.ike.IkeSaProposal;
+import android.net.ipsec.ike.IkeSessionCallback;
+import android.net.ipsec.ike.IkeSessionConfiguration;
+import android.net.ipsec.ike.IkeSessionParams;
+import android.net.ipsec.ike.IkeTrafficSelector;
+import android.net.ipsec.ike.TunnelModeChildSessionParams;
+import android.net.ipsec.ike.exceptions.IkeException;
+import android.net.ipsec.ike.exceptions.IkeProtocolException;
+import android.net.util.IpRange;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.internal.net.VpnProfile;
+import com.android.internal.util.HexDump;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * Utility class to build and convert IKEv2/IPsec parameters.
+ *
+ * @hide
+ */
+public class VpnIkev2Utils {
+    static IkeSessionParams buildIkeSessionParams(
+            @NonNull Ikev2VpnProfile profile, @NonNull UdpEncapsulationSocket socket) {
+        // TODO(b/149356682): Update this based on new IKE API. Only numeric addresses supported
+        //                    until then. All others throw IAE (caught by caller).
+        final InetAddress serverAddr = InetAddresses.parseNumericAddress(profile.getServerAddr());
+        final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity());
+        final IkeIdentification remoteId = parseIkeIdentification(profile.getServerAddr());
+
+        // TODO(b/149356682): Update this based on new IKE API.
+        final IkeSessionParams.Builder ikeOptionsBuilder =
+                new IkeSessionParams.Builder()
+                        .setServerAddress(serverAddr)
+                        .setUdpEncapsulationSocket(socket)
+                        .setLocalIdentification(localId)
+                        .setRemoteIdentification(remoteId);
+        setIkeAuth(profile, ikeOptionsBuilder);
+
+        for (final IkeSaProposal ikeProposal : getIkeSaProposals()) {
+            ikeOptionsBuilder.addSaProposal(ikeProposal);
+        }
+
+        return ikeOptionsBuilder.build();
+    }
+
+    static ChildSessionParams buildChildSessionParams() {
+        final TunnelModeChildSessionParams.Builder childOptionsBuilder =
+                new TunnelModeChildSessionParams.Builder();
+
+        for (final ChildSaProposal childProposal : getChildSaProposals()) {
+            childOptionsBuilder.addSaProposal(childProposal);
+        }
+
+        childOptionsBuilder.addInternalAddressRequest(OsConstants.AF_INET);
+        childOptionsBuilder.addInternalAddressRequest(OsConstants.AF_INET6);
+        childOptionsBuilder.addInternalDnsServerRequest(OsConstants.AF_INET);
+        childOptionsBuilder.addInternalDnsServerRequest(OsConstants.AF_INET6);
+
+        return childOptionsBuilder.build();
+    }
+
+    private static void setIkeAuth(
+            @NonNull Ikev2VpnProfile profile, @NonNull IkeSessionParams.Builder builder) {
+        switch (profile.getType()) {
+            case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
+                final EapSessionConfig eapConfig =
+                        new EapSessionConfig.Builder()
+                                .setEapMsChapV2Config(profile.getUsername(), profile.getPassword())
+                                .build();
+                builder.setAuthEap(profile.getServerRootCaCert(), eapConfig);
+                break;
+            case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
+                builder.setAuthPsk(profile.getPresharedKey());
+                break;
+            case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
+                builder.setAuthDigitalSignature(
+                        profile.getServerRootCaCert(),
+                        profile.getUserCert(),
+                        profile.getRsaPrivateKey());
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown auth method set");
+        }
+    }
+
+    private static List<IkeSaProposal> getIkeSaProposals() {
+        // TODO: filter this based on allowedAlgorithms
+        final List<IkeSaProposal> proposals = new ArrayList<>();
+
+        // Encryption Algorithms: Currently only AES_CBC is supported.
+        final IkeSaProposal.Builder normalModeBuilder = new IkeSaProposal.Builder();
+
+        // Currently only AES_CBC is supported.
+        normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256);
+        normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192);
+        normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128);
+
+        // Authentication/Integrity Algorithms
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256);
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192);
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_AES_XCBC_96);
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+
+        // Add AEAD options
+        final IkeSaProposal.Builder aeadBuilder = new IkeSaProposal.Builder();
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128);
+
+        // Add dh, prf for both builders
+        for (final IkeSaProposal.Builder builder : Arrays.asList(normalModeBuilder, aeadBuilder)) {
+            builder.addDhGroup(DH_GROUP_2048_BIT_MODP);
+            builder.addDhGroup(DH_GROUP_1024_BIT_MODP);
+            builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_AES128_XCBC);
+            builder.addPseudorandomFunction(PSEUDORANDOM_FUNCTION_HMAC_SHA1);
+        }
+
+        proposals.add(normalModeBuilder.build());
+        proposals.add(aeadBuilder.build());
+        return proposals;
+    }
+
+    private static List<ChildSaProposal> getChildSaProposals() {
+        // TODO: filter this based on allowedAlgorithms
+        final List<ChildSaProposal> proposals = new ArrayList<>();
+
+        // Add non-AEAD options
+        final ChildSaProposal.Builder normalModeBuilder = new ChildSaProposal.Builder();
+
+        // Encryption Algorithms: Currently only AES_CBC is supported.
+        normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_256);
+        normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_192);
+        normalModeBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_CBC, KEY_LEN_AES_128);
+
+        // Authentication/Integrity Algorithms
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_512_256);
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_384_192);
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA2_256_128);
+        normalModeBuilder.addIntegrityAlgorithm(INTEGRITY_ALGORITHM_HMAC_SHA1_96);
+
+        // Add AEAD options
+        final ChildSaProposal.Builder aeadBuilder = new ChildSaProposal.Builder();
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_256);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_256);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_256);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_192);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_192);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_192);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_16, KEY_LEN_AES_128);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_12, KEY_LEN_AES_128);
+        aeadBuilder.addEncryptionAlgorithm(ENCRYPTION_ALGORITHM_AES_GCM_8, KEY_LEN_AES_128);
+
+        proposals.add(normalModeBuilder.build());
+        proposals.add(aeadBuilder.build());
+        return proposals;
+    }
+
+    static class IkeSessionCallbackImpl implements IkeSessionCallback {
+        private final String mTag;
+        private final Vpn.IkeV2VpnRunnerCallback mCallback;
+        private final Network mNetwork;
+
+        IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) {
+            mTag = tag;
+            mCallback = callback;
+            mNetwork = network;
+        }
+
+        @Override
+        public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) {
+            Log.d(mTag, "IkeOpened for network " + mNetwork);
+            // Nothing to do here.
+        }
+
+        @Override
+        public void onClosed() {
+            Log.d(mTag, "IkeClosed for network " + mNetwork);
+            mCallback.onSessionLost(mNetwork); // Server requested session closure. Retry?
+        }
+
+        @Override
+        public void onClosedExceptionally(@NonNull IkeException exception) {
+            Log.d(mTag, "IkeClosedExceptionally for network " + mNetwork, exception);
+            mCallback.onSessionLost(mNetwork);
+        }
+
+        @Override
+        public void onError(@NonNull IkeProtocolException exception) {
+            Log.d(mTag, "IkeError for network " + mNetwork, exception);
+            // Non-fatal, log and continue.
+        }
+    }
+
+    static class ChildSessionCallbackImpl implements ChildSessionCallback {
+        private final String mTag;
+        private final Vpn.IkeV2VpnRunnerCallback mCallback;
+        private final Network mNetwork;
+
+        ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) {
+            mTag = tag;
+            mCallback = callback;
+            mNetwork = network;
+        }
+
+        @Override
+        public void onOpened(@NonNull ChildSessionConfiguration childConfig) {
+            Log.d(mTag, "ChildOpened for network " + mNetwork);
+            mCallback.onChildOpened(mNetwork, childConfig);
+        }
+
+        @Override
+        public void onClosed() {
+            Log.d(mTag, "ChildClosed for network " + mNetwork);
+            mCallback.onSessionLost(mNetwork);
+        }
+
+        @Override
+        public void onClosedExceptionally(@NonNull IkeException exception) {
+            Log.d(mTag, "ChildClosedExceptionally for network " + mNetwork, exception);
+            mCallback.onSessionLost(mNetwork);
+        }
+
+        @Override
+        public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) {
+            Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; network " + mNetwork);
+            mCallback.onChildTransformCreated(mNetwork, transform, direction);
+        }
+
+        @Override
+        public void onIpSecTransformDeleted(@NonNull IpSecTransform transform, int direction) {
+            // Nothing to be done; no references to the IpSecTransform are held by the
+            // Ikev2VpnRunner (or this callback class), and this transform will be closed by the
+            // IKE library.
+            Log.d(mTag,
+                    "ChildTransformDeleted; Direction: " + direction + "; for network " + mNetwork);
+        }
+    }
+
+    static class Ikev2VpnNetworkCallback extends NetworkCallback {
+        private final String mTag;
+        private final Vpn.IkeV2VpnRunnerCallback mCallback;
+
+        Ikev2VpnNetworkCallback(String tag, Vpn.IkeV2VpnRunnerCallback callback) {
+            mTag = tag;
+            mCallback = callback;
+        }
+
+        @Override
+        public void onAvailable(@NonNull Network network) {
+            Log.d(mTag, "Starting IKEv2/IPsec session on new network: " + network);
+            mCallback.onDefaultNetworkChanged(network);
+        }
+
+        @Override
+        public void onLost(@NonNull Network network) {
+            Log.d(mTag, "Tearing down; lost network: " + network);
+            mCallback.onSessionLost(network);
+        }
+    }
+
+    /**
+     * Identity parsing logic using similar logic to open source implementations of IKEv2
+     *
+     * <p>This method does NOT support using type-prefixes (eg 'fqdn:' or 'keyid'), or ASN.1 encoded
+     * identities.
+     */
+    private static IkeIdentification parseIkeIdentification(@NonNull String identityStr) {
+        // TODO: Add identity formatting to public API javadocs.
+        if (identityStr.contains("@")) {
+            if (identityStr.startsWith("@#")) {
+                // KEY_ID
+                final String hexStr = identityStr.substring(2);
+                return new IkeKeyIdIdentification(HexDump.hexStringToByteArray(hexStr));
+            } else if (identityStr.startsWith("@@")) {
+                // RFC822 (USER_FQDN)
+                return new IkeRfc822AddrIdentification(identityStr.substring(2));
+            } else if (identityStr.startsWith("@")) {
+                // FQDN
+                return new IkeFqdnIdentification(identityStr.substring(1));
+            } else {
+                // RFC822 (USER_FQDN)
+                return new IkeRfc822AddrIdentification(identityStr);
+            }
+        } else if (InetAddresses.isNumericAddress(identityStr)) {
+            final InetAddress addr = InetAddresses.parseNumericAddress(identityStr);
+            if (addr instanceof Inet4Address) {
+                // IPv4
+                return new IkeIpv4AddrIdentification((Inet4Address) addr);
+            } else if (addr instanceof Inet6Address) {
+                // IPv6
+                return new IkeIpv6AddrIdentification((Inet6Address) addr);
+            } else {
+                throw new IllegalArgumentException("IP version not supported");
+            }
+        } else {
+            if (identityStr.contains(":")) {
+                // KEY_ID
+                return new IkeKeyIdIdentification(identityStr.getBytes());
+            } else {
+                // FQDN
+                return new IkeFqdnIdentification(identityStr);
+            }
+        }
+    }
+
+    static Collection<RouteInfo> getRoutesFromTrafficSelectors(
+            List<IkeTrafficSelector> trafficSelectors) {
+        final HashSet<RouteInfo> routes = new HashSet<>();
+
+        for (final IkeTrafficSelector selector : trafficSelectors) {
+            for (final IpPrefix prefix :
+                    new IpRange(selector.startingAddress, selector.endingAddress).asIpPrefixes()) {
+                routes.add(new RouteInfo(prefix, null));
+            }
+        }
+
+        return routes;
+    }
+}
diff --git a/services/core/xsd/vts/Android.bp b/services/core/xsd/vts/Android.bp
index 5545656..636d110 100644
--- a/services/core/xsd/vts/Android.bp
+++ b/services/core/xsd/vts/Android.bp
@@ -31,4 +31,12 @@
         "-Wall",
         "-Werror",
     ],
+    data: [
+        ":default-permissions",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core"
+    ],
+    test_config: "vts_defaultPermissions_validate_test.xml",
 }
diff --git a/services/core/xsd/vts/vts_defaultPermissions_validate_test.xml b/services/core/xsd/vts/vts_defaultPermissions_validate_test.xml
new file mode 100644
index 0000000..1ccacae
--- /dev/null
+++ b/services/core/xsd/vts/vts_defaultPermissions_validate_test.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs vts_defaultPermissions_validate_test.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="default-permissions.xsd->/data/local/tmp/default-permissions.xsd" />
+        <option name="push" value="vts_defaultPermissions_validate_test->/data/local/tmp/vts_defaultPermissions_validate_test" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="vts_defaultPermissions_validate_test" />
+    </test>
+</configuration>
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index ec99f36..52213d8 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -17,6 +17,7 @@
 package android.telecom;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -458,8 +459,14 @@
         /** Call supports the deflect feature. */
         public static final int CAPABILITY_SUPPORT_DEFLECT = 0x01000000;
 
+        /**
+         * Call supports adding participants to the call via
+         * {@link #addConferenceParticipants(List)}.
+         * @hide
+         */
+        public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
         //******************************************************************************************
-        // Next CAPABILITY value: 0x02000000
+        // Next CAPABILITY value: 0x04000000
         //******************************************************************************************
 
         /**
@@ -539,7 +546,7 @@
          *
          * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
          */
-        public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
+        public static final int PROPERTY_ASSISTED_DIALING = 0x00000200;
 
         /**
          * Indicates that the call is an RTT call. Use {@link #getRttCall()} to get the
@@ -689,6 +696,9 @@
             if (can(capabilities, CAPABILITY_SUPPORT_DEFLECT)) {
                 builder.append(" CAPABILITY_SUPPORT_DEFLECT");
             }
+            if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
+                builder.append(" CAPABILITY_ADD_PARTICIPANT");
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -744,7 +754,7 @@
             if (hasProperty(properties, PROPERTY_HAS_CDMA_VOICE_PRIVACY)) {
                 builder.append(" PROPERTY_HAS_CDMA_VOICE_PRIVACY");
             }
-            if (hasProperty(properties, PROPERTY_ASSISTED_DIALING_USED)) {
+            if (hasProperty(properties, PROPERTY_ASSISTED_DIALING)) {
                 builder.append(" PROPERTY_ASSISTED_DIALING_USED");
             }
             if (hasProperty(properties, PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL)) {
@@ -1703,6 +1713,17 @@
     }
 
     /**
+     * Pulls participants to existing call by forming a conference call.
+     * See {@link Details#CAPABILITY_ADD_PARTICIPANT}.
+     *
+     * @param participants participants to be pulled to existing call.
+     * @hide
+     */
+    public void addConferenceParticipants(@NonNull List<Uri> participants) {
+        mInCallAdapter.addConferenceParticipants(mTelecomCallId, participants);
+    }
+
+    /**
      * Initiates a request to the {@link ConnectionService} to pull an external call to the local
      * device.
      * <p>
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 56acdff..f019a9d 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -16,8 +16,13 @@
 
 package android.telecom;
 
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.net.Uri;
@@ -319,6 +324,13 @@
     public void onConnectionAdded(Connection connection) {}
 
     /**
+     * Notifies the {@link Conference} of a request to add a new participants to the conference call
+     * @param participants that will be added to this conference call
+     * @hide
+     */
+    public void onAddConferenceParticipants(@NonNull List<Uri> participants) {}
+
+    /**
      * Notifies this Conference, which is in {@code STATE_RINGING}, of
      * a request to accept.
      * For managed {@link ConnectionService}s, this will be called when the user answers a call via
@@ -625,12 +637,12 @@
      * Should be specified in wall-clock time returned by {@link System#currentTimeMillis()}.
      * <p>
      * When setting the connection time, you should always set the connection elapsed time via
-     * {@link #setConnectionStartElapsedRealTime(long)} to ensure the duration is reflected.
+     * {@link #setConnectionStartElapsedRealtimeMillis(long)} to ensure the duration is reflected.
      *
      * @param connectionTimeMillis The connection time, in milliseconds, as returned by
      *                             {@link System#currentTimeMillis()}.
      */
-    public final void setConnectionTime(long connectionTimeMillis) {
+    public final void setConnectionTime(@IntRange(from = 0) long connectionTimeMillis) {
         mConnectTimeMillis = connectionTimeMillis;
     }
 
@@ -646,8 +658,28 @@
      *
      * @param connectionStartElapsedRealTime The connection time, as measured by
      * {@link SystemClock#elapsedRealtime()}.
+     * @deprecated use {@link #setConnectionStartElapsedRealtimeMillis(long)} instead.
      */
+    @Deprecated
     public final void setConnectionStartElapsedRealTime(long connectionStartElapsedRealTime) {
+        setConnectionStartElapsedRealtimeMillis(connectionStartElapsedRealTime);
+    }
+
+    /**
+     * Sets the start time of the {@link Conference} which is the basis for the determining the
+     * duration of the {@link Conference}.
+     * <p>
+     * You should use a value returned by {@link SystemClock#elapsedRealtime()} to ensure that time
+     * zone changes do not impact the conference duration.
+     * <p>
+     * When setting this, you should also set the connection time via
+     * {@link #setConnectionTime(long)}.
+     *
+     * @param connectionStartElapsedRealTime The connection time, as measured by
+     * {@link SystemClock#elapsedRealtime()}.
+     */
+    public final void setConnectionStartElapsedRealtimeMillis(
+            @ElapsedRealtimeLong long connectionStartElapsedRealTime) {
         mConnectionStartElapsedRealTime = connectionStartElapsedRealTime;
     }
 
@@ -668,7 +700,7 @@
      *
      * @return The time at which the {@code Conference} was connected.
      */
-    public final long getConnectionTime() {
+    public final @IntRange(from = 0) long getConnectionTime() {
         return mConnectTimeMillis;
     }
 
@@ -685,11 +717,8 @@
      * has no general use other than to the Telephony framework.
      *
      * @return The elapsed time at which the {@link Conference} was connected.
-     * @hide
      */
-    @SystemApi
-    @TestApi
-    public final long getConnectionStartElapsedRealTime() {
+    public final @ElapsedRealtimeLong long getConnectionStartElapsedRealtimeMillis() {
         return mConnectionStartElapsedRealTime;
     }
 
@@ -987,6 +1016,7 @@
      */
     @SystemApi
     @TestApi
+    @RequiresPermission(MODIFY_PHONE_STATE)
     public void setConferenceState(boolean isConference) {
         for (Listener l : mListeners) {
             l.onConferenceStateChanged(this, isConference);
@@ -1007,6 +1037,7 @@
      */
     @SystemApi
     @TestApi
+    @RequiresPermission(MODIFY_PHONE_STATE)
     public final void setAddress(@NonNull Uri address,
             @TelecomManager.Presentation int presentation) {
         Log.d(this, "setAddress %s", address);
@@ -1113,12 +1144,52 @@
     }
 
     /**
-     * Sends an event associated with this {@code Conference} with associated event extras to the
-     * {@link InCallService} (note: this is identical in concept to
-     * {@link Connection#sendConnectionEvent(String, Bundle)}).
-     * @see Connection#sendConnectionEvent(String, Bundle)
+     * Sends an event associated with this {@link Conference} with associated event extras to the
+     * {@link InCallService}.
+     * <p>
+     * Connection events are used to communicate point in time information from a
+     * {@link ConnectionService} to an {@link InCallService} implementation.  An example of a
+     * custom connection event includes notifying the UI when a WIFI call has been handed over to
+     * LTE, which the InCall UI might use to inform the user that billing charges may apply.  The
+     * Android Telephony framework will send the {@link Connection#EVENT_MERGE_COMPLETE}
+     * connection event when a call to {@link Call#mergeConference()} has completed successfully.
+     * <p>
+     * Events are exposed to {@link InCallService} implementations via
+     * {@link Call.Callback#onConnectionEvent(Call, String, Bundle)}.
+     * <p>
+     * No assumptions should be made as to how an In-Call UI or service will handle these events.
+     * The {@link ConnectionService} must assume that the In-Call UI could even chose to ignore
+     * some events altogether.
+     * <p>
+     * Events should be fully qualified (e.g. {@code com.example.event.MY_EVENT}) to avoid
+     * conflicts between {@link ConnectionService} implementations.  Further, custom
+     * {@link ConnectionService} implementations shall not re-purpose events in the
+     * {@code android.*} namespace, nor shall they define new event types in this namespace.  When
+     * defining a custom event type, ensure the contents of the extras {@link Bundle} is clearly
+     * defined.  Extra keys for this bundle should be named similar to the event type (e.g.
+     * {@code com.example.extra.MY_EXTRA}).
+     * <p>
+     * When defining events and the associated extras, it is important to keep their behavior
+     * consistent when the associated {@link ConnectionService} is updated.  Support for deprecated
+     * events/extras should me maintained to ensure backwards compatibility with older
+     * {@link InCallService} implementations which were built to support the older behavior.
+     * <p>
+     * Expected connection events from the Telephony stack are:
+     * <p>
+     * <ul>
+     *      <li>{@link Connection#EVENT_CALL_HOLD_FAILED} with {@code null} {@code extras} when the
+     *      {@link Conference} could not be held.</li>
+     *      <li>{@link Connection#EVENT_MERGE_START} with {@code null} {@code extras} when a new
+     *      call is being merged into the conference.</li>
+     *      <li>{@link Connection#EVENT_MERGE_COMPLETE} with {@code null} {@code extras} a new call
+     *      has completed being merged into the conference.</li>
+     *      <li>{@link Connection#EVENT_CALL_MERGE_FAILED} with {@code null} {@code extras} a new
+     *      call has failed to merge into the conference (the dialer app can determine which call
+     *      failed to merge based on the fact that the call still exists outside of the conference
+     *      at the end of the merge process).</li>
+     * </ul>
      *
-     * @param event The connection event.
+     * @param event The conference event.
      * @param extras Optional bundle containing extra information associated with the event.
      */
     public void sendConferenceEvent(@NonNull String event, @Nullable Bundle extras) {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 8049459..3b0ba25 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -16,9 +16,14 @@
 
 package android.telecom;
 
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.app.Notification;
@@ -376,8 +381,14 @@
     /** Call supports the deflect feature. */
     public static final int CAPABILITY_SUPPORT_DEFLECT = 0x02000000;
 
+    /**
+     * When set, indicates that this {@link Connection} supports initiation of a conference call
+     * by directly adding participants using {@link #onAddConferenceParticipants(List)}.
+     * @hide
+     */
+    public static final int CAPABILITY_ADD_PARTICIPANT = 0x04000000;
     //**********************************************************************************************
-    // Next CAPABILITY value: 0x04000000
+    // Next CAPABILITY value: 0x08000000
     //**********************************************************************************************
 
     /**
@@ -474,7 +485,7 @@
      *
      * @see TelecomManager#EXTRA_USE_ASSISTED_DIALING
      */
-    public static final int PROPERTY_ASSISTED_DIALING_USED = 1 << 9;
+    public static final int PROPERTY_ASSISTED_DIALING = 1 << 9;
 
     /**
      * Set by the framework to indicate that the network has identified a Connection as an emergency
@@ -953,7 +964,9 @@
         if ((capabilities & CAPABILITY_SUPPORT_DEFLECT) == CAPABILITY_SUPPORT_DEFLECT) {
             builder.append(isLong ? " CAPABILITY_SUPPORT_DEFLECT" : " sup_def");
         }
-
+        if ((capabilities & CAPABILITY_ADD_PARTICIPANT) == CAPABILITY_ADD_PARTICIPANT) {
+            builder.append(isLong ? " CAPABILITY_ADD_PARTICIPANT" : " add_participant");
+        }
         builder.append("]");
         return builder.toString();
     }
@@ -2109,19 +2122,24 @@
      */
     @SystemApi
     @TestApi
-    public final long getConnectTimeMillis() {
+    public final @IntRange(from = 0) long getConnectTimeMillis() {
         return mConnectTimeMillis;
     }
 
     /**
      * Retrieves the connection start time of the {@link Connection}, if specified.  A value of
      * {@link Conference#CONNECT_TIME_NOT_SPECIFIED} indicates that Telecom should determine the
-     * start time of the conference.
+     * start time of the connection.
      * <p>
      * Based on the value of {@link SystemClock#elapsedRealtime()}, which ensures that wall-clock
      * changes do not impact the call duration.
      * <p>
      * Used internally in Telephony when migrating conference participant data for IMS conferences.
+     * <p>
+     * The value returned is the same one set using
+     * {@link #setConnectionStartElapsedRealtimeMillis(long)}.  This value is never updated from
+     * the Telecom framework, so no permission enforcement occurs when retrieving the value with
+     * this method.
      *
      * @return The time at which the {@link Connection} was connected.
      *
@@ -2129,7 +2147,7 @@
      */
     @SystemApi
     @TestApi
-    public final long getConnectElapsedTimeMillis() {
+    public final @ElapsedRealtimeLong long getConnectionStartElapsedRealtimeMillis() {
         return mConnectElapsedTimeMillis;
     }
 
@@ -2550,6 +2568,9 @@
      * Sets the time at which a call became active on this Connection. This is set only
      * when a conference call becomes active on this connection.
      * <p>
+     * This time corresponds to the date/time of connection and is stored in the call log in
+     * {@link android.provider.CallLog.Calls#DATE}.
+     * <p>
      * Used by telephony to maintain calls associated with an IMS Conference.
      *
      * @param connectTimeMillis The connection time, in milliseconds.  Should be set using a value
@@ -2559,7 +2580,8 @@
      */
     @SystemApi
     @TestApi
-    public final void setConnectTimeMillis(long connectTimeMillis) {
+    @RequiresPermission(MODIFY_PHONE_STATE)
+    public final void setConnectTimeMillis(@IntRange(from = 0) long connectTimeMillis) {
         mConnectTimeMillis = connectTimeMillis;
     }
 
@@ -2567,15 +2589,23 @@
      * Sets the time at which a call became active on this Connection. This is set only
      * when a conference call becomes active on this connection.
      * <p>
+     * This time is used to establish the duration of a call.  It uses
+     * {@link SystemClock#elapsedRealtime()} to ensure that the call duration is not impacted by
+     * time zone changes during a call.  The difference between the current
+     * {@link SystemClock#elapsedRealtime()} and the value set at the connection start time is used
+     * to populate {@link android.provider.CallLog.Calls#DURATION} in the call log.
+     * <p>
      * Used by telephony to maintain calls associated with an IMS Conference.
+     *
      * @param connectElapsedTimeMillis The connection time, in milliseconds.  Stored in the format
      *                              {@link SystemClock#elapsedRealtime()}.
-     *
      * @hide
      */
     @SystemApi
     @TestApi
-    public final void setConnectionStartElapsedRealTime(long connectElapsedTimeMillis) {
+    @RequiresPermission(MODIFY_PHONE_STATE)
+    public final void setConnectionStartElapsedRealtimeMillis(
+            @ElapsedRealtimeLong long connectElapsedTimeMillis) {
         mConnectElapsedTimeMillis = connectElapsedTimeMillis;
     }
 
@@ -2953,6 +2983,14 @@
     public void onSeparate() {}
 
     /**
+     * Supports initiation of a conference call by directly adding participants to an ongoing call.
+     *
+     * @param participants with which conference call will be formed.
+     * @hide
+     */
+    public void onAddConferenceParticipants(@NonNull List<Uri> participants) {}
+
+    /**
      * Notifies this Connection of a request to abort.
      */
     public void onAbort() {}
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 00c2918..2aea723 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -18,7 +18,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.app.Service;
@@ -142,6 +141,7 @@
     private static final String SESSION_SPLIT_CONFERENCE = "CS.sFC";
     private static final String SESSION_MERGE_CONFERENCE = "CS.mC";
     private static final String SESSION_SWAP_CONFERENCE = "CS.sC";
+    private static final String SESSION_ADD_PARTICIPANT = "CS.aP";
     private static final String SESSION_POST_DIAL_CONT = "CS.oPDC";
     private static final String SESSION_PULL_EXTERNAL_CALL = "CS.pEC";
     private static final String SESSION_SEND_CALL_EVENT = "CS.sCE";
@@ -195,6 +195,7 @@
     private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36;
     private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
     private static final int MSG_REJECT_WITH_REASON = 38;
+    private static final int MSG_ADD_PARTICIPANT = 39;
 
     private static Connection sNullConnection;
 
@@ -627,6 +628,21 @@
         }
 
         @Override
+        public void addConferenceParticipants(String callId, List<Uri> participants,
+                Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_ADD_PARTICIPANT);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.arg2 = participants;
+                args.arg3 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_ADD_PARTICIPANT, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void onPostDialContinue(String callId, boolean proceed, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, SESSION_POST_DIAL_CONT);
             try {
@@ -1224,6 +1240,19 @@
                     }
                     break;
                 }
+                case MSG_ADD_PARTICIPANT: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    try {
+                        Log.continueSession((Session) args.arg3,
+                                SESSION_HANDLER + SESSION_ADD_PARTICIPANT);
+                        addConferenceParticipants((String) args.arg1, (List<Uri>)args.arg2);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
+
                 case MSG_ON_POST_DIAL_CONTINUE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     try {
@@ -1778,7 +1807,7 @@
                         null : conference.getVideoProvider().getInterface(),
                 conference.getVideoState(),
                 conference.getConnectTimeMillis(),
-                conference.getConnectionStartElapsedRealTime(),
+                conference.getConnectionStartElapsedRealtimeMillis(),
                 conference.getStatusHints(),
                 conference.getExtras(),
                 conference.getAddress(),
@@ -1884,7 +1913,7 @@
                         connection.isRingbackRequested(),
                         connection.getAudioModeIsVoip(),
                         connection.getConnectTimeMillis(),
-                        connection.getConnectElapsedTimeMillis(),
+                        connection.getConnectionStartElapsedRealtimeMillis(),
                         connection.getStatusHints(),
                         connection.getDisconnectCause(),
                         createIdList(connection.getConferenceables()),
@@ -2152,6 +2181,17 @@
         }
     }
 
+    private void addConferenceParticipants(String callId, List<Uri> participants) {
+        Log.d(this, "addConferenceParticipants(%s)", callId);
+        if (mConnectionById.containsKey(callId)) {
+            findConnectionForAction(callId, "addConferenceParticipants")
+                    .onAddConferenceParticipants(participants);
+        } else {
+            findConferenceForAction(callId, "addConferenceParticipants")
+                    .onAddConferenceParticipants(participants);
+        }
+    }
+
     /**
      * Notifies a {@link Connection} of a request to pull an external call.
      *
@@ -2374,7 +2414,7 @@
                             null : conference.getVideoProvider().getInterface(),
                     conference.getVideoState(),
                     conference.getConnectTimeMillis(),
-                    conference.getConnectionStartElapsedRealTime(),
+                    conference.getConnectionStartElapsedRealtimeMillis(),
                     conference.getStatusHints(),
                     conference.getExtras(),
                     conference.getAddress(),
@@ -2465,7 +2505,7 @@
                     connection.isRingbackRequested(),
                     connection.getAudioModeIsVoip(),
                     connection.getConnectTimeMillis(),
-                    connection.getConnectElapsedTimeMillis(),
+                    connection.getConnectionStartElapsedRealtimeMillis(),
                     connection.getStatusHints(),
                     connection.getDisconnectCause(),
                     emptyList,
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 594c1eb..9d291740 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -283,6 +283,20 @@
     }
 
     /**
+     * Instructs Telecom to pull participants to existing call
+     *
+     * @param callId The unique ID of the call.
+     * @param participants participants to be pulled to existing call.
+     */
+    public void addConferenceParticipants(String callId, List<Uri> participants) {
+        try {
+            mAdapter.addConferenceParticipants(callId, participants);
+        } catch (RemoteException ignored) {
+        }
+    }
+
+
+    /**
      * Instructs Telecom to split the specified call from any conference call with which it may be
      * connected.
      *
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index ebfa3a1..982e5f3 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -20,6 +20,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.app.Service;
+import android.app.UiModeManager;
 import android.bluetooth.BluetoothDevice;
 import android.content.Intent;
 import android.hardware.camera2.CameraManager;
@@ -43,12 +44,32 @@
  * phone calls.
  * <h2>Becoming the Default Phone App</h2>
  * The default dialer/phone app is one which provides the in-call user interface while the device is
- * in a call.  A device is bundled with a system provided default dialer/phone app.  The user may
- * choose a single app to take over this role from the system app.  An app which wishes to fulfill
- * one this role uses the {@code android.app.role.RoleManager} to request that they fill the role.
+ * in a call.  It also provides the user with a means to initiate calls and see a history of calls
+ * on their device.  A device is bundled with a system provided default dialer/phone app.  The user
+ * may choose a single app to take over this role from the system app.  An app which wishes to
+ * fulfill one this role uses the {@link android.app.role.RoleManager} to request that they fill the
+ * {@link android.app.role.RoleManager#ROLE_DIALER} role.
  * <p>
- * An app filling the role of the default phone app provides a user interface while the device is in
- * a call, and the device is not in car mode.
+ * The default phone app provides a user interface while the device is in a call, and the device is
+ * not in car mode (i.e. {@link UiModeManager#getCurrentModeType()} is not
+ * {@link android.content.res.Configuration#UI_MODE_TYPE_CAR}).
+ * <p>
+ * In order to fill the {@link android.app.role.RoleManager#ROLE_DIALER} role, an app must meet a
+ * number of requirements:
+ * <ul>
+ *     <li>It must handle the {@link Intent#ACTION_DIAL} intent.  This means the app must provide
+ *     a dial pad UI for the user to initiate outgoing calls.</li>
+ *     <li>It must fully implement the {@link InCallService} API and provide both an incoming call
+ *     UI, as well as an ongoing call UI.</li>
+ * </ul>
+ * <p>
+ * Note: If the app filling the {@link android.app.role.RoleManager#ROLE_DIALER} crashes during
+ * {@link InCallService} binding, the Telecom framework will automatically fall back to using the
+ * dialer app pre-loaded on the device.  The system will display a notification to the user to let
+ * them know that the app has crashed and that their call was continued using the pre-loaded dialer
+ * app.
+ * <p>
+ * Further, the pre-loaded dialer will ALWAYS be used when the user places an emergency call.
  * <p>
  * Below is an example manifest registration for an {@code InCallService}. The meta-data
  * {@link TelecomManager#METADATA_IN_CALL_SERVICE_UI} indicates that this particular
@@ -82,6 +103,11 @@
  *           <action android:name="android.intent.action.DIAL" />
  *           <category android:name="android.intent.category.DEFAULT" />
  *      </intent-filter>
+ *      <intent-filter>
+ *           <action android:name="android.intent.action.DIAL" />
+ *           <category android:name="android.intent.category.DEFAULT" />
+ *           <data android:scheme="tel" />
+ *      </intent-filter>
  * </activity>
  * }
  * </pre>
@@ -111,6 +137,7 @@
  *         }
  *     }
  * }
+ * }
  * </pre>
  * <p id="incomingCallNotification">
  * <h3>Showing the Incoming Call Notification</h3>
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index abb210f..6ae4a08 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -16,7 +16,10 @@
 
 package android.telecom;
 
+import static android.Manifest.permission.MODIFY_PHONE_STATE;
+
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.content.Intent;
@@ -605,7 +608,8 @@
          * time. By default, there is no group Id for a {@link PhoneAccount} (an empty String). Only
          * grouped {@link PhoneAccount}s with the same {@link ConnectionService} can be replaced.
          * <p>
-         * Note: This is an API specific to the Telephony stack.
+         * Note: This is an API specific to the Telephony stack; the group Id will be ignored for
+         * callers not holding the correct permission.
          *
          * @param groupId The group Id of the {@link PhoneAccount} that will replace any other
          * registered {@link PhoneAccount} in Telecom with the same Group Id.
@@ -614,6 +618,7 @@
          */
         @SystemApi
         @TestApi
+        @RequiresPermission(MODIFY_PHONE_STATE)
         public @NonNull Builder setGroupId(@NonNull String groupId) {
             if (groupId != null) {
                 mGroupId = groupId;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 7e5fd46..a7024f9 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -802,8 +802,8 @@
      * automatically add dialing prefixes when placing international calls.
      * <p>
      * Setting this extra on the outgoing call extras will cause the
-     * {@link Connection#PROPERTY_ASSISTED_DIALING_USED} property and
-     * {@link Call.Details#PROPERTY_ASSISTED_DIALING_USED} property to be set on the
+     * {@link Connection#PROPERTY_ASSISTED_DIALING} property and
+     * {@link Call.Details#PROPERTY_ASSISTED_DIALING} property to be set on the
      * {@link Connection}/{@link Call} in question.  When the call is logged to the call log, the
      * {@link android.provider.CallLog.Calls#FEATURES_ASSISTED_DIALING_USED} call feature is set to
      * indicate that assisted dialing was used for the call.
@@ -1368,7 +1368,7 @@
     /**
      * Used to determine the currently selected default dialer package for a specific user.
      *
-     * @param userId the user id to query the default dialer package for.
+     * @param userHandle the user id to query the default dialer package for.
      * @return package name for the default dialer package or null if no package has been
      *         selected as the default dialer.
      * @hide
@@ -1376,10 +1376,11 @@
     @SystemApi
     @TestApi
     @RequiresPermission(READ_PRIVILEGED_PHONE_STATE)
-    public @Nullable String getDefaultDialerPackage(int userId) {
+    public @Nullable String getDefaultDialerPackage(@NonNull UserHandle userHandle) {
         try {
             if (isServiceConnected()) {
-                return getTelecomService().getDefaultDialerPackageForUser(userId);
+                return getTelecomService().getDefaultDialerPackageForUser(
+                        userHandle.getIdentifier());
             }
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException attempting to get the default dialer package name.", e);
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 4249dff..a397d77 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -104,6 +104,9 @@
 
     void swapConference(String conferenceCallId, in Session.Info sessionInfo);
 
+    void addConferenceParticipants(String CallId, in List<Uri> participants,
+    in Session.Info sessionInfo);
+
     void onPostDialContinue(String callId, boolean proceed, in Session.Info sessionInfo);
 
     void pullExternalCall(String callId, in Session.Info sessionInfo);
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index eb2d714..9beff22 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -67,6 +67,8 @@
 
     void swapConference(String callId);
 
+    void addConferenceParticipants(String callId, in List<Uri> participants);
+
     void turnOnProximitySensor();
 
     void turnOffProximitySensor(boolean screenOnImmediately);
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 610eef8..01abb26 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -153,22 +153,55 @@
         public static final int BAND_12 = 12;
         public static final int BAND_13 = 13;
         public static final int BAND_14 = 14;
-        /** band 15, 16, 17, 18 are reserved */
+        // band 15, 16, 17, 18 are reserved
         public static final int BAND_19 = 19;
         public static final int BAND_20 = 20;
         public static final int BAND_21 = 21;
         public static final int BAND_22 = 22;
-        /** band 23, 24 are reserved */
+        // band 23, 24 are reserved
         public static final int BAND_25 = 25;
         public static final int BAND_26 = 26;
 
-        /** Frequency bands for TD-SCDMA. Defined in 3GPP TS 25.102, Table 5.2. */
+        // Frequency bands for TD-SCDMA. Defined in 3GPP TS 25.102, Table 5.2.
+
+        /**
+         * Band A
+         * 1900 - 1920 MHz: Uplink and downlink transmission
+         * 2010 - 2025 MHz: Uplink and downlink transmission
+         */
         public static final int BAND_A = 101;
+
+        /**
+         * Band B
+         * 1850 - 1910 MHz: Uplink and downlink transmission
+         * 1930 - 1990 MHz: Uplink and downlink transmission
+         */
         public static final int BAND_B = 102;
+
+        /**
+         * Band C
+         * 1910 - 1930 MHz: Uplink and downlink transmission
+         */
         public static final int BAND_C = 103;
+
+        /**
+         * Band D
+         * 2570 - 2620 MHz: Uplink and downlink transmission
+         */
         public static final int BAND_D = 104;
+
+        /**
+         * Band E
+         * 2300—2400 MHz: Uplink and downlink transmission
+         */
         public static final int BAND_E = 105;
+
+        /**
+         * Band F
+         * 1880 - 1920 MHz: Uplink and downlink transmission
+         */
         public static final int BAND_F = 106;
+
         /** @hide */
         private UtranBand() {}
     }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3823133..05a29e9 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1089,6 +1089,14 @@
             "support_adhoc_conference_calls_bool";
 
     /**
+     * Determines whether conference participants can be added to existing call.  When {@code true},
+     * adding conference participants to existing call is supported, {@code false otherwise}.
+     * @hide
+     */
+    public static final String KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL =
+            "support_add_conference_participants_bool";
+
+    /**
      * Determines whether conference calls are supported by a carrier.  When {@code true},
      * conference calling is supported, {@code false otherwise}.
      */
@@ -3571,6 +3579,7 @@
         sDefaults.putBoolean(KEY_IGNORE_RTT_MODE_SETTING_BOOL, false);
         sDefaults.putInt(KEY_CDMA_3WAYCALL_FLASH_DELAY_INT , 0);
         sDefaults.putBoolean(KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL, false);
+        sDefaults.putBoolean(KEY_SUPPORT_ADD_CONFERENCE_PARTICIPANTS_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_CONFERENCE_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_MANAGE_IMS_CONFERENCE_CALL_BOOL, true);
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index ec86c14..bfa209b 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -16,9 +16,9 @@
 
 package android.telephony;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.SuppressLint;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.hardware.radio.V1_4.CellInfo.Info;
 import android.os.Parcel;
@@ -178,18 +178,18 @@
     /**
      * Approximate time this cell information was received from the modem.
      *
-     * @return a time stamp in nanos since boot.
+     * @return a time stamp in millis since boot.
      */
-    @SuppressLint("MethodNameUnits")
-    public long getTimestampNanos() {
-        return mTimeStamp;
+    @ElapsedRealtimeLong
+    public long getTimestampMillis() {
+        return mTimeStamp / 1000000;
     }
 
     /**
      * Approximate time this cell information was received from the modem.
      *
      * @return a time stamp in nanos since boot.
-     * @deprecated Use {@link #getTimestampNanos} instead.
+     * @deprecated Use {@link #getTimestampMillis} instead.
      */
     @Deprecated
     public long getTimeStamp() {
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
index 54980a2..250d9e8 100644
--- a/telephony/java/android/telephony/PreciseDisconnectCause.java
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -256,337 +256,6 @@
     /** Access Blocked by CDMA network. */
     public static final int CDMA_ACCESS_BLOCKED                              = 1009;
 
-    /** Mapped from ImsReasonInfo */
-    // TODO: remove ImsReasonInfo from preciseDisconnectCause
-    /* The passed argument is an invalid */
-    /** @hide */
-    public static final int LOCAL_ILLEGAL_ARGUMENT                           = 1200;
-    // The operation is invoked in invalid call state
-    /** @hide */
-    public static final int LOCAL_ILLEGAL_STATE                              = 1201;
-    // IMS service internal error
-    /** @hide */
-    public static final int LOCAL_INTERNAL_ERROR                             = 1202;
-    // IMS service goes down (service connection is lost)
-    /** @hide */
-    public static final int LOCAL_IMS_SERVICE_DOWN                           = 1203;
-    // No pending incoming call exists
-    /** @hide */
-    public static final int LOCAL_NO_PENDING_CALL                            = 1204;
-    // Service unavailable; by power off
-    /** @hide */
-    public static final int LOCAL_POWER_OFF                                  = 1205;
-    // Service unavailable; by low battery
-    /** @hide */
-    public static final int LOCAL_LOW_BATTERY                                = 1206;
-    // Service unavailable; by out of service (data service state)
-    /** @hide */
-    public static final int LOCAL_NETWORK_NO_SERVICE                         = 1207;
-    /* Service unavailable; by no LTE coverage
-     * (VoLTE is not supported even though IMS is registered)
-     */
-    /** @hide */
-    public static final int LOCAL_NETWORK_NO_LTE_COVERAGE                    = 1208;
-    /** Service unavailable; by located in roaming area */
-    /** @hide */
-    public static final int LOCAL_NETWORK_ROAMING                            = 1209;
-    /** Service unavailable; by IP changed */
-    /** @hide */
-    public static final int LOCAL_NETWORK_IP_CHANGED                         = 1210;
-    /** Service unavailable; other */
-    /** @hide */
-    public static final int LOCAL_SERVICE_UNAVAILABLE                        = 1211;
-    /* Service unavailable; IMS connection is lost (IMS is not registered) */
-    /** @hide */
-    public static final int LOCAL_NOT_REGISTERED                             = 1212;
-    /** Max call exceeded */
-    /** @hide */
-    public static final int LOCAL_MAX_CALL_EXCEEDED                          = 1213;
-    /** Call decline */
-    /** @hide */
-    public static final int LOCAL_CALL_DECLINE                               = 1214;
-    /** SRVCC is in progress */
-    /** @hide */
-    public static final int LOCAL_CALL_VCC_ON_PROGRESSING                    = 1215;
-    /** Resource reservation is failed (QoS precondition) */
-    /** @hide */
-    public static final int LOCAL_CALL_RESOURCE_RESERVATION_FAILED           = 1216;
-    /** Retry CS call; VoLTE service can't be provided by the network or remote end
-     *  Resolve the extra code(EXTRA_CODE_CALL_RETRY_*) if the below code is set
-     *  @hide
-     */
-    public static final int LOCAL_CALL_CS_RETRY_REQUIRED                     = 1217;
-    /** Retry VoLTE call; VoLTE service can't be provided by the network temporarily */
-    /** @hide */
-    public static final int LOCAL_CALL_VOLTE_RETRY_REQUIRED                  = 1218;
-    /** IMS call is already terminated (in TERMINATED state) */
-    /** @hide */
-    public static final int LOCAL_CALL_TERMINATED                            = 1219;
-    /** Handover not feasible */
-    /** @hide */
-    public static final int LOCAL_HO_NOT_FEASIBLE                            = 1220;
-
-    /** 1xx waiting timer is expired after sending INVITE request (MO only) */
-    /** @hide */
-    public static final int TIMEOUT_1XX_WAITING                              = 1221;
-    /** User no answer during call setup operation (MO/MT)
-     *  MO : 200 OK to INVITE request is not received,
-     *  MT : No action from user after alerting the call
-     *  @hide
-     */
-    public static final int TIMEOUT_NO_ANSWER                                = 1222;
-    /** User no answer during call update operation (MO/MT)
-     *  MO : 200 OK to re-INVITE request is not received,
-     *  MT : No action from user after alerting the call
-     *  @hide
-     */
-    public static final int TIMEOUT_NO_ANSWER_CALL_UPDATE                    = 1223;
-
-    /**
-     * STATUSCODE (SIP response code) (IMS -> Telephony)
-     */
-    /** SIP request is redirected */
-    /** @hide */
-    public static final int SIP_REDIRECTED                                   = 1300;
-    /** 4xx responses */
-    /** 400 : Bad Request */
-    /** @hide */
-    public static final int SIP_BAD_REQUEST                                  = 1310;
-    /** 403 : Forbidden */
-    /** @hide */
-    public static final int SIP_FORBIDDEN                                    = 1311;
-    /** 404 : Not Found */
-    /** @hide */
-    public static final int SIP_NOT_FOUND                                    = 1312;
-    /** 415 : Unsupported Media Type
-     *  416 : Unsupported URI Scheme
-     *  420 : Bad Extension
-     */
-    /** @hide */
-    public static final int SIP_NOT_SUPPORTED                                = 1313;
-    /** 408 : Request Timeout */
-    /** @hide */
-    public static final int SIP_REQUEST_TIMEOUT                              = 1314;
-    /** 480 : Temporarily Unavailable */
-    /** @hide */
-    public static final int SIP_TEMPRARILY_UNAVAILABLE                       = 1315;
-    /** 484 : Address Incomplete */
-    /** @hide */
-    public static final int SIP_BAD_ADDRESS                                  = 1316;
-    /** 486 : Busy Here
-     *  600 : Busy Everywhere
-     */
-    /** @hide */
-    public static final int SIP_BUSY                                         = 1317;
-    /** 487 : Request Terminated */
-    /** @hide */
-    public static final int SIP_REQUEST_CANCELLED                            = 1318;
-    /** 406 : Not Acceptable
-     *  488 : Not Acceptable Here
-     *  606 : Not Acceptable
-     */
-    /** @hide */
-    public static final int SIP_NOT_ACCEPTABLE                               = 1319;
-    /** 410 : Gone
-     *  604 : Does Not Exist Anywhere
-     */
-    /** @hide */
-    public static final int SIP_NOT_REACHABLE                                = 1320;
-    /** Others */
-    /** @hide */
-    public static final int SIP_CLIENT_ERROR                                 = 1321;
-    /** 481 : Transaction Does Not Exist */
-    /** @hide */
-    public static final int SIP_TRANSACTION_DOES_NOT_EXIST                   = 1322;
-    /** 5xx responses
-     *  501 : Server Internal Error
-     */
-    /** @hide */
-    public static final int SIP_SERVER_INTERNAL_ERROR                        = 1330;
-    /** 503 : Service Unavailable */
-    /** @hide */
-    public static final int SIP_SERVICE_UNAVAILABLE                          = 1331;
-    /** 504 : Server Time-out */
-    /** @hide */
-    public static final int SIP_SERVER_TIMEOUT                               = 1332;
-    /** Others */
-    /** @hide */
-    public static final int SIP_SERVER_ERROR                                 = 1333;
-    /** 6xx responses
-     *  603 : Decline
-     */
-    /** @hide */
-    public static final int SIP_USER_REJECTED                                = 1340;
-    /** Others */
-    /** @hide */
-    public static final int SIP_GLOBAL_ERROR                                 = 1341;
-    /** Emergency failure */
-    /** @hide */
-    public static final int EMERGENCY_TEMP_FAILURE                           = 1342;
-    /** @hide */
-    public static final int EMERGENCY_PERM_FAILURE                           = 1343;
-    /** Media resource initialization failed */
-    /** @hide */
-    public static final int MEDIA_INIT_FAILED                                = 1400;
-    /** RTP timeout (no audio / video traffic in the session) */
-    /** @hide */
-    public static final int MEDIA_NO_DATA                                    = 1401;
-    /** Media is not supported; so dropped the call */
-    /** @hide */
-    public static final int MEDIA_NOT_ACCEPTABLE                             = 1402;
-    /** Unknown media related errors */
-    /** @hide */
-    public static final int MEDIA_UNSPECIFIED                                = 1403;
-    /** User triggers the call end */
-    /** @hide */
-    public static final int USER_TERMINATED                                  = 1500;
-    /** No action while an incoming call is ringing */
-    /** @hide */
-    public static final int USER_NOANSWER                                    = 1501;
-    /** User ignores an incoming call */
-    /** @hide */
-    public static final int USER_IGNORE                                      = 1502;
-    /** User declines an incoming call */
-    /** @hide */
-    public static final int USER_DECLINE                                     = 1503;
-    /** Device declines/ends a call due to low battery */
-    /** @hide */
-    public static final int LOW_BATTERY                                      = 1504;
-    /** Device declines call due to blacklisted call ID */
-    /** @hide */
-    public static final int BLACKLISTED_CALL_ID                              = 1505;
-    /** The call is terminated by the network or remote user */
-    /** @hide */
-    public static final int USER_TERMINATED_BY_REMOTE                        = 1510;
-
-    /**
-     * UT
-     */
-    /** @hide */
-    public static final int UT_NOT_SUPPORTED                                 = 1800;
-    /** @hide */
-    public static final int UT_SERVICE_UNAVAILABLE                           = 1801;
-    /** @hide */
-    public static final int UT_OPERATION_NOT_ALLOWED                         = 1802;
-    /** @hide */
-    public static final int UT_NETWORK_ERROR                                 = 1803;
-    /** @hide */
-    public static final int UT_CB_PASSWORD_MISMATCH                          = 1804;
-
-    /**
-     * ECBM
-     * @hide
-     */
-    public static final int ECBM_NOT_SUPPORTED                               = 1900;
-
-    /**
-     * Fail code used to indicate that Multi-endpoint is not supported by the Ims framework.
-     * @hide
-     */
-    public static final int MULTIENDPOINT_NOT_SUPPORTED                      = 1901;
-
-    /**
-     * CALL DROP error codes (Call could drop because of many reasons like Network not available,
-     *  handover, failed, etc)
-     */
-
-    /**
-     * CALL DROP error code for the case when a device is ePDG capable and when the user is on an
-     * active wifi call and at the edge of coverage and there is no qualified LTE network available
-     * to handover the call to. We get a handover NOT_TRIGERRED message from the modem. This error
-     * code is received as part of the handover message.
-     * @hide
-     */
-    public static final int CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE               = 2000;
-
-    /**
-     * MT call has ended due to a release from the network
-     * because the call was answered elsewhere
-     * @hide
-     */
-    public static final int ANSWERED_ELSEWHERE                               = 2100;
-
-    /**
-     * For MultiEndpoint - Call Pull request has failed
-     * @hide
-     */
-    public static final int CALL_PULL_OUT_OF_SYNC                            = 2101;
-
-    /**
-     * For MultiEndpoint - Call has been pulled from primary to secondary
-     * @hide
-     */
-    public static final int CALL_PULLED                                      = 2102;
-
-    /**
-     * Supplementary services (HOLD/RESUME) failure error codes.
-     * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
-     * @hide
-     */
-    public static final int SUPP_SVC_FAILED                                  = 2300;
-    /** @hide */
-    public static final int SUPP_SVC_CANCELLED                               = 2301;
-    /** @hide */
-    public static final int SUPP_SVC_REINVITE_COLLISION                      = 2302;
-
-    /**
-     * DPD Procedure received no response or send failed
-     * @hide
-     */
-    public static final int IWLAN_DPD_FAILURE                                = 2400;
-
-    /**
-     * Establishment of the ePDG Tunnel Failed
-     * @hide
-     */
-    public static final int EPDG_TUNNEL_ESTABLISH_FAILURE                    = 2500;
-
-    /**
-     * Re-keying of the ePDG Tunnel Failed; may not always result in teardown
-     * @hide
-     */
-    public static final int EPDG_TUNNEL_REKEY_FAILURE                        = 2501;
-
-    /**
-     * Connection to the packet gateway is lost
-     * @hide
-     */
-    public static final int EPDG_TUNNEL_LOST_CONNECTION                      = 2502;
-
-    /**
-     * The maximum number of calls allowed has been reached.  Used in a multi-endpoint scenario
-     * where the number of calls across all connected devices has reached the maximum.
-     * @hide
-     */
-    public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED                  = 2503;
-
-    /**
-     * Similar to {@link #CODE_LOCAL_CALL_DECLINE}, except indicates that a remote device has
-     * declined the call.  Used in a multi-endpoint scenario where a remote device declined an
-     * incoming call.
-     * @hide
-     */
-    public static final int REMOTE_CALL_DECLINE                              = 2504;
-
-    /**
-     * Indicates the call was disconnected due to the user reaching their data limit.
-     * @hide
-     */
-    public static final int DATA_LIMIT_REACHED                               = 2505;
-
-    /**
-     * Indicates the call was disconnected due to the user disabling cellular data.
-     * @hide
-     */
-    public static final int DATA_DISABLED                                    = 2506;
-
-    /**
-     * Indicates a call was disconnected due to loss of wifi signal.
-     * @hide
-     */
-    public static final int WIFI_LOST                                        = 2507;
-
-
     /* OEM specific error codes. To be used by OEMs when they don't want to
        reveal error code which would be replaced by ERROR_UNSPECIFIED */
     public static final int OEM_CAUSE_1                                      = 0xf001;
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index 483ccc4..16fbd07 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -16,8 +16,8 @@
 
 package android.telephony;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
-import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -79,8 +79,9 @@
     /* The type of signal measurement */
     private static final String MEASUREMENT_TYPE_RSCP = "rscp";
 
-    // timeStamp of signalStrength in nanoseconds since boot
-    private long mTimestamp = Long.MAX_VALUE;
+    // Timestamp of SignalStrength since boot
+    // Effectively final. Timestamp is set during construction of SignalStrength
+    private long mTimestampMillis;
 
     CellSignalStrengthCdma mCdma;
     CellSignalStrengthGsm mGsm;
@@ -140,7 +141,7 @@
         mTdscdma = tdscdma;
         mLte = lte;
         mNr = nr;
-        mTimestamp = SystemClock.elapsedRealtimeNanos();
+        mTimestampMillis = SystemClock.elapsedRealtime();
     }
 
     /**
@@ -275,7 +276,6 @@
         mTdscdma.updateLevel(cc, ss);
         mLte.updateLevel(cc, ss);
         mNr.updateLevel(cc, ss);
-        mTimestamp = SystemClock.elapsedRealtimeNanos();
     }
 
     /**
@@ -301,7 +301,7 @@
         mTdscdma = new CellSignalStrengthTdscdma(s.mTdscdma);
         mLte = new CellSignalStrengthLte(s.mLte);
         mNr = new CellSignalStrengthNr(s.mNr);
-        mTimestamp = s.getTimestampNanos();
+        mTimestampMillis = s.getTimestampMillis();
     }
 
     /**
@@ -319,7 +319,7 @@
         mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader());
         mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
         mNr = in.readParcelable(CellSignalStrengthLte.class.getClassLoader());
-        mTimestamp = in.readLong();
+        mTimestampMillis = in.readLong();
     }
 
     /**
@@ -332,15 +332,17 @@
         out.writeParcelable(mTdscdma, flags);
         out.writeParcelable(mLte, flags);
         out.writeParcelable(mNr, flags);
-        out.writeLong(mTimestamp);
+        out.writeLong(mTimestampMillis);
     }
 
     /**
-     * @return mTimestamp in nanoseconds
+     * @return timestamp in milliseconds since boot for {@link SignalStrength}.
+     * This timestamp reports the approximate time that the signal was measured and reported
+     * by the modem. It can be used to compare the recency of {@link SignalStrength} instances.
      */
-    @SuppressLint("MethodNameUnits")
-    public long getTimestampNanos() {
-        return mTimestamp;
+    @ElapsedRealtimeLong
+    public long getTimestampMillis() {
+        return mTimestampMillis;
     }
 
    /**
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index efea91a..3e4f3d8 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -272,24 +272,10 @@
         netCap.setOwnerUid(123);
         assertParcelingIsLossless(netCap);
         netCap.setSSID(TEST_SSID);
-        assertParcelSane(netCap, 15);
+        assertParcelSane(netCap, 13);
     }
 
     @Test
-    public void testParcelNetworkCapabilitiesWithRequestorUidAndPackageName() {
-        final NetworkCapabilities netCap = new NetworkCapabilities()
-                .addCapability(NET_CAPABILITY_INTERNET)
-                .setRequestorUid(9304)
-                .setRequestorPackageName("com.android.test")
-                .addCapability(NET_CAPABILITY_EIMS)
-                .addCapability(NET_CAPABILITY_NOT_METERED);
-        assertParcelingIsLossless(netCap);
-        netCap.setSSID(TEST_SSID);
-        assertParcelSane(netCap, 15);
-    }
-
-
-    @Test
     public void testOemPaid() {
         NetworkCapabilities nc = new NetworkCapabilities();
         // By default OEM_PAID is neither in the unwanted or required lists and the network is not
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index d6bf334..7ede144 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -212,8 +212,7 @@
         ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
 
         // register callback
-        when(mService.requestNetwork(
-                any(), captor.capture(), anyInt(), any(), anyInt(), any()))
+        when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt()))
                 .thenReturn(request);
         manager.requestNetwork(request, callback, handler);
 
@@ -241,8 +240,7 @@
         ArgumentCaptor<Messenger> captor = ArgumentCaptor.forClass(Messenger.class);
 
         // register callback
-        when(mService.requestNetwork(
-                any(), captor.capture(), anyInt(), any(), anyInt(), any()))
+        when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt()))
                 .thenReturn(req1);
         manager.requestNetwork(req1, callback, handler);
 
@@ -260,8 +258,7 @@
         verify(callback, timeout(100).times(0)).onLosing(any(), anyInt());
 
         // callback can be registered again
-        when(mService.requestNetwork(
-                any(), captor.capture(), anyInt(), any(), anyInt(), any()))
+        when(mService.requestNetwork(any(), captor.capture(), anyInt(), any(), anyInt()))
                 .thenReturn(req2);
         manager.requestNetwork(req2, callback, handler);
 
@@ -285,8 +282,7 @@
         info.targetSdkVersion = VERSION_CODES.N_MR1 + 1;
 
         when(mCtx.getApplicationInfo()).thenReturn(info);
-        when(mService.requestNetwork(any(), any(), anyInt(), any(), anyInt(), any()))
-                .thenReturn(request);
+        when(mService.requestNetwork(any(), any(), anyInt(), any(), anyInt())).thenReturn(request);
 
         Handler handler = new Handler(Looper.getMainLooper());
         manager.requestNetwork(request, callback, handler);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index f40e57f..8da1a5b 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -107,7 +107,6 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -306,7 +305,6 @@
     private static final String MOBILE_IFNAME = "test_rmnet_data0";
     private static final String WIFI_IFNAME = "test_wlan0";
     private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
-    private static final String TEST_PACKAGE_NAME = "com.android.test.package";
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
     private MockContext mServiceContext;
@@ -656,7 +654,7 @@
 
             if (mNmValidationRedirectUrl != null) {
                 mNmCallbacks.showProvisioningNotification(
-                        "test_provisioning_notif_action", TEST_PACKAGE_NAME);
+                        "test_provisioning_notif_action", "com.android.test.package");
                 mNmProvNotificationRequested = true;
             }
         }
@@ -2974,7 +2972,7 @@
             networkCapabilities.addTransportType(TRANSPORT_WIFI)
                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
             mService.requestNetwork(networkCapabilities, null, 0, null,
-                    ConnectivityManager.TYPE_WIFI, TEST_PACKAGE_NAME);
+                    ConnectivityManager.TYPE_WIFI);
         });
 
         class NonParcelableSpecifier extends NetworkSpecifier {
@@ -3013,12 +3011,31 @@
     }
 
     @Test
-    public void testNetworkRequestUidSpoofSecurityException() throws Exception {
+    public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
+        class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
+            @Override
+            public boolean satisfiedBy(NetworkSpecifier other) {
+                return true;
+            }
+
+            @Override
+            public void assertValidFromUid(int requestorUid) {
+                throw new SecurityException("failure");
+            }
+
+            @Override
+            public int describeContents() { return 0; }
+            @Override
+            public void writeToParcel(Parcel dest, int flags) {}
+        }
+
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(false);
-        NetworkRequest networkRequest = newWifiRequestBuilder().build();
+
+        UidAwareNetworkSpecifier networkSpecifier = new UidAwareNetworkSpecifier();
+        NetworkRequest networkRequest = newWifiRequestBuilder().setNetworkSpecifier(
+                networkSpecifier).build();
         TestNetworkCallback networkCallback = new TestNetworkCallback();
-        doThrow(new SecurityException()).when(mAppOpsManager).checkPackage(anyInt(), anyString());
         assertThrows(SecurityException.class, () -> {
             mCm.requestNetwork(networkRequest, networkCallback);
         });
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 155c61f..eb78529 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -148,6 +148,7 @@
     @Mock private AppOpsManager mAppOps;
     @Mock private NotificationManager mNotificationManager;
     @Mock private Vpn.SystemServices mSystemServices;
+    @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator;
     @Mock private ConnectivityManager mConnectivityManager;
     @Mock private KeyStore mKeyStore;
     private final VpnProfile mVpnProfile = new VpnProfile("key");
@@ -867,7 +868,8 @@
      * Mock some methods of vpn object.
      */
     private Vpn createVpn(@UserIdInt int userId) {
-        return new Vpn(Looper.myLooper(), mContext, mNetService, userId, mSystemServices);
+        return new Vpn(Looper.myLooper(), mContext, mNetService,
+                userId, mSystemServices, mIkev2SessionCreator);
     }
 
     private static void assertBlocked(Vpn vpn, int... uids) {
diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
index 20fbc9f..24aa23a 100644
--- a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java
@@ -200,6 +200,12 @@
     }
 
     @Override
+    public void assertValidFromUid(int requestorUid) {
+        throw new IllegalStateException("WifiNetworkAgentSpecifier should never be used "
+                + "for requests.");
+    }
+
+    @Override
     public NetworkSpecifier redact() {
         return null;
     }
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index e1d3c43..6c2d7ff 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -598,4 +598,12 @@
         // not make much sense!
         return equals(other);
     }
+
+    /** @hide */
+    @Override
+    public void assertValidFromUid(int requestorUid) {
+        if (this.requestorUid != requestorUid) {
+            throw new SecurityException("mismatched UIDs");
+        }
+    }
 }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
index 282fda8..9164d04 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
@@ -144,6 +144,12 @@
     }
 
     @Override
+    public void assertValidFromUid(int requestorUid) {
+        throw new SecurityException(
+                "WifiAwareAgentNetworkSpecifier should not be used in network requests");
+    }
+
+    @Override
     public NetworkSpecifier redact() {
         return null;
     }
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
index ad656e1..0511f24 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareNetworkSpecifier.java
@@ -289,6 +289,14 @@
         return sb.toString();
     }
 
+    /** @hide */
+    @Override
+    public void assertValidFromUid(int requestorUid) {
+        if (this.requestorUid != requestorUid) {
+            throw new SecurityException("mismatched UIDs");
+        }
+    }
+
     /**
      * A builder class for a Wi-Fi Aware network specifier to set up an Aware connection with a
      * peer.
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
index 61a7299..e6eece8 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkAgentSpecifierTest.java
@@ -22,6 +22,7 @@
 
 import android.net.MacAddress;
 import android.net.MatchAllNetworkSpecifier;
+import android.net.NetworkRequest;
 import android.os.Parcel;
 import android.os.PatternMatcher;
 import android.util.Pair;
@@ -70,6 +71,16 @@
     }
 
     /**
+     * Validate that the NetworkAgentSpecifier cannot be used in a {@link NetworkRequest} by apps.
+     */
+    @Test(expected = IllegalStateException.class)
+    public void testWifiNetworkAgentSpecifierNotUsedInNetworkRequest() {
+        WifiNetworkAgentSpecifier specifier = createDefaultNetworkAgentSpecifier();
+
+        specifier.assertValidFromUid(TEST_UID);
+    }
+
+    /**
      * Validate NetworkAgentSpecifier equals with itself.
      * a) Create network agent specifier 1 for WPA_PSK network
      * b) Create network agent specifier 2 with the same params as specifier 1.
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index ef9c6a3..c3b6285 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -162,6 +162,17 @@
         collector.checkThat("Match unexpected", oldNs.satisfiedBy(newNs), equalTo(false));
     }
 
+    /**
+     * Validate that agent network specifier cannot be used as in network requests - i.e. that
+     * throws an exception when queried for UID validity.
+     */
+    @Test(expected = SecurityException.class)
+    public void testNoUsageInRequest() {
+        WifiAwareAgentNetworkSpecifier dut = new WifiAwareAgentNetworkSpecifier();
+
+        dut.assertValidFromUid(0);
+    }
+
     // utilities
 
     /**