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)