Add boolean to ApfFilter to indicate whether mechanism is running
This change adds a boolean and corresponding getter implementation
(including a default implementation to satisfy LegacyApfFilter) to
ApfFilter. This boolean will indicate whether the ApfFilter is currently
running, i.e. it is allowed to install programs.
For test (and debug) purposes, new adb shell cmd interfaces are being
added that will support pausing and resuming ApfFilter generation.
Test: builds
Change-Id: I0cf3fe69e9d457385e5fa581ae72461e2ee19545
diff --git a/src/android/net/apf/AndroidPacketFilter.java b/src/android/net/apf/AndroidPacketFilter.java
index 18c704e..8e907b3 100644
--- a/src/android/net/apf/AndroidPacketFilter.java
+++ b/src/android/net/apf/AndroidPacketFilter.java
@@ -77,4 +77,12 @@
* Dump the status of APF.
*/
void dump(IndentingPrintWriter pw);
+
+ /**
+ * Indicates whether the ApfFilter is currently running / paused for test and debugging
+ * purposes.
+ */
+ default boolean isRunning() {
+ return true;
+ }
}
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index dc4a0f5..d864919 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -337,6 +337,11 @@
@GuardedBy("this")
private int mIPv4PrefixLength;
+ // mIsRunning is reflects the state of the ApfFilter during integration tests. ApfFilter can be
+ // paused using "adb shell cmd apf <iface> <cmd>" commands. A paused ApfFilter will not install
+ // any new programs, but otherwise operate normally.
+ private volatile boolean mIsRunning = true;
+
private final Dependencies mDependencies;
public ApfFilter(Context context, ApfConfiguration config, InterfaceParams ifParams,
@@ -498,7 +503,7 @@
// Clear the APF memory to reset all counters upon connecting to the first AP
// in an SSID. This is limited to APFv4 devices because this large write triggers
// a crash on some older devices (b/78905546).
- if (mApfCapabilities.hasDataAccess()) {
+ if (mIsRunning && mApfCapabilities.hasDataAccess()) {
byte[] zeroes = new byte[mApfCapabilities.maximumApfProgramSize];
if (!mIpClientCallback.installPacketFilter(zeroes)) {
sendNetworkQuirkMetrics(NetworkQuirkEvent.QE_APF_INSTALL_FAILURE);
@@ -2120,10 +2125,12 @@
sendNetworkQuirkMetrics(NetworkQuirkEvent.QE_APF_GENERATE_FILTER_EXCEPTION);
return;
}
- // Update data snapshot every time we install a new program
- mIpClientCallback.startReadPacketFilter();
- if (!mIpClientCallback.installPacketFilter(program)) {
- sendNetworkQuirkMetrics(NetworkQuirkEvent.QE_APF_INSTALL_FAILURE);
+ if (mIsRunning) {
+ // Update data snapshot every time we install a new program
+ mIpClientCallback.startReadPacketFilter();
+ if (!mIpClientCallback.installPacketFilter(program)) {
+ sendNetworkQuirkMetrics(NetworkQuirkEvent.QE_APF_INSTALL_FAILURE);
+ }
}
mLastTimeInstalledProgram = timeSeconds;
mLastInstalledProgramMinLifetime = programMinLft;
@@ -2418,6 +2425,7 @@
public synchronized void dump(IndentingPrintWriter pw) {
pw.println("Capabilities: " + mApfCapabilities);
pw.println("InstallableProgramSizeClamp: " + mInstallableProgramSizeClamp);
+ pw.println("Filter update status: " + (mIsRunning ? "RUNNING" : "PAUSED"));
pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
pw.println("Multicast: " + (mMulticastFilter ? "DROP" : "ALLOW"));
pw.println("Minimum RDNSS lifetime: " + mMinRdnssLifetimeSec);
@@ -2523,6 +2531,11 @@
pw.decreaseIndent();
}
+ /** Return ApfFilter update status for testing purposes. */
+ public boolean isRunning() {
+ return mIsRunning;
+ }
+
// TODO: move to android.net.NetworkUtils
@VisibleForTesting
public static int ipv4BroadcastAddress(byte[] addrBytes, int prefixLength) {