Loading packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt +59 −64 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.plugins.BcSmartspaceConfigPlugin import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView import com.android.systemui.plugins.FalsingManager import com.android.systemui.settings.UserTracker import com.android.systemui.smartspace.dagger.SmartspaceViewComponent import com.android.systemui.util.concurrency.Execution import com.android.systemui.util.mockito.any Loading @@ -46,66 +47,51 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.anyInt import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.Mockito.anyInt import org.mockito.MockitoAnnotations import org.mockito.Spy @SmallTest @RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class DreamSmartspaceControllerTest : SysuiTestCase() { @Mock private lateinit var smartspaceManager: SmartspaceManager @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var execution: Execution @Mock private lateinit var userContextPrimary: Context @Mock private lateinit var uiExecutor: Executor @Mock private lateinit var smartspaceManager: SmartspaceManager @Mock private lateinit var viewComponentFactory: SmartspaceViewComponent.Factory @Mock private lateinit var execution: Execution @Mock private lateinit var viewComponent: SmartspaceViewComponent @Mock private lateinit var uiExecutor: Executor @Mock private lateinit var weatherViewComponent: SmartspaceViewComponent @Mock private lateinit var viewComponentFactory: SmartspaceViewComponent.Factory private val weatherSmartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var viewComponent: SmartspaceViewComponent @Mock private lateinit var targetFilter: SmartspaceTargetFilter @Mock private lateinit var weatherViewComponent: SmartspaceViewComponent @Mock private lateinit var plugin: BcSmartspaceDataPlugin private val weatherSmartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var weatherPlugin: BcSmartspaceDataPlugin @Mock private lateinit var targetFilter: SmartspaceTargetFilter @Mock private lateinit var precondition: SmartspacePrecondition @Mock private lateinit var plugin: BcSmartspaceDataPlugin private val smartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var weatherPlugin: BcSmartspaceDataPlugin @Mock private lateinit var precondition: SmartspacePrecondition @Mock private lateinit var listener: BcSmartspaceDataPlugin.SmartspaceTargetListener private val smartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var session: SmartspaceSession @Mock private lateinit var listener: BcSmartspaceDataPlugin.SmartspaceTargetListener @Mock private lateinit var session: SmartspaceSession private lateinit var controller: DreamSmartspaceController // TODO(b/272811280): Remove usage of real view private val fakeParent by lazy { FrameLayout(context) } private val fakeParent by lazy { FrameLayout(context) } /** * A class which implements SmartspaceView and extends View. This is mocked to provide the right Loading Loading @@ -134,9 +120,13 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { override fun setMediaTarget(target: SmartspaceTarget?) {} override fun getSelectedPage(): Int { return 0; } override fun getSelectedPage(): Int { return 0 } override fun getCurrentCardTopPadding(): Int { return 0; } override fun getCurrentCardTopPadding(): Int { return 0 } } @Before Loading @@ -150,14 +140,24 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { `when`(weatherViewComponent.getView()).thenReturn(weatherSmartspaceView) `when`(smartspaceManager.createSmartspaceSession(any())).thenReturn(session) controller = DreamSmartspaceController(context, smartspaceManager, execution, uiExecutor, viewComponentFactory, precondition, Optional.of(targetFilter), Optional.of(plugin), Optional.of(weatherPlugin)) `when`(userTracker.userContext).thenReturn(userContextPrimary) `when`(userContextPrimary.getSystemService(SmartspaceManager::class.java)) .thenReturn(smartspaceManager) controller = DreamSmartspaceController( userTracker, execution, uiExecutor, viewComponentFactory, precondition, Optional.of(targetFilter), Optional.of(plugin), Optional.of(weatherPlugin), ) } /** * Ensures smartspace session begins on a listener only flow. */ /** Ensures smartspace session begins on a listener only flow. */ @Test fun testConnectOnListen() { `when`(precondition.conditionsMet()).thenReturn(true) Loading @@ -165,7 +165,8 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(smartspaceManager).createSmartspaceSession(any()) var targetListener = withArgCaptor<SmartspaceSession.OnTargetsAvailableListener> { var targetListener = withArgCaptor<SmartspaceSession.OnTargetsAvailableListener> { verify(session).addOnTargetsAvailableListener(any(), capture()) } Loading @@ -174,9 +175,8 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { var target = Mockito.mock(SmartspaceTarget::class.java) targetListener.onTargetsAvailable(listOf(target)) var targets = withArgCaptor<List<SmartspaceTarget>> { verify(plugin).onTargetsAvailable(capture()) } var targets = withArgCaptor<List<SmartspaceTarget>> { verify(plugin).onTargetsAvailable(capture()) } assertThat(targets.contains(target)).isTrue() Loading @@ -185,15 +185,14 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(session).close() } /** * Ensures session begins when a view is attached. */ /** Ensures session begins when a view is attached. */ @Test fun testConnectOnViewCreate() { `when`(precondition.conditionsMet()).thenReturn(true) controller.buildAndConnectView(Mockito.mock(ViewGroup::class.java)) val stateChangeListener = withArgCaptor<View.OnAttachStateChangeListener> { val stateChangeListener = withArgCaptor<View.OnAttachStateChangeListener> { verify(viewComponentFactory).create(any(), eq(plugin), capture(), eq(null)) } Loading @@ -209,9 +208,7 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(session).close() } /** * Ensures session is created when weather smartspace view is created and attached. */ /** Ensures session is created when weather smartspace view is created and attached. */ @Test fun testConnectOnWeatherViewCreate() { `when`(precondition.conditionsMet()).thenReturn(true) Loading @@ -223,8 +220,8 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { // Then weather view is created with custom view and the default weatherPlugin.getView // should not be called verify(viewComponentFactory).create(eq(fakeParent), eq(weatherPlugin), any(), eq(customView)) verify(viewComponentFactory) .create(eq(fakeParent), eq(weatherPlugin), any(), eq(customView)) verify(weatherPlugin, Mockito.never()).getView(fakeParent) // And then session is created Loading @@ -234,9 +231,7 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(weatherSmartspaceView).setDozeAmount(0f) } /** * Ensures weather plugin registers target listener when it is added from the controller. */ /** Ensures weather plugin registers target listener when it is added from the controller. */ @Test fun testAddListenerInController_registersListenerForWeatherPlugin() { val customView = Mockito.mock(TestView::class.java) Loading packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt +67 −63 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.smartspace.SmartspaceConfig import android.app.smartspace.SmartspaceManager import android.app.smartspace.SmartspaceSession import android.app.smartspace.SmartspaceTarget import android.content.Context import android.graphics.Color import android.util.Log import android.view.View Loading @@ -31,6 +30,7 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView import com.android.systemui.plugins.BcSmartspaceDataPlugin.UI_SURFACE_DREAM import com.android.systemui.settings.UserTracker import com.android.systemui.smartspace.SmartspacePrecondition import com.android.systemui.smartspace.SmartspaceTargetFilter import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_DATA_PLUGIN Loading @@ -44,13 +44,12 @@ import java.util.concurrent.Executor import javax.inject.Inject import javax.inject.Named /** * Controller for managing the smartspace view on the dream */ /** Controller for managing the smartspace view on the dream */ @SysUISingleton class DreamSmartspaceController @Inject constructor( private val context: Context, private val smartspaceManager: SmartspaceManager?, class DreamSmartspaceController @Inject constructor( private val userTracker: UserTracker, private val execution: Execution, @Main private val uiExecutor: Executor, private val smartspaceViewComponentFactory: SmartspaceViewComponent.Factory, Loading @@ -65,6 +64,7 @@ class DreamSmartspaceController @Inject constructor( private const val TAG = "DreamSmartspaceCtrlr" } private var userSmartspaceManager: SmartspaceManager? = null private var session: SmartspaceSession? = null private val weatherPlugin: BcSmartspaceDataPlugin? = optionalWeatherPlugin.orElse(null) private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null) Loading @@ -78,7 +78,8 @@ class DreamSmartspaceController @Inject constructor( // Smartspace can be used on multiple displays, such as when the user casts their screen private var smartspaceViews = mutableSetOf<SmartspaceView>() var preconditionListener = object : SmartspacePrecondition.Listener { var preconditionListener = object : SmartspacePrecondition.Listener { override fun onCriteriaChanged() { reloadSmartspace() } Loading @@ -88,7 +89,8 @@ class DreamSmartspaceController @Inject constructor( precondition.addListener(preconditionListener) } var filterListener = object : SmartspaceTargetFilter.Listener { var filterListener = object : SmartspaceTargetFilter.Listener { override fun onCriteriaChanged() { reloadSmartspace() } Loading @@ -98,7 +100,8 @@ class DreamSmartspaceController @Inject constructor( targetFilter?.addListener(filterListener) } var stateChangeListener = object : View.OnAttachStateChangeListener { var stateChangeListener = object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { val view = v as SmartspaceView // Until there is dream color matching Loading @@ -117,27 +120,26 @@ class DreamSmartspaceController @Inject constructor( } } private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> execution.assertIsMainThread() // The weather data plugin takes unfiltered targets and performs the filtering internally. // The weather data plugin takes unfiltered targets and performs the filtering // internally. weatherPlugin?.onTargetsAvailable(targets) onTargetsAvailableUnfiltered(targets) val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true } val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true } plugin?.onTargetsAvailable(filteredTargets) } /** * Constructs the weather view with custom layout and connects it to the weather plugin. */ /** Constructs the weather view with custom layout and connects it to the weather plugin. */ fun buildAndConnectWeatherView(parent: ViewGroup, customView: View?): View? { return buildAndConnectViewWithPlugin(parent, weatherPlugin, customView) } /** * Constructs the smartspace view and connects it to the smartspace service. */ /** Constructs the smartspace view and connects it to the smartspace service. */ fun buildAndConnectView(parent: ViewGroup): View? { return buildAndConnectViewWithPlugin(parent, plugin, null) } Loading @@ -145,7 +147,7 @@ class DreamSmartspaceController @Inject constructor( private fun buildAndConnectViewWithPlugin( parent: ViewGroup, smartspaceDataPlugin: BcSmartspaceDataPlugin?, customView: View? customView: View?, ): View? { execution.assertIsMainThread() Loading @@ -163,11 +165,12 @@ class DreamSmartspaceController @Inject constructor( private fun buildView( parent: ViewGroup, smartspaceDataPlugin: BcSmartspaceDataPlugin?, customView: View? customView: View?, ): View? { return if (smartspaceDataPlugin != null) { val view = smartspaceViewComponentFactory.create(parent, smartspaceDataPlugin, stateChangeListener, customView) val view = smartspaceViewComponentFactory .create(parent, smartspaceDataPlugin, stateChangeListener, customView) .getView() if (view !is View) { return null Loading @@ -179,12 +182,17 @@ class DreamSmartspaceController @Inject constructor( } private fun hasActiveSessionListeners(): Boolean { return smartspaceViews.isNotEmpty() || listeners.isNotEmpty() || return smartspaceViews.isNotEmpty() || listeners.isNotEmpty() || unfilteredListeners.isNotEmpty() } private fun connectSession() { if (smartspaceManager == null) { if (userSmartspaceManager == null) { userSmartspaceManager = userTracker.userContext.getSystemService(SmartspaceManager::class.java) } if (userSmartspaceManager == null) { return } if (plugin == null && weatherPlugin == null) { Loading @@ -198,25 +206,21 @@ class DreamSmartspaceController @Inject constructor( return } val newSession = smartspaceManager.createSmartspaceSession( SmartspaceConfig.Builder(context, UI_SURFACE_DREAM).build() val newSession = userSmartspaceManager?.createSmartspaceSession( SmartspaceConfig.Builder(userTracker.userContext, UI_SURFACE_DREAM).build() ) Log.d(TAG, "Starting smartspace session for dream") newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener) newSession?.addOnTargetsAvailableListener(uiExecutor, sessionListener) this.session = newSession weatherPlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) } plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) } plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) } reloadSmartspace() } /** * Disconnects the smartspace view from the smartspace service and cleans up any resources. */ /** Disconnects the smartspace view from the smartspace service and cleans up any resources. */ private fun disconnect() { if (hasActiveSessionListeners()) return Loading Loading @@ -259,7 +263,7 @@ class DreamSmartspaceController @Inject constructor( private fun addAndRegisterListener( listener: SmartspaceTargetListener, smartspaceDataPlugin: BcSmartspaceDataPlugin? smartspaceDataPlugin: BcSmartspaceDataPlugin?, ) { execution.assertIsMainThread() smartspaceDataPlugin?.registerListener(listener) Loading @@ -270,7 +274,7 @@ class DreamSmartspaceController @Inject constructor( private fun removeAndUnregisterListener( listener: SmartspaceTargetListener, smartspaceDataPlugin: BcSmartspaceDataPlugin? smartspaceDataPlugin: BcSmartspaceDataPlugin?, ) { execution.assertIsMainThread() smartspaceDataPlugin?.unregisterListener(listener) Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt +59 −64 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import com.android.systemui.plugins.BcSmartspaceConfigPlugin import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView import com.android.systemui.plugins.FalsingManager import com.android.systemui.settings.UserTracker import com.android.systemui.smartspace.dagger.SmartspaceViewComponent import com.android.systemui.util.concurrency.Execution import com.android.systemui.util.mockito.any Loading @@ -46,66 +47,51 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.Mockito.anyInt import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.Mockito.anyInt import org.mockito.MockitoAnnotations import org.mockito.Spy @SmallTest @RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper class DreamSmartspaceControllerTest : SysuiTestCase() { @Mock private lateinit var smartspaceManager: SmartspaceManager @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var execution: Execution @Mock private lateinit var userContextPrimary: Context @Mock private lateinit var uiExecutor: Executor @Mock private lateinit var smartspaceManager: SmartspaceManager @Mock private lateinit var viewComponentFactory: SmartspaceViewComponent.Factory @Mock private lateinit var execution: Execution @Mock private lateinit var viewComponent: SmartspaceViewComponent @Mock private lateinit var uiExecutor: Executor @Mock private lateinit var weatherViewComponent: SmartspaceViewComponent @Mock private lateinit var viewComponentFactory: SmartspaceViewComponent.Factory private val weatherSmartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var viewComponent: SmartspaceViewComponent @Mock private lateinit var targetFilter: SmartspaceTargetFilter @Mock private lateinit var weatherViewComponent: SmartspaceViewComponent @Mock private lateinit var plugin: BcSmartspaceDataPlugin private val weatherSmartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var weatherPlugin: BcSmartspaceDataPlugin @Mock private lateinit var targetFilter: SmartspaceTargetFilter @Mock private lateinit var precondition: SmartspacePrecondition @Mock private lateinit var plugin: BcSmartspaceDataPlugin private val smartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var weatherPlugin: BcSmartspaceDataPlugin @Mock private lateinit var precondition: SmartspacePrecondition @Mock private lateinit var listener: BcSmartspaceDataPlugin.SmartspaceTargetListener private val smartspaceView: SmartspaceView by lazy { Mockito.spy(TestView(context)) } @Mock private lateinit var session: SmartspaceSession @Mock private lateinit var listener: BcSmartspaceDataPlugin.SmartspaceTargetListener @Mock private lateinit var session: SmartspaceSession private lateinit var controller: DreamSmartspaceController // TODO(b/272811280): Remove usage of real view private val fakeParent by lazy { FrameLayout(context) } private val fakeParent by lazy { FrameLayout(context) } /** * A class which implements SmartspaceView and extends View. This is mocked to provide the right Loading Loading @@ -134,9 +120,13 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { override fun setMediaTarget(target: SmartspaceTarget?) {} override fun getSelectedPage(): Int { return 0; } override fun getSelectedPage(): Int { return 0 } override fun getCurrentCardTopPadding(): Int { return 0; } override fun getCurrentCardTopPadding(): Int { return 0 } } @Before Loading @@ -150,14 +140,24 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { `when`(weatherViewComponent.getView()).thenReturn(weatherSmartspaceView) `when`(smartspaceManager.createSmartspaceSession(any())).thenReturn(session) controller = DreamSmartspaceController(context, smartspaceManager, execution, uiExecutor, viewComponentFactory, precondition, Optional.of(targetFilter), Optional.of(plugin), Optional.of(weatherPlugin)) `when`(userTracker.userContext).thenReturn(userContextPrimary) `when`(userContextPrimary.getSystemService(SmartspaceManager::class.java)) .thenReturn(smartspaceManager) controller = DreamSmartspaceController( userTracker, execution, uiExecutor, viewComponentFactory, precondition, Optional.of(targetFilter), Optional.of(plugin), Optional.of(weatherPlugin), ) } /** * Ensures smartspace session begins on a listener only flow. */ /** Ensures smartspace session begins on a listener only flow. */ @Test fun testConnectOnListen() { `when`(precondition.conditionsMet()).thenReturn(true) Loading @@ -165,7 +165,8 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(smartspaceManager).createSmartspaceSession(any()) var targetListener = withArgCaptor<SmartspaceSession.OnTargetsAvailableListener> { var targetListener = withArgCaptor<SmartspaceSession.OnTargetsAvailableListener> { verify(session).addOnTargetsAvailableListener(any(), capture()) } Loading @@ -174,9 +175,8 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { var target = Mockito.mock(SmartspaceTarget::class.java) targetListener.onTargetsAvailable(listOf(target)) var targets = withArgCaptor<List<SmartspaceTarget>> { verify(plugin).onTargetsAvailable(capture()) } var targets = withArgCaptor<List<SmartspaceTarget>> { verify(plugin).onTargetsAvailable(capture()) } assertThat(targets.contains(target)).isTrue() Loading @@ -185,15 +185,14 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(session).close() } /** * Ensures session begins when a view is attached. */ /** Ensures session begins when a view is attached. */ @Test fun testConnectOnViewCreate() { `when`(precondition.conditionsMet()).thenReturn(true) controller.buildAndConnectView(Mockito.mock(ViewGroup::class.java)) val stateChangeListener = withArgCaptor<View.OnAttachStateChangeListener> { val stateChangeListener = withArgCaptor<View.OnAttachStateChangeListener> { verify(viewComponentFactory).create(any(), eq(plugin), capture(), eq(null)) } Loading @@ -209,9 +208,7 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(session).close() } /** * Ensures session is created when weather smartspace view is created and attached. */ /** Ensures session is created when weather smartspace view is created and attached. */ @Test fun testConnectOnWeatherViewCreate() { `when`(precondition.conditionsMet()).thenReturn(true) Loading @@ -223,8 +220,8 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { // Then weather view is created with custom view and the default weatherPlugin.getView // should not be called verify(viewComponentFactory).create(eq(fakeParent), eq(weatherPlugin), any(), eq(customView)) verify(viewComponentFactory) .create(eq(fakeParent), eq(weatherPlugin), any(), eq(customView)) verify(weatherPlugin, Mockito.never()).getView(fakeParent) // And then session is created Loading @@ -234,9 +231,7 @@ class DreamSmartspaceControllerTest : SysuiTestCase() { verify(weatherSmartspaceView).setDozeAmount(0f) } /** * Ensures weather plugin registers target listener when it is added from the controller. */ /** Ensures weather plugin registers target listener when it is added from the controller. */ @Test fun testAddListenerInController_registersListenerForWeatherPlugin() { val customView = Mockito.mock(TestView::class.java) Loading
packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt +67 −63 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.smartspace.SmartspaceConfig import android.app.smartspace.SmartspaceManager import android.app.smartspace.SmartspaceSession import android.app.smartspace.SmartspaceTarget import android.content.Context import android.graphics.Color import android.util.Log import android.view.View Loading @@ -31,6 +30,7 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView import com.android.systemui.plugins.BcSmartspaceDataPlugin.UI_SURFACE_DREAM import com.android.systemui.settings.UserTracker import com.android.systemui.smartspace.SmartspacePrecondition import com.android.systemui.smartspace.SmartspaceTargetFilter import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DREAM_SMARTSPACE_DATA_PLUGIN Loading @@ -44,13 +44,12 @@ import java.util.concurrent.Executor import javax.inject.Inject import javax.inject.Named /** * Controller for managing the smartspace view on the dream */ /** Controller for managing the smartspace view on the dream */ @SysUISingleton class DreamSmartspaceController @Inject constructor( private val context: Context, private val smartspaceManager: SmartspaceManager?, class DreamSmartspaceController @Inject constructor( private val userTracker: UserTracker, private val execution: Execution, @Main private val uiExecutor: Executor, private val smartspaceViewComponentFactory: SmartspaceViewComponent.Factory, Loading @@ -65,6 +64,7 @@ class DreamSmartspaceController @Inject constructor( private const val TAG = "DreamSmartspaceCtrlr" } private var userSmartspaceManager: SmartspaceManager? = null private var session: SmartspaceSession? = null private val weatherPlugin: BcSmartspaceDataPlugin? = optionalWeatherPlugin.orElse(null) private val plugin: BcSmartspaceDataPlugin? = optionalPlugin.orElse(null) Loading @@ -78,7 +78,8 @@ class DreamSmartspaceController @Inject constructor( // Smartspace can be used on multiple displays, such as when the user casts their screen private var smartspaceViews = mutableSetOf<SmartspaceView>() var preconditionListener = object : SmartspacePrecondition.Listener { var preconditionListener = object : SmartspacePrecondition.Listener { override fun onCriteriaChanged() { reloadSmartspace() } Loading @@ -88,7 +89,8 @@ class DreamSmartspaceController @Inject constructor( precondition.addListener(preconditionListener) } var filterListener = object : SmartspaceTargetFilter.Listener { var filterListener = object : SmartspaceTargetFilter.Listener { override fun onCriteriaChanged() { reloadSmartspace() } Loading @@ -98,7 +100,8 @@ class DreamSmartspaceController @Inject constructor( targetFilter?.addListener(filterListener) } var stateChangeListener = object : View.OnAttachStateChangeListener { var stateChangeListener = object : View.OnAttachStateChangeListener { override fun onViewAttachedToWindow(v: View) { val view = v as SmartspaceView // Until there is dream color matching Loading @@ -117,27 +120,26 @@ class DreamSmartspaceController @Inject constructor( } } private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> private val sessionListener = SmartspaceSession.OnTargetsAvailableListener { targets -> execution.assertIsMainThread() // The weather data plugin takes unfiltered targets and performs the filtering internally. // The weather data plugin takes unfiltered targets and performs the filtering // internally. weatherPlugin?.onTargetsAvailable(targets) onTargetsAvailableUnfiltered(targets) val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true } val filteredTargets = targets.filter { targetFilter?.filterSmartspaceTarget(it) ?: true } plugin?.onTargetsAvailable(filteredTargets) } /** * Constructs the weather view with custom layout and connects it to the weather plugin. */ /** Constructs the weather view with custom layout and connects it to the weather plugin. */ fun buildAndConnectWeatherView(parent: ViewGroup, customView: View?): View? { return buildAndConnectViewWithPlugin(parent, weatherPlugin, customView) } /** * Constructs the smartspace view and connects it to the smartspace service. */ /** Constructs the smartspace view and connects it to the smartspace service. */ fun buildAndConnectView(parent: ViewGroup): View? { return buildAndConnectViewWithPlugin(parent, plugin, null) } Loading @@ -145,7 +147,7 @@ class DreamSmartspaceController @Inject constructor( private fun buildAndConnectViewWithPlugin( parent: ViewGroup, smartspaceDataPlugin: BcSmartspaceDataPlugin?, customView: View? customView: View?, ): View? { execution.assertIsMainThread() Loading @@ -163,11 +165,12 @@ class DreamSmartspaceController @Inject constructor( private fun buildView( parent: ViewGroup, smartspaceDataPlugin: BcSmartspaceDataPlugin?, customView: View? customView: View?, ): View? { return if (smartspaceDataPlugin != null) { val view = smartspaceViewComponentFactory.create(parent, smartspaceDataPlugin, stateChangeListener, customView) val view = smartspaceViewComponentFactory .create(parent, smartspaceDataPlugin, stateChangeListener, customView) .getView() if (view !is View) { return null Loading @@ -179,12 +182,17 @@ class DreamSmartspaceController @Inject constructor( } private fun hasActiveSessionListeners(): Boolean { return smartspaceViews.isNotEmpty() || listeners.isNotEmpty() || return smartspaceViews.isNotEmpty() || listeners.isNotEmpty() || unfilteredListeners.isNotEmpty() } private fun connectSession() { if (smartspaceManager == null) { if (userSmartspaceManager == null) { userSmartspaceManager = userTracker.userContext.getSystemService(SmartspaceManager::class.java) } if (userSmartspaceManager == null) { return } if (plugin == null && weatherPlugin == null) { Loading @@ -198,25 +206,21 @@ class DreamSmartspaceController @Inject constructor( return } val newSession = smartspaceManager.createSmartspaceSession( SmartspaceConfig.Builder(context, UI_SURFACE_DREAM).build() val newSession = userSmartspaceManager?.createSmartspaceSession( SmartspaceConfig.Builder(userTracker.userContext, UI_SURFACE_DREAM).build() ) Log.d(TAG, "Starting smartspace session for dream") newSession.addOnTargetsAvailableListener(uiExecutor, sessionListener) newSession?.addOnTargetsAvailableListener(uiExecutor, sessionListener) this.session = newSession weatherPlugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) } plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) } plugin?.registerSmartspaceEventNotifier { e -> session?.notifySmartspaceEvent(e) } reloadSmartspace() } /** * Disconnects the smartspace view from the smartspace service and cleans up any resources. */ /** Disconnects the smartspace view from the smartspace service and cleans up any resources. */ private fun disconnect() { if (hasActiveSessionListeners()) return Loading Loading @@ -259,7 +263,7 @@ class DreamSmartspaceController @Inject constructor( private fun addAndRegisterListener( listener: SmartspaceTargetListener, smartspaceDataPlugin: BcSmartspaceDataPlugin? smartspaceDataPlugin: BcSmartspaceDataPlugin?, ) { execution.assertIsMainThread() smartspaceDataPlugin?.registerListener(listener) Loading @@ -270,7 +274,7 @@ class DreamSmartspaceController @Inject constructor( private fun removeAndUnregisterListener( listener: SmartspaceTargetListener, smartspaceDataPlugin: BcSmartspaceDataPlugin? smartspaceDataPlugin: BcSmartspaceDataPlugin?, ) { execution.assertIsMainThread() smartspaceDataPlugin?.unregisterListener(listener) Loading