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

Commit 24e8e2c5 authored by Jasna Marin's avatar Jasna Marin Committed by Android (Google) Code Review
Browse files

Merge "Introduce preferred notes mode config." into main

parents 31090d7e 59304690
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -506,6 +506,12 @@
         icon will be shown. -->
    <string name="config_screenshotFilesApp" translatable="false"></string>

    <!-- Recommends a UI mode for the default note-taking app when launched with
         android.content.Intent#ACTION_CREATE_NOTE
         0: No UI recommendation. The note app should use its default mode
         1: Recommend a UI optimized for stylus input. -->
    <integer name="config_preferredNotesMode">1</integer>

    <!-- The component name of the screenshot editing activity that provides the App Clips flow.
         The App Clips flow includes taking a screenshot, showing user screenshot cropping activity
         and finally letting user send the screenshot to the calling notes app. This activity
+14 −5
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.log.DebugLogger.debugLog
import com.android.systemui.notetask.NoteTaskEntryPoint.KEYBOARD_SHORTCUT
import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON
import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
@@ -117,7 +118,6 @@ constructor(
            } else {
                getUserForHandlingNotesTaking(entryPoint)
            }

        activityContext.startActivityAsUser(createNotesRoleHolderSettingsIntent(), user)
    }

@@ -206,9 +206,17 @@ constructor(
        try {
            // TODO(b/266686199): We should handle when app not available. For now, we log.
            debugLog { "onShowNoteTask - start: $info on user#${user.identifier}" }
            val useStylusMode =
                when {
                    info.entryPoint == TAIL_BUTTON -> true
                    info.entryPoint == KEYBOARD_SHORTCUT -> false
                    else ->
                        context.resources.getInteger(R.integer.config_preferredNotesMode) ==
                            PREFERRED_NOTES_MODE_STYLUS
                }
            when (info.launchMode) {
                is NoteTaskLaunchMode.AppBubble -> {
                    val intent = createNoteTaskIntent(info)
                    val intent = createNoteTaskIntent(info, useStylusMode)
                    val icon =
                        Icon.createWithResource(context, R.drawable.ic_note_task_shortcut_widget)
                    noteTaskBubblesController.showOrHideAppBubble(
@@ -229,7 +237,7 @@ constructor(
                        eventLogger.logNoteTaskClosed(info)
                        debugLog { "onShowNoteTask - closed as activity: $info" }
                    } else {
                        val intent = createNoteTaskIntent(info)
                        val intent = createNoteTaskIntent(info, useStylusMode)
                        context.startActivityAsUser(intent, user)
                        eventLogger.logNoteTaskOpened(info)
                        debugLog { "onShowNoteTask - opened as activity: $info" }
@@ -393,6 +401,8 @@ constructor(
         */
        const val EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE = "extra_shortcut_badge_override_package"

        const val PREFERRED_NOTES_MODE_STYLUS = 1

        /** Returns notes role holder settings intent. */
        fun createNotesRoleHolderSettingsIntent() =
            Intent(Intent.ACTION_MANAGE_DEFAULT_APP).putExtra(Intent.EXTRA_ROLE_NAME, ROLE_NOTES)
@@ -400,13 +410,12 @@ constructor(
}

/** Creates an [Intent] for [ROLE_NOTES]. */
private fun createNoteTaskIntent(info: NoteTaskInfo): Intent =
private fun createNoteTaskIntent(info: NoteTaskInfo, useStylusMode: Boolean): Intent =
    Intent(Intent.ACTION_CREATE_NOTE).apply {
        setPackage(info.packageName)

        // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint
        // was used to start the note task.
        val useStylusMode = info.entryPoint != NoteTaskEntryPoint.KEYBOARD_SHORTCUT
        putExtra(Intent.EXTRA_USE_STYLUS_MODE, useStylusMode)

        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+108 −29
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED
import android.content.pm.ShortcutManager
import android.content.pm.UserInfo
import android.content.res.Resources
import android.graphics.drawable.Icon
import android.os.UserHandle
import android.os.UserManager
@@ -84,6 +85,7 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.whenever

@@ -106,6 +108,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
    @Mock private lateinit var shortcutManager: ShortcutManager
    @Mock private lateinit var activityManager: ActivityManager
    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
    private lateinit var spiedResources: Resources
    private val userTracker = FakeUserTracker()
    private val testDispatcher = UnconfinedTestDispatcher()
    private val testScope = TestScope(testDispatcher)
@@ -130,7 +133,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(
                devicePolicyManager.getKeyguardDisabledFeatures(
                    /* admin= */ eq(null),
                    /* userHandle= */ anyInt()
                    /* userHandle= */ anyInt(),
                )
            )
            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE)
@@ -139,6 +142,9 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(activityManager.getRunningTasks(anyInt())).thenReturn(emptyList())
        whenever(userManager.isManagedProfile(workUserInfo.id)).thenReturn(true)
        whenever(context.resources).thenReturn(getContext().resources)

        spiedResources = spy(context.resources)
        `when`(context.resources).thenReturn(spiedResources)
    }

    private fun createNoteTaskController(
@@ -161,7 +167,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
            noteTaskBubblesController =
                FakeNoteTaskBubbleController(context, testDispatcher, Optional.ofNullable(bubbles)),
            applicationScope = testScope,
            bgCoroutineContext = testScope.backgroundScope.coroutineContext
            bgCoroutineContext = testScope.backgroundScope.coroutineContext,
        )

    // region onBubbleExpandChanged
@@ -225,11 +231,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {

    @Test
    fun onBubbleExpandChanged_notKeyAppBubble_shouldDoNothing() {
        createNoteTaskController()
            .onBubbleExpandChanged(
                isExpanding = true,
                key = "any other key",
            )
        createNoteTaskController().onBubbleExpandChanged(isExpanding = true, key = "any other key")

        verifyNoMoreInteractions(bubbles, keyguardManager, userManager, eventLogger)
    }
@@ -251,11 +253,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
    fun showNoteTaskAsUser_keyguardIsLocked_shouldStartActivityWithExpectedUserAndLogUiEvent() {
        val user10 = UserHandle.of(/* userId= */ 10)
        val expectedInfo =
            NOTE_TASK_INFO.copy(
                entryPoint = TAIL_BUTTON,
                isKeyguardLocked = true,
                user = user10,
            )
            NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true, user = user10)
        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)

@@ -360,7 +358,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        secureSettings.putIntForUser(
            /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
            /* value= */ 10,
            /* userHandle= */ userTracker.userId
            /* userHandle= */ userTracker.userId,
        )
        val user10 = UserHandle.of(/* userId= */ 10)

@@ -373,10 +371,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)

        createNoteTaskController()
            .showNoteTask(
                entryPoint = expectedInfo.entryPoint!!,
            )
        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)

        val intentCaptor = argumentCaptor<Intent>()
        val userCaptor = argumentCaptor<UserHandle>()
@@ -456,6 +451,85 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        verifyNoMoreInteractions(bubbles)
    }

    @Test
    fun showNoteTask_stylusModePreferred_keyboardShortcut_shouldStartInDefaultUIMode() {
        `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(1)
        val expectedInfo =
            NOTE_TASK_INFO.copy(entryPoint = KEYBOARD_SHORTCUT, isKeyguardLocked = true)
        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)

        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)

        val intentCaptor = argumentCaptor<Intent>()
        val userCaptor = argumentCaptor<UserHandle>()
        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
        assertThat(intentCaptor.value).run {
            hasAction(ACTION_CREATE_NOTE)
            hasPackage(NOTE_TASK_PACKAGE_NAME)
            extras().bool(EXTRA_USE_STYLUS_MODE).isFalse()
        }
    }

    @Test
    fun showNoteTask_stylusModePreferred_quickAffordance_shouldStartInStylusUIMode() {
        `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(1)
        val expectedInfo =
            NOTE_TASK_INFO.copy(entryPoint = QUICK_AFFORDANCE, isKeyguardLocked = true)
        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)

        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)

        val intentCaptor = argumentCaptor<Intent>()
        val userCaptor = argumentCaptor<UserHandle>()
        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
        assertThat(intentCaptor.value).run {
            hasAction(ACTION_CREATE_NOTE)
            hasPackage(NOTE_TASK_PACKAGE_NAME)
            extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
        }
    }

    @Test
    fun showNoteTask_noUIRecommendation_quickAffordance_shouldStartInDefaultUIMode() {
        `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(0)
        val expectedInfo =
            NOTE_TASK_INFO.copy(entryPoint = QUICK_AFFORDANCE, isKeyguardLocked = true)
        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)

        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)

        val intentCaptor = argumentCaptor<Intent>()
        val userCaptor = argumentCaptor<UserHandle>()
        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
        assertThat(intentCaptor.value).run {
            hasAction(ACTION_CREATE_NOTE)
            hasPackage(NOTE_TASK_PACKAGE_NAME)
            extras().bool(EXTRA_USE_STYLUS_MODE).isFalse()
        }
    }

    @Test
    fun showNoteTask_noUIRecommendation_tailButton_shouldStartInStylusUIMode() {
        `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(0)
        val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
        whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
        whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)

        createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)

        val intentCaptor = argumentCaptor<Intent>()
        val userCaptor = argumentCaptor<UserHandle>()
        verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
        assertThat(intentCaptor.value).run {
            hasAction(ACTION_CREATE_NOTE)
            hasPackage(NOTE_TASK_PACKAGE_NAME)
            extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
        }
    }

    // endregion

    // region setNoteTaskShortcutEnabled
@@ -543,7 +617,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(
                devicePolicyManager.getKeyguardDisabledFeatures(
                    /* admin= */ eq(null),
                    /* userHandle= */ anyInt()
                    /* userHandle= */ anyInt(),
                )
            )
            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
@@ -559,7 +633,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(
                devicePolicyManager.getKeyguardDisabledFeatures(
                    /* admin= */ eq(null),
                    /* userHandle= */ anyInt()
                    /* userHandle= */ anyInt(),
                )
            )
            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
@@ -575,7 +649,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(
                devicePolicyManager.getKeyguardDisabledFeatures(
                    /* admin= */ eq(null),
                    /* userHandle= */ anyInt()
                    /* userHandle= */ anyInt(),
                )
            )
            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
@@ -591,7 +665,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(
                devicePolicyManager.getKeyguardDisabledFeatures(
                    /* admin= */ eq(null),
                    /* userHandle= */ anyInt()
                    /* userHandle= */ anyInt(),
                )
            )
            .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
@@ -604,8 +678,9 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
    // endregion

    // region showNoteTask, COPE devices
    @Suppress("ktlint:standard:max-line-length")
    @Test
    fun showNoteTask_copeDevices_quickAffordanceEntryPoint_managedProfileNotFound_shouldStartBubbleInTheMainProfile() { // ktlint-disable max-line-length
    fun showNoteTask_copeDevices_quickAffordanceEntryPoint_managedProfileNotFound_shouldStartBubbleInTheMainProfile() {
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(listOf(mainUserInfo), mainAndWorkProfileUsers.indexOf(mainUserInfo))

@@ -629,7 +704,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        secureSettings.putIntForUser(
            /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
            /* value= */ mainUserInfo.id,
            /* userHandle= */ userTracker.userId
            /* userHandle= */ userTracker.userId,
        )
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
@@ -836,12 +911,13 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        assertThat(user).isEqualTo(UserHandle.of(workUserInfo.id))
    }

    @Suppress("ktlint:standard:max-line-length")
    @Test
    fun getUserForHandlingNotesTaking_cope_userSelectedWorkProfile_tailButton_shouldReturnWorkProfileUser() { // ktlint-disable max-line-length
    fun getUserForHandlingNotesTaking_cope_userSelectedWorkProfile_tailButton_shouldReturnWorkProfileUser() {
        secureSettings.putIntForUser(
            /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
            /* value= */ workUserInfo.id,
            /* userHandle= */ userTracker.userId
            /* userHandle= */ userTracker.userId,
        )
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
@@ -851,12 +927,13 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        assertThat(user).isEqualTo(UserHandle.of(workUserInfo.id))
    }

    @Suppress("ktlint:standard:max-line-length")
    @Test
    fun getUserForHandlingNotesTaking_cope_userSelectedMainProfile_tailButton_shouldReturnMainProfileUser() { // ktlint-disable max-line-length
    fun getUserForHandlingNotesTaking_cope_userSelectedMainProfile_tailButton_shouldReturnMainProfileUser() {
        secureSettings.putIntForUser(
            /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
            /* value= */ mainUserInfo.id,
            /* userHandle= */ userTracker.userId
            /* userHandle= */ userTracker.userId,
        )
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
@@ -934,8 +1011,9 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        assertThat(userCaptor.value).isEqualTo(UserHandle.of(mainUserInfo.id))
    }

    @Suppress("ktlint:standard:max-line-length")
    @Test
    fun startNotesRoleSetting_noManagement_quickAffordance_shouldStartNoteRoleIntentWithCurrentUser() { // ktlint-disable max-line-length
    fun startNotesRoleSetting_noManagement_quickAffordance_shouldStartNoteRoleIntentWithCurrentUser() {
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))

        createNoteTaskController().startNotesRoleSetting(context, QUICK_AFFORDANCE)
@@ -947,8 +1025,9 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        assertThat(userCaptor.value).isEqualTo(UserHandle.of(mainUserInfo.id))
    }

    @Suppress("ktlint:standard:max-line-length")
    @Test
    fun startNotesRoleSetting_noManagement_nullEntryPoint_shouldStartNoteRoleIntentWithCurrentUser() { // ktlint-disable max-line-length
    fun startNotesRoleSetting_noManagement_nullEntryPoint_shouldStartNoteRoleIntentWithCurrentUser() {
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))

        createNoteTaskController().startNotesRoleSetting(context, entryPoint = null)