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

Commit 45b74c69 authored by Steven Ng's avatar Steven Ng
Browse files

Add a proxy activity for launch bubble for another user in primary user

This CL is required for work profile notes app shortcuts to be able to
launch in a bubble.

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

Change-Id: I8c5cce46c5b7cf6d0c9e6031628ebe3735171723
parent 7a64585e
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -354,6 +354,7 @@ android_library {
        "androidx.test.uiautomator_uiautomator",
        "androidx.test.uiautomator_uiautomator",
        "mockito-target-extended-minus-junit4",
        "mockito-target-extended-minus-junit4",
        "androidx.test.ext.junit",
        "androidx.test.ext.junit",
        "androidx.test.ext.truth",
    ],
    ],
    libs: [
    libs: [
        "android.test.runner",
        "android.test.runner",
+10 −0
Original line number Original line Diff line number Diff line
@@ -983,6 +983,16 @@
            android:excludeFromRecents="true"
            android:excludeFromRecents="true"
            android:resizeableActivity="false"
            android:resizeableActivity="false"
            android:theme="@android:style/Theme.NoDisplay" />
            android:theme="@android:style/Theme.NoDisplay" />

        <!-- LaunchNoteTaskManagedProfileProxyActivity MUST NOT be exported because it allows caller
             to specify an Android user when launching the default notes app. -->
        <activity
            android:name=".notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity"
            android:exported="false"
            android:enabled="true"
            android:excludeFromRecents="true"
            android:resizeableActivity="false"
            android:theme="@android:style/Theme.NoDisplay" />
        <!-- endregion -->
        <!-- endregion -->


        <!-- started from ControlsRequestReceiver -->
        <!-- started from ControlsRequestReceiver -->
+14 −1
Original line number Original line Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
import com.android.systemui.notetask.NoteTaskRoleManagerExt.getDefaultRoleHolderAsUser
import com.android.systemui.notetask.NoteTaskRoleManagerExt.getDefaultRoleHolderAsUser
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import com.android.systemui.settings.UserTracker
import com.android.systemui.settings.UserTracker
import com.android.systemui.util.kotlin.getOrNull
import com.android.systemui.util.kotlin.getOrNull
import com.android.wm.shell.bubbles.Bubble
import com.android.wm.shell.bubbles.Bubble
@@ -94,6 +95,18 @@ constructor(
        }
        }
    }
    }


    /** Starts [LaunchNoteTaskProxyActivity] on the given [user]. */
    fun startNoteTaskProxyActivityForUser(user: UserHandle) {
        context.startActivityAsUser(
            Intent().apply {
                component =
                    ComponentName(context, LaunchNoteTaskManagedProfileProxyActivity::class.java)
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            },
            user
        )
    }

    /**
    /**
     * Shows a note task. How the task is shown will depend on when the method is invoked.
     * Shows a note task. How the task is shown will depend on when the method is invoked.
     *
     *
@@ -146,7 +159,7 @@ constructor(
            when (info.launchMode) {
            when (info.launchMode) {
                is NoteTaskLaunchMode.AppBubble -> {
                is NoteTaskLaunchMode.AppBubble -> {
                    // TODO: provide app bubble icon
                    // TODO: provide app bubble icon
                    bubbles.showOrHideAppBubble(intent, userTracker.userHandle, null /* icon */)
                    bubbles.showOrHideAppBubble(intent, user, null /* icon */)
                    // 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" }
                }
                }
+4 −0
Original line number Original line Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.systemui.flags.Flags
import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import dagger.Binds
import dagger.Binds
import dagger.Module
import dagger.Module
import dagger.Provides
import dagger.Provides
@@ -36,6 +37,9 @@ interface NoteTaskModule {
    @[Binds IntoMap ClassKey(LaunchNoteTaskActivity::class)]
    @[Binds IntoMap ClassKey(LaunchNoteTaskActivity::class)]
    fun LaunchNoteTaskActivity.bindNoteTaskLauncherActivity(): Activity
    fun LaunchNoteTaskActivity.bindNoteTaskLauncherActivity(): Activity


    @[Binds IntoMap ClassKey(LaunchNoteTaskManagedProfileProxyActivity::class)]
    fun LaunchNoteTaskManagedProfileProxyActivity.bindNoteTaskLauncherProxyActivity(): Activity

    @[Binds IntoMap ClassKey(CreateNoteTaskShortcutActivity::class)]
    @[Binds IntoMap ClassKey(CreateNoteTaskShortcutActivity::class)]
    fun CreateNoteTaskShortcutActivity.bindNoteTaskShortcutActivity(): Activity
    fun CreateNoteTaskShortcutActivity.bindNoteTaskShortcutActivity(): Activity


+36 −2
Original line number Original line Diff line number Diff line
@@ -18,10 +18,13 @@ package com.android.systemui.notetask.shortcut


import android.content.Context
import android.content.Context
import android.content.Intent
import android.content.Intent
import android.content.pm.UserInfo
import android.os.Bundle
import android.os.Bundle
import android.os.UserManager
import androidx.activity.ComponentActivity
import androidx.activity.ComponentActivity
import com.android.systemui.notetask.NoteTaskController
import com.android.systemui.notetask.NoteTaskController
import com.android.systemui.notetask.NoteTaskEntryPoint
import com.android.systemui.notetask.NoteTaskEntryPoint
import com.android.systemui.settings.UserTracker
import javax.inject.Inject
import javax.inject.Inject


/** Activity responsible for launching the note experience, and finish. */
/** Activity responsible for launching the note experience, and finish. */
@@ -29,11 +32,43 @@ class LaunchNoteTaskActivity
@Inject
@Inject
constructor(
constructor(
    private val controller: NoteTaskController,
    private val controller: NoteTaskController,
    private val userManager: UserManager,
    private val userTracker: UserTracker,
) : ComponentActivity() {
) : ComponentActivity() {


    override fun onCreate(savedInstanceState: Bundle?) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        super.onCreate(savedInstanceState)

        // Under the hood, notes app shortcuts are shown in a floating window, called Bubble.
        // Bubble API is only available in the main user but not work profile.
        //
        // On devices with work profile (WP), SystemUI provides both personal notes app shortcuts &
        // work profile notes app shortcuts. In order to make work profile notes app shortcuts to
        // show in Bubble, a few redirections across users are required:
        // 1. When `LaunchNoteTaskActivity` is started in the work profile user, we launch
        //    `LaunchNoteTaskManagedProfileProxyActivity` on the main user, which has access to the
        //    Bubble API.
        // 2. `LaunchNoteTaskManagedProfileProxyActivity` calls `Bubble#showOrHideAppBubble` with
        //     the work profile user ID.
        // 3. Bubble renders the work profile notes app activity in a floating window, which is
        //    hosted in the main user.
        //
        //            WP                                main user
        //  ------------------------          -------------------------------------------
        // | LaunchNoteTaskActivity |   ->   | LaunchNoteTaskManagedProfileProxyActivity |
        //  ------------------------          -------------------------------------------
        //                                                        |
        //                 main user                              |
        //         ----------------------------                   |
        //        | Bubble#showOrHideAppBubble |   <--------------
        //        |      (with WP user ID)     |
        //         ----------------------------
        val mainUser: UserInfo? = userTracker.userProfiles.firstOrNull { it.isMain }
        if (userManager.isManagedProfile && mainUser != null) {
            controller.startNoteTaskProxyActivityForUser(mainUser.userHandle)
        } else {
            controller.showNoteTask(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)
            controller.showNoteTask(entryPoint = NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT)
        }
        finish()
        finish()
    }
    }


@@ -43,7 +78,6 @@ constructor(
        fun newIntent(context: Context): Intent {
        fun newIntent(context: Context): Intent {
            return Intent(context, LaunchNoteTaskActivity::class.java).apply {
            return Intent(context, LaunchNoteTaskActivity::class.java).apply {
                // Intent's action must be set in shortcuts, or an exception will be thrown.
                // Intent's action must be set in shortcuts, or an exception will be thrown.
                // TODO(b/254606432): Use Intent.ACTION_CREATE_NOTE instead.
                action = Intent.ACTION_CREATE_NOTE
                action = Intent.ACTION_CREATE_NOTE
            }
            }
        }
        }
Loading