Loading packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +25 −14 Original line number Diff line number Diff line Loading @@ -96,21 +96,32 @@ class DeviceControlsTile @Inject constructor( } override fun handleClick(view: View?) { if (state.state == Tile.STATE_ACTIVE) { mUiHandler.post { val i = Intent().apply { if (state.state == Tile.STATE_UNAVAILABLE) { return } val intent = Intent().apply { component = ComponentName(mContext, ControlsActivity::class.java) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(ControlsUiController.EXTRA_ANIMATE, true) } if (keyguardStateController.isUnlocked()) { val animationController = view?.let { ActivityLaunchAnimator.Controller.fromView(it) } mActivityStarter.startActivity(i, true /* dismissShade */, animationController) mUiHandler.post { if (keyguardStateController.isUnlocked) { mActivityStarter.startActivity( intent, true /* dismissShade */, animationController) } else { if (state.state == Tile.STATE_ACTIVE) { mHost.collapsePanels() mContext.startActivity(i) // With an active tile, don't use ActivityStarter so that the activity is // started without prompting keyguard unlock. mContext.startActivity(intent) } else { mActivityStarter.postStartActivityDismissingKeyguard( intent, 0 /* delay */, animationController) } } } Loading packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt +74 −10 Original line number Diff line number Diff line Loading @@ -17,9 +17,9 @@ package com.android.systemui.qs.tiles import android.content.ComponentName import android.os.Handler import android.content.Context import android.content.Intent import android.os.Handler import android.provider.Settings import android.service.quicksettings.Tile import android.testing.AndroidTestingRunner Loading Loading @@ -52,14 +52,17 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.doNothing import org.mockito.Mockito.never import org.mockito.Mockito.nullable import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions import org.mockito.MockitoAnnotations import java.util.Optional Loading Loading @@ -95,6 +98,8 @@ class DeviceControlsTileTest : SysuiTestCase() { @Captor private lateinit var listingCallbackCaptor: ArgumentCaptor<ControlsListingController.ControlsListingCallback> @Captor private lateinit var intentCaptor: ArgumentCaptor<Intent> private lateinit var testableLooper: TestableLooper private lateinit var tile: DeviceControlsTile Loading Loading @@ -259,21 +264,42 @@ class DeviceControlsTileTest : SysuiTestCase() { } @Test fun testNoDialogWhenUnavailable() { fun handleClick_unavailable_noActivityStarted() { tile.click(null /* view */) testableLooper.processAllMessages() verifyZeroInteractions(activityStarter) } @Test fun handleClick_availableAndLocked_activityStarted() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(keyguardStateController.isUnlocked).thenReturn(false) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter, never()).startActivity(any(), anyBoolean(), any<ActivityLaunchAnimator.Controller>()) // The activity should be started right away and not require a keyguard dismiss. verifyZeroInteractions(activityStarter) verify(spiedContext).startActivity(intentCaptor.capture()) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun testDialogShowWhenAvailable() { fun handleClick_availableAndUnlocked_activityStarted() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(keyguardStateController.isUnlocked).thenReturn(true) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() Loading @@ -281,18 +307,23 @@ class DeviceControlsTileTest : SysuiTestCase() { tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter).startActivity(any(), eq(true) /* dismissShade */, eq(null) as ActivityLaunchAnimator.Controller?) verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) verify(activityStarter).startActivity( intentCaptor.capture(), eq(true) /* dismissShade */, nullable(ActivityLaunchAnimator.Controller::class.java)) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun testNoDialogWhenInactive() { fun handleClick_availableAfterUnlockAndIsLocked_keyguardDismissRequired() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) `when`(keyguardStateController.isUnlocked).thenReturn(false) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() Loading @@ -300,8 +331,39 @@ class DeviceControlsTileTest : SysuiTestCase() { tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter, never()).startActivity(any(), anyBoolean(), any<ActivityLaunchAnimator.Controller>()) verify(activityStarter, never()).startActivity( any(), anyBoolean() /* dismissShade */, nullable(ActivityLaunchAnimator.Controller::class.java)) verify(activityStarter).postStartActivityDismissingKeyguard( intentCaptor.capture(), anyInt(), nullable(ActivityLaunchAnimator.Controller::class.java)) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun handleClick_availableAfterUnlockAndIsUnlocked_activityStarted() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) `when`(keyguardStateController.isUnlocked).thenReturn(true) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) verify(activityStarter).startActivity( intentCaptor.capture(), eq(true) /* dismissShade */, nullable(ActivityLaunchAnimator.Controller::class.java)) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } private fun createTile(): DeviceControlsTile { Loading @@ -319,3 +381,5 @@ class DeviceControlsTileTest : SysuiTestCase() { ) } } private const val CONTROLS_ACTIVITY_CLASS_NAME = "com.android.systemui.controls.ui.ControlsActivity" Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +25 −14 Original line number Diff line number Diff line Loading @@ -96,21 +96,32 @@ class DeviceControlsTile @Inject constructor( } override fun handleClick(view: View?) { if (state.state == Tile.STATE_ACTIVE) { mUiHandler.post { val i = Intent().apply { if (state.state == Tile.STATE_UNAVAILABLE) { return } val intent = Intent().apply { component = ComponentName(mContext, ControlsActivity::class.java) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(ControlsUiController.EXTRA_ANIMATE, true) } if (keyguardStateController.isUnlocked()) { val animationController = view?.let { ActivityLaunchAnimator.Controller.fromView(it) } mActivityStarter.startActivity(i, true /* dismissShade */, animationController) mUiHandler.post { if (keyguardStateController.isUnlocked) { mActivityStarter.startActivity( intent, true /* dismissShade */, animationController) } else { if (state.state == Tile.STATE_ACTIVE) { mHost.collapsePanels() mContext.startActivity(i) // With an active tile, don't use ActivityStarter so that the activity is // started without prompting keyguard unlock. mContext.startActivity(intent) } else { mActivityStarter.postStartActivityDismissingKeyguard( intent, 0 /* delay */, animationController) } } } Loading
packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt +74 −10 Original line number Diff line number Diff line Loading @@ -17,9 +17,9 @@ package com.android.systemui.qs.tiles import android.content.ComponentName import android.os.Handler import android.content.Context import android.content.Intent import android.os.Handler import android.provider.Settings import android.service.quicksettings.Tile import android.testing.AndroidTestingRunner Loading Loading @@ -52,14 +52,17 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyInt import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.`when` import org.mockito.Mockito.doNothing import org.mockito.Mockito.never import org.mockito.Mockito.nullable import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions import org.mockito.MockitoAnnotations import java.util.Optional Loading Loading @@ -95,6 +98,8 @@ class DeviceControlsTileTest : SysuiTestCase() { @Captor private lateinit var listingCallbackCaptor: ArgumentCaptor<ControlsListingController.ControlsListingCallback> @Captor private lateinit var intentCaptor: ArgumentCaptor<Intent> private lateinit var testableLooper: TestableLooper private lateinit var tile: DeviceControlsTile Loading Loading @@ -259,21 +264,42 @@ class DeviceControlsTileTest : SysuiTestCase() { } @Test fun testNoDialogWhenUnavailable() { fun handleClick_unavailable_noActivityStarted() { tile.click(null /* view */) testableLooper.processAllMessages() verifyZeroInteractions(activityStarter) } @Test fun handleClick_availableAndLocked_activityStarted() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(keyguardStateController.isUnlocked).thenReturn(false) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter, never()).startActivity(any(), anyBoolean(), any<ActivityLaunchAnimator.Controller>()) // The activity should be started right away and not require a keyguard dismiss. verifyZeroInteractions(activityStarter) verify(spiedContext).startActivity(intentCaptor.capture()) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun testDialogShowWhenAvailable() { fun handleClick_availableAndUnlocked_activityStarted() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(keyguardStateController.isUnlocked).thenReturn(true) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() Loading @@ -281,18 +307,23 @@ class DeviceControlsTileTest : SysuiTestCase() { tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter).startActivity(any(), eq(true) /* dismissShade */, eq(null) as ActivityLaunchAnimator.Controller?) verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) verify(activityStarter).startActivity( intentCaptor.capture(), eq(true) /* dismissShade */, nullable(ActivityLaunchAnimator.Controller::class.java)) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun testNoDialogWhenInactive() { fun handleClick_availableAfterUnlockAndIsLocked_keyguardDismissRequired() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) `when`(keyguardStateController.isUnlocked).thenReturn(false) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() Loading @@ -300,8 +331,39 @@ class DeviceControlsTileTest : SysuiTestCase() { tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter, never()).startActivity(any(), anyBoolean(), any<ActivityLaunchAnimator.Controller>()) verify(activityStarter, never()).startActivity( any(), anyBoolean() /* dismissShade */, nullable(ActivityLaunchAnimator.Controller::class.java)) verify(activityStarter).postStartActivityDismissingKeyguard( intentCaptor.capture(), anyInt(), nullable(ActivityLaunchAnimator.Controller::class.java)) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun handleClick_availableAfterUnlockAndIsUnlocked_activityStarted() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) `when`(keyguardStateController.isUnlocked).thenReturn(true) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() tile.click(null /* view */) testableLooper.processAllMessages() verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt()) verify(activityStarter).startActivity( intentCaptor.capture(), eq(true) /* dismissShade */, nullable(ActivityLaunchAnimator.Controller::class.java)) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } private fun createTile(): DeviceControlsTile { Loading @@ -319,3 +381,5 @@ class DeviceControlsTileTest : SysuiTestCase() { ) } } private const val CONTROLS_ACTIVITY_CLASS_NAME = "com.android.systemui.controls.ui.ControlsActivity"