diff --git a/Tethering/src/com/android/networkstack/tethering/Tethering.java b/Tethering/src/com/android/networkstack/tethering/Tethering.java index 771a9ff7b0..00103d68af 100644 --- a/Tethering/src/com/android/networkstack/tethering/Tethering.java +++ b/Tethering/src/com/android/networkstack/tethering/Tethering.java @@ -960,13 +960,15 @@ public class Tethering { // reachable before next onServiceConnected. mIsConnected = false; - if (mPendingPanRequestListener != null) { - sendTetherResultAndRemoveOnError( - mRequestTracker.getOrCreatePendingRequest(TETHERING_BLUETOOTH), - mPendingPanRequestListener, - TETHER_ERROR_SERVICE_UNAVAIL); - } - mPendingPanRequestListener = null; + // Remove any pending request even if bluetooth tethering is not started. + // Call sendTetherResultAndRemoveOnError for convenience (and to update the metrics) + // even though mPendingPanRequestListener is guaranteed to be null here (when the + // service connects onServiceConnected sets it to null, and whenever the service is + // connected, it's never set to non-null). + sendTetherResultAndRemoveOnError( + mRequestTracker.getOrCreatePendingRequest(TETHERING_BLUETOOTH), + null /* listener */, + TETHER_ERROR_SERVICE_UNAVAIL); mBluetoothIfaceRequest = null; mBluetoothCallback = null; maybeDisableBluetoothIpServing(); 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 a68bc51be9..5614a35219 100644 --- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java @@ -3292,6 +3292,10 @@ public class TetheringTest { @Override public void onResult(final int resultCode) { + if (mHasResult) { + fail("Received result: " + resultCode + ", but we already have a result: " + + mExpectedResult); + } mHasResult = true; if (resultCode != mExpectedResult) { fail("expected result: " + mExpectedResult + " but actual result: " + resultCode); @@ -3314,11 +3318,9 @@ public class TetheringTest { final LinkAddress serverLinkAddr = new LinkAddress("192.168.20.1/24"); final LinkAddress clientLinkAddr = new LinkAddress("192.168.20.42/24"); final String serverAddr = "192.168.20.1"; - final ResultListener firstResult = new ResultListener(TETHER_ERROR_NO_ERROR); - final ResultListener secondResult = new ResultListener(TETHER_ERROR_NO_ERROR); - final ResultListener thirdResult = new ResultListener(TETHER_ERROR_NO_ERROR); // Enable USB tethering and check that Tethering starts USB. + final ResultListener firstResult = new ResultListener(TETHER_ERROR_NO_ERROR); mTethering.startTethering(createTetheringRequest(TETHERING_USB), TEST_CALLER_PKG, firstResult); mLooper.dispatchAll(); @@ -3327,6 +3329,7 @@ public class TetheringTest { verifyNoMoreInteractions(mUsbManager); // Enable USB tethering again with the same request and expect no change to USB. + final ResultListener secondResult = new ResultListener(TETHER_ERROR_NO_ERROR); mTethering.startTethering(createTetheringRequest(TETHERING_USB), TEST_CALLER_PKG, secondResult); mLooper.dispatchAll(); @@ -3336,22 +3339,24 @@ public class TetheringTest { // Enable USB tethering again with the same request but different uid/package and expect no // change to USB. + final ResultListener thirdResult = new ResultListener(TETHER_ERROR_NO_ERROR); TetheringRequest differentUidPackage = createTetheringRequest(TETHERING_USB); differentUidPackage.setUid(TEST_CALLER_UID_2); differentUidPackage.setPackageName(TEST_CALLER_PKG_2); - mTethering.startTethering(differentUidPackage, TEST_CALLER_PKG_2, secondResult); + mTethering.startTethering(differentUidPackage, TEST_CALLER_PKG_2, thirdResult); mLooper.dispatchAll(); - secondResult.assertHasResult(); + thirdResult.assertHasResult(); verify(mUsbManager, never()).setCurrentFunctions(UsbManager.FUNCTION_NONE); reset(mUsbManager); // Enable USB tethering with a different request and expect that USB is stopped and // started. + final ResultListener fourthResult = new ResultListener(TETHER_ERROR_NO_ERROR); mTethering.startTethering(createTetheringRequest(TETHERING_USB, serverLinkAddr, clientLinkAddr, false, CONNECTIVITY_SCOPE_GLOBAL, null), - TEST_CALLER_PKG, thirdResult); + TEST_CALLER_PKG, fourthResult); mLooper.dispatchAll(); - thirdResult.assertHasResult(); + fourthResult.assertHasResult(); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NONE); verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS); @@ -3988,6 +3993,38 @@ public class TetheringTest { verifyNetdCommandForBtTearDown(); } + @Test + @IgnoreUpTo(Build.VERSION_CODES.S_V2) + public void testPendingBluetoothRequestRemovedWhenPanServiceDisconnectsBeforeIfaceAvailable() + throws Exception { + initTetheringOnTestThread(); + + final ResultListener result = new ResultListener(TETHER_ERROR_NO_ERROR); + mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */); + mTethering.startTethering(createTetheringRequest(TETHERING_BLUETOOTH), + TEST_CALLER_PKG, result); + mLooper.dispatchAll(); + ServiceListener serviceListener = + verifySetBluetoothTethering(true /* enable */, true /* bindToPanService */); + result.assertHasResult(); + + // Mock BT turning off + serviceListener.onServiceDisconnected(BluetoothProfile.PAN); + mLooper.dispatchAll(); + + // Pending request should be removed + assertTrue(mTethering.getPendingTetheringRequests().isEmpty()); + // Mock BT tethering started again should succeed + final ResultListener result2 = new ResultListener(TETHER_ERROR_NO_ERROR); + mockBluetoothSettings(true /* bluetoothOn */, true /* tetheringOn */); + mTethering.startTethering(createTetheringRequest(TETHERING_BLUETOOTH), + TEST_CALLER_PKG, result2); + serviceListener.onServiceConnected(BluetoothProfile.PAN, mBluetoothPan); + mLooper.dispatchAll(); + verifySetBluetoothTethering(true /* enable */, false /* bindToPanService */); + result2.assertHasResult(); + } + @Test @IgnoreAfter(Build.VERSION_CODES.S_V2) public void testBluetoothTetheringBeforeT() throws Exception { @@ -4203,7 +4240,7 @@ public class TetheringTest { } verify(mBluetoothPan).isTetheringOn(); verifyNoMoreInteractions(mBluetoothAdapter, mBluetoothPan); - reset(mBluetoothAdapter, mBluetoothPan); + reset(mBluetoothAdapter, mBluetoothPan, mBluetoothPanShim); return listener; }