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

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

Merge "Add SysUI plugin to add or modify actions in Cuebar" into main

parents a042b964 114f2f89
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -2229,3 +2229,10 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "ambient_cue_plugin"
    namespace: "ailabs"
    description: "Enable plugin for ambient cue project"
    bug: "439907833"
}
 No newline at end of file
+72 −2
Original line number Diff line number Diff line
@@ -26,10 +26,10 @@ import android.app.smartspace.SmartspaceSession.OnTargetsAvailableListener
import android.app.smartspace.SmartspaceTarget
import android.content.ComponentName
import android.content.Intent
import android.content.applicationContext
import android.content.testableContext
import android.os.Binder
import android.os.Bundle
import android.platform.test.annotations.EnableFlags
import android.view.WindowManagerPolicyConstants
import android.view.autofill.AutofillId
import android.view.autofill.AutofillManager
@@ -47,9 +47,9 @@ import com.android.systemui.ambientcue.data.repository.AmbientCueRepositoryImpl.
import com.android.systemui.ambientcue.data.repository.AmbientCueRepositoryImpl.Companion.MA_ACTION_TYPE_NAME
import com.android.systemui.ambientcue.data.repository.AmbientCueRepositoryImpl.Companion.MR_ACTION_TYPE_NAME
import com.android.systemui.ambientcue.shared.logger.ambientCueLogger
import com.android.systemui.ambientcue.shared.model.ActionModel
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.dump.DumpManager
import com.android.systemui.Flags.FLAG_AMBIENT_CUE_PLUGIN
import com.android.systemui.kosmos.advanceTimeBy
import com.android.systemui.kosmos.advanceUntilIdle
import com.android.systemui.kosmos.backgroundScope
@@ -60,6 +60,11 @@ import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.navigationbar.NavigationModeController
import com.android.systemui.navigationbar.NavigationModeController.ModeChangedListener
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.PluginListener
import com.android.systemui.plugins.PluginManager
import com.android.systemui.plugins.cuebar.ActionModel
import com.android.systemui.plugins.cuebar.CuebarPlugin
import com.android.systemui.plugins.cuebar.CuebarPlugin.OnNewActionsListener
import com.android.systemui.shade.data.repository.fakeFocusedDisplayRepository
import com.android.systemui.shared.settings.data.repository.secureSettingsRepository
import com.android.systemui.shared.system.taskStackChangeListeners
@@ -73,6 +78,7 @@ import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

@RunWith(AndroidJUnit4::class)
@SmallTest
@@ -88,6 +94,7 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
        mock<SmartspaceManager>() {
            on { createSmartspaceSession(any()) } doReturn smartSpaceSession
        }
    private val pluginManager = mock<PluginManager>()
    val onTargetsAvailableListenerCaptor = argumentCaptor<OnTargetsAvailableListener>()
    val navigationModeChangeListenerCaptor = argumentCaptor<ModeChangedListener>()
    val launcherProxyListenerCaptor = argumentCaptor<LauncherProxyListener>()
@@ -106,6 +113,7 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
            backgroundDispatcher = kosmos.testDispatcher,
            secureSettingsRepository = kosmos.secureSettingsRepository,
            ambientCueLogger = kosmos.ambientCueLogger,
            pluginManager = pluginManager,
        )

    @Test
@@ -343,6 +351,61 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
            }
        }

    @Test
    @EnableFlags(FLAG_AMBIENT_CUE_PLUGIN)
    fun actions_whenPluginEmitsActions() =
        kosmos.runTest {
            val actions by collectLastValue(underTest.actions)
            runCurrent()

            val pluginListenerCaptor = argumentCaptor<PluginListener<CuebarPlugin>>()
            verify(pluginManager).addPluginListener(pluginListenerCaptor.capture(), any(), any())

            val cuebarPlugin = mock<CuebarPlugin>()
            whenever(cuebarPlugin.addOnNewActionsListener(any())).thenAnswer { invocation ->
                val realListener = invocation.getArgument<OnNewActionsListener>(0)
                realListener.onNewActions(validActions)
            }

            pluginListenerCaptor.firstValue.onPluginLoaded(cuebarPlugin, mock(), mock())
            runCurrent()

            assertThat(actions).isEqualTo(validActions)
        }

    @Test
    @EnableFlags(FLAG_AMBIENT_CUE_PLUGIN)
    fun actions_whenPluginFiltersActions() =
        kosmos.runTest {
            val actions by collectLastValue(underTest.actions)
            runCurrent()

            val pluginListenerCaptor = argumentCaptor<PluginListener<CuebarPlugin>>()
            verify(pluginManager).addPluginListener(pluginListenerCaptor.capture(), any(), any())

            val filteredActions = validActions

            val cuebarPlugin = mock<CuebarPlugin>()
            whenever(cuebarPlugin.filterActions(any())).thenReturn(filteredActions)

            pluginListenerCaptor.firstValue.onPluginLoaded(cuebarPlugin, mock(), mock())
            runCurrent()

            verify(smartSpaceSession)
                .addOnTargetsAvailableListener(any(), onTargetsAvailableListenerCaptor.capture())
            onTargetsAvailableListenerCaptor.firstValue.onTargetsAvailable(listOf(validTarget))
            runCurrent()

            val originalActionsCaptor = argumentCaptor<List<ActionModel>>()
            verify(cuebarPlugin).filterActions(originalActionsCaptor.capture())

            assertThat(originalActionsCaptor.firstValue).hasSize(2)
            assertThat(originalActionsCaptor.firstValue.first().label).isEqualTo(TITLE_1)
            assertThat(originalActionsCaptor.firstValue.last().label).isEqualTo(TITLE_2)

            assertThat(actions).isEqualTo(filteredActions)
        }

    @Test
    fun globallyFocusedTaskId_whenFocusedTaskChange_taskIdUpdated() =
        kosmos.runTest {
@@ -656,5 +719,12 @@ class AmbientCueRepositoryTest : SysuiTestCase() {
            }

        private val allTargets = listOf(validTarget, invalidTarget1)

        private val validActions = listOf(
            ActionModel(icon = mock(), label = TITLE_1,
                attribution = SUBTITLE_1, onPerformAction = {}, onPerformLongClick = {}),
            ActionModel(icon = mock(), label = TITLE_2,
                attribution = SUBTITLE_2, onPerformAction = {}, onPerformLongClick = {})
        )
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -23,14 +23,14 @@ import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.SysuiTestCase
import com.android.systemui.ambientcue.data.repository.ambientCueRepository
import com.android.systemui.ambientcue.data.repository.fake
import com.android.systemui.ambientcue.shared.model.ActionModel
import com.android.systemui.ambientcue.shared.model.IconModel
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.plugins.cuebar.ActionModel
import com.android.systemui.plugins.cuebar.IconModel
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
+2 −2
Original line number Diff line number Diff line
@@ -27,8 +27,6 @@ import com.android.systemui.ambientcue.data.repository.ambientCueRepository
import com.android.systemui.ambientcue.data.repository.fake
import com.android.systemui.ambientcue.domain.interactor.ambientCueInteractor
import com.android.systemui.ambientcue.shared.logger.ambientCueLogger
import com.android.systemui.ambientcue.shared.model.ActionModel
import com.android.systemui.ambientcue.shared.model.IconModel
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.advanceTimeBy
@@ -36,6 +34,8 @@ import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.plugins.cuebar.ActionModel
import com.android.systemui.plugins.cuebar.IconModel
import com.android.systemui.res.R
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
+14 −3
Original line number Diff line number Diff line
@@ -14,11 +14,13 @@
 * limitations under the License.
 */

package com.android.systemui.ambientcue.shared.model
package com.android.systemui.plugins.cuebar

import android.app.ActivityTaskManager.INVALID_TASK_ID
import android.graphics.drawable.Drawable
import com.android.systemui.plugins.annotations.ProvidesInterface

@ProvidesInterface(version = ActionModel.VERSION)
data class ActionModel(
    val icon: IconModel,
    val label: String,
@@ -30,6 +32,15 @@ data class ActionModel(
    val actionType: String? = null,
    val oneTapEnabled: Boolean = false,
    val oneTapDelayMs: Long = 0L,
)
) {
    companion object {
        const val VERSION = 1
    }
}

data class IconModel(val small: Drawable, val large: Drawable, val iconId: String)
@ProvidesInterface(version = IconModel.VERSION)
data class IconModel(val small: Drawable, val large: Drawable, val iconId: String) {
    companion object {
        const val VERSION = 1
    }
}
Loading