Notify Caller of ConnectionInfo changes.

This CL updates IkeSessionStateMachine to notify callers whenever a
Mobility Event occurs. Callers will be notified via
IkeSessionCallback#onIkeSessionConnectionInfoChanged.

Bug: 172014224
Bug: 172013873
Test: atest FrameworksIkeTests
Change-Id: I271a4ff42359300832ecff211a9d7ae5b9cfbf54
diff --git a/src/java/android/net/ipsec/ike/IkeSessionCallback.java b/src/java/android/net/ipsec/ike/IkeSessionCallback.java
index 1d0f783..2dce4ce 100644
--- a/src/java/android/net/ipsec/ike/IkeSessionCallback.java
+++ b/src/java/android/net/ipsec/ike/IkeSessionCallback.java
@@ -84,4 +84,24 @@
      * @hide
      */
     void onError(@NonNull IkeException exception);
+
+    /**
+     * Called if the IkeSessionConnectionInfo for an established {@link IkeSession} changes.
+     *
+     * <p>This method will only be called for MOBIKE-enabled Sessions, and only after a Mobility
+     * Event occurs.
+     *
+     * <p>A Mobility Event is an event that causes the established, MOBIKE-enabled IKE Session to
+     * undergo an address update. Specifically, these events are:
+     *
+     * <ul>
+     *   <li>The underlying Network changing, or
+     *   <li>The local address disappearing from the current underlying (and unchanged) Network, or
+     *   <li>The remote address changing.
+     * </ul>
+     *
+     * @param connectionInfo the updated IkeSessionConnectionInfo for the Session.
+     * @hide
+     */
+    void onIkeSessionConnectionInfoChanged(@NonNull IkeSessionConnectionInfo connectionInfo);
 }
diff --git a/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java b/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
index d3735d2..aff9fe8 100644
--- a/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
+++ b/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachine.java
@@ -5101,7 +5101,13 @@
                 validateResp(resp);
 
                 // TODO(b/172015298): migrate Child SAs or schedule rekey
-                // TODO(b/172013873): notify caller of Network Change, IPsec SA changes
+
+                IkeSessionConnectionInfo connectionInfo =
+                        new IkeSessionConnectionInfo(mLocalAddress, mRemoteAddress, mNetwork);
+                executeUserCallback(
+                        () ->
+                                mIkeSessionCallback.onIkeSessionConnectionInfoChanged(
+                                        connectionInfo));
 
                 transitionTo(mIdle);
             } catch (IkeProtocolException | IOException e) {
diff --git a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java
index 5fa5a30..9b0724c 100644
--- a/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java
+++ b/tests/iketests/src/java/com/android/internal/net/ipsec/ike/IkeSessionStateMachineTest.java
@@ -5729,7 +5729,10 @@
         verifyUpdateSaAddressesResp(
                 true /* natTraversalSupported */,
                 true /* localNatDetected */,
-                true /* remoteNatDetected */);
+                true /* remoteNatDetected */,
+                mIkeSessionStateMachine.mNetwork,
+                mIkeSessionStateMachine.mLocalAddress,
+                mIkeSessionStateMachine.mRemoteAddress);
     }
 
     @Test
@@ -5746,7 +5749,10 @@
         verifyUpdateSaAddressesResp(
                 false /* natTraversalSupported */,
                 false /* localNatDetected */,
-                false /* remoteNatDetected */);
+                false /* remoteNatDetected */,
+                mIkeSessionStateMachine.mNetwork,
+                mIkeSessionStateMachine.mLocalAddress,
+                mIkeSessionStateMachine.mRemoteAddress);
     }
 
     private void verifyUpdateSaAddressesReq(boolean expectNatDetection) throws Exception {
@@ -5762,7 +5768,12 @@
     }
 
     private void verifyUpdateSaAddressesResp(
-            boolean natTraversalSupported, boolean localNatDetected, boolean remoteNatDetected)
+            boolean natTraversalSupported,
+            boolean localNatDetected,
+            boolean remoteNatDetected,
+            Network expectedNetwork,
+            InetAddress expectedLocalAddr,
+            InetAddress expectedRemoteAddr)
             throws Exception {
         List<Integer> respPayloadTypeList = new ArrayList<>();
         List<String> respPayloadHexStringList = new ArrayList<>();
@@ -5789,6 +5800,16 @@
         assertEquals(localNatDetected, mIkeSessionStateMachine.mLocalNatDetected);
         assertEquals(remoteNatDetected, mIkeSessionStateMachine.mRemoteNatDetected);
 
+        ArgumentCaptor<IkeSessionConnectionInfo> connectionInfoCaptor =
+                ArgumentCaptor.forClass(IkeSessionConnectionInfo.class);
+        verify(mMockIkeSessionCallback)
+                .onIkeSessionConnectionInfoChanged(connectionInfoCaptor.capture());
+
+        IkeSessionConnectionInfo newConnectionInfo = connectionInfoCaptor.getValue();
+        assertEquals(expectedNetwork, newConnectionInfo.getNetwork());
+        assertEquals(expectedLocalAddr, newConnectionInfo.getLocalAddress());
+        assertEquals(expectedRemoteAddr, newConnectionInfo.getRemoteAddress());
+
         // TODO(b/173237734): check IkeSocket - if includeNatDetection then expect UdpEncap
     }