[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
This commit is contained in:
junyulai
2021-03-10 15:26:50 +08:00
parent 36aa3f237c
commit 184d458181
6 changed files with 123 additions and 39 deletions

View File

@@ -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",

View File

@@ -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<String, LinkProperties> 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);

View File

@@ -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<IOffloadControl, Integer> 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<IOffloadControl, Integer>(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<IOffloadControl, Integer> 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. */

View File

@@ -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";

View File

@@ -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<IOffloadControl, Integer> getOffloadControl() {
return new Pair<IOffloadControl, Integer>(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);

View File

@@ -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);
}