From e25d3edec10f7b9cd60c291808f760a490b7d31d Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Mon, 16 Apr 2018 13:48:10 +0900 Subject: WifiNative plumbing for reading back the APF program & data buffer Bug: 73804303 Test: frameworks/opt/net/wifi/tests/wifitests/runtests.sh Change-Id: Ib2a0f2ec04df28aabf422fa3149850f601f55db9 --- .../java/com/android/server/wifi/WifiNative.java | 12 ++++- .../com/android/server/wifi/WifiStateMachine.java | 16 ++++++- .../com/android/server/wifi/WifiVendorHal.java | 51 ++++++++++++++++++++++ .../com/android/server/wifi/WifiVendorHalTest.java | 26 ++++++++++- 4 files changed, 101 insertions(+), 4 deletions(-) diff --git a/service/java/com/android/server/wifi/WifiNative.java b/service/java/com/android/server/wifi/WifiNative.java index c86f566a0..8a76c4d3b 100644 --- a/service/java/com/android/server/wifi/WifiNative.java +++ b/service/java/com/android/server/wifi/WifiNative.java @@ -2195,7 +2195,7 @@ public class WifiNative { /** * Installs an APF program on this iface, replacing any existing program. * - * @param ifaceName Name of the interface. + * @param ifaceName Name of the interface * @param filter is the android packet filter program * @return true for success */ @@ -2203,6 +2203,16 @@ public class WifiNative { return mWifiVendorHal.installPacketFilter(ifaceName, filter); } + /** + * Reads the APF program and data buffer for this iface. + * + * @param ifaceName Name of the interface + * @return the buffer returned by the driver, or null in case of an error + */ + public byte[] readPacketFilter(@NonNull String ifaceName) { + return mWifiVendorHal.readPacketFilter(ifaceName); + } + /** * Set country code for this AP iface. * @param ifaceName Name of the interface. diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java index 32427c92c..4cb7d3722 100644 --- a/service/java/com/android/server/wifi/WifiStateMachine.java +++ b/service/java/com/android/server/wifi/WifiStateMachine.java @@ -636,6 +636,9 @@ public class WifiStateMachine extends StateMachine { /* used to indicate that the foreground user was switched */ static final int CMD_USER_STOP = BASE + 207; + /* Read the APF program & data buffer */ + static final int CMD_READ_PACKET_FILTER = BASE + 208; + /* Indicates that diagnostics should time out a connection start event. */ private static final int CMD_DIAGS_CONNECT_TIMEOUT = BASE + 252; @@ -1064,6 +1067,11 @@ public class WifiStateMachine extends StateMachine { sendMessage(CMD_INSTALL_PACKET_FILTER, filter); } + @Override + public void startReadPacketFilter() { + sendMessage(CMD_READ_PACKET_FILTER); + } + @Override public void setFallbackMulticastFilter(boolean enabled) { sendMessage(CMD_SET_FALLBACK_PACKET_FILTERING, enabled); @@ -3578,6 +3586,10 @@ public class WifiStateMachine extends StateMachine { case CMD_INSTALL_PACKET_FILTER: mWifiNative.installPacketFilter(mInterfaceName, (byte[]) message.obj); break; + case CMD_READ_PACKET_FILTER: + byte[] data = mWifiNative.readPacketFilter(mInterfaceName); + mIpClient.readPacketFilterComplete(data); + break; case CMD_SET_FALLBACK_PACKET_FILTERING: if ((boolean) message.obj) { mWifiNative.startFilteringMulticastV4Packets(mInterfaceName); @@ -5636,8 +5648,8 @@ public class WifiStateMachine extends StateMachine { } /** - * State machine initiated requests can have replyTo set to null indicating - * there are no recepients, we ignore those reply actions. + * State machine initiated requests can have replyTo set to null, indicating + * there are no recipients, we ignore those reply actions. */ private void replyToMessage(Message msg, int what) { if (msg.replyTo == null) return; diff --git a/service/java/com/android/server/wifi/WifiVendorHal.java b/service/java/com/android/server/wifi/WifiVendorHal.java index 36060fa55..16a279833 100644 --- a/service/java/com/android/server/wifi/WifiVendorHal.java +++ b/service/java/com/android/server/wifi/WifiVendorHal.java @@ -74,6 +74,7 @@ import android.util.MutableInt; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; +import com.android.internal.util.HexDump; import com.android.server.wifi.HalDeviceManager.InterfaceDestroyedListener; import com.android.server.wifi.util.BitMask; import com.android.server.wifi.util.NativeUtil; @@ -184,6 +185,26 @@ public class WifiVendorHal { return result; } + /** + * Logs the argument along with the method name. + * + * Always returns its argument. + */ + private byte[] byteArrayResult(byte[] result) { + if (mVerboseLog == sNoLog) return result; + // Currently only seen if verbose logging is on + + Thread cur = Thread.currentThread(); + StackTraceElement[] trace = cur.getStackTrace(); + + mVerboseLog.err("% returns %") + .c(niceMethodName(trace, 3)) + .c(HexDump.dumpHexString(result)) + .flush(); + + return result; + } + /** * Logs at method entry * @@ -1737,6 +1758,36 @@ public class WifiVendorHal { } } + /** + * Reads the APF program and data buffer on this iface. + * + * @param ifaceName Name of the interface + * @return the buffer returned by the driver, or null in case of an error + */ + public byte[] readPacketFilter(@NonNull String ifaceName) { + class AnswerBox { + public byte[] data = null; + } + AnswerBox answer = new AnswerBox(); + enter("").flush(); + // TODO: Must also take the wakelock here to prevent going to sleep with APF disabled. + synchronized (sLock) { + try { + android.hardware.wifi.V1_2.IWifiStaIface ifaceV12 = + getWifiStaIfaceForV1_2Mockable(ifaceName); + if (ifaceV12 == null) return byteArrayResult(null); + ifaceV12.readApfPacketFilterData((status, dataByteArray) -> { + if (!ok(status)) return; + answer.data = NativeUtil.byteArrayFromArrayList(dataByteArray); + }); + return byteArrayResult(answer.data); + } catch (RemoteException e) { + handleRemoteException(e); + return byteArrayResult(null); + } + } + } + /** * Set country code for this AP iface. * diff --git a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java index 70c612918..9d20235ad 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiVendorHalTest.java @@ -1232,6 +1232,31 @@ public class WifiVendorHalTest { verify(mIWifiStaIface).installApfPacketFilter(eq(0), eq(expected)); } + /** + * Test that an APF program and data buffer can be read back. + */ + @Test + public void testReadApf() throws Exception { + // Expose the 1.2 IWifiStaIface. + mWifiVendorHal = new WifiVendorHalSpyV1_2(mHalDeviceManager, mLooper.getLooper()); + + byte[] program = new byte[] {65, 66, 67}; + ArrayList expected = new ArrayList<>(3); + for (byte b : program) expected.add(b); + + doAnswer(new AnswerWithArguments() { + public void answer( + android.hardware.wifi.V1_2.IWifiStaIface.readApfPacketFilterDataCallback cb) + throws RemoteException { + cb.onValues(mWifiStatusSuccess, expected); + } + }).when(mIWifiStaIfaceV12).readApfPacketFilterData(any( + android.hardware.wifi.V1_2.IWifiStaIface.readApfPacketFilterDataCallback.class)); + + assertTrue(mWifiVendorHal.startVendorHalSta()); + assertArrayEquals(program, mWifiVendorHal.readPacketFilter(TEST_IFACE_NAME)); + } + /** * Test that the country code is set in AP mode (when it should be). */ @@ -1348,7 +1373,6 @@ public class WifiVendorHalTest { assertEquals(halBufferStatus.size(), actual.length); assertEquals(oneExpect, actual[0].toString()); assertEquals(two.ringId, actual[1].ringBufferId); - } /** -- cgit v1.2.3