Merge "Make MGF1 Digest setter NotNull" into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index e0745fa..fdd0505 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -161,7 +161,7 @@
     name: "android.security.flags-aconfig-java-host",
     aconfig_declarations: "android.security.flags-aconfig",
     host_supported: true,
-    test: true,
+    mode: "test",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
 
diff --git a/core/java/android/os/DeadObjectException.java b/core/java/android/os/DeadObjectException.java
index 65ed618..61aa222 100644
--- a/core/java/android/os/DeadObjectException.java
+++ b/core/java/android/os/DeadObjectException.java
@@ -19,8 +19,29 @@
 
 /**
  * The object you are calling has died, because its hosting process
- * no longer exists. This is also thrown for low-level binder
- * errors.
+ * no longer exists, or there has been a low-level binder error.
+ *
+ * If you get this exception from a system service, the error is
+ * usually nonrecoverable as the framework will restart. If you
+ * receive this error from an app, at a minimum, you should
+ * recover by resetting the connection. For instance, you should
+ * drop the binder, clean up associated state, and reset your
+ * connection to the service which through this error. In order
+ * to simplify your error recovery paths, you may also want to
+ * "simply" restart your process. However, this may not be an
+ * option if the service you are talking to is unreliable or
+ * crashes frequently.
+ *
+ * If this isn't from a service death and is instead from a
+ * low-level binder error, it will be from:
+ * - a oneway call queue filling up (too many oneway calls)
+ * - from the binder buffer being filled up, so that the transaction
+ *   is rejected.
+ *
+ * In these cases, more information about the error will be
+ * logged. However, there isn't a good way to differentiate
+ * this information at runtime. So, you should handle the
+ * error, as if the service died.
  */
 public class DeadObjectException extends RemoteException {
     public DeadObjectException() {
diff --git a/core/java/android/os/DeadSystemRuntimeException.java b/core/java/android/os/DeadSystemRuntimeException.java
index 82b1ad8..3b10798 100644
--- a/core/java/android/os/DeadSystemRuntimeException.java
+++ b/core/java/android/os/DeadSystemRuntimeException.java
@@ -19,10 +19,12 @@
 /**
  * Exception thrown when a call into system_server resulted in a
  * DeadObjectException, meaning that the system_server has died or
- * experienced a low-level binder error.  There's * nothing apps can
+ * experienced a low-level binder error.  There's nothing apps can
  * do at this point - the system will automatically restart - so
  * there's no point in catching this.
  *
+ * See {@link android.os.DeadObjectException}.
+ *
  * @hide
  */
 public class DeadSystemRuntimeException extends RuntimeException {
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index 0947ec1..f62094d 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -618,4 +618,14 @@
     public int describeContents() {
         return 0;
     }
+
+    @Override
+    public VpnProfile clone() {
+        try {
+            return (VpnProfile) super.clone();
+        } catch (CloneNotSupportedException e) {
+            Log.wtf(TAG, e);
+            return null;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index d56448d..469582d 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -4122,7 +4122,7 @@
             pw.println("      -D: enable debugging");
             pw.println("      --suspend: debugged app suspend threads at startup (only with -D)");
             pw.println("      -N: enable native debugging");
-            pw.println("      -W: wait for launch to complete");
+            pw.println("      -W: wait for launch to complete (initial display)");
             pw.println("      --start-profiler <FILE>: start profiler and send results to <FILE>");
             pw.println("      --sampling INTERVAL: use sample profiling with INTERVAL microseconds");
             pw.println("          between samples (use with --start-profiler)");
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a12243b..b0abf94 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -2621,8 +2621,9 @@
      *
      * Callers are responsible for checking permissions if needed.
      */
-    public void startLegacyVpnPrivileged(VpnProfile profile,
+    public void startLegacyVpnPrivileged(VpnProfile profileToStart,
             @Nullable Network underlying, @NonNull LinkProperties egress) {
+        final VpnProfile profile = profileToStart.clone();
         UserInfo user = mUserManager.getUserInfo(mUserId);
         if (user.isRestricted() || mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN,
                     new UserHandle(mUserId))) {
@@ -3385,6 +3386,13 @@
          *              given network to start a new IKE session.
          */
         private void startOrMigrateIkeSession(@Nullable Network underlyingNetwork) {
+            synchronized (Vpn.this) {
+                // Ignore stale runner.
+                if (mVpnRunner != this) return;
+                setVpnNetworkPreference(mSessionKey,
+                        createUserAndRestrictedProfilesRanges(mUserId,
+                                mConfig.allowedApplications, mConfig.disallowedApplications));
+            }
             if (underlyingNetwork == null) {
                 // For null underlyingNetwork case, there will not be a NetworkAgent available so
                 // no underlying network update is necessary here. Note that updating
@@ -3905,6 +3913,7 @@
                 updateState(DetailedState.FAILED, exception.getMessage());
             }
 
+            clearVpnNetworkPreference(mSessionKey);
             disconnectVpnRunner();
         }
 
@@ -4039,6 +4048,13 @@
             }
 
             resetIkeState();
+            if (errorCode != VpnManager.ERROR_CODE_NETWORK_LOST
+                    // Clear the VPN network preference when the retry delay is higher than 5s.
+                    // mRetryCount was increased when scheduleRetryNewIkeSession() is called,
+                    // therefore use mRetryCount - 1 here.
+                    && mDeps.getNextRetryDelayMs(mRetryCount - 1) > 5_000L) {
+                clearVpnNetworkPreference(mSessionKey);
+            }
         }
 
         /**
@@ -4085,13 +4101,17 @@
             mCarrierConfigManager.unregisterCarrierConfigChangeListener(
                     mCarrierConfigChangeListener);
             mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
-            clearVpnNetworkPreference(mSessionKey);
 
             mExecutor.shutdown();
         }
 
         @Override
         public void exitVpnRunner() {
+            // mSessionKey won't be changed since the Ikev2VpnRunner is created, so it's ok to use
+            // it outside the mExecutor. And clearing the VPN network preference here can prevent
+            // the case that the VPN network preference isn't cleared when Ikev2VpnRunner became
+            // stale.
+            clearVpnNetworkPreference(mSessionKey);
             try {
                 mExecutor.execute(() -> {
                     disconnectVpnRunner();