From acd7366b65a6607620f1a88a6cefae8dfea70110 Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Tue, 15 Apr 2025 15:15:36 +0900 Subject: [PATCH] Optionally remove legacy bluetooth tethering address cache on T+ After T, Bluetooth tethering could use a random address. But if we keep putting the legacy Bluetooth address in the cache, the coordinator will always assign the legacy address first until it runs into a conflict. This change in itself does not do anything. Once we have a trunk-stable namespace for mainline beta, we will add a flag for this change, and check the flag in PrivateAddressCoordinator. Bug: 287177081 Test: new unit tests Flag: EXEMPT no behaviour changes Change-Id: I56810b5b0e1098a5f89cbb1ad665d2b8652e860c --- .../PrivateAddressCoordinatorTest.java | 33 +++++++++++++++---- .../util/PrivateAddressCoordinator.java | 18 ++++++++-- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java index c6692bfe02..7d4aa697b6 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java @@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_VPN; import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.TetheringManager.CONNECTIVITY_SCOPE_GLOBAL; import static android.net.TetheringManager.CONNECTIVITY_SCOPE_LOCAL; +import static android.net.TetheringManager.TETHERING_BLUETOOTH; import static android.net.TetheringManager.TETHERING_ETHERNET; import static android.net.TetheringManager.TETHERING_USB; import static android.net.TetheringManager.TETHERING_WIFI; @@ -75,12 +76,13 @@ public final class PrivateAddressCoordinatorTest { @Mock private IpServer mUsbIpServer; @Mock private IpServer mEthernetIpServer; @Mock private IpServer mWifiP2pIpServer; + @Mock private IpServer mBluetoothIpServer; @Mock private Context mContext; @Mock private ConnectivityManager mConnectivityMgr; @Mock private PrivateAddressCoordinator.Dependencies mDeps; private PrivateAddressCoordinator mPrivateAddressCoordinator; - private final LinkAddress mBluetoothAddress = new LinkAddress("192.168.44.1/24"); + private final LinkAddress mLegacyBluetoothAddress = new LinkAddress("192.168.44.1/24"); private final LinkAddress mLegacyWifiP2pAddress = new LinkAddress("192.168.49.1/24"); private final Network mWifiNetwork = new Network(1); private final Network mMobileNetwork = new Network(2); @@ -117,6 +119,7 @@ public final class PrivateAddressCoordinatorTest { setUpIpServer(mHotspotIpServer, TETHERING_WIFI); setUpIpServer(mLocalHotspotIpServer, TETHERING_WIFI); setUpIpServer(mWifiP2pIpServer, TETHERING_WIFI_P2P); + setUpIpServer(mBluetoothIpServer, TETHERING_BLUETOOTH); } @Before @@ -158,7 +161,7 @@ public final class PrivateAddressCoordinatorTest { @Test public void testRequestDownstreamAddressWithoutUsingLastAddress() throws Exception { - final IpPrefix bluetoothPrefix = asIpPrefix(mBluetoothAddress); + final IpPrefix bluetoothPrefix = asIpPrefix(mLegacyBluetoothAddress); final LinkAddress address = requestDownstreamAddress(mHotspotIpServer); final IpPrefix hotspotPrefix = asIpPrefix(address); assertNotEquals(hotspotPrefix, bluetoothPrefix); @@ -181,11 +184,11 @@ public final class PrivateAddressCoordinatorTest { public void testReservedPrefix() throws Exception { // - Test bluetooth prefix is reserved. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( - getSubAddress(mBluetoothAddress.getAddress().getAddress())); + getSubAddress(mLegacyBluetoothAddress.getAddress().getAddress())); final LinkAddress hotspotAddress = requestStickyDownstreamAddress(mHotspotIpServer, CONNECTIVITY_SCOPE_GLOBAL); final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddress); - assertNotEquals(asIpPrefix(mBluetoothAddress), hotspotPrefix); + assertNotEquals(asIpPrefix(mLegacyBluetoothAddress), hotspotPrefix); releaseDownstream(mHotspotIpServer); // - Test previous enabled hotspot prefix(cached prefix) is reserved. @@ -193,7 +196,7 @@ public final class PrivateAddressCoordinatorTest { getSubAddress(hotspotAddress.getAddress().getAddress())); final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer); final IpPrefix usbPrefix = asIpPrefix(usbAddress); - assertNotEquals(asIpPrefix(mBluetoothAddress), usbPrefix); + assertNotEquals(asIpPrefix(mLegacyBluetoothAddress), usbPrefix); assertNotEquals(hotspotPrefix, usbPrefix); releaseDownstream(mUsbIpServer); @@ -203,7 +206,7 @@ public final class PrivateAddressCoordinatorTest { final LinkAddress etherAddress = requestDownstreamAddress(mEthernetIpServer); final IpPrefix etherPrefix = asIpPrefix(etherAddress); assertNotEquals(asIpPrefix(mLegacyWifiP2pAddress), etherPrefix); - assertNotEquals(asIpPrefix(mBluetoothAddress), etherPrefix); + assertNotEquals(asIpPrefix(mLegacyBluetoothAddress), etherPrefix); assertNotEquals(hotspotPrefix, etherPrefix); releaseDownstream(mEthernetIpServer); } @@ -346,4 +349,22 @@ public final class PrivateAddressCoordinatorTest { prefixBase.containsPrefix(asIpPrefix(address))); } + + @Test + public void testBluetoothPrefix_legacy() throws Exception { + when(mDeps.shouldBluetoothUseRandomAddress()).thenReturn(false); + mPrivateAddressCoordinator = makePrivateAddressCoordinator(); + final LinkAddress bluetoothAddress = requestStickyDownstreamAddress(mBluetoothIpServer, + CONNECTIVITY_SCOPE_GLOBAL); + assertEquals(mLegacyBluetoothAddress, bluetoothAddress); + } + + @Test + public void testBluetoothPrefix_randomized() throws Exception { + when(mDeps.shouldBluetoothUseRandomAddress()).thenReturn(true); + mPrivateAddressCoordinator = makePrivateAddressCoordinator(); + final LinkAddress bluetoothAddress = requestStickyDownstreamAddress(mBluetoothIpServer, + CONNECTIVITY_SCOPE_GLOBAL); + assertNotEquals(mLegacyBluetoothAddress, bluetoothAddress); + } } diff --git a/staticlibs/device/com/android/net/module/util/PrivateAddressCoordinator.java b/staticlibs/device/com/android/net/module/util/PrivateAddressCoordinator.java index e21d27127e..474005b85c 100644 --- a/staticlibs/device/com/android/net/module/util/PrivateAddressCoordinator.java +++ b/staticlibs/device/com/android/net/module/util/PrivateAddressCoordinator.java @@ -40,6 +40,7 @@ import android.util.ArrayMap; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.build.SdkLevel; import java.io.PrintWriter; import java.net.Inet4Address; @@ -108,6 +109,15 @@ public class PrivateAddressCoordinator { public boolean isFeatureNotChickenedOut(String featureName) { return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(mContext, featureName); } + + /** + * Whether to randomize the tethering prefix for bluetooth as well. Requires T+ because + * in S this code is in the platform. + */ + public boolean shouldBluetoothUseRandomAddress() { + // TODO: add a mainline beta flag to enable the new behaviour. + return SdkLevel.isAtLeastT() && false; + } } public PrivateAddressCoordinator(Supplier getAllNetworksSupplier, Context context) { @@ -122,9 +132,11 @@ public class PrivateAddressCoordinator { mGetAllNetworksSupplier = getAllNetworksSupplier; mDeps = deps; mCachedAddresses = new ArrayMap(); - // Reserved static addresses for bluetooth and wifi p2p. - mCachedAddresses.put(new AddressKey(TETHERING_BLUETOOTH, CONNECTIVITY_SCOPE_GLOBAL), - new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS)); + // Reserved static addresses for BLUETOOTH pre-T and WIFI_P2P. + if (!mDeps.shouldBluetoothUseRandomAddress()) { + mCachedAddresses.put(new AddressKey(TETHERING_BLUETOOTH, CONNECTIVITY_SCOPE_GLOBAL), + new LinkAddress(LEGACY_BLUETOOTH_IFACE_ADDRESS)); + } mCachedAddresses.put(new AddressKey(TETHERING_WIFI_P2P, CONNECTIVITY_SCOPE_LOCAL), new LinkAddress(LEGACY_WIFI_P2P_IFACE_ADDRESS));