Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae9b8951 authored by Alex Shabalin's avatar Alex Shabalin
Browse files

Don't stop scanning until connection is established or failed.

Connection fails when an application is in the background and there is
no active scan.

Fix: 444623240
Test: atest SuggestedDeviceConnectionManagerTest
Test: On a physical device
Flag: com.android.media.flags.use_suggested_device_connection_manager
Change-Id: I7cea195e70f3fc0f8702a662f7f3ff3b7527cff9
parent b2afdd7d
Loading
Loading
Loading
Loading
+28 −18
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
@@ -81,21 +83,31 @@ open class SuggestedDeviceConnectionManager(
    private suspend fun awaitConnect(
        suggestedDeviceState: SuggestedDeviceState,
        routingChangeInfo: RoutingChangeInfo,
    ): Boolean {
    ): Boolean = coroutineScope {
        var scanStarted = false
        try {
            val suggestedRouteId = suggestedDeviceState.suggestedDeviceInfo.routeId
        val deviceFromCache = getDeviceByRouteId(localMediaManager.mediaDevices, suggestedRouteId)
            val deviceFromCache =
                getDeviceByRouteId(localMediaManager.mediaDevices, suggestedRouteId)
            val deviceToConnect =
                deviceFromCache?.also { Log.i(TAG, "Device from cache found.") }
                    ?: run {
                        Log.i(TAG, "Scanning for device.")
                    awaitScanForDevice(suggestedRouteId)
                        // Start listening before starting scan to avoid missing events.
                        val scanResultDeferred = async { awaitScanForDevice(suggestedRouteId) }
                        localMediaManager.startScan()
                        scanStarted = true
                        scanResultDeferred.await()
                    }
            if (deviceToConnect == null) {
                Log.w(TAG, "Failed to find a device to connect to. routeId = $suggestedRouteId")
            return false
                return@coroutineScope false
            }
            Log.i(TAG, "Connecting to device. id = ${deviceToConnect.id}")
        return awaitConnectToDevice(deviceToConnect, routingChangeInfo)
            return@coroutineScope awaitConnectToDevice(deviceToConnect, routingChangeInfo)
        } finally {
            if (scanStarted) localMediaManager.stopScan()
        }
    }

    private suspend fun awaitScanForDevice(suggestedRouteId: String): MediaDevice? {
@@ -111,12 +123,11 @@ open class SuggestedDeviceConnectionManager(
                                    TAG,
                                    "Scan found matched device. routeId = $suggestedRouteId",
                                )
                                continuation.resume(device)
                                if (continuation.isActive) continuation.resume(device)
                            }
                        }
                    }
                    localMediaManager.registerCallback(callback)
                    localMediaManager.startScan()
                }
            } ?: run {
                Log.w(TAG, "Scan timed out. routeId = $suggestedRouteId")
@@ -124,7 +135,6 @@ open class SuggestedDeviceConnectionManager(
            }
        } finally {
            localMediaManager.unregisterCallback(callback)
            localMediaManager.stopScan()
        }
    }

@@ -149,7 +159,7 @@ open class SuggestedDeviceConnectionManager(
                        private fun checkConnectionStatus() {
                            if (localMediaManager.currentConnectedDevice?.id == deviceId) {
                                Log.i(TAG, "Successfully connected to device. id = $deviceId")
                                continuation.resume(true)
                                if (continuation.isActive) continuation.resume(true)
                            }
                        }
                    }
+2 −1
Original line number Diff line number Diff line
@@ -162,7 +162,6 @@ class SuggestedDeviceConnectionManagerTest {
        emulateOnDeviceListUpdate(mediaDevices)
        runCurrent()

        verify(localMediaManager).stopScan()
        verify(localMediaManager).connectDevice(mediaDevice1, ROUTING_CHANGE_INFO)
        assertThat(deviceCallbacks).hasSize(1) // Callback for connection state change
    }
@@ -230,11 +229,13 @@ class SuggestedDeviceConnectionManagerTest {
        runCurrent()

        verify(localMediaManager).connectDevice(mediaDevice1, ROUTING_CHANGE_INFO)
        verify(localMediaManager, never()).stopScan() // don't stop scan until connected.
        localMediaManager.stub { on { currentConnectedDevice } doReturn mediaDevice1 }
        emulateOnSelectedDeviceStateChanged(mediaDevice1, STATE_CONNECTED)
        runCurrent()

        verify(callback).invoke(suggestedDeviceState, true)
        verify(localMediaManager).stopScan()
        assertThat(deviceCallbacks).hasSize(0)
    }