From 5454e8978e37d08d638e0c10f0640eb22274aa92 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 17:00:29 +0800 Subject: [PATCH] [SP33] Adapt ITetheringOffloadCallback V1.1 This is a no-op change that redirect both V1.0 and V1.1 callback events to the same handling function. Since the V1.1 callback is extended from V1.0 callback, we can safely use V1.1 callback for both V1.0 and V1.1 control. The change also provides interface for subsequent OffloadController changes to set warning and limit at the same time. Test: atest TetheringTests Bug: 149467454 Ignore-AOSP-First: avoid long automerger delay Change-Id: I6505a04de8c57357dd1fa9ce898c13395e497816 --- .../tethering/OffloadHardwareInterface.java | 104 ++++++++++++++---- .../OffloadHardwareInterfaceTest.java | 84 +++++++++++--- 2 files changed, 150 insertions(+), 38 deletions(-) diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java index 7685847680..e3ac660910 100644 --- a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java +++ b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java @@ -24,10 +24,10 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; -import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; +import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback; import android.net.netlink.NetlinkSocket; import android.net.netlink.StructNfGenMsg; import android.net.netlink.StructNlMsgHdr; @@ -39,6 +39,7 @@ import android.os.RemoteException; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import android.util.Log; import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; @@ -140,6 +141,8 @@ public class OffloadHardwareInterface { public void onSupportAvailable() {} /** Offload stopped because of usage limit reached. */ public void onStoppedLimitReached() {} + /** Indicate that data warning quota is reached. */ + public void onWarningReached() {} /** Indicate to update NAT timeout. */ public void onNatTimeoutUpdate(int proto, @@ -381,7 +384,8 @@ public class OffloadHardwareInterface { (controlCb == null) ? "null" : "0x" + Integer.toHexString(System.identityHashCode(controlCb))); - mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, mControlCallback, mLog); + mTetheringOffloadCallback = new TetheringOffloadCallback( + mHandler, mControlCallback, mLog, mOffloadControlVersion); final CbResults results = new CbResults(); try { mOffloadControl.initOffload( @@ -480,6 +484,33 @@ public class OffloadHardwareInterface { return results.mSuccess; } + /** Set data warning and limit value to offload management process. */ + public boolean setDataWarningAndLimit(String iface, long warning, long limit) { + if (mOffloadControlVersion < OFFLOAD_HAL_VERSION_1_1) { + throw new IllegalArgumentException( + "setDataWarningAndLimit is not supported below HAL V1.1"); + } + final String logmsg = + String.format("setDataWarningAndLimit(%s, %d, %d)", iface, warning, limit); + + final CbResults results = new CbResults(); + try { + ((android.hardware.tetheroffload.control.V1_1.IOffloadControl) mOffloadControl) + .setDataWarningAndLimit( + iface, warning, limit, + (boolean success, String errMsg) -> { + results.mSuccess = success; + results.mErrMsg = errMsg; + }); + } catch (RemoteException e) { + record(logmsg, e); + return false; + } + + record(logmsg, results); + return results.mSuccess; + } + /** Set upstream parameters to offload management process. */ public boolean setUpstreamParameters( String iface, String v4addr, String v4gateway, ArrayList v6gws) { @@ -565,35 +596,64 @@ public class OffloadHardwareInterface { public final Handler handler; public final ControlCallback controlCb; public final SharedLog log; + private final int mOffloadControlVersion; - TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) { + TetheringOffloadCallback( + Handler h, ControlCallback cb, SharedLog sharedLog, int offloadControlVersion) { handler = h; controlCb = cb; log = sharedLog; + this.mOffloadControlVersion = offloadControlVersion; + } + + private void handleOnEvent(int event) { + switch (event) { + case OffloadCallbackEvent.OFFLOAD_STARTED: + controlCb.onStarted(); + break; + case OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR: + controlCb.onStoppedError(); + break; + case OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED: + controlCb.onStoppedUnsupported(); + break; + case OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE: + controlCb.onSupportAvailable(); + break; + case OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED: + controlCb.onStoppedLimitReached(); + break; + case android.hardware.tetheroffload.control + .V1_1.OffloadCallbackEvent.OFFLOAD_WARNING_REACHED: + controlCb.onWarningReached(); + break; + default: + log.e("Unsupported OffloadCallbackEvent: " + event); + } } @Override public void onEvent(int event) { + // The implementation should never call onEvent()) if the event is already reported + // through newer callback. + if (mOffloadControlVersion > OFFLOAD_HAL_VERSION_1_0) { + Log.wtf(TAG, "onEvent(" + event + ") fired on HAL " + + halVerToString(mOffloadControlVersion)); + } handler.post(() -> { - switch (event) { - case OffloadCallbackEvent.OFFLOAD_STARTED: - controlCb.onStarted(); - break; - case OffloadCallbackEvent.OFFLOAD_STOPPED_ERROR: - controlCb.onStoppedError(); - break; - case OffloadCallbackEvent.OFFLOAD_STOPPED_UNSUPPORTED: - controlCb.onStoppedUnsupported(); - break; - case OffloadCallbackEvent.OFFLOAD_SUPPORT_AVAILABLE: - controlCb.onSupportAvailable(); - break; - case OffloadCallbackEvent.OFFLOAD_STOPPED_LIMIT_REACHED: - controlCb.onStoppedLimitReached(); - break; - default: - log.e("Unsupported OffloadCallbackEvent: " + event); - } + handleOnEvent(event); + }); + } + + @Override + public void onEvent_1_1(int event) { + if (mOffloadControlVersion < OFFLOAD_HAL_VERSION_1_1) { + Log.wtf(TAG, "onEvent_1_1(" + event + ") fired on HAL " + + halVerToString(mOffloadControlVersion)); + return; + } + handler.post(() -> { + handleOnEvent(event); }); } diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java index f4194e5d77..a8b3b92de9 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java @@ -22,22 +22,27 @@ import static android.system.OsConstants.AF_UNIX; import static android.system.OsConstants.SOCK_STREAM; import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_0; +import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_1; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; -import android.hardware.tetheroffload.control.V1_0.ITetheringOffloadCallback; import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate; import android.hardware.tetheroffload.control.V1_0.NetworkProtocol; -import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent; +import android.hardware.tetheroffload.control.V1_1.ITetheringOffloadCallback; +import android.hardware.tetheroffload.control.V1_1.OffloadCallbackEvent; import android.net.netlink.StructNfGenMsg; import android.net.netlink.StructNlMsgHdr; import android.net.util.SharedLog; @@ -56,6 +61,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -76,7 +82,7 @@ public final class OffloadHardwareInterfaceTest { private OffloadHardwareInterface.ControlCallback mControlCallback; @Mock private IOffloadConfig mIOffloadConfig; - @Mock private IOffloadControl mIOffloadControl; + private IOffloadControl mIOffloadControl; @Mock private NativeHandle mNativeHandle; // Random values to test Netlink message. @@ -84,8 +90,10 @@ public final class OffloadHardwareInterfaceTest { private static final short TEST_FLAGS = 263; class MyDependencies extends OffloadHardwareInterface.Dependencies { - MyDependencies(SharedLog log) { + private final int mMockControlVersion; + MyDependencies(SharedLog log, final int mockControlVersion) { super(log); + mMockControlVersion = mockControlVersion; } @Override @@ -95,7 +103,19 @@ public final class OffloadHardwareInterfaceTest { @Override public Pair getOffloadControl() { - return new Pair(mIOffloadControl, OFFLOAD_HAL_VERSION_1_0); + switch (mMockControlVersion) { + case OFFLOAD_HAL_VERSION_1_0: + mIOffloadControl = mock(IOffloadControl.class); + break; + case OFFLOAD_HAL_VERSION_1_1: + mIOffloadControl = + mock(android.hardware.tetheroffload.control.V1_1.IOffloadControl.class); + break; + default: + throw new IllegalArgumentException("Invalid offload control version " + + mMockControlVersion); + } + return new Pair(mIOffloadControl, mMockControlVersion); } @Override @@ -107,14 +127,13 @@ public final class OffloadHardwareInterfaceTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); - final SharedLog log = new SharedLog("test"); - mOffloadHw = new OffloadHardwareInterface(new Handler(mTestLooper.getLooper()), log, - new MyDependencies(log)); mControlCallback = spy(new OffloadHardwareInterface.ControlCallback()); } - // TODO: Pass version to test version specific operations. - private void startOffloadHardwareInterface() throws Exception { + private void startOffloadHardwareInterface(int controlVersion) throws Exception { + final SharedLog log = new SharedLog("test"); + mOffloadHw = new OffloadHardwareInterface(new Handler(mTestLooper.getLooper()), log, + new MyDependencies(log, controlVersion)); mOffloadHw.initOffloadConfig(); mOffloadHw.initOffloadControl(mControlCallback); final ArgumentCaptor mOffloadCallbackCaptor = @@ -125,7 +144,7 @@ public final class OffloadHardwareInterfaceTest { @Test public void testGetForwardedStats() throws Exception { - startOffloadHardwareInterface(); + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); final OffloadHardwareInterface.ForwardedStats stats = mOffloadHw.getForwardedStats(RMNET0); verify(mIOffloadControl).getForwardedStats(eq(RMNET0), any()); assertNotNull(stats); @@ -133,7 +152,7 @@ public final class OffloadHardwareInterfaceTest { @Test public void testSetLocalPrefixes() throws Exception { - startOffloadHardwareInterface(); + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); final ArrayList localPrefixes = new ArrayList<>(); localPrefixes.add("127.0.0.0/8"); localPrefixes.add("fe80::/64"); @@ -143,15 +162,32 @@ public final class OffloadHardwareInterfaceTest { @Test public void testSetDataLimit() throws Exception { - startOffloadHardwareInterface(); + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); final long limit = 12345; mOffloadHw.setDataLimit(RMNET0, limit); verify(mIOffloadControl).setDataLimit(eq(RMNET0), eq(limit), any()); } + @Test + public void testSetDataWarningAndLimit() throws Exception { + // Verify V1.0 control HAL would reject the function call with exception. + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); + final long warning = 12345; + final long limit = 67890; + assertThrows(IllegalArgumentException.class, + () -> mOffloadHw.setDataWarningAndLimit(RMNET0, warning, limit)); + reset(mIOffloadControl); + + // Verify V1.1 control HAL could receive this function call. + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_1); + mOffloadHw.setDataWarningAndLimit(RMNET0, warning, limit); + verify((android.hardware.tetheroffload.control.V1_1.IOffloadControl) mIOffloadControl) + .setDataWarningAndLimit(eq(RMNET0), eq(warning), eq(limit), any()); + } + @Test public void testSetUpstreamParameters() throws Exception { - startOffloadHardwareInterface(); + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); final String v4addr = "192.168.10.1"; final String v4gateway = "192.168.10.255"; final ArrayList v6gws = new ArrayList<>(0); @@ -170,7 +206,7 @@ public final class OffloadHardwareInterfaceTest { @Test public void testUpdateDownstreamPrefix() throws Exception { - startOffloadHardwareInterface(); + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); final String ifName = "wlan1"; final String prefix = "192.168.43.0/24"; mOffloadHw.addDownstreamPrefix(ifName, prefix); @@ -182,7 +218,7 @@ public final class OffloadHardwareInterfaceTest { @Test public void testTetheringOffloadCallback() throws Exception { - startOffloadHardwareInterface(); + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); mTetheringOffloadCallback.onEvent(OffloadCallbackEvent.OFFLOAD_STARTED); mTestLooper.dispatchAll(); @@ -221,10 +257,26 @@ public final class OffloadHardwareInterfaceTest { eq(uint16(udpParams.src.port)), eq(udpParams.dst.addr), eq(uint16(udpParams.dst.port))); + reset(mControlCallback); + + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_1); + + // Verify the interface will process the events that comes from V1.1 HAL. + mTetheringOffloadCallback.onEvent_1_1(OffloadCallbackEvent.OFFLOAD_STARTED); + mTestLooper.dispatchAll(); + final InOrder inOrder = inOrder(mControlCallback); + inOrder.verify(mControlCallback).onStarted(); + inOrder.verifyNoMoreInteractions(); + + mTetheringOffloadCallback.onEvent_1_1(OffloadCallbackEvent.OFFLOAD_WARNING_REACHED); + mTestLooper.dispatchAll(); + inOrder.verify(mControlCallback).onWarningReached(); + inOrder.verifyNoMoreInteractions(); } @Test public void testSendIpv4NfGenMsg() throws Exception { + startOffloadHardwareInterface(OFFLOAD_HAL_VERSION_1_0); FileDescriptor writeSocket = new FileDescriptor(); FileDescriptor readSocket = new FileDescriptor(); try {