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

Commit 5fff4778 authored by Steven Ng's avatar Steven Ng
Browse files

Default to the work profile notes app on COPE devices

The default to the work profile notes app on COPE devices only applies
to `TAIL_BUTTON` & `QUICK_AFFORDANCE` entry points, which don't allow
users to select the work or personal default notes app to be launched.

Test: atest SystemUITests:com.android.systemui.notetask.NoteTaskControllerTest
Bug: 259952057

Change-Id: I572b00e17c4b4296952ab0807a262cd79b8a0527
parent 55a6e8d0
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -107,11 +107,30 @@ constructor(
     * bubble is already opened.
     *
     * That will let users open other apps in full screen, and take contextual notes.
     *
     * On company owned personally enabled (COPE) devices, if the given [entryPoint] is in the
     * [FORCE_WORK_NOTE_APPS_ENTRY_POINTS_ON_COPE_DEVICES] list, the default notes app in the work
     * profile user will always be launched.
     */
    fun showNoteTask(
        entryPoint: NoteTaskEntryPoint,
    ) {
        showNoteTaskAsUser(entryPoint, userTracker.userHandle)
        if (!isEnabled) return

        val user: UserHandle =
            if (
                entryPoint in FORCE_WORK_NOTE_APPS_ENTRY_POINTS_ON_COPE_DEVICES &&
                    devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile
            ) {
                userTracker.userProfiles
                    .firstOrNull { userManager.isManagedProfile(it.id) }
                    ?.userHandle
                    ?: userTracker.userHandle
            } else {
                userTracker.userHandle
            }

        showNoteTaskAsUser(entryPoint, user)
    }

    /** A variant of [showNoteTask] which launches note task in the given [user]. */
@@ -149,7 +168,7 @@ constructor(
            when (info.launchMode) {
                is NoteTaskLaunchMode.AppBubble -> {
                    // TODO: provide app bubble icon
                    bubbles.showOrHideAppBubble(intent, userTracker.userHandle, null /* icon */)
                    bubbles.showOrHideAppBubble(intent, user, null /* icon */)
                    // App bubble logging happens on `onBubbleExpandChanged`.
                    logDebug { "onShowNoteTask - opened as app bubble: $info" }
                }
@@ -239,6 +258,16 @@ constructor(
         * @see com.android.launcher3.icons.IconCache.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE
         */
        const val EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE = "extra_shortcut_badge_override_package"

        /**
         * A list of entry points which should be redirected to the work profile default notes app
         * on company owned personally enabled (COPE) devices.
         *
         * Entry points in this list don't let users / admin to select the work or personal default
         * notes app to be launched.
         */
        val FORCE_WORK_NOTE_APPS_ENTRY_POINTS_ON_COPE_DEVICES =
            listOf(NoteTaskEntryPoint.TAIL_BUTTON, NoteTaskEntryPoint.QUICK_AFFORDANCE)
    }
}

+70 −22
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.content.pm.UserInfo
import android.os.UserHandle
import android.os.UserManager
import androidx.test.filters.SmallTest
@@ -44,7 +45,6 @@ import com.android.systemui.notetask.NoteTaskController.Companion.SHORTCUT_ID
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
@@ -81,7 +81,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
    @Mock private lateinit var shortcutManager: ShortcutManager
    @Mock private lateinit var activityManager: ActivityManager
    @Mock private lateinit var devicePolicyManager: DevicePolicyManager
    private val userTracker: UserTracker = FakeUserTracker()
    private val userTracker = FakeUserTracker()

    @Before
    fun setUp() {
@@ -102,6 +102,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
        whenever(roleManager.getRoleHoldersAsUser(ROLE_NOTES, userTracker.userHandle))
            .thenReturn(listOf(NOTE_TASK_PACKAGE_NAME))
        whenever(activityManager.getRunningTasks(anyInt())).thenReturn(emptyList())
        whenever(userManager.isManagedProfile(workUserInfo.id)).thenReturn(true)
    }

    private fun createNoteTaskController(
@@ -308,15 +309,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
            )

        verifyZeroInteractions(context)
        val intentCaptor = argumentCaptor<Intent>()
        verify(bubbles)
            .showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle), isNull())
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTE_TASK_PACKAGE_NAME)
            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
        verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
        verifyZeroInteractions(eventLogger)
    }

@@ -443,15 +436,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {

        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)

        val intentCaptor = argumentCaptor<Intent>()
        verify(bubbles)
            .showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle), isNull())
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTE_TASK_PACKAGE_NAME)
            assertThat(intent.flags).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
        verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
    }

    @Test
@@ -467,9 +452,67 @@ internal class NoteTaskControllerTest : SysuiTestCase() {

        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)

        verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
    }
    // endregion

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

        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)

        verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
    }

    @Test
    fun showNoteTask_copeDevices_quickAffordanceEntryPoint_shouldStartBubbleInWorkProfile() {
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))

        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.QUICK_AFFORDANCE)

        verifyNoteTaskOpenInBubbleInUser(workUserInfo.userHandle)
    }

    @Test
    fun showNoteTask_copeDevices_tailButtonEntryPoint_shouldStartBubbleInWorkProfile() {
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))

        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.TAIL_BUTTON)

        verifyNoteTaskOpenInBubbleInUser(workUserInfo.userHandle)
    }

    @Test
    fun showNoteTask_copeDevices_shortcutsEntryPoint_shouldStartBubbleInTheSelectedUser() {
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))

        createNoteTaskController()
            .showNoteTask(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)

        verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
    }

    @Test
    fun showNoteTask_copeDevices_appClipsEntryPoint_shouldStartBubbleInTheSelectedUser() {
        whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
        userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))

        createNoteTaskController().showNoteTask(entryPoint = NoteTaskEntryPoint.APP_CLIPS)

        verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
    }
    // endregion

    private fun verifyNoteTaskOpenInBubbleInUser(userHandle: UserHandle) {
        val intentCaptor = argumentCaptor<Intent>()
        verify(bubbles)
            .showOrHideAppBubble(capture(intentCaptor), eq(userTracker.userHandle), isNull())
            .showOrHideAppBubble(capture(intentCaptor), eq(userHandle), /* icon = */ isNull())
        intentCaptor.value.let { intent ->
            assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
            assertThat(intent.`package`).isEqualTo(NOTE_TASK_PACKAGE_NAME)
@@ -477,7 +520,6 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
            assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
        }
    }
    // endregion

    // region updateNoteTaskAsUser
    @Test
@@ -564,5 +606,11 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
            ActivityManager.RunningTaskInfo().apply {
                topActivity = ComponentName(NOTE_TASK_PACKAGE_NAME, NOTE_TASK_ACTIVITY_NAME)
            }

        val mainUserInfo =
            UserInfo(/* id= */ 0, /* name= */ "primary", /* flags= */ UserInfo.FLAG_MAIN)
        val workUserInfo =
            UserInfo(/* id= */ 10, /* name= */ "work", /* flags= */ UserInfo.FLAG_PROFILE)
        val mainAndWorkProfileUsers = listOf(mainUserInfo, workUserInfo)
    }
}