From 184d4581818e9772cd5f675d0a5304b3fb947185 Mon Sep 17 00:00:00 2001 From: junyulai Date: Wed, 10 Mar 2021 15:26:50 +0800 Subject: [PATCH] [SP32] Try to get 1.1 OffloadControl hardware if available This is a no-op change that try to use 1.1 HAL if available. Otherwise, fallback to 1.0 HAL. The change also provides version information for subsequent patches to determine what to do for specific version. Test: atest TetheringTests Bug: 149467454 Ignore-AOSP-First: avoid long automerger delay Change-Id: I6a3ce877cdff2496087b97b191a9bfd5b0792827 --- Tethering/Android.bp | 1 + .../tethering/OffloadController.java | 12 ++- .../tethering/OffloadHardwareInterface.java | 83 ++++++++++++++++--- .../tethering/OffloadControllerTest.java | 43 ++++++---- .../OffloadHardwareInterfaceTest.java | 8 +- .../networkstack/tethering/TetheringTest.java | 15 ++-- 6 files changed, 123 insertions(+), 39 deletions(-) diff --git a/Tethering/Android.bp b/Tethering/Android.bp index 4eafc2afa9..89f1505b0c 100644 --- a/Tethering/Android.bp +++ b/Tethering/Android.bp @@ -36,6 +36,7 @@ java_defaults { "networkstack-client", "android.hardware.tetheroffload.config-V1.0-java", "android.hardware.tetheroffload.control-V1.0-java", + "android.hardware.tetheroffload.control-V1.1-java", "net-utils-framework-common", "net-utils-device-common", "netd-client", diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadController.java b/Tethering/src/com/android/networkstack/tethering/OffloadController.java index 88c77b07e7..44e3916bdf 100644 --- a/Tethering/src/com/android/networkstack/tethering/OffloadController.java +++ b/Tethering/src/com/android/networkstack/tethering/OffloadController.java @@ -26,6 +26,7 @@ import static android.net.NetworkStats.UID_TETHERING; import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; +import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE; import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; import android.annotation.NonNull; @@ -96,7 +97,8 @@ public class OffloadController { private final SharedLog mLog; private final HashMap mDownstreams; private boolean mConfigInitialized; - private boolean mControlInitialized; + @OffloadHardwareInterface.OffloadHalVersion + private int mControlHalVersion; private LinkProperties mUpstreamLinkProperties; // The complete set of offload-exempt prefixes passed in via Tethering from // all upstream and downstream sources. @@ -179,7 +181,7 @@ public class OffloadController { } } - mControlInitialized = mHwInterface.initOffloadControl( + mControlHalVersion = mHwInterface.initOffloadControl( // OffloadHardwareInterface guarantees that these callback // methods are called on the handler passed to it, which is the // same as mHandler, as coordinated by the setup in Tethering. @@ -278,7 +280,7 @@ public class OffloadController { updateStatsForCurrentUpstream(); mUpstreamLinkProperties = null; mHwInterface.stopOffloadControl(); - mControlInitialized = false; + mControlHalVersion = OFFLOAD_HAL_VERSION_NONE; mConfigInitialized = false; if (mHandler.hasCallbacks(mScheduledPollingTask)) { mHandler.removeCallbacks(mScheduledPollingTask); @@ -287,7 +289,7 @@ public class OffloadController { } private boolean started() { - return mConfigInitialized && mControlInitialized; + return mConfigInitialized && mControlHalVersion != OFFLOAD_HAL_VERSION_NONE; } @VisibleForTesting @@ -696,6 +698,8 @@ public class OffloadController { } final boolean isStarted = started(); pw.println("Offload HALs " + (isStarted ? "started" : "not started")); + pw.println("Offload Control HAL version: " + + OffloadHardwareInterface.halVerToString(mControlHalVersion)); LinkProperties lp = mUpstreamLinkProperties; String upstream = (lp != null) ? lp.getInterfaceName() : null; pw.println("Current upstream: " + upstream); diff --git a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java index da5f25b2a5..7685847680 100644 --- a/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java +++ b/Tethering/src/com/android/networkstack/tethering/OffloadHardwareInterface.java @@ -20,6 +20,7 @@ import static android.net.netlink.StructNlMsgHdr.NLM_F_DUMP; import static android.net.netlink.StructNlMsgHdr.NLM_F_REQUEST; import static android.net.util.TetheringUtils.uint16; +import android.annotation.IntDef; import android.annotation.NonNull; import android.hardware.tetheroffload.config.V1_0.IOffloadConfig; import android.hardware.tetheroffload.control.V1_0.IOffloadControl; @@ -38,12 +39,15 @@ import android.os.RemoteException; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import java.io.FileDescriptor; import java.io.IOException; import java.io.InterruptedIOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.net.SocketAddress; import java.net.SocketException; import java.nio.ByteBuffer; @@ -82,6 +86,37 @@ public class OffloadHardwareInterface { private final SharedLog mLog; private final Dependencies mDeps; private IOffloadControl mOffloadControl; + + // TODO: Use major-minor version control to prevent from defining new constants. + static final int OFFLOAD_HAL_VERSION_NONE = 0; + static final int OFFLOAD_HAL_VERSION_1_0 = 1; + static final int OFFLOAD_HAL_VERSION_1_1 = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "OFFLOAD_HAL_VERSION_", value = { + OFFLOAD_HAL_VERSION_NONE, + OFFLOAD_HAL_VERSION_1_0, + OFFLOAD_HAL_VERSION_1_1 + }) + public @interface OffloadHalVersion {} + @OffloadHalVersion + private int mOffloadControlVersion = OFFLOAD_HAL_VERSION_NONE; + + @NonNull + static String halVerToString(int version) { + switch(version) { + case OFFLOAD_HAL_VERSION_1_0: + return "1.0"; + case OFFLOAD_HAL_VERSION_1_1: + return "1.1"; + case OFFLOAD_HAL_VERSION_NONE: + return "None"; + default: + throw new IllegalArgumentException("Unsupported version int " + version); + } + + } + private TetheringOffloadCallback mTetheringOffloadCallback; private ControlCallback mControlCallback; @@ -167,13 +202,30 @@ public class OffloadHardwareInterface { } } - public IOffloadControl getOffloadControl() { + @NonNull + public Pair getOffloadControl() { + IOffloadControl hal = null; + int version = OFFLOAD_HAL_VERSION_NONE; try { - return IOffloadControl.getService(true /*retry*/); - } catch (RemoteException | NoSuchElementException e) { - mLog.e("tethering offload control not supported: " + e); - return null; + hal = android.hardware.tetheroffload.control + .V1_1.IOffloadControl.getService(true /*retry*/); + version = OFFLOAD_HAL_VERSION_1_1; + } catch (NoSuchElementException e) { + // Unsupported by device. + } catch (RemoteException e) { + mLog.e("Unable to get offload control " + OFFLOAD_HAL_VERSION_1_1); } + if (hal == null) { + try { + hal = IOffloadControl.getService(true /*retry*/); + version = OFFLOAD_HAL_VERSION_1_0; + } catch (NoSuchElementException e) { + // Unsupported by device. + } catch (RemoteException e) { + mLog.e("Unable to get offload control " + OFFLOAD_HAL_VERSION_1_0); + } + } + return new Pair(hal, version); } public NativeHandle createConntrackSocket(final int groups) { @@ -304,16 +356,25 @@ public class OffloadHardwareInterface { } } - /** Initialize the tethering offload HAL. */ - public boolean initOffloadControl(ControlCallback controlCb) { + /** + * Initialize the tethering offload HAL. + * + * @return one of {@code OFFLOAD_HAL_VERSION_*} represents the HAL version, or + * {@link #OFFLOAD_HAL_VERSION_NONE} if failed. + */ + public int initOffloadControl(ControlCallback controlCb) { mControlCallback = controlCb; if (mOffloadControl == null) { - mOffloadControl = mDeps.getOffloadControl(); + final Pair halAndVersion = mDeps.getOffloadControl(); + mOffloadControl = halAndVersion.first; + mOffloadControlVersion = halAndVersion.second; if (mOffloadControl == null) { mLog.e("tethering IOffloadControl.getService() returned null"); - return false; + return OFFLOAD_HAL_VERSION_NONE; } + mLog.i("tethering offload control version " + + halVerToString(mOffloadControlVersion) + " is supported."); } final String logmsg = String.format("initOffloadControl(%s)", @@ -331,11 +392,11 @@ public class OffloadHardwareInterface { }); } catch (RemoteException e) { record(logmsg, e); - return false; + return OFFLOAD_HAL_VERSION_NONE; } record(logmsg, results); - return results.mSuccess; + return results.mSuccess ? mOffloadControlVersion : OFFLOAD_HAL_VERSION_NONE; } /** Stop IOffloadControl. */ diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java index 9bd82f96de..88f205445e 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadControllerTest.java @@ -29,6 +29,8 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_IFACE; import static com.android.networkstack.tethering.OffloadController.StatsType.STATS_PER_UID; import static com.android.networkstack.tethering.OffloadHardwareInterface.ForwardedStats; +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 com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; import static com.android.testutils.MiscAsserts.assertContainsAll; import static com.android.testutils.MiscAsserts.assertThrows; @@ -141,10 +143,10 @@ public class OffloadControllerTest { FakeSettingsProvider.clearSettingsProvider(); } - private void setupFunctioningHardwareInterface() { + private void setupFunctioningHardwareInterface(int controlVersion) { when(mHardware.initOffloadConfig()).thenReturn(true); when(mHardware.initOffloadControl(mControlCallbackCaptor.capture())) - .thenReturn(true); + .thenReturn(controlVersion); when(mHardware.setUpstreamParameters(anyString(), any(), any(), any())).thenReturn(true); when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats()); when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true); @@ -170,6 +172,7 @@ public class OffloadControllerTest { ArgumentCaptor.forClass(OffloadController.OffloadTetheringStatsProvider.class); verify(mStatsManager).registerNetworkStatsProvider(anyString(), tetherStatsProviderCaptor.capture()); + reset(mStatsManager); mTetherStatsProvider = tetherStatsProviderCaptor.getValue(); assertNotNull(mTetherStatsProvider); mTetherStatsProviderCb = new TestableNetworkStatsProviderCbBinder(); @@ -177,10 +180,18 @@ public class OffloadControllerTest { return offload; } + @Test + public void testStartStop() throws Exception { + stopOffloadController( + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/)); + stopOffloadController( + startOffloadController(OFFLOAD_HAL_VERSION_1_1, true /*expectStart*/)); + } + @NonNull - private OffloadController startOffloadController(boolean expectStart) + private OffloadController startOffloadController(int controlVersion, boolean expectStart) throws Exception { - setupFunctioningHardwareInterface(); + setupFunctioningHardwareInterface(controlVersion); final OffloadController offload = makeOffloadController(); offload.start(); @@ -208,7 +219,7 @@ public class OffloadControllerTest { when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1); assertThrows(SettingNotFoundException.class, () -> Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED)); - startOffloadController(false /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, false /*expectStart*/); } @Test @@ -216,26 +227,26 @@ public class OffloadControllerTest { when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0); assertThrows(SettingNotFoundException.class, () -> Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED)); - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); } @Test public void testSettingsAllowsStart() throws Exception { Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 0); - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); } @Test public void testSettingsDisablesStart() throws Exception { Settings.Global.putInt(mContentResolver, TETHER_OFFLOAD_DISABLED, 1); - startOffloadController(false /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, false /*expectStart*/); } @Test public void testSetUpstreamLinkPropertiesWorking() throws Exception { enableOffload(); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); // In reality, the UpstreamNetworkMonitor would have passed down to us // a covering set of local prefixes representing a minimum essential @@ -406,7 +417,7 @@ public class OffloadControllerTest { public void testGetForwardedStats() throws Exception { enableOffload(); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); final String ethernetIface = "eth1"; final String mobileIface = "rmnet_data0"; @@ -496,7 +507,7 @@ public class OffloadControllerTest { public void testSetInterfaceQuota() throws Exception { enableOffload(); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); final String ethernetIface = "eth1"; final String mobileIface = "rmnet_data0"; @@ -558,7 +569,7 @@ public class OffloadControllerTest { public void testDataLimitCallback() throws Exception { enableOffload(); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue(); callback.onStoppedLimitReached(); @@ -569,7 +580,7 @@ public class OffloadControllerTest { public void testAddRemoveDownstreams() throws Exception { enableOffload(); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); final InOrder inOrder = inOrder(mHardware); // Tethering makes several calls to setLocalPrefixes() before add/remove @@ -636,7 +647,7 @@ public class OffloadControllerTest { public void testControlCallbackOnStoppedUnsupportedFetchesAllStats() throws Exception { enableOffload(); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); // Pretend to set a few different upstreams (only the interface name // matters for this test; we're ignoring IP and route information). @@ -667,7 +678,7 @@ public class OffloadControllerTest { throws Exception { enableOffload(); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); // Pretend to set a few different upstreams (only the interface name // matters for this test; we're ignoring IP and route information). @@ -745,7 +756,7 @@ public class OffloadControllerTest { enableOffload(); setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); final OffloadController offload = - startOffloadController(true /*expectStart*/); + startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); // Initialize with fake eth upstream. final String ethernetIface = "eth1"; 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 38b19dd3da..f4194e5d77 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/OffloadHardwareInterfaceTest.java @@ -21,6 +21,8 @@ import static android.system.OsConstants.AF_INET; 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 org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; @@ -45,6 +47,7 @@ import android.os.test.TestLooper; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; +import android.util.Pair; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -91,8 +94,8 @@ public final class OffloadHardwareInterfaceTest { } @Override - public IOffloadControl getOffloadControl() { - return mIOffloadControl; + public Pair getOffloadControl() { + return new Pair(mIOffloadControl, OFFLOAD_HAL_VERSION_1_0); } @Override @@ -110,6 +113,7 @@ public final class OffloadHardwareInterfaceTest { mControlCallback = spy(new OffloadHardwareInterface.ControlCallback()); } + // TODO: Pass version to test version specific operations. private void startOffloadHardwareInterface() throws Exception { mOffloadHw.initOffloadConfig(); mOffloadHw.initOffloadControl(mControlCallback); diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java index b207af911d..b7a82f7a9f 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -60,6 +60,8 @@ import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static com.android.net.module.util.Inet4AddressUtils.inet4AddressToIntHTH; import static com.android.net.module.util.Inet4AddressUtils.intToInet4AddressHTH; +import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_0; +import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE; import static com.android.networkstack.tethering.TestConnectivityManager.BROADCAST_FIRST; import static com.android.networkstack.tethering.TestConnectivityManager.CALLBACKS_FIRST; import static com.android.networkstack.tethering.Tethering.UserRestrictionActionListener; @@ -622,7 +624,7 @@ public class TetheringTest { mInterfaceConfiguration.flags = new String[0]; when(mRouterAdvertisementDaemon.start()) .thenReturn(true); - initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */, + initOffloadConfiguration(true /* offloadConfig */, OFFLOAD_HAL_VERSION_1_0, 0 /* defaultDisabled */); when(mOffloadHardwareInterface.getForwardedStats(any())).thenReturn(mForwardedStats); @@ -1711,7 +1713,7 @@ public class TetheringTest { callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); // 1. Offload fail if no OffloadConfig. - initOffloadConfiguration(false /* offloadConfig */, true /* offloadControl */, + initOffloadConfiguration(false /* offloadConfig */, OFFLOAD_HAL_VERSION_1_0, 0 /* defaultDisabled */); runUsbTethering(upstreamState); callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED); @@ -1719,7 +1721,7 @@ public class TetheringTest { callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); reset(mUsbManager); // 2. Offload fail if no OffloadControl. - initOffloadConfiguration(true /* offloadConfig */, false /* offloadControl */, + initOffloadConfiguration(true /* offloadConfig */, OFFLOAD_HAL_VERSION_NONE, 0 /* defaultDisabled */); runUsbTethering(upstreamState); callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED); @@ -1727,7 +1729,7 @@ public class TetheringTest { callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_STOPPED); reset(mUsbManager); // 3. Offload fail if disabled by settings. - initOffloadConfiguration(true /* offloadConfig */, true /* offloadControl */, + initOffloadConfiguration(true /* offloadConfig */, OFFLOAD_HAL_VERSION_1_0, 1 /* defaultDisabled */); runUsbTethering(upstreamState); callback.expectOffloadStatusChanged(TETHER_HARDWARE_OFFLOAD_FAILED); @@ -1743,9 +1745,10 @@ public class TetheringTest { } private void initOffloadConfiguration(final boolean offloadConfig, - final boolean offloadControl, final int defaultDisabled) { + @OffloadHardwareInterface.OffloadHalVersion final int offloadControlVersion, + final int defaultDisabled) { when(mOffloadHardwareInterface.initOffloadConfig()).thenReturn(offloadConfig); - when(mOffloadHardwareInterface.initOffloadControl(any())).thenReturn(offloadControl); + when(mOffloadHardwareInterface.initOffloadControl(any())).thenReturn(offloadControlVersion); when(mOffloadHardwareInterface.getDefaultTetherOffloadDisabled()).thenReturn( defaultDisabled); }