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

Commit f85d969f authored by Steven Ng's avatar Steven Ng Committed by Android (Google) Code Review
Browse files

Merge "Default to the work profile notes app on COPE devices" into udc-dev

parents c9da5f84 5fff4778
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)
    }
}