From bec4b5b8d41d30875380ffd123b735740f8b0f7d Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Tue, 13 May 2025 15:37:32 +0900 Subject: [PATCH] Disallow the legacy tether API for Wi-Fi. AOSP code has never used this API, and metrics from production show no usage either. Removing it will allow simplifying the code. This CL removes testRequestStaticIpLegacyTether because it makes legacyTether a no-op and there is already a test for static IP request right above it. Bug: 408087033 Flag: EXEMPT dead code Test: updated existing tests Change-Id: Ib94ed0860ab57abfd9fc7bdfdc911f5ab57003ed --- .../networkstack/tethering/Tethering.java | 50 +++++-------------- .../networkstack/tethering/TetheringTest.java | 36 +++---------- .../tethering/cts/TetheringManagerTest.java | 25 ++++------ 3 files changed, 29 insertions(+), 82 deletions(-) diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java index efbaee4ea6..3348c9e8a5 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -52,6 +52,7 @@ import static android.net.TetheringManager.TETHER_ERROR_UNAVAIL_IFACE; import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_REQUEST; import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_TYPE; +import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; @@ -75,10 +76,6 @@ import static com.android.networkstack.tethering.TetheringConfiguration.TETHER_F import static com.android.networkstack.tethering.TetheringNotificationUpdater.DOWNSTREAM_NONE; import static com.android.networkstack.tethering.UpstreamNetworkMonitor.isCellular; import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED; -import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI; -import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P; -import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P_SUCCESS; -import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_SUCCESS; import static com.android.networkstack.tethering.metrics.TetheringStatsLog.CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_TETHER_WITH_PLACEHOLDER_REQUEST; import static com.android.networkstack.tethering.util.TetheringMessageBase.BASE_MAIN_SM; import static com.android.networkstack.tethering.util.TetheringUtils.createImplicitLocalOnlyTetheringRequest; @@ -1137,41 +1134,17 @@ public class Tethering { return; } + if (type == TETHERING_WIFI || type == TETHERING_WIFI_P2P) { + // Metrics show no usage of this legacy codepath. Stop supporing it. + sendTetherResult(listener, TETHER_ERROR_UNSUPPORTED); + return; + } + TetheringRequest request = mRequestTracker.getNextPendingRequest(type); if (request == null) { request = createLegacyGlobalScopeTetheringRequest(type); } - int result = tetherInternal(request, iface); - switch (type) { - case TETHERING_WIFI: - Log.i(TAG, "Legacy tether API called on Wifi iface " + iface); - TetheringStatsLog.write( - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED, - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI); - if (result == TETHER_ERROR_NO_ERROR) { - Log.i(TAG, "Legacy tether API succeeded on Wifi iface " + iface); - TetheringStatsLog.write( - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED, - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_SUCCESS); - } - break; - case TETHERING_WIFI_P2P: - Log.i(TAG, "Legacy tether API called on Wifi P2P iface " + iface); - TetheringStatsLog.write( - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED, - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P); - if (result == TETHER_ERROR_NO_ERROR) { - Log.i(TAG, "Legacy tether API succeeded on Wifi P2P iface " + iface); - TetheringStatsLog.write( - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED, - CORE_NETWORKING_TERRIBLE_ERROR_OCCURRED__ERROR_TYPE__TYPE_LEGACY_TETHER_WITH_TYPE_WIFI_P2P_SUCCESS); - } - break; - default: - // Do nothing - break; - } - sendTetherResult(listener, result); + sendTetherResult(listener, tetherInternal(request, iface)); } /** @@ -1181,11 +1154,12 @@ public class Tethering { * processInterfaceStateChanged beforehand, which is only possible for * - WIGIG Pre-S * - BLUETOOTH Pre-T + * It was previously supported but no longer allowed for: * - WIFI * - WIFI_P2P. - * Note that WIFI and WIFI_P2P already start tethering on their respective ifaces via - * WIFI_(AP/P2P_STATE_CHANGED broadcasts, which makes this API redundant for those types unless - * those broadcasts are disabled by OEM. + * because metrics show that there is no usage of this method for these types in production. + * These types start tethering on their respective ifaces via WIFI_(AP/P2P_STATE_CHANGED + * broadcasts instead. */ void legacyTether(String iface, final IIntResultListener listener) { mHandler.post(() -> handleLegacyTether(iface, listener)); 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 7a262ded62..cb25145a4d 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -57,6 +57,7 @@ import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; import static android.net.TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL; import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_IFACE; import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_REQUEST; +import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_FAILED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STARTED; import static android.net.TetheringManager.TETHER_HARDWARE_OFFLOAD_STOPPED; @@ -3415,39 +3416,18 @@ public class TetheringTest { @Test @IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM) - public void testRequestStaticIpLegacyTether() throws Exception { + public void testLegacyTetherUnsupported() throws Exception { initTetheringOnTestThread(); - // Call startTethering with static ip - final LinkAddress serverLinkAddr = new LinkAddress("192.168.0.123/24"); - final LinkAddress clientLinkAddr = new LinkAddress("192.168.0.42/24"); - final String serverAddr = "192.168.0.123"; - final int clientAddrParceled = 0xc0a8002a; - final ArgumentCaptor dhcpParamsCaptor = - ArgumentCaptor.forClass(DhcpServingParamsParcel.class); - mTethering.startTethering(createTetheringRequest(TETHERING_WIFI, - serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL, null), - TEST_CALLER_PKG, null); + mTethering.interfaceAdded(TEST_WIFI_IFNAME); mLooper.dispatchAll(); - verifyWifiTetheringRequested(); - mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true); + mTethering.interfaceStatusChanged(TEST_WIFI_IFNAME, false); + mTethering.interfaceStatusChanged(TEST_WIFI_IFNAME, true); - // Call legacyTether on the interface before the link layer event comes back. - // This happens, for example, in pre-T bluetooth tethering: Settings calls startTethering, - // and then the bluetooth code calls the tether() API. - final ResultListener tetherResult = new ResultListener(TETHER_ERROR_NO_ERROR); - mTethering.legacyTether(TEST_WLAN_IFNAME, tetherResult); + final ResultListener result = new ResultListener(TETHER_ERROR_UNSUPPORTED); + mTethering.legacyTether(TEST_WIFI_IFNAME, result); mLooper.dispatchAll(); - tetherResult.assertHasResult(); - - // Verify that the static ip set in startTethering is used - verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr))); - verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(), - any()); - final DhcpServingParamsParcel params = dhcpParamsCaptor.getValue(); - assertEquals(serverAddr, intToInet4AddressHTH(params.serverAddr).getHostAddress()); - assertEquals(24, params.serverAddrPrefixLength); - assertEquals(clientAddrParceled, params.singleClientAddr); + result.assertHasResult(); } @Test diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java index 006eafd8b9..c5e604fb65 100644 --- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java +++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java @@ -41,6 +41,7 @@ import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN; import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION; import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR; import static android.net.TetheringManager.TETHER_ERROR_UNKNOWN_REQUEST; +import static android.net.TetheringManager.TETHER_ERROR_UNSUPPORTED; import static android.net.cts.util.CtsTetheringUtils.isAnyIfaceMatch; import static android.os.Process.INVALID_UID; @@ -432,28 +433,20 @@ public class TetheringManagerTest { mCtsTetheringUtils.startWifiTethering(tetherEventCallback, softApConfig); assertNotNull(tetheredIface); + final String wifiTetheringIface = tetheredIface.getInterface(); if (SdkLevel.isAtLeastB()) { assertEquals(softApConfig, tetheredIface.getSoftApConfiguration()); } mCtsTetheringUtils.stopWifiTethering(tetherEventCallback); - if (!SdkLevel.isAtLeastB()) { - final String wifiTetheringIface = tetheredIface.getInterface(); - try { - final int ret = runAsShell(TETHER_PRIVILEGED, - () -> mTM.tether(wifiTetheringIface)); - // There is no guarantee that the wifi interface will be available after - // disabling the hotspot, so don't fail the test if the call to tether() fails. - if (ret == TETHER_ERROR_NO_ERROR) { - // If calling #tether successful, there is a callback to tell the result of - // tethering setup. - tetherEventCallback.expectErrorOrTethered( - new TetheringInterface(TETHERING_WIFI, wifiTetheringIface)); - } - } finally { - runAsShell(TETHER_PRIVILEGED, () -> mTM.untether(wifiTetheringIface)); - } + if (SdkLevel.isAtLeastB()) { + assertThrows(UnsupportedOperationException.class, + () -> runAsShell(TETHER_PRIVILEGED, + () -> mTM.tether(wifiTetheringIface))); + } else { + final int ret = runAsShell(TETHER_PRIVILEGED, () -> mTM.tether(wifiTetheringIface)); + assertEquals(TETHER_ERROR_UNSUPPORTED, ret); } } finally { mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);