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
This commit is contained in:
Yuyang Huang 2025-04-15 15:15:36 +09:00 • committed by Lorenzo Colitti
commit acd7366b65
2 changed files with 42 additions and 9 deletions

View file

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

View file

@ -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<Network[]> getAllNetworksSupplier, Context context) {
@ -122,9 +132,11 @@ public class PrivateAddressCoordinator {
mGetAllNetworksSupplier = getAllNetworksSupplier;
mDeps = deps;
mCachedAddresses = new ArrayMap<AddressKey, LinkAddress>();
// 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));