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

Commit a606c186 authored by Marcello Galhardo's avatar Marcello Galhardo
Browse files

Use current user to launch note task

It retrieves the system user using the UserTracker, so the NoteTask is associated with the current logged in user or system user if locked out (b/267634412).

Additionally, clean-up the code by removing the unnecessary optional parameters (b/269724992) and adds the missing flags for opening note task correctly (b/271280243).

Test: atest SystemUITests:NoteTaskControllerTest

Fixes: b/267634412
Fixes: b/269724992
Fixes: b/271280243

Change-Id: Id6e1261dac7855c35c6d4a00e362d84709816339
parent 2610029d
Loading
Loading
Loading
Loading
+20 −9
Original line number Original line Diff line number Diff line
@@ -22,6 +22,9 @@ import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.ComponentName
import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.os.Build
import android.os.Build
import android.os.UserManager
import android.os.UserManager
@@ -54,8 +57,8 @@ constructor(
    private val resolver: NoteTaskInfoResolver,
    private val resolver: NoteTaskInfoResolver,
    private val eventLogger: NoteTaskEventLogger,
    private val eventLogger: NoteTaskEventLogger,
    private val optionalBubbles: Optional<Bubbles>,
    private val optionalBubbles: Optional<Bubbles>,
    private val optionalUserManager: Optional<UserManager>,
    private val userManager: UserManager,
    private val optionalKeyguardManager: Optional<KeyguardManager>,
    private val keyguardManager: KeyguardManager,
    @NoteTaskEnabledKey private val isEnabled: Boolean,
    @NoteTaskEnabledKey private val isEnabled: Boolean,
    private val devicePolicyManager: DevicePolicyManager,
    private val devicePolicyManager: DevicePolicyManager,
    private val userTracker: UserTracker,
    private val userTracker: UserTracker,
@@ -106,8 +109,6 @@ constructor(
        if (!isEnabled) return
        if (!isEnabled) return


        val bubbles = optionalBubbles.getOrNull() ?: return
        val bubbles = optionalBubbles.getOrNull() ?: return
        val userManager = optionalUserManager.getOrNull() ?: return
        val keyguardManager = optionalKeyguardManager.getOrNull() ?: return


        // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
        // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
        if (!userManager.isUserUnlocked) return
        if (!userManager.isUserUnlocked) return
@@ -140,12 +141,13 @@ constructor(
            logDebug { "onShowNoteTask - start: $info" }
            logDebug { "onShowNoteTask - start: $info" }
            when (info.launchMode) {
            when (info.launchMode) {
                is NoteTaskLaunchMode.AppBubble -> {
                is NoteTaskLaunchMode.AppBubble -> {
                    // TODO(b/267634412, b/268351693): Should use `showOrHideAppBubbleAsUser`
                    bubbles.showOrHideAppBubble(intent)
                    bubbles.showOrHideAppBubble(intent)
                    // App bubble logging happens on `onBubbleExpandChanged`.
                    // App bubble logging happens on `onBubbleExpandChanged`.
                    logDebug { "onShowNoteTask - opened as app bubble: $info" }
                    logDebug { "onShowNoteTask - opened as app bubble: $info" }
                }
                }
                is NoteTaskLaunchMode.Activity -> {
                is NoteTaskLaunchMode.Activity -> {
                    context.startActivity(intent)
                    context.startActivityAsUser(intent, userTracker.userHandle)
                    eventLogger.logNoteTaskOpened(info)
                    eventLogger.logNoteTaskOpened(info)
                    logDebug { "onShowNoteTask - opened as activity: $info" }
                    logDebug { "onShowNoteTask - opened as activity: $info" }
                }
                }
@@ -198,12 +200,21 @@ constructor(
}
}


private fun createNoteIntent(info: NoteTaskInfo): Intent =
private fun createNoteIntent(info: NoteTaskInfo): Intent =
    Intent(NoteTaskController.ACTION_CREATE_NOTE)
    Intent(NoteTaskController.ACTION_CREATE_NOTE).apply {
        .setPackage(info.packageName)
        setPackage(info.packageName)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

        // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
        // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
        // was used to start it.
        // was used to start it.
        .putExtra(NoteTaskController.INTENT_EXTRA_USE_STYLUS_MODE, true)
        putExtra(NoteTaskController.INTENT_EXTRA_USE_STYLUS_MODE, true)

        addFlags(FLAG_ACTIVITY_NEW_TASK)
        // We should ensure the note experience can be open both as a full screen (lock screen)
        // and inside the app bubble (contextual). These additional flags will do that.
        if (info.launchMode == NoteTaskLaunchMode.Activity) {
            addFlags(FLAG_ACTIVITY_MULTIPLE_TASK)
            addFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
        }
    }


private inline fun logDebug(message: () -> String) {
private inline fun logDebug(message: () -> String) {
    if (Build.IS_DEBUGGABLE) {
    if (Build.IS_DEBUGGABLE) {
+3 −3
Original line number Original line Diff line number Diff line
@@ -17,19 +17,19 @@
package com.android.systemui.notetask
package com.android.systemui.notetask


import android.app.role.RoleManager
import android.app.role.RoleManager
import android.content.Context
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.content.pm.PackageManager.ApplicationInfoFlags
import android.content.pm.PackageManager.ApplicationInfoFlags
import android.os.UserHandle
import android.os.UserHandle
import android.util.Log
import android.util.Log
import com.android.systemui.settings.UserTracker
import javax.inject.Inject
import javax.inject.Inject


class NoteTaskInfoResolver
class NoteTaskInfoResolver
@Inject
@Inject
constructor(
constructor(
    private val context: Context,
    private val roleManager: RoleManager,
    private val roleManager: RoleManager,
    private val packageManager: PackageManager,
    private val packageManager: PackageManager,
    private val userTracker: UserTracker,
) {
) {


    fun resolveInfo(
    fun resolveInfo(
@@ -38,7 +38,7 @@ constructor(
        isKeyguardLocked: Boolean = false,
        isKeyguardLocked: Boolean = false,
    ): NoteTaskInfo? {
    ): NoteTaskInfo? {
        // TODO(b/267634412): Select UserHandle depending on where the user initiated note-taking.
        // TODO(b/267634412): Select UserHandle depending on where the user initiated note-taking.
        val user = context.user
        val user = userTracker.userHandle
        val packageName =
        val packageName =
            roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user).firstOrNull()
            roleManager.getRoleHoldersAsUser(RoleManager.ROLE_NOTES, user).firstOrNull()


+0 −15
Original line number Original line Diff line number Diff line
@@ -17,11 +17,7 @@
package com.android.systemui.notetask
package com.android.systemui.notetask


import android.app.Activity
import android.app.Activity
import android.app.KeyguardManager
import android.app.role.RoleManager
import android.app.role.RoleManager
import android.content.Context
import android.os.UserManager
import androidx.core.content.getSystemService
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.flags.Flags
import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
@@ -32,7 +28,6 @@ import dagger.Module
import dagger.Provides
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import dagger.multibindings.IntoMap
import java.util.Optional


/** Compose all dependencies required by Note Task feature. */
/** Compose all dependencies required by Note Task feature. */
@Module(includes = [NoteTaskQuickAffordanceModule::class])
@Module(includes = [NoteTaskQuickAffordanceModule::class])
@@ -55,15 +50,5 @@ interface NoteTaskModule {
            val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
            val isFeatureEnabled = featureFlags.isEnabled(Flags.NOTE_TASKS)
            return isRoleAvailable && isFeatureEnabled
            return isRoleAvailable && isFeatureEnabled
        }
        }

        @Provides
        fun provideOptionalKeyguardManager(context: Context): Optional<KeyguardManager> {
            return Optional.ofNullable(context.getSystemService())
        }

        @Provides
        fun provideOptionalUserManager(context: Context): Optional<UserManager> {
            return Optional.ofNullable(context.getSystemService())
        }
    }
    }
}
}
+30 −34
Original line number Original line Diff line number Diff line
@@ -20,12 +20,17 @@ import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.ComponentName
import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.pm.PackageManager
import android.content.pm.PackageManager
import android.os.UserHandle
import android.os.UserManager
import android.os.UserManager
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.argumentCaptor
@@ -57,8 +62,8 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
    @Mock lateinit var keyguardManager: KeyguardManager
    @Mock lateinit var keyguardManager: KeyguardManager
    @Mock lateinit var userManager: UserManager
    @Mock lateinit var userManager: UserManager
    @Mock lateinit var eventLogger: NoteTaskEventLogger
    @Mock lateinit var eventLogger: NoteTaskEventLogger
    @Mock private lateinit var userTracker: UserTracker
    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
    private val userTracker: UserTracker = FakeUserTracker()


    private val noteTaskInfo = NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)
    private val noteTaskInfo = NoteTaskInfo(packageName = NOTES_PACKAGE_NAME, uid = NOTES_UID)


@@ -81,16 +86,14 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
    private fun createNoteTaskController(
    private fun createNoteTaskController(
        isEnabled: Boolean = true,
        isEnabled: Boolean = true,
        bubbles: Bubbles? = this.bubbles,
        bubbles: Bubbles? = this.bubbles,
        keyguardManager: KeyguardManager? = this.keyguardManager,
        userManager: UserManager? = this.userManager,
    ): NoteTaskController =
    ): NoteTaskController =
        NoteTaskController(
        NoteTaskController(
            context = context,
            context = context,
            resolver = resolver,
            resolver = resolver,
            eventLogger = eventLogger,
            eventLogger = eventLogger,
            optionalBubbles = Optional.ofNullable(bubbles),
            optionalBubbles = Optional.ofNullable(bubbles),
            optionalUserManager = Optional.ofNullable(userManager),
            userManager = userManager,
            optionalKeyguardManager = Optional.ofNullable(keyguardManager),
            keyguardManager = keyguardManager,
            isEnabled = isEnabled,
            isEnabled = isEnabled,
            devicePolicyManager = devicePolicyManager,
            devicePolicyManager = devicePolicyManager,
            userTracker = userTracker,
            userTracker = userTracker,
@@ -225,13 +228,19 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
            )
            )


        val intentCaptor = argumentCaptor<Intent>()
        val intentCaptor = argumentCaptor<Intent>()
        verify(context).startActivity(capture(intentCaptor))
        val userCaptor = argumentCaptor<UserHandle>()
        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
        intentCaptor.value.let { intent ->
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.flags and FLAG_ACTIVITY_NEW_TASK).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.flags and FLAG_ACTIVITY_MULTIPLE_TASK)
                .isEqualTo(FLAG_ACTIVITY_MULTIPLE_TASK)
            assertThat(intent.flags and FLAG_ACTIVITY_NEW_DOCUMENT)
                .isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
        }
        assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
        verify(eventLogger).logNoteTaskOpened(expectedInfo)
        verify(eventLogger).logNoteTaskOpened(expectedInfo)
        verifyZeroInteractions(bubbles)
        verifyZeroInteractions(bubbles)
    }
    }
@@ -259,7 +268,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        intentCaptor.value.let { intent ->
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
        }
        verifyZeroInteractions(eventLogger)
        verifyZeroInteractions(eventLogger)
@@ -283,13 +292,22 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
            )
            )


        val intentCaptor = argumentCaptor<Intent>()
        val intentCaptor = argumentCaptor<Intent>()
        verify(context).startActivity(capture(intentCaptor))
        val userCaptor = argumentCaptor<UserHandle>()
        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))

        (intentCaptor.value.flags and FLAG_ACTIVITY_NEW_TASK) == FLAG_ACTIVITY_NEW_TASK

        intentCaptor.value.let { intent ->
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.flags and FLAG_ACTIVITY_NEW_TASK).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.flags and FLAG_ACTIVITY_MULTIPLE_TASK)
                .isEqualTo(FLAG_ACTIVITY_MULTIPLE_TASK)
            assertThat(intent.flags and FLAG_ACTIVITY_NEW_DOCUMENT)
                .isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
        }
        assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
        verify(eventLogger).logNoteTaskOpened(expectedInfo)
        verify(eventLogger).logNoteTaskOpened(expectedInfo)
        verifyZeroInteractions(bubbles)
        verifyZeroInteractions(bubbles)
    }
    }
@@ -305,28 +323,6 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        verifyZeroInteractions(context, bubbles, eventLogger)
        verifyZeroInteractions(context, bubbles, eventLogger)
    }
    }


    @Test
    fun showNoteTask_keyguardManagerIsNull_shouldDoNothing() {
        createNoteTaskController(keyguardManager = null)
            .showNoteTask(
                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
                isInMultiWindowMode = false,
            )

        verifyZeroInteractions(context, bubbles, eventLogger)
    }

    @Test
    fun showNoteTask_userManagerIsNull_shouldDoNothing() {
        createNoteTaskController(userManager = null)
            .showNoteTask(
                entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
                isInMultiWindowMode = false,
            )

        verifyZeroInteractions(context, bubbles, eventLogger)
    }

    @Test
    @Test
    fun showNoteTask_intentResolverReturnsNull_shouldDoNothing() {
    fun showNoteTask_intentResolverReturnsNull_shouldDoNothing() {
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(null)
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(null)
@@ -460,7 +456,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        intentCaptor.value.let { intent ->
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
        }
    }
    }
@@ -487,7 +483,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        intentCaptor.value.let { intent ->
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
            assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
            assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
        }
    }
    }
+4 −1
Original line number Original line Diff line number Diff line
@@ -22,6 +22,8 @@ import android.content.pm.PackageManager
import android.test.suitebuilder.annotation.SmallTest
import android.test.suitebuilder.annotation.SmallTest
import androidx.test.runner.AndroidJUnit4
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
@@ -44,13 +46,14 @@ internal class NoteTaskInfoResolverTest : SysuiTestCase() {


    @Mock lateinit var packageManager: PackageManager
    @Mock lateinit var packageManager: PackageManager
    @Mock lateinit var roleManager: RoleManager
    @Mock lateinit var roleManager: RoleManager
    private val userTracker: UserTracker = FakeUserTracker()


    private lateinit var underTest: NoteTaskInfoResolver
    private lateinit var underTest: NoteTaskInfoResolver


    @Before
    @Before
    fun setUp() {
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        MockitoAnnotations.initMocks(this)
        underTest = NoteTaskInfoResolver(context, roleManager, packageManager)
        underTest = NoteTaskInfoResolver(roleManager, packageManager, userTracker)
    }
    }


    @Test
    @Test