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

Commit 987035d3 authored by Matt Pietal's avatar Matt Pietal
Browse files

Fix blank screen when launching controls activity

It was possible to attempt to launch a non showWhenLocked activity
over the keyguard by passing the wrong value into the
activityStarter. In addition, the existing code would trampoline
activities which produced a bad opening animation.

Directly launch the correct activity, and also set the
showOverLockscreenWhenLocked flag to the correct value to ensure the
animation runs properly.

Fixes: 235769893
Test: atest DeviceControlsTileTest
Test: manual, follow steps in bug to repro
Change-Id: I64ebd82b47547beecaee15d570a14dc20fe663ef
parent d8ebffe4
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -32,6 +32,12 @@ interface ControlsUiController {
    fun show(parent: ViewGroup, onDismiss: Runnable, activityContext: Context)
    fun hide()

    /**
     * Returns the preferred activity to start, depending on if the user has favorited any
     * controls.
     */
    fun resolveActivity(): Class<*>

    /**
     * Request all open dialogs be closed. Set [immediately] to true to dismiss without
     * animations.
+13 −0
Original line number Diff line number Diff line
@@ -149,6 +149,19 @@ class ControlsUiControllerImpl @Inject constructor (
        }
    }

    override fun resolveActivity(): Class<*> {
        val allStructures = controlsController.get().getFavorites()
        val selectedStructure = getPreferredStructure(allStructures)

        return if (controlsController.get().addSeedingFavoritesCallback(onSeedingComplete)) {
            ControlsActivity::class.java
        } else if (selectedStructure.controls.isEmpty() && allStructures.size <= 1) {
            ControlsProviderSelectorActivity::class.java
        } else {
            ControlsActivity::class.java
        }
    }

    override fun show(
        parent: ViewGroup,
        onDismiss: Runnable,
+12 −9
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -42,7 +41,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject

@@ -55,8 +53,7 @@ class DeviceControlsTile @Inject constructor(
    statusBarStateController: StatusBarStateController,
    activityStarter: ActivityStarter,
    qsLogger: QSLogger,
    private val controlsComponent: ControlsComponent,
    private val keyguardStateController: KeyguardStateController
    private val controlsComponent: ControlsComponent
) : QSTileImpl<QSTile.State>(
        host,
        backgroundLooper,
@@ -105,7 +102,8 @@ class DeviceControlsTile @Inject constructor(
        }

        val intent = Intent().apply {
            component = ComponentName(mContext, ControlsActivity::class.java)
            component = ComponentName(mContext, controlsComponent.getControlsUiController().get()
                .resolveActivity())
            addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
            putExtra(ControlsUiController.EXTRA_ANIMATE, true)
        }
@@ -127,10 +125,15 @@ class DeviceControlsTile @Inject constructor(
        state.icon = icon
        if (controlsComponent.isEnabled() && hasControlsApps.get()) {
            if (controlsComponent.getVisibility() == AVAILABLE) {
                val structure = controlsComponent
                    .getControlsController().get().getPreferredStructure().structure
                state.state = Tile.STATE_ACTIVE
                state.secondaryLabel = if (structure == tileLabel) null else structure
                val structureInfo = controlsComponent
                    .getControlsController().get().getPreferredStructure()
                state.state = if (structureInfo.controls.isEmpty()) {
                    Tile.STATE_INACTIVE
                } else {
                    Tile.STATE_ACTIVE
                }
                val label = structureInfo.structure
                state.secondaryLabel = if (label == tileLabel) null else label
            } else {
                state.state = Tile.STATE_INACTIVE
                state.secondaryLabel = mContext.getText(R.string.controls_tile_locked)
+44 −10
Original line number Diff line number Diff line
@@ -33,17 +33,18 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.ActivityLaunchAnimator
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlInfo
import com.android.systemui.controls.controller.ControlsController
import com.android.systemui.controls.controller.StructureInfo
import com.android.systemui.controls.dagger.ControlsComponent
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.ui.ControlsActivity
import com.android.systemui.controls.ui.ControlsUiController
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -57,13 +58,13 @@ import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when`
import org.mockito.Mockito.doNothing
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

@SmallTest
@@ -93,8 +94,6 @@ class DeviceControlsTileTest : SysuiTestCase() {
    private lateinit var serviceInfo: ControlsServiceInfo
    @Mock
    private lateinit var uiEventLogger: UiEventLogger
    @Mock
    private lateinit var keyguardStateController: KeyguardStateController
    @Captor
    private lateinit var listingCallbackCaptor:
            ArgumentCaptor<ControlsListingController.ControlsListingCallback>
@@ -119,7 +118,6 @@ class DeviceControlsTileTest : SysuiTestCase() {
        `when`(qsHost.context).thenReturn(spiedContext)
        `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
        `when`(controlsComponent.isEnabled()).thenReturn(true)
        `when`(keyguardStateController.isUnlocked()).thenReturn(true)
        `when`(controlsController.getPreferredStructure())
                .thenReturn(StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()))
        secureSettings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 1)
@@ -222,12 +220,19 @@ class DeviceControlsTileTest : SysuiTestCase() {
    }

    @Test
    fun testStateAvailableIfListings() {
    fun testStateActiveIfListingsHasControlsFavorited() {
        verify(controlsListingController).observe(
                any(LifecycleOwner::class.java),
                capture(listingCallbackCaptor)
        )
        `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
        `when`(controlsController.getPreferredStructure()).thenReturn(
            StructureInfo(
                ComponentName("pkg", "cls"),
                "structure",
                listOf(ControlInfo("id", "title", "subtitle", 1))
            )
        )

        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
        testableLooper.processAllMessages()
@@ -235,6 +240,22 @@ class DeviceControlsTileTest : SysuiTestCase() {
        assertThat(tile.state.state).isEqualTo(Tile.STATE_ACTIVE)
    }

    @Test
    fun testStateInactiveIfListingsHasNoControlsFavorited() {
        verify(controlsListingController).observe(
                any(LifecycleOwner::class.java),
                capture(listingCallbackCaptor)
        )
        `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
        `when`(controlsController.getPreferredStructure())
                .thenReturn(StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()))

        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
        testableLooper.processAllMessages()

        assertThat(tile.state.state).isEqualTo(Tile.STATE_INACTIVE)
    }

    @Test
    fun testStateInactiveIfLocked() {
        verify(controlsListingController).observe(
@@ -281,7 +302,14 @@ class DeviceControlsTileTest : SysuiTestCase() {
                capture(listingCallbackCaptor)
        )
        `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
        `when`(keyguardStateController.isUnlocked).thenReturn(true)
        `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java)
        `when`(controlsController.getPreferredStructure()).thenReturn(
            StructureInfo(
                ComponentName("pkg", "cls"),
                "structure",
                listOf(ControlInfo("id", "title", "subtitle", 1))
            )
        )

        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
        testableLooper.processAllMessages()
@@ -305,7 +333,14 @@ class DeviceControlsTileTest : SysuiTestCase() {
        )
        `when`(controlsComponent.getVisibility())
            .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
        `when`(keyguardStateController.isUnlocked).thenReturn(false)
        `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java)
        `when`(controlsController.getPreferredStructure()).thenReturn(
            StructureInfo(
                ComponentName("pkg", "cls"),
                "structure",
                listOf(ControlInfo("id", "title", "subtitle", 1))
            )
        )

        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
        testableLooper.processAllMessages()
@@ -345,8 +380,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
                statusBarStateController,
                activityStarter,
                qsLogger,
                controlsComponent,
                keyguardStateController
                controlsComponent
        ).also {
            it.initialize()
            testableLooper.processAllMessages()