Snap for 13204655 from cfc67e7df8c1d1745ef24c2148c93d3609967cb5 to 25Q2-release
Change-Id: Idaa6fee75b6e875025a934f5f350bdbb7aa2e012
diff --git a/Tethering/common/TetheringLib/Android.bp b/Tethering/common/TetheringLib/Android.bp
index e2498e4..d2a8c13 100644
--- a/Tethering/common/TetheringLib/Android.bp
+++ b/Tethering/common/TetheringLib/Android.bp
@@ -111,6 +111,7 @@
"sdk_module-lib_current_framework-wifi",
],
static_libs: [
+ "modules-utils-build",
"com.android.net.flags-aconfig-java",
],
aidl: {
diff --git a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 0ac97f0..0a66f01 100644
--- a/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -42,6 +42,7 @@
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.modules.utils.build.SdkLevel;
import com.android.net.flags.Flags;
import java.lang.annotation.Retention;
@@ -664,7 +665,7 @@
}
private void unsupportedAfterV() {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ if (SdkLevel.isAtLeastB()) {
throw new UnsupportedOperationException("Not supported after SDK version "
+ Build.VERSION_CODES.VANILLA_ICE_CREAM);
}
diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java
index 1589509..1a26658 100644
--- a/Tethering/src/com/android/networkstack/tethering/Tethering.java
+++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java
@@ -117,7 +117,6 @@
import android.net.wifi.p2p.WifiP2pInfo;
import android.net.wifi.p2p.WifiP2pManager;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -146,6 +145,7 @@
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.flags.Flags;
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.CollectionUtils;
import com.android.net.module.util.HandlerUtils;
@@ -290,7 +290,10 @@
private SettingsObserver mSettingsObserver;
private BluetoothPan mBluetoothPan;
private PanServiceListener mBluetoothPanListener;
- private final ArrayList<IIntResultListener> mPendingPanRequestListeners;
+ // Pending listener for starting Bluetooth tethering before the PAN service is connected. Once
+ // the service is connected, the bluetooth iface will be requested and the listener will be
+ // called.
+ private IIntResultListener mPendingPanRequestListener;
// AIDL doesn't support Set<Integer>. Maintain a int bitmap here. When the bitmap is passed to
// TetheringManager, TetheringManager would convert it to a set of Integer types.
// mSupportedTypeBitmap should always be updated inside tethering internal thread but it may be
@@ -308,11 +311,6 @@
mTetheringMetrics = mDeps.makeTetheringMetrics(mContext);
mRequestTracker = new RequestTracker();
- // This is intended to ensrure that if something calls startTethering(bluetooth) just after
- // bluetooth is enabled. Before onServiceConnected is called, store the calls into this
- // list and handle them as soon as onServiceConnected is called.
- mPendingPanRequestListeners = new ArrayList<>();
-
mTetherStates = new ArrayMap<>();
mConnectedClientsTracker = new ConnectedClientsTracker();
@@ -463,7 +461,7 @@
}
boolean isTetheringWithSoftApConfigEnabled() {
- return mDeps.isTetheringWithSoftApConfigEnabled();
+ return SdkLevel.isAtLeastB() && Flags.tetheringWithSoftApConfig();
}
/**
@@ -637,7 +635,7 @@
// TODO: fix the teardown path to stop depending on interface state notifications.
// These are not necessary since most/all link layers have their own teardown
// notifications, and can race with those notifications.
- if (enabled && Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ if (enabled && SdkLevel.isAtLeastB()) {
return;
}
@@ -862,15 +860,21 @@
if (!enable) {
// The service is not connected. If disabling tethering, there's no point starting
// the service just to stop tethering since tethering is not started. Just remove
- // any pending requests to enable tethering, and notify them that they have failed.
- for (IIntResultListener pendingListener : mPendingPanRequestListeners) {
- sendTetherResult(pendingListener, TETHER_ERROR_SERVICE_UNAVAIL,
+ // any pending request to enable tethering, and notify them that they have failed.
+ if (mPendingPanRequestListener != null) {
+ sendTetherResult(mPendingPanRequestListener, TETHER_ERROR_SERVICE_UNAVAIL,
TETHERING_BLUETOOTH);
}
- mPendingPanRequestListeners.clear();
+ mPendingPanRequestListener = null;
return TETHER_ERROR_NO_ERROR;
}
- mPendingPanRequestListeners.add(listener);
+
+ // Only allow one pending request at a time.
+ if (mPendingPanRequestListener != null) {
+ return TETHER_ERROR_SERVICE_UNAVAIL;
+ }
+
+ mPendingPanRequestListener = listener;
// Bluetooth tethering is not a popular feature. To avoid bind to bluetooth pan service all
// the time but user never use bluetooth tethering. mBluetoothPanListener is created first
@@ -897,12 +901,12 @@
mBluetoothPan = (BluetoothPan) proxy;
mIsConnected = true;
- for (IIntResultListener pendingListener : mPendingPanRequestListeners) {
+ if (mPendingPanRequestListener != null) {
final int result = setBluetoothTetheringSettings(mBluetoothPan,
true /* enable */);
- sendTetherResult(pendingListener, result, TETHERING_BLUETOOTH);
+ sendTetherResult(mPendingPanRequestListener, result, TETHERING_BLUETOOTH);
}
- mPendingPanRequestListeners.clear();
+ mPendingPanRequestListener = null;
});
}
@@ -913,11 +917,11 @@
// reachable before next onServiceConnected.
mIsConnected = false;
- for (IIntResultListener pendingListener : mPendingPanRequestListeners) {
- sendTetherResult(pendingListener, TETHER_ERROR_SERVICE_UNAVAIL,
+ if (mPendingPanRequestListener != null) {
+ sendTetherResult(mPendingPanRequestListener, TETHER_ERROR_SERVICE_UNAVAIL,
TETHERING_BLUETOOTH);
}
- mPendingPanRequestListeners.clear();
+ mPendingPanRequestListener = null;
mBluetoothIfaceRequest = null;
mBluetoothCallback = null;
maybeDisableBluetoothIpServing();
@@ -1078,7 +1082,7 @@
}
private void handleLegacyTether(String iface, final IIntResultListener listener) {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ if (SdkLevel.isAtLeastB()) {
// After V, the TetheringManager and ConnectivityManager tether and untether methods
// throw UnsupportedOperationException, so this cannot happen in normal use. Ensure
// that this code cannot run even if callers use raw binder calls or other
@@ -1179,7 +1183,7 @@
}
void legacyUntether(String iface, final IIntResultListener listener) {
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ if (SdkLevel.isAtLeastB()) {
// After V, the TetheringManager and ConnectivityManager tether and untether methods
// throw UnsupportedOperationException, so this cannot happen in normal use. Ensure
// that this code cannot run even if callers use raw binder calls or other
diff --git a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
index 8e17085..bd35cf2 100644
--- a/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
+++ b/Tethering/src/com/android/networkstack/tethering/TetheringDependencies.java
@@ -214,7 +214,6 @@
* Wrapper for tethering_with_soft_ap_config feature flag.
*/
public boolean isTetheringWithSoftApConfigEnabled() {
- return Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM
- && Flags.tetheringWithSoftApConfig();
+ return SdkLevel.isAtLeastB() && Flags.tetheringWithSoftApConfig();
}
}
diff --git a/Tethering/tests/unit/Android.bp b/Tethering/tests/unit/Android.bp
index ee82776..c282618 100644
--- a/Tethering/tests/unit/Android.bp
+++ b/Tethering/tests/unit/Android.bp
@@ -51,11 +51,13 @@
"src/**/*.kt",
],
static_libs: [
+ // Include mockito extended first so it takes precedence, as other libraries like
+ // TetheringCommonTests bundle non-extended mockito.
+ // TODO: use non-extended mockito in tethering tests instead
+ "mockito-target-extended-minus-junit4",
"TetheringCommonTests",
"androidx.test.rules",
"frameworks-base-testutils",
- "mockito-target-extended-minus-junit4",
- "net-tests-utils",
"testables",
"truth",
],
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 031b652..12a04b0 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -101,6 +101,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
@@ -3571,6 +3572,32 @@
failedEnable.assertHasResult();
}
+ @Test
+ public void testStartBluetoothTetheringFailsWhenTheresAnExistingRequestWaitingForPanService()
+ throws Exception {
+ initTetheringOnTestThread();
+
+ mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */);
+ final ResultListener firstResult = new ResultListener(TETHER_ERROR_NO_ERROR);
+ mTethering.startTethering(createTetheringRequest(TETHERING_BLUETOOTH),
+ TEST_CALLER_PKG, firstResult);
+ mLooper.dispatchAll();
+ firstResult.assertDoesNotHaveResult();
+
+ // Second request should fail.
+ final ResultListener secondResult = new ResultListener(TETHER_ERROR_SERVICE_UNAVAIL);
+ mTethering.startTethering(createTetheringRequest(TETHERING_BLUETOOTH),
+ TEST_CALLER_PKG, secondResult);
+ mLooper.dispatchAll();
+ secondResult.assertHasResult();
+ firstResult.assertDoesNotHaveResult();
+
+ // Bind to PAN service should succeed for first listener only. If the second result is
+ // called with TETHER_ERROR_NO_ERROR, ResultListener will fail an assertion.
+ verifySetBluetoothTethering(true /* enable */, true /* bindToPanService */);
+ firstResult.assertHasResult();
+ }
+
private void mockBluetoothSettings(boolean bluetoothOn, boolean tetheringOn) {
when(mBluetoothAdapter.isEnabled()).thenReturn(bluetoothOn);
when(mBluetoothPan.isTetheringOn()).thenReturn(tetheringOn);
@@ -3618,7 +3645,7 @@
private ServiceListener verifySetBluetoothTethering(final boolean enable,
final boolean bindToPanService) throws Exception {
ServiceListener listener = null;
- verify(mBluetoothAdapter).isEnabled();
+ verify(mBluetoothAdapter, atLeastOnce()).isEnabled();
if (bindToPanService) {
final ArgumentCaptor<ServiceListener> listenerCaptor =
ArgumentCaptor.forClass(ServiceListener.class);
diff --git a/staticlibs/Android.bp b/staticlibs/Android.bp
index 8034e57..b064723 100644
--- a/staticlibs/Android.bp
+++ b/staticlibs/Android.bp
@@ -81,17 +81,6 @@
},
}
-java_defaults {
- name: "lib_mockito_extended",
- static_libs: [
- "mockito-target-extended-minus-junit4",
- ],
- jni_libs: [
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- ],
-}
-
java_library {
name: "net-utils-dnspacket-common",
srcs: [
diff --git a/staticlibs/testutils/Android.bp b/staticlibs/testutils/Android.bp
index ec486fb..b59ccc6 100644
--- a/staticlibs/testutils/Android.bp
+++ b/staticlibs/testutils/Android.bp
@@ -25,7 +25,6 @@
],
defaults: [
"framework-connectivity-test-defaults",
- "lib_mockito_extended",
],
libs: [
"androidx.annotation_annotation",
@@ -36,6 +35,7 @@
"collector-device-lib",
"kotlin-reflect",
"libnanohttpd",
+ "mockito-target-minus-junit4",
"net-tests-utils-host-device-common",
"net-utils-device-common",
"net-utils-device-common-async",
diff --git a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
index 4b9429b..8a255c6 100644
--- a/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
+++ b/staticlibs/testutils/devicetests/com/android/testutils/ConnectivityDiagnosticsCollector.kt
@@ -224,7 +224,7 @@
// Echo the current pid, and replace it (with exec) with the tcpdump process, so the
// tcpdump pid is known.
writer.write(
- "echo $$; exec su 0 tcpdump -n -i any -U -xx".encodeToByteArray()
+ "echo $$; exec su 0 tcpdump -n -i any -l -xx".encodeToByteArray()
)
}
val reader = FileReader(stdout.fileDescriptor).buffered()
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index 9e49926..e645f67 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -73,7 +73,6 @@
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiSsid;
-import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.ResultReceiver;
@@ -391,7 +390,7 @@
mCtsTetheringUtils.stopWifiTethering(tetherEventCallback);
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
+ if (!SdkLevel.isAtLeastB()) {
try {
final int ret = runAsShell(TETHER_PRIVILEGED,
() -> mTM.tether(wifiTetheringIface));
@@ -480,8 +479,7 @@
}
private boolean isTetheringWithSoftApConfigEnabled() {
- return Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM
- && Flags.tetheringWithSoftApConfig();
+ return SdkLevel.isAtLeastB() && Flags.tetheringWithSoftApConfig();
}
@Test
@@ -636,7 +634,7 @@
@Test
public void testLegacyTetherApisThrowUnsupportedOperationExceptionAfterV() {
- assumeTrue(Build.VERSION.SDK_INT > Build.VERSION_CODES.VANILLA_ICE_CREAM);
+ assumeTrue(SdkLevel.isAtLeastB());
assertThrows(UnsupportedOperationException.class, () -> mTM.tether("iface"));
assertThrows(UnsupportedOperationException.class, () -> mTM.untether("iface"));
}
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 869c027..66af56b 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -65,7 +65,6 @@
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
import static com.android.server.net.NetworkStatsEventLogger.POLL_REASON_RAT_CHANGED;
import static com.android.server.net.NetworkStatsEventLogger.PollEvent.pollReasonNameOf;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
@@ -96,6 +95,7 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
diff --git a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
index 62f9035..c4e373a 100644
--- a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
+++ b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
@@ -595,7 +595,8 @@
DeviceConfigUtils.getDeviceConfigPropertyBoolean(
"thread_network", "TrelFeature__enabled", false));
- NsdServiceInfo discoveredService = discoverService(mNsdManager, "_trel._udp");
+ NsdServiceInfo discoveredService =
+ discoverService(mNsdManager, "_trel._udp", mOtCtl.getExtendedAddr());
assertThat(discoveredService).isNotNull();
// Resolve service with the current TREL port, otherwise it may return stale service from
// a previous infra link setup.
@@ -618,7 +619,9 @@
DeviceConfigUtils.getDeviceConfigPropertyBoolean(
"thread_network", "TrelFeature__enabled", false));
- assertThrows(TimeoutException.class, () -> discoverService(mNsdManager, "_trel._udp"));
+ assertThrows(
+ TimeoutException.class,
+ () -> discoverService(mNsdManager, "_trel._udp", mOtCtl.getExtendedAddr()));
}
private void registerService(NsdServiceInfo serviceInfo, RegistrationListener listener)
diff --git a/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.kt b/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.kt
index 773167c..f41e903 100644
--- a/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.kt
+++ b/thread/tests/integration/src/android/net/thread/utils/IntegrationTestUtils.kt
@@ -479,15 +479,31 @@
return addresses
}
- /** Return the first discovered service of `serviceType`. */
+ /** Return the first discovered service of `serviceType`. */
@JvmStatic
@Throws(Exception::class)
fun discoverService(nsdManager: NsdManager, serviceType: String): NsdServiceInfo {
+ return discoverService(nsdManager, serviceType, null)
+ }
+
+ /**
+ * Returns the service that matches `serviceType` and `serviceName`.
+ *
+ * If `serviceName` is null, returns the first discovered service. `serviceName` is not case
+ * sensitive.
+ */
+ @JvmStatic
+ @Throws(Exception::class)
+ fun discoverService(nsdManager: NsdManager, serviceType: String, serviceName: String?):
+ NsdServiceInfo {
val serviceInfoFuture = CompletableFuture<NsdServiceInfo>()
val listener: NsdManager.DiscoveryListener = object : DefaultDiscoveryListener() {
override fun onServiceFound(serviceInfo: NsdServiceInfo) {
Log.d(TAG, "onServiceFound: $serviceInfo")
- serviceInfoFuture.complete(serviceInfo)
+ if (serviceName == null ||
+ serviceInfo.getServiceName().equals(serviceName, true /* ignore case */)) {
+ serviceInfoFuture.complete(serviceInfo)
+ }
}
}
nsdManager.discoverServices(serviceType, NsdManager.PROTOCOL_DNS_SD, listener)