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

Commit 154bf5aa authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Send instances creation in media device manager to bg thread." into main

parents 1d36f711 9939babd
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1400,6 +1400,16 @@ flag {
    }
}

flag {
    name: "media_controls_device_manager_background_execution"
    namespace: "systemui"
    description: "Sends some instances creation to background thread"
    bug: "400200474"
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}

flag {
  name: "output_switcher_redesign"
  namespace: "systemui"
+59 −32
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import com.android.settingslib.media.LocalMediaManager
import com.android.settingslib.media.MediaDevice
import com.android.settingslib.media.PhoneMediaDevice
import com.android.settingslib.media.flags.Flags
import com.android.systemui.Flags.mediaControlsDeviceManagerBackgroundExecution
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.shared.MediaControlDrawables
@@ -94,8 +95,39 @@ constructor(
        data: MediaData,
        immediately: Boolean,
        receivedSmartspaceCardLatency: Int,
        isSsReactivated: Boolean
        isSsReactivated: Boolean,
    ) {
        if (mediaControlsDeviceManagerBackgroundExecution()) {
            bgExecutor.execute { onMediaLoaded(key, oldKey, data) }
        } else {
            onMediaLoaded(key, oldKey, data)
        }
    }

    override fun onMediaDataRemoved(key: String, userInitiated: Boolean) {
        if (mediaControlsDeviceManagerBackgroundExecution()) {
            bgExecutor.execute { onMediaRemoved(key, userInitiated) }
        } else {
            onMediaRemoved(key, userInitiated)
        }
    }

    fun dump(pw: PrintWriter) {
        with(pw) {
            println("MediaDeviceManager state:")
            entries.forEach { (key, entry) ->
                println("  key=$key")
                entry.dump(pw)
            }
        }
    }

    @MainThread
    private fun processDevice(key: String, oldKey: String?, device: MediaDeviceData?) {
        listeners.forEach { it.onMediaDeviceChanged(key, oldKey, device) }
    }

    private fun onMediaLoaded(key: String, oldKey: String?, data: MediaData) {
        if (oldKey != null && oldKey != key) {
            val oldEntry = entries.remove(oldKey)
            oldEntry?.stop()
@@ -104,9 +136,13 @@ constructor(
        if (entry == null || entry.token != data.token) {
            entry?.stop()
            if (data.device != null) {
                // If we were already provided device info (e.g. from RCN), keep that and don't
                // listen for updates, but process once to push updates to listeners
                // If we were already provided device info (e.g. from RCN), keep that and
                // don't listen for updates, but process once to push updates to listeners
                if (mediaControlsDeviceManagerBackgroundExecution()) {
                    fgExecutor.execute { processDevice(key, oldKey, data.device) }
                } else {
                    processDevice(key, oldKey, data.device)
                }
                return
            }
            val controller = data.token?.let { controllerFactory.create(it) }
@@ -120,25 +156,16 @@ constructor(
        }
    }

    override fun onMediaDataRemoved(key: String, userInitiated: Boolean) {
    private fun onMediaRemoved(key: String, userInitiated: Boolean) {
        val token = entries.remove(key)
        token?.stop()
        if (mediaControlsDeviceManagerBackgroundExecution()) {
            fgExecutor.execute {
                token?.let { listeners.forEach { it.onKeyRemoved(key, userInitiated) } }
            }

    fun dump(pw: PrintWriter) {
        with(pw) {
            println("MediaDeviceManager state:")
            entries.forEach { (key, entry) ->
                println("  key=$key")
                entry.dump(pw)
            }
        }
        } else {
            token?.let { listeners.forEach { it.onKeyRemoved(key, userInitiated) } }
        }

    @MainThread
    private fun processDevice(key: String, oldKey: String?, device: MediaDeviceData?) {
        listeners.forEach { it.onMediaDeviceChanged(key, oldKey, device) }
    }

    interface Listener {
@@ -260,7 +287,7 @@ constructor(
        override fun onAboutToConnectDeviceAdded(
            deviceAddress: String,
            deviceName: String,
            deviceIcon: Drawable?
            deviceIcon: Drawable?,
        ) {
            aboutToConnectDeviceOverride =
                AboutToConnectDevice(
@@ -270,8 +297,8 @@ constructor(
                            /* enabled */ enabled = true,
                            /* icon */ deviceIcon,
                            /* name */ deviceName,
                            /* showBroadcastButton */ showBroadcastButton = false
                        )
                            /* showBroadcastButton */ showBroadcastButton = false,
                        ),
                )
            updateCurrent()
        }
@@ -292,7 +319,7 @@ constructor(

        override fun onBroadcastMetadataChanged(
            broadcastId: Int,
            metadata: BluetoothLeBroadcastMetadata
            metadata: BluetoothLeBroadcastMetadata,
        ) {
            logger.logBroadcastMetadataChanged(broadcastId, metadata.toString())
            updateCurrent()
@@ -352,14 +379,14 @@ constructor(
                            //           route.
                            connectedDevice?.copy(
                                name = it.name ?: connectedDevice.name,
                                icon = icon
                                icon = icon,
                            )
                        }
                            ?: MediaDeviceData(
                                enabled = false,
                                icon = MediaControlDrawables.getHomeDevices(context),
                                name = context.getString(R.string.media_seamless_other_device),
                                showBroadcastButton = false
                                showBroadcastButton = false,
                            )
                    logger.logRemoteDevice(routingSession?.name, connectedDevice)
                } else {
@@ -398,7 +425,7 @@ constructor(
                        device?.iconWithoutBackground,
                        name,
                        id = device?.id,
                        showBroadcastButton = false
                        showBroadcastButton = false,
                    )
            }
        }
@@ -415,7 +442,7 @@ constructor(
                icon = iconWithoutBackground,
                name = name,
                id = id,
                showBroadcastButton = false
                showBroadcastButton = false,
            )

        private fun getLeAudioBroadcastDeviceData(): MediaDeviceData {
@@ -425,7 +452,7 @@ constructor(
                    icon = MediaControlDrawables.getLeAudioSharing(context),
                    name = context.getString(R.string.audio_sharing_description),
                    intent = null,
                    showBroadcastButton = false
                    showBroadcastButton = false,
                )
            } else {
                MediaDeviceData(
@@ -433,7 +460,7 @@ constructor(
                    icon = MediaControlDrawables.getAntenna(context),
                    name = broadcastDescription,
                    intent = null,
                    showBroadcastButton = true
                    showBroadcastButton = true,
                )
            }
        }
@@ -449,7 +476,7 @@ constructor(
                device,
                controller,
                routingSession?.name,
                selectedRoutes?.firstOrNull()?.name
                selectedRoutes?.firstOrNull()?.name,
            )

            if (controller == null) {
@@ -514,7 +541,7 @@ constructor(
                MediaDataUtils.getAppLabel(
                    context,
                    localMediaManager.packageName,
                    context.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name)
                    context.getString(R.string.bt_le_audio_broadcast_dialog_unknown_name),
                )
            val isCurrentBroadcastedApp = TextUtils.equals(mediaApp, currentBroadcastedApp)
            if (isCurrentBroadcastedApp) {
@@ -538,5 +565,5 @@ constructor(
 */
private data class AboutToConnectDevice(
    val fullMediaDevice: MediaDevice? = null,
    val backupMediaDeviceData: MediaDeviceData? = null
    val backupMediaDeviceData: MediaDeviceData? = null,
)
+23 −4
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ import android.platform.test.annotations.EnableFlags
import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.annotations.RequiresFlagsEnabled
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast
import com.android.settingslib.bluetooth.LocalBluetoothManager
@@ -77,6 +77,8 @@ import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
import org.mockito.kotlin.eq
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters

private const val KEY = "TEST_KEY"
private const val KEY_OLD = "TEST_KEY_OLD"
@@ -89,12 +91,24 @@ private const val BROADCAST_APP_NAME = "BROADCAST_APP_NAME"
private const val NORMAL_APP_NAME = "NORMAL_APP_NAME"

@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(ParameterizedAndroidJunit4::class)
@TestableLooper.RunWithLooper
public class MediaDeviceManagerTest : SysuiTestCase() {
public class MediaDeviceManagerTest(flags: FlagsParameterization) : SysuiTestCase() {

    private companion object {
    companion object {
        val OTHER_DEVICE_ICON_STUB = TestStubDrawable()

        @JvmStatic
        @Parameters(name = "{0}")
        fun getParams(): List<FlagsParameterization> {
            return FlagsParameterization.progressionOf(
                com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_DEVICE_MANAGER_BACKGROUND_EXECUTION
            )
        }
    }

    init {
        mSetFlagsRule.setFlagsParameterization(flags)
    }

    @get:Rule val checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@@ -187,6 +201,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
    @Test
    fun loadMediaData() {
        manager.onMediaDataLoaded(KEY, null, mediaData)
        fakeBgExecutor.runAllReady()
        fakeFgExecutor.runAllReady()
        verify(lmmFactory).create(PACKAGE)
    }

@@ -195,6 +211,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
        manager.onMediaDataLoaded(KEY, null, mediaData)
        manager.onMediaDataRemoved(KEY, false)
        fakeBgExecutor.runAllReady()
        fakeFgExecutor.runAllReady()
        verify(lmm).unregisterCallback(any())
        verify(muteAwaitManager).stopListening()
    }
@@ -406,6 +423,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
        manager.onMediaDataLoaded(KEY, null, mediaData)
        // WHEN the notification is removed
        manager.onMediaDataRemoved(KEY, true)
        fakeBgExecutor.runAllReady()
        fakeFgExecutor.runAllReady()
        // THEN the listener receives key removed event
        verify(listener).onKeyRemoved(eq(KEY), eq(true))
    }