summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/net/ip/IpClientLinkObserver.java17
-rw-r--r--tests/integration/src/android/net/ip/IpClientIntegrationTest.java19
2 files changed, 32 insertions, 4 deletions
diff --git a/src/android/net/ip/IpClientLinkObserver.java b/src/android/net/ip/IpClientLinkObserver.java
index dc58e7b..ee7f18b 100644
--- a/src/android/net/ip/IpClientLinkObserver.java
+++ b/src/android/net/ip/IpClientLinkObserver.java
@@ -238,6 +238,7 @@ public class IpClientLinkObserver implements NetworkObserver {
// while interfaceDnsServerInfo() is being called, we'll end up with no DNS servers in
// mLinkProperties, as desired.
mDnsServerRepository = new DnsServerRepository(mConfig.minRdnssLifetime);
+ mNetlinkMonitor.clearAlarms();
mLinkProperties.clear();
mLinkProperties.setInterfaceName(mInterfaceName);
}
@@ -281,18 +282,27 @@ public class IpClientLinkObserver implements NetworkObserver {
mIfindex = ifindex;
}
+ void clearAlarms() {
+ cancelPref64Alarm();
+ }
+
private final AlarmManager.OnAlarmListener mExpirePref64Alarm = () -> {
+ // Ignore the alarm if cancelPref64Alarm has already been called.
+ //
// TODO: in the rare case where the alarm fires and posts the lambda to the handler
// thread while we are processing an RA that changes the lifetime of the same prefix,
// this code will run anyway even if the alarm is rescheduled or cancelled. If the
- // lifetime in the RA is zero this doesn't matter (we just harmlessly cancel the alarm
- // one extra time) but if the lifetime is nonzero then the prefix will be added and
- // immediately removed by this code.
+ // lifetime in the RA is zero this code will correctly do nothing, but if the lifetime
+ // is nonzero then the prefix will be added and immediately removed by this code.
+ if (mNat64PrefixExpiry == 0) return;
updatePref64(mShim.getNat64Prefix(mLinkProperties),
mNat64PrefixExpiry, mNat64PrefixExpiry);
};
private void cancelPref64Alarm() {
+ // Clear the expiry in case the alarm just fired and has not been processed yet.
+ if (mNat64PrefixExpiry == 0) return;
+ mNat64PrefixExpiry = 0;
mAlarmManager.cancel(mExpirePref64Alarm);
}
@@ -342,7 +352,6 @@ public class IpClientLinkObserver implements NetworkObserver {
schedulePref64Alarm();
} else {
mShim.setNat64Prefix(mLinkProperties, null);
- mNat64PrefixExpiry = 0;
cancelPref64Alarm();
}
diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
index 225f598..4a3f445 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
@@ -1527,6 +1527,25 @@ public class IpClientIntegrationTest {
mIpc.getHandler().post(() -> lastAlarm.onAlarm());
expectAlarmCancelled(inOrder, pref64Alarm);
expectNat64PrefixUpdate(inOrder, null);
+
+ // Re-announce the prefix.
+ pref64 = new StructNdOptPref64(prefix, 600).toByteBuffer();
+ ra = buildRaPacket(pio, rdnss, pref64);
+ mPacketReader.sendResponse(ra);
+ final OnAlarmListener clearAlarm = expectAlarmSet(inOrder, "PREF64", 600);
+ expectNat64PrefixUpdate(inOrder, prefix);
+ reset(mCb, mAlarm);
+
+ // Check that the alarm is cancelled when IpClient is stopped.
+ mIpc.stop();
+ HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
+ expectAlarmCancelled(inOrder, clearAlarm);
+ expectNat64PrefixUpdate(inOrder, null);
+
+ // Check that even if the alarm was already in the message queue while it was cancelled, it
+ // is safely ignored.
+ mIpc.getHandler().post(() -> clearAlarm.onAlarm());
+ HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
}
private void addIpAddressAndWaitForIt(final String iface) throws Exception {