Enable work profile notes app shortcut when notes role is set

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

Change-Id: I88e39d48c34e157b8b22437bbbba235e69876c9b
This commit is contained in:
Steven Ng
2023-04-03 17:47:50 +00:00
parent 0e6239a9f7
commit 9b11048e8c
4 changed files with 98 additions and 27 deletions

View File

@@ -214,7 +214,7 @@ constructor(
* If the shortcut entry `android:enabled` is set to `true`, the shortcut will be visible in the
* Widget Picker to all users.
*/
fun setNoteTaskShortcutEnabled(value: Boolean) {
fun setNoteTaskShortcutEnabled(value: Boolean, user: UserHandle) {
val componentName = ComponentName(context, CreateNoteTaskShortcutActivity::class.java)
val enabledState =
@@ -224,7 +224,16 @@ constructor(
PackageManager.COMPONENT_ENABLED_STATE_DISABLED
}
context.packageManager.setComponentEnabledSetting(
// If the required user matches the tracking user, the injected context is already a context
// of the required user. Avoid calling #createContextAsUser because creating a context for
// a user takes time.
val userContext =
if (user == userTracker.userHandle) {
context
} else {
context.createContextAsUser(user, /* flags= */ 0)
}
userContext.packageManager.setComponentEnabledSetting(
componentName,
enabledState,
PackageManager.DONT_KILL_APP,
@@ -246,7 +255,7 @@ constructor(
val packageName = roleManager.getDefaultRoleHolderAsUser(ROLE_NOTES, user)
val hasNotesRoleHolder = isEnabled && !packageName.isNullOrEmpty()
setNoteTaskShortcutEnabled(hasNotesRoleHolder)
setNoteTaskShortcutEnabled(hasNotesRoleHolder, user)
if (hasNotesRoleHolder) {
shortcutManager.enableShortcuts(listOf(SHORTCUT_ID))

View File

@@ -20,6 +20,7 @@ import android.os.UserHandle
import android.view.KeyEvent
import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.CommandQueue
import com.android.wm.shell.bubbles.Bubbles
import java.util.Optional
@@ -36,6 +37,7 @@ constructor(
private val optionalBubbles: Optional<Bubbles>,
@Background private val backgroundExecutor: Executor,
@NoteTaskEnabledKey private val isEnabled: Boolean,
private val userTracker: UserTracker,
) {
@VisibleForTesting
@@ -44,8 +46,9 @@ constructor(
override fun handleSystemKey(key: KeyEvent) {
if (key.keyCode == KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL) {
controller.showNoteTask(NoteTaskEntryPoint.TAIL_BUTTON)
} else if (key.keyCode == KeyEvent.KEYCODE_N && key.isMetaPressed &&
key.isCtrlPressed) {
} else if (
key.keyCode == KeyEvent.KEYCODE_N && key.isMetaPressed && key.isCtrlPressed
) {
controller.showNoteTask(NoteTaskEntryPoint.KEYBOARD_SHORTCUT)
}
}
@@ -55,7 +58,7 @@ constructor(
// Guard against feature not being enabled or mandatory dependencies aren't available.
if (!isEnabled || optionalBubbles.isEmpty) return
controller.setNoteTaskShortcutEnabled(true)
controller.setNoteTaskShortcutEnabled(true, userTracker.userHandle)
commandQueue.addCallback(callbacks)
roleManager.addOnRoleHoldersChangedListenerAsUser(
backgroundExecutor,

View File

@@ -75,7 +75,9 @@ import org.mockito.MockitoAnnotations
internal class NoteTaskControllerTest : SysuiTestCase() {
@Mock private lateinit var context: Context
@Mock private lateinit var workProfileContext: Context
@Mock private lateinit var packageManager: PackageManager
@Mock private lateinit var workProfilePackageManager: PackageManager
@Mock private lateinit var resolver: NoteTaskInfoResolver
@Mock private lateinit var bubbles: Bubbles
@Mock private lateinit var keyguardManager: KeyguardManager
@@ -373,17 +375,17 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
@Test
fun showNoteTask_keyboardShortcut_shouldStartActivity() {
val expectedInfo =
NOTE_TASK_INFO.copy(
entryPoint = NoteTaskEntryPoint.KEYBOARD_SHORTCUT,
isKeyguardLocked = true,
)
NOTE_TASK_INFO.copy(
entryPoint = NoteTaskEntryPoint.KEYBOARD_SHORTCUT,
isKeyguardLocked = true,
)
whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
whenever(resolver.resolveInfo(any(), any())).thenReturn(expectedInfo)
createNoteTaskController()
.showNoteTask(
entryPoint = expectedInfo.entryPoint!!,
)
.showNoteTask(
entryPoint = expectedInfo.entryPoint!!,
)
val intentCaptor = argumentCaptor<Intent>()
val userCaptor = argumentCaptor<UserHandle>()
@@ -393,9 +395,9 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
assertThat(intent.`package`).isEqualTo(NOTE_TASK_PACKAGE_NAME)
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)
.isEqualTo(FLAG_ACTIVITY_MULTIPLE_TASK)
assertThat(intent.flags and FLAG_ACTIVITY_NEW_DOCUMENT)
.isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
.isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, true)).isFalse()
}
assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
@@ -407,7 +409,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
// region setNoteTaskShortcutEnabled
@Test
fun setNoteTaskShortcutEnabled_setTrue() {
createNoteTaskController().setNoteTaskShortcutEnabled(value = true)
createNoteTaskController().setNoteTaskShortcutEnabled(value = true, userTracker.userHandle)
val argument = argumentCaptor<ComponentName>()
verify(context.packageManager)
@@ -422,7 +424,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
@Test
fun setNoteTaskShortcutEnabled_setFalse() {
createNoteTaskController().setNoteTaskShortcutEnabled(value = false)
createNoteTaskController().setNoteTaskShortcutEnabled(value = false, userTracker.userHandle)
val argument = argumentCaptor<ComponentName>()
verify(context.packageManager)
@@ -434,6 +436,47 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
assertThat(argument.value.className)
.isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
}
@Test
fun setNoteTaskShortcutEnabled_workProfileUser_setTrue() {
whenever(context.createContextAsUser(eq(workUserInfo.userHandle), any()))
.thenReturn(workProfileContext)
whenever(workProfileContext.packageManager).thenReturn(workProfilePackageManager)
userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
createNoteTaskController().setNoteTaskShortcutEnabled(value = true, workUserInfo.userHandle)
val argument = argumentCaptor<ComponentName>()
verify(workProfilePackageManager)
.setComponentEnabledSetting(
argument.capture(),
eq(COMPONENT_ENABLED_STATE_ENABLED),
eq(PackageManager.DONT_KILL_APP),
)
assertThat(argument.value.className)
.isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
}
@Test
fun setNoteTaskShortcutEnabled_workProfileUser_setFalse() {
whenever(context.createContextAsUser(eq(workUserInfo.userHandle), any()))
.thenReturn(workProfileContext)
whenever(workProfileContext.packageManager).thenReturn(workProfilePackageManager)
userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
createNoteTaskController()
.setNoteTaskShortcutEnabled(value = false, workUserInfo.userHandle)
val argument = argumentCaptor<ComponentName>()
verify(workProfilePackageManager)
.setComponentEnabledSetting(
argument.capture(),
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
assertThat(argument.value.className)
.isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
}
// endregion
// region keyguard policy

View File

@@ -20,9 +20,11 @@ import android.test.suitebuilder.annotation.SmallTest
import android.view.KeyEvent
import androidx.test.runner.AndroidJUnit4
import com.android.systemui.SysuiTestCase
import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import com.android.wm.shell.bubbles.Bubbles
import java.util.Optional
@@ -46,6 +48,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
@Mock lateinit var roleManager: RoleManager
private val clock = FakeSystemClock()
private val executor = FakeExecutor(clock)
private val userTracker = FakeUserTracker()
@Before
fun setUp() {
@@ -63,6 +66,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
isEnabled = isEnabled,
roleManager = roleManager,
backgroundExecutor = executor,
userTracker = userTracker,
)
}
@@ -71,7 +75,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
fun initialize() {
createNoteTaskInitializer().initialize()
verify(controller).setNoteTaskShortcutEnabled(true)
verify(controller).setNoteTaskShortcutEnabled(eq(true), eq(userTracker.userHandle))
verify(commandQueue).addCallback(any())
verify(roleManager).addOnRoleHoldersChangedListenerAsUser(any(), any(), any())
}
@@ -80,7 +84,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
fun initialize_flagDisabled() {
createNoteTaskInitializer(isEnabled = false).initialize()
verify(controller, never()).setNoteTaskShortcutEnabled(any())
verify(controller, never()).setNoteTaskShortcutEnabled(any(), any())
verify(commandQueue, never()).addCallback(any())
verify(roleManager, never()).addOnRoleHoldersChangedListenerAsUser(any(), any(), any())
}
@@ -89,7 +93,7 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
fun initialize_bubblesNotPresent() {
createNoteTaskInitializer(bubbles = null).initialize()
verify(controller, never()).setNoteTaskShortcutEnabled(any())
verify(controller, never()).setNoteTaskShortcutEnabled(any(), any())
verify(commandQueue, never()).addCallback(any())
verify(roleManager, never()).addOnRoleHoldersChangedListenerAsUser(any(), any(), any())
}
@@ -98,24 +102,36 @@ internal class NoteTaskInitializerTest : SysuiTestCase() {
// region handleSystemKey
@Test
fun handleSystemKey_receiveValidSystemKey_shouldShowNoteTask() {
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL))
createNoteTaskInitializer()
.callbacks
.handleSystemKey(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_STYLUS_BUTTON_TAIL))
verify(controller).showNoteTask(entryPoint = NoteTaskEntryPoint.TAIL_BUTTON)
}
@Test
fun handleSystemKey_receiveKeyboardShortcut_shouldShowNoteTask() {
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_N, 0, KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON))
createNoteTaskInitializer()
.callbacks
.handleSystemKey(
KeyEvent(
0,
0,
KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_N,
0,
KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON
)
)
verify(controller).showNoteTask(entryPoint = NoteTaskEntryPoint.KEYBOARD_SHORTCUT)
}
@Test
fun handleSystemKey_receiveInvalidSystemKey_shouldDoNothing() {
createNoteTaskInitializer().callbacks.handleSystemKey(KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_UNKNOWN))
createNoteTaskInitializer()
.callbacks
.handleSystemKey(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_UNKNOWN))
verifyZeroInteractions(controller)
}