Set underlying network as soon as VPN tries using the network

This commit sets the VPN underlying network as soon as VPN
tries using the network.

The existing code sets the VPN underlying network when the
IKE susccessfully migrates to the network. If the migration
fails, the underlying network in the NetworkCapabilities will
stay in the previous network which does not match the system
default network. Also, this will be a confusing information
for apps if apps get the underlying network from the NC of the
VPN network.

Bug: 289606688
Test: atest FrameworksNetTests
Change-Id: I9c3f50f4ea8241f9b51ebea2e097a0085dc2c17d
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index cba5039..ff35b19 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -3296,13 +3296,6 @@
                         }
                         agentConnect(this::onValidationStatus);
                         return; // Link properties are already sent.
-                    } else {
-                        // Underlying networks also set in agentConnect()
-                        doSetUnderlyingNetworks(networkAgent, Collections.singletonList(network));
-                        mNetworkCapabilities =
-                                new NetworkCapabilities.Builder(mNetworkCapabilities)
-                                        .setUnderlyingNetworks(Collections.singletonList(network))
-                                        .build();
                     }
 
                     lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked
@@ -3384,8 +3377,6 @@
 
                     final LinkProperties oldLp = makeLinkProperties();
 
-                    final boolean underlyingNetworkHasChanged =
-                            !Arrays.equals(mConfig.underlyingNetworks, new Network[]{network});
                     mConfig.underlyingNetworks = new Network[] {network};
                     mConfig.mtu = calculateVpnMtu();
 
@@ -3417,18 +3408,9 @@
                                     removed.getAddress(), removed.getPrefixLength());
                         }
                     } else {
-                        // Put below 3 updates into else block is because agentConnect() will do
-                        // those things, so there is no need to do the redundant work.
+                        // Put below update into else block is because agentConnect() will do
+                        // the same things, so there is no need to do the redundant work.
                         if (!newLp.equals(oldLp)) doSendLinkProperties(mNetworkAgent, newLp);
-                        if (underlyingNetworkHasChanged) {
-                            mNetworkCapabilities =
-                                    new NetworkCapabilities.Builder(mNetworkCapabilities)
-                                            .setUnderlyingNetworks(
-                                                    Collections.singletonList(network))
-                                            .build();
-                            doSetUnderlyingNetworks(mNetworkAgent,
-                                    Collections.singletonList(network));
-                        }
                     }
                 }
 
@@ -3554,10 +3536,28 @@
          */
         private void startOrMigrateIkeSession(@Nullable Network underlyingNetwork) {
             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
+                // mNetworkCapabilities here would also be reasonable, but it will be updated next
+                // time the VPN connects anyway.
                 Log.d(TAG, "There is no active network for starting an IKE session");
                 return;
             }
 
+            final List<Network> networks = Collections.singletonList(underlyingNetwork);
+            // Update network capabilities if underlying network is changed.
+            if (!networks.equals(mNetworkCapabilities.getUnderlyingNetworks())) {
+                mNetworkCapabilities =
+                        new NetworkCapabilities.Builder(mNetworkCapabilities)
+                                .setUnderlyingNetworks(networks)
+                                .build();
+                // No NetworkAgent case happens when Vpn tries to start a new VPN. The underlying
+                // network update will be done later with NetworkAgent connected event.
+                if (mNetworkAgent != null) {
+                    doSetUnderlyingNetworks(mNetworkAgent, networks);
+                }
+            }
+
             if (maybeMigrateIkeSessionAndUpdateVpnTransportInfo(underlyingNetwork)) return;
 
             startIkeSession(underlyingNetwork);