Merge "[Device Controls] Handle taps correctly when the tile is in an inactive state." into sc-dev

This commit is contained in:
Caitlin Cassidy
2021-06-04 13:54:08 +00:00
committed by Android (Google) Code Review
2 changed files with 99 additions and 24 deletions

View File

@@ -96,21 +96,32 @@ class DeviceControlsTile @Inject constructor(
} }
override fun handleClick(view: View?) { override fun handleClick(view: View?) {
if (state.state == Tile.STATE_ACTIVE) { if (state.state == Tile.STATE_UNAVAILABLE) {
mUiHandler.post { return
val i = Intent().apply { }
val intent = Intent().apply {
component = ComponentName(mContext, ControlsActivity::class.java) component = ComponentName(mContext, ControlsActivity::class.java)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(ControlsUiController.EXTRA_ANIMATE, true) putExtra(ControlsUiController.EXTRA_ANIMATE, true)
} }
if (keyguardStateController.isUnlocked()) {
val animationController = view?.let { val animationController = view?.let {
ActivityLaunchAnimator.Controller.fromView(it) ActivityLaunchAnimator.Controller.fromView(it)
} }
mActivityStarter.startActivity(i, true /* dismissShade */, animationController)
mUiHandler.post {
if (keyguardStateController.isUnlocked) {
mActivityStarter.startActivity(
intent, true /* dismissShade */, animationController)
} else { } else {
if (state.state == Tile.STATE_ACTIVE) {
mHost.collapsePanels() 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)
} }
} }
} }

View File

@@ -17,9 +17,9 @@
package com.android.systemui.qs.tiles package com.android.systemui.qs.tiles
import android.content.ComponentName import android.content.ComponentName
import android.os.Handler
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Handler
import android.provider.Settings import android.provider.Settings
import android.service.quicksettings.Tile import android.service.quicksettings.Tile
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
@@ -52,14 +52,17 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Captor import org.mockito.Captor
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.`when` import org.mockito.Mockito.`when`
import org.mockito.Mockito.doNothing import org.mockito.Mockito.doNothing
import org.mockito.Mockito.never import org.mockito.Mockito.never
import org.mockito.Mockito.nullable
import org.mockito.Mockito.spy import org.mockito.Mockito.spy
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.MockitoAnnotations import org.mockito.MockitoAnnotations
import java.util.Optional import java.util.Optional
@@ -95,6 +98,8 @@ class DeviceControlsTileTest : SysuiTestCase() {
@Captor @Captor
private lateinit var listingCallbackCaptor: private lateinit var listingCallbackCaptor:
ArgumentCaptor<ControlsListingController.ControlsListingCallback> ArgumentCaptor<ControlsListingController.ControlsListingCallback>
@Captor
private lateinit var intentCaptor: ArgumentCaptor<Intent>
private lateinit var testableLooper: TestableLooper private lateinit var testableLooper: TestableLooper
private lateinit var tile: DeviceControlsTile private lateinit var tile: DeviceControlsTile
@@ -259,21 +264,21 @@ class DeviceControlsTileTest : SysuiTestCase() {
} }
@Test @Test
fun testNoDialogWhenUnavailable() { fun handleClick_unavailable_noActivityStarted() {
tile.click(null /* view */) tile.click(null /* view */)
testableLooper.processAllMessages() testableLooper.processAllMessages()
verify(activityStarter, never()).startActivity(any(), anyBoolean(), verifyZeroInteractions(activityStarter)
any<ActivityLaunchAnimator.Controller>())
} }
@Test @Test
fun testDialogShowWhenAvailable() { fun handleClick_availableAndLocked_activityStarted() {
verify(controlsListingController).observe( verify(controlsListingController).observe(
any(LifecycleOwner::class.java), any(LifecycleOwner::class.java),
capture(listingCallbackCaptor) capture(listingCallbackCaptor)
) )
`when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
`when`(keyguardStateController.isUnlocked).thenReturn(false)
listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
testableLooper.processAllMessages() testableLooper.processAllMessages()
@@ -281,18 +286,44 @@ class DeviceControlsTileTest : SysuiTestCase() {
tile.click(null /* view */) tile.click(null /* view */)
testableLooper.processAllMessages() testableLooper.processAllMessages()
verify(activityStarter).startActivity(any(), eq(true) /* dismissShade */, // The activity should be started right away and not require a keyguard dismiss.
eq(null) as ActivityLaunchAnimator.Controller?) verifyZeroInteractions(activityStarter)
verify(spiedContext).startActivity(intentCaptor.capture())
assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
} }
@Test @Test
fun testNoDialogWhenInactive() { 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()
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)
}
@Test
fun handleClick_availableAfterUnlockAndIsLocked_keyguardDismissRequired() {
verify(controlsListingController).observe( verify(controlsListingController).observe(
any(LifecycleOwner::class.java), any(LifecycleOwner::class.java),
capture(listingCallbackCaptor) capture(listingCallbackCaptor)
) )
`when`(controlsComponent.getVisibility()) `when`(controlsComponent.getVisibility())
.thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
`when`(keyguardStateController.isUnlocked).thenReturn(false)
listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
testableLooper.processAllMessages() testableLooper.processAllMessages()
@@ -300,8 +331,39 @@ class DeviceControlsTileTest : SysuiTestCase() {
tile.click(null /* view */) tile.click(null /* view */)
testableLooper.processAllMessages() testableLooper.processAllMessages()
verify(activityStarter, never()).startActivity(any(), anyBoolean(), verify(activityStarter, never()).startActivity(
any<ActivityLaunchAnimator.Controller>()) 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 { private fun createTile(): DeviceControlsTile {
@@ -319,3 +381,5 @@ class DeviceControlsTileTest : SysuiTestCase() {
) )
} }
} }
private const val CONTROLS_ACTIVITY_CLASS_NAME = "com.android.systemui.controls.ui.ControlsActivity"