1 /*
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 @file:OptIn(InternalNoteTaskApi::class)
17 
18 package com.android.systemui.notetask
19 
20 import android.app.ActivityManager
21 import android.app.KeyguardManager
22 import android.app.admin.DevicePolicyManager
23 import android.app.role.RoleManager
24 import android.app.role.RoleManager.ROLE_NOTES
25 import android.content.ComponentName
26 import android.content.Context
27 import android.content.Intent
28 import android.content.Intent.ACTION_CREATE_NOTE
29 import android.content.Intent.ACTION_MAIN
30 import android.content.Intent.ACTION_MANAGE_DEFAULT_APP
31 import android.content.Intent.CATEGORY_HOME
32 import android.content.Intent.EXTRA_USE_STYLUS_MODE
33 import android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK
34 import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT
35 import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
36 import android.content.pm.PackageManager
37 import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
38 import android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED
39 import android.content.pm.ShortcutManager
40 import android.content.pm.UserInfo
41 import android.content.res.Resources
42 import android.graphics.drawable.Icon
43 import android.os.UserHandle
44 import android.os.UserManager
45 import android.provider.Settings
46 import androidx.test.ext.junit.runners.AndroidJUnit4
47 import androidx.test.ext.truth.content.IntentSubject.assertThat
48 import androidx.test.filters.SmallTest
49 import com.android.systemui.SysuiTestCase
50 import com.android.systemui.notetask.NoteTaskController.Companion.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE
51 import com.android.systemui.notetask.NoteTaskController.Companion.SHORTCUT_ID
52 import com.android.systemui.notetask.NoteTaskEntryPoint.APP_CLIPS
53 import com.android.systemui.notetask.NoteTaskEntryPoint.KEYBOARD_SHORTCUT
54 import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE
55 import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON
56 import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT
57 import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
58 import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
59 import com.android.systemui.res.R
60 import com.android.systemui.settings.FakeUserTracker
61 import com.android.systemui.util.mockito.any
62 import com.android.systemui.util.mockito.argumentCaptor
63 import com.android.systemui.util.mockito.capture
64 import com.android.systemui.util.mockito.eq
65 import com.android.systemui.util.mockito.mock
66 import com.android.systemui.util.mockito.withArgCaptor
67 import com.android.systemui.util.settings.FakeSettings
68 import com.android.wm.shell.bubbles.Bubble
69 import com.android.wm.shell.bubbles.Bubbles
70 import com.google.common.truth.Truth.assertThat
71 import java.util.Optional
72 import kotlin.test.assertNotNull
73 import kotlinx.coroutines.ExperimentalCoroutinesApi
74 import kotlinx.coroutines.test.TestScope
75 import kotlinx.coroutines.test.UnconfinedTestDispatcher
76 import kotlinx.coroutines.test.runCurrent
77 import org.junit.Before
78 import org.junit.Test
79 import org.junit.runner.RunWith
80 import org.mockito.ArgumentMatchers.anyInt
81 import org.mockito.Mock
82 import org.mockito.Mockito.atLeastOnce
83 import org.mockito.Mockito.doNothing
84 import org.mockito.Mockito.never
85 import org.mockito.Mockito.spy
86 import org.mockito.Mockito.verify
87 import org.mockito.Mockito.verifyNoMoreInteractions
88 import org.mockito.Mockito.`when`
89 import org.mockito.MockitoAnnotations
90 import org.mockito.kotlin.whenever
91 
92 /** atest SystemUITests:NoteTaskControllerTest */
93 @OptIn(ExperimentalCoroutinesApi::class)
94 @SmallTest
95 @RunWith(AndroidJUnit4::class)
96 internal class NoteTaskControllerTest : SysuiTestCase() {
97 
98     @Mock private lateinit var context: Context
99     @Mock private lateinit var workProfileContext: Context
100     @Mock private lateinit var packageManager: PackageManager
101     @Mock private lateinit var workProfilePackageManager: PackageManager
102     @Mock private lateinit var resolver: NoteTaskInfoResolver
103     @Mock private lateinit var bubbles: Bubbles
104     @Mock private lateinit var keyguardManager: KeyguardManager
105     @Mock private lateinit var userManager: UserManager
106     @Mock private lateinit var eventLogger: NoteTaskEventLogger
107     @Mock private lateinit var roleManager: RoleManager
108     @Mock private lateinit var shortcutManager: ShortcutManager
109     @Mock private lateinit var activityManager: ActivityManager
110     @Mock private lateinit var devicePolicyManager: DevicePolicyManager
111     private lateinit var spiedResources: Resources
112     private val userTracker = FakeUserTracker()
113     private val testDispatcher = UnconfinedTestDispatcher()
114     private val testScope = TestScope(testDispatcher)
115     private val secureSettings = FakeSettings(testDispatcher) { userTracker.userId }
116 
117     @Before
118     fun setUp() {
119         MockitoAnnotations.initMocks(this)
120 
121         whenever(context.getString(R.string.note_task_button_label))
122             .thenReturn(NOTE_TASK_SHORT_LABEL)
123         whenever(context.getString(eq(R.string.note_task_shortcut_long_label), any()))
124             .thenReturn(NOTE_TASK_LONG_LABEL)
125         whenever(context.packageManager).thenReturn(packageManager)
126         whenever(context.createContextAsUser(any(), any())).thenReturn(context)
127         whenever(packageManager.getApplicationInfo(any(), any<Int>())).thenReturn(mock())
128         whenever(packageManager.getApplicationLabel(any())).thenReturn(NOTE_TASK_LONG_LABEL)
129         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(NOTE_TASK_INFO)
130         whenever(userManager.isUserUnlocked).thenReturn(true)
131         whenever(userManager.isUserUnlocked(any<Int>())).thenReturn(true)
132         whenever(userManager.isUserUnlocked(any<UserHandle>())).thenReturn(true)
133         whenever(
134                 devicePolicyManager.getKeyguardDisabledFeatures(
135                     /* admin= */ eq(null),
136                     /* userHandle= */ anyInt(),
137                 )
138             )
139             .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE)
140         whenever(roleManager.getRoleHoldersAsUser(ROLE_NOTES, userTracker.userHandle))
141             .thenReturn(listOf(NOTE_TASK_PACKAGE_NAME))
142         whenever(activityManager.getRunningTasks(anyInt())).thenReturn(emptyList())
143         whenever(userManager.isManagedProfile(workUserInfo.id)).thenReturn(true)
144         whenever(context.resources).thenReturn(getContext().resources)
145 
146         spiedResources = spy(context.resources)
147         `when`(context.resources).thenReturn(spiedResources)
148     }
149 
150     private fun createNoteTaskController(
151         isEnabled: Boolean = true,
152         bubbles: Bubbles? = this.bubbles,
153     ): NoteTaskController =
154         NoteTaskController(
155             context = context,
156             resolver = resolver,
157             eventLogger = eventLogger,
158             userManager = userManager,
159             keyguardManager = keyguardManager,
160             isEnabled = isEnabled,
161             devicePolicyManager = devicePolicyManager,
162             userTracker = userTracker,
163             roleManager = roleManager,
164             shortcutManager = shortcutManager,
165             activityManager = activityManager,
166             secureSettings = secureSettings,
167             noteTaskBubblesController =
168                 FakeNoteTaskBubbleController(context, testDispatcher, Optional.ofNullable(bubbles)),
169             applicationScope = testScope,
170             bgCoroutineContext = testScope.backgroundScope.coroutineContext,
171         )
172 
173     // region onBubbleExpandChanged
174     @Test
175     fun onBubbleExpandChanged_expanding_logNoteTaskOpened() {
176         val expectedInfo = NOTE_TASK_INFO.copy(isKeyguardLocked = false)
177 
178         createNoteTaskController()
179             .apply { infoReference.set(expectedInfo) }
180             .onBubbleExpandChanged(
181                 isExpanding = true,
182                 key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
183             )
184 
185         verify(eventLogger).logNoteTaskOpened(expectedInfo)
186         verifyNoMoreInteractions(bubbles, keyguardManager, userManager)
187     }
188 
189     @Test
190     fun onBubbleExpandChanged_collapsing_logNoteTaskClosed() {
191         val expectedInfo = NOTE_TASK_INFO.copy(isKeyguardLocked = false)
192 
193         createNoteTaskController()
194             .apply { infoReference.set(expectedInfo) }
195             .onBubbleExpandChanged(
196                 isExpanding = false,
197                 key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
198             )
199 
200         verify(eventLogger).logNoteTaskClosed(expectedInfo)
201         verifyNoMoreInteractions(bubbles, keyguardManager, userManager)
202     }
203 
204     @Test
205     fun onBubbleExpandChanged_expandingAndKeyguardLocked_shouldDoNothing() {
206         val expectedInfo = NOTE_TASK_INFO.copy(isKeyguardLocked = true)
207 
208         createNoteTaskController()
209             .apply { infoReference.set(expectedInfo) }
210             .onBubbleExpandChanged(
211                 isExpanding = true,
212                 key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
213             )
214 
215         verifyNoMoreInteractions(bubbles, keyguardManager, userManager, eventLogger)
216     }
217 
218     @Test
219     fun onBubbleExpandChanged_notExpandingAndKeyguardLocked_shouldDoNothing() {
220         val expectedInfo = NOTE_TASK_INFO.copy(isKeyguardLocked = true)
221 
222         createNoteTaskController()
223             .apply { infoReference.set(expectedInfo) }
224             .onBubbleExpandChanged(
225                 isExpanding = false,
226                 key = Bubble.getAppBubbleKeyForApp(expectedInfo.packageName, expectedInfo.user),
227             )
228 
229         verifyNoMoreInteractions(bubbles, keyguardManager, userManager, eventLogger)
230     }
231 
232     @Test
233     fun onBubbleExpandChanged_notKeyAppBubble_shouldDoNothing() {
234         createNoteTaskController().onBubbleExpandChanged(isExpanding = true, key = "any other key")
235 
236         verifyNoMoreInteractions(bubbles, keyguardManager, userManager, eventLogger)
237     }
238 
239     @Test
240     fun onBubbleExpandChanged_flagDisabled_shouldDoNothing() {
241         createNoteTaskController(isEnabled = false)
242             .onBubbleExpandChanged(
243                 isExpanding = true,
244                 key = Bubble.getAppBubbleKeyForApp(NOTE_TASK_INFO.packageName, NOTE_TASK_INFO.user),
245             )
246 
247         verifyNoMoreInteractions(bubbles, keyguardManager, userManager, eventLogger)
248     }
249 
250     // endregion
251 
252     // region showNoteTask
253     fun showNoteTaskAsUser_keyguardIsLocked_shouldStartActivityWithExpectedUserAndLogUiEvent() {
254         val user10 = UserHandle.of(/* userId= */ 10)
255         val expectedInfo =
256             NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true, user = user10)
257         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
258         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
259 
260         createNoteTaskController()
261             .showNoteTaskAsUser(entryPoint = expectedInfo.entryPoint!!, user = user10)
262 
263         val intentCaptor = argumentCaptor<Intent>()
264         val userCaptor = argumentCaptor<UserHandle>()
265         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
266         assertThat(intentCaptor.value).run {
267             hasAction(ACTION_CREATE_NOTE)
268             hasPackage(NOTE_TASK_PACKAGE_NAME)
269             hasFlags(FLAG_ACTIVITY_NEW_TASK)
270             hasFlags(FLAG_ACTIVITY_MULTIPLE_TASK)
271             hasFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
272             extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
273         }
274         assertThat(userCaptor.value).isEqualTo(user10)
275         verify(eventLogger).logNoteTaskOpened(expectedInfo)
276         verifyNoMoreInteractions(bubbles)
277     }
278 
279     @Test
280     fun showNoteTask_keyguardIsLocked_notesIsClosed_shouldStartActivityAndLogUiEvent() {
281         val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
282         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
283         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
284 
285         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
286 
287         val intentCaptor = argumentCaptor<Intent>()
288         val userCaptor = argumentCaptor<UserHandle>()
289         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
290         assertThat(intentCaptor.value).run {
291             hasAction(ACTION_CREATE_NOTE)
292             hasPackage(NOTE_TASK_PACKAGE_NAME)
293             hasFlags(FLAG_ACTIVITY_NEW_TASK)
294             hasFlags(FLAG_ACTIVITY_MULTIPLE_TASK)
295             hasFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
296             extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
297         }
298         assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
299         verify(eventLogger).logNoteTaskOpened(expectedInfo)
300         verifyNoMoreInteractions(bubbles)
301     }
302 
303     @Test
304     fun showNoteTask_keyguardIsLocked_noteIsOpen_shouldCloseActivityAndLogUiEvent() {
305         val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
306         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
307         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
308         whenever(activityManager.getRunningTasks(anyInt()))
309             .thenReturn(listOf(NOTE_RUNNING_TASK_INFO))
310 
311         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
312 
313         val intentCaptor = argumentCaptor<Intent>()
314         val userCaptor = argumentCaptor<UserHandle>()
315         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
316         assertThat(intentCaptor.value).run {
317             hasAction(ACTION_MAIN)
318             categories().contains(CATEGORY_HOME)
319             hasFlags(FLAG_ACTIVITY_NEW_TASK)
320         }
321         assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
322         verify(eventLogger).logNoteTaskClosed(expectedInfo)
323         verifyNoMoreInteractions(bubbles)
324     }
325 
326     @Test
327     fun showNoteTask_keyguardIsUnlocked_noteIsClosed_shouldStartBubblesWithoutLoggingUiEvent() {
328         val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = false)
329         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
330         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
331 
332         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
333 
334         // Context package name used to create bubble icon from drawable resource id
335         verify(context, atLeastOnce()).packageName
336         verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
337         verifyNoMoreInteractions(eventLogger)
338     }
339 
340     @Test
341     fun showNoteTask_keyguardIsUnlocked_noteIsOpen_shouldStartBubblesWithoutLoggingUiEvent() {
342         val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = false)
343         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
344         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
345         whenever(activityManager.getRunningTasks(anyInt()))
346             .thenReturn(listOf(NOTE_RUNNING_TASK_INFO))
347 
348         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
349 
350         // Context package name used to create bubble icon from drawable resource id
351         verify(context, atLeastOnce()).packageName
352         verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
353         verifyNoMoreInteractions(eventLogger)
354     }
355 
356     @Test
357     fun showNoteTask_defaultUserSet_shouldStartActivityWithExpectedUserAndLogUiEvent() {
358         secureSettings.putIntForUser(
359             /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
360             /* value= */ 10,
361             /* userHandle= */ userTracker.userId,
362         )
363         val user10 = UserHandle.of(/* userId= */ 10)
364 
365         val expectedInfo =
366             NOTE_TASK_INFO.copy(
367                 entryPoint = NoteTaskEntryPoint.TAIL_BUTTON,
368                 isKeyguardLocked = true,
369                 user = user10,
370             )
371         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
372         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
373 
374         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
375 
376         val intentCaptor = argumentCaptor<Intent>()
377         val userCaptor = argumentCaptor<UserHandle>()
378         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
379         intentCaptor.value.let { intent ->
380             assertThat(intent.action).isEqualTo(Intent.ACTION_CREATE_NOTE)
381             assertThat(intent.`package`).isEqualTo(NOTE_TASK_PACKAGE_NAME)
382             assertThat(intent.flags and FLAG_ACTIVITY_NEW_TASK).isEqualTo(FLAG_ACTIVITY_NEW_TASK)
383             assertThat(intent.flags and FLAG_ACTIVITY_MULTIPLE_TASK)
384                 .isEqualTo(FLAG_ACTIVITY_MULTIPLE_TASK)
385             assertThat(intent.flags and FLAG_ACTIVITY_NEW_DOCUMENT)
386                 .isEqualTo(FLAG_ACTIVITY_NEW_DOCUMENT)
387             assertThat(intent.getBooleanExtra(Intent.EXTRA_USE_STYLUS_MODE, false)).isTrue()
388         }
389         assertThat(userCaptor.value).isEqualTo(user10)
390         verify(eventLogger).logNoteTaskOpened(expectedInfo)
391         verifyNoMoreInteractions(bubbles)
392     }
393 
394     @Test
395     fun showNoteTask_bubblesIsNull_shouldDoNothing() {
396         createNoteTaskController(bubbles = null).showNoteTask(entryPoint = TAIL_BUTTON)
397 
398         verifyNoMoreInteractions(bubbles, eventLogger)
399     }
400 
401     @Test
402     fun showNoteTask_intentResolverReturnsNull_shouldShowToast() {
403         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(null)
404         val noteTaskController = spy(createNoteTaskController())
405         doNothing().whenever(noteTaskController).showNoDefaultNotesAppToast()
406 
407         noteTaskController.showNoteTask(entryPoint = TAIL_BUTTON)
408 
409         verify(noteTaskController).showNoDefaultNotesAppToast()
410         verifyNoMoreInteractions(bubbles, eventLogger)
411     }
412 
413     @Test
414     fun showNoteTask_flagDisabled_shouldDoNothing() {
415         createNoteTaskController(isEnabled = false).showNoteTask(entryPoint = TAIL_BUTTON)
416 
417         verifyNoMoreInteractions(bubbles, eventLogger)
418     }
419 
420     @Test
421     fun showNoteTask_userIsLocked_shouldDoNothing() {
422         whenever(userManager.isUserUnlocked).thenReturn(false)
423 
424         createNoteTaskController().showNoteTask(entryPoint = TAIL_BUTTON)
425 
426         verifyNoMoreInteractions(bubbles, eventLogger)
427     }
428 
429     @Test
430     fun showNoteTask_keyboardShortcut_shouldStartActivity() {
431         val expectedInfo =
432             NOTE_TASK_INFO.copy(entryPoint = KEYBOARD_SHORTCUT, isKeyguardLocked = true)
433         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
434         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
435 
436         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
437 
438         val intentCaptor = argumentCaptor<Intent>()
439         val userCaptor = argumentCaptor<UserHandle>()
440         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
441         assertThat(intentCaptor.value).run {
442             hasAction(ACTION_CREATE_NOTE)
443             hasPackage(NOTE_TASK_PACKAGE_NAME)
444             hasFlags(FLAG_ACTIVITY_NEW_TASK)
445             hasFlags(FLAG_ACTIVITY_MULTIPLE_TASK)
446             hasFlags(FLAG_ACTIVITY_NEW_DOCUMENT)
447             extras().bool(EXTRA_USE_STYLUS_MODE).isFalse()
448         }
449         assertThat(userCaptor.value).isEqualTo(userTracker.userHandle)
450         verify(eventLogger).logNoteTaskOpened(expectedInfo)
451         verifyNoMoreInteractions(bubbles)
452     }
453 
454     @Test
455     fun showNoteTask_stylusModePreferred_keyboardShortcut_shouldStartInDefaultUIMode() {
456         `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(1)
457         val expectedInfo =
458             NOTE_TASK_INFO.copy(entryPoint = KEYBOARD_SHORTCUT, isKeyguardLocked = true)
459         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
460         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
461 
462         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
463 
464         val intentCaptor = argumentCaptor<Intent>()
465         val userCaptor = argumentCaptor<UserHandle>()
466         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
467         assertThat(intentCaptor.value).run {
468             hasAction(ACTION_CREATE_NOTE)
469             hasPackage(NOTE_TASK_PACKAGE_NAME)
470             extras().bool(EXTRA_USE_STYLUS_MODE).isFalse()
471         }
472     }
473 
474     @Test
475     fun showNoteTask_stylusModePreferred_quickAffordance_shouldStartInStylusUIMode() {
476         `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(1)
477         val expectedInfo =
478             NOTE_TASK_INFO.copy(entryPoint = QUICK_AFFORDANCE, isKeyguardLocked = true)
479         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
480         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
481 
482         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
483 
484         val intentCaptor = argumentCaptor<Intent>()
485         val userCaptor = argumentCaptor<UserHandle>()
486         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
487         assertThat(intentCaptor.value).run {
488             hasAction(ACTION_CREATE_NOTE)
489             hasPackage(NOTE_TASK_PACKAGE_NAME)
490             extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
491         }
492     }
493 
494     @Test
495     fun showNoteTask_noUIRecommendation_quickAffordance_shouldStartInDefaultUIMode() {
496         `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(0)
497         val expectedInfo =
498             NOTE_TASK_INFO.copy(entryPoint = QUICK_AFFORDANCE, isKeyguardLocked = true)
499         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
500         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
501 
502         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
503 
504         val intentCaptor = argumentCaptor<Intent>()
505         val userCaptor = argumentCaptor<UserHandle>()
506         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
507         assertThat(intentCaptor.value).run {
508             hasAction(ACTION_CREATE_NOTE)
509             hasPackage(NOTE_TASK_PACKAGE_NAME)
510             extras().bool(EXTRA_USE_STYLUS_MODE).isFalse()
511         }
512     }
513 
514     @Test
515     fun showNoteTask_noUIRecommendation_tailButton_shouldStartInStylusUIMode() {
516         `when`(spiedResources.getInteger(R.integer.config_preferredNotesMode)).thenReturn(0)
517         val expectedInfo = NOTE_TASK_INFO.copy(entryPoint = TAIL_BUTTON, isKeyguardLocked = true)
518         whenever(keyguardManager.isKeyguardLocked).thenReturn(expectedInfo.isKeyguardLocked)
519         whenever(resolver.resolveInfo(any(), any(), any())).thenReturn(expectedInfo)
520 
521         createNoteTaskController().showNoteTask(entryPoint = expectedInfo.entryPoint!!)
522 
523         val intentCaptor = argumentCaptor<Intent>()
524         val userCaptor = argumentCaptor<UserHandle>()
525         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
526         assertThat(intentCaptor.value).run {
527             hasAction(ACTION_CREATE_NOTE)
528             hasPackage(NOTE_TASK_PACKAGE_NAME)
529             extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
530         }
531     }
532 
533     // endregion
534 
535     // region setNoteTaskShortcutEnabled
536     @Test
537     fun setNoteTaskShortcutEnabled_setTrue() {
538         createNoteTaskController().setNoteTaskShortcutEnabled(value = true, userTracker.userHandle)
539 
540         val argument = argumentCaptor<ComponentName>()
541         verify(context.packageManager)
542             .setComponentEnabledSetting(
543                 argument.capture(),
544                 eq(COMPONENT_ENABLED_STATE_ENABLED),
545                 eq(PackageManager.DONT_KILL_APP),
546             )
547 
548         assertThat(argument.value.className)
549             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
550     }
551 
552     @Test
553     fun setNoteTaskShortcutEnabled_setFalse() {
554         createNoteTaskController().setNoteTaskShortcutEnabled(value = false, userTracker.userHandle)
555 
556         val argument = argumentCaptor<ComponentName>()
557         verify(context.packageManager)
558             .setComponentEnabledSetting(
559                 argument.capture(),
560                 eq(COMPONENT_ENABLED_STATE_DISABLED),
561                 eq(PackageManager.DONT_KILL_APP),
562             )
563 
564         assertThat(argument.value.className)
565             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
566     }
567 
568     @Test
569     fun setNoteTaskShortcutEnabled_workProfileUser_setTrue() {
570         whenever(context.createContextAsUser(eq(workUserInfo.userHandle), any()))
571             .thenReturn(workProfileContext)
572         whenever(workProfileContext.packageManager).thenReturn(workProfilePackageManager)
573         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
574 
575         createNoteTaskController().setNoteTaskShortcutEnabled(value = true, workUserInfo.userHandle)
576 
577         val argument = argumentCaptor<ComponentName>()
578         verify(workProfilePackageManager)
579             .setComponentEnabledSetting(
580                 argument.capture(),
581                 eq(COMPONENT_ENABLED_STATE_ENABLED),
582                 eq(PackageManager.DONT_KILL_APP),
583             )
584 
585         assertThat(argument.value.className)
586             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
587     }
588 
589     @Test
590     fun setNoteTaskShortcutEnabled_workProfileUser_setFalse() {
591         whenever(context.createContextAsUser(eq(workUserInfo.userHandle), any()))
592             .thenReturn(workProfileContext)
593         whenever(workProfileContext.packageManager).thenReturn(workProfilePackageManager)
594         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
595 
596         createNoteTaskController()
597             .setNoteTaskShortcutEnabled(value = false, workUserInfo.userHandle)
598 
599         val argument = argumentCaptor<ComponentName>()
600         verify(workProfilePackageManager)
601             .setComponentEnabledSetting(
602                 argument.capture(),
603                 eq(COMPONENT_ENABLED_STATE_DISABLED),
604                 eq(PackageManager.DONT_KILL_APP),
605             )
606 
607         assertThat(argument.value.className)
608             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
609     }
610 
611     // endregion
612 
613     // region keyguard policy
614     @Test
615     fun showNoteTask_keyguardLocked_keyguardDisableShortcutsAll_shouldDoNothing() {
616         whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
617         whenever(
618                 devicePolicyManager.getKeyguardDisabledFeatures(
619                     /* admin= */ eq(null),
620                     /* userHandle= */ anyInt(),
621                 )
622             )
623             .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
624 
625         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
626 
627         verifyNoMoreInteractions(bubbles, eventLogger)
628     }
629 
630     @Test
631     fun showNoteTask_keyguardLocked_keyguardDisableFeaturesAll_shouldDoNothing() {
632         whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
633         whenever(
634                 devicePolicyManager.getKeyguardDisabledFeatures(
635                     /* admin= */ eq(null),
636                     /* userHandle= */ anyInt(),
637                 )
638             )
639             .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
640 
641         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
642 
643         verifyNoMoreInteractions(bubbles, eventLogger)
644     }
645 
646     @Test
647     fun showNoteTask_keyguardUnlocked_keyguardDisableShortcutsAll_shouldStartBubble() {
648         whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
649         whenever(
650                 devicePolicyManager.getKeyguardDisabledFeatures(
651                     /* admin= */ eq(null),
652                     /* userHandle= */ anyInt(),
653                 )
654             )
655             .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
656 
657         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
658 
659         verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
660     }
661 
662     @Test
663     fun showNoteTask_keyguardUnlocked_keyguardDisableFeaturesAll_shouldStartBubble() {
664         whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
665         whenever(
666                 devicePolicyManager.getKeyguardDisabledFeatures(
667                     /* admin= */ eq(null),
668                     /* userHandle= */ anyInt(),
669                 )
670             )
671             .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
672 
673         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
674 
675         verifyNoteTaskOpenInBubbleInUser(userTracker.userHandle)
676     }
677 
678     // endregion
679 
680     // region showNoteTask, COPE devices
681     @Suppress("ktlint:standard:max-line-length")
682     @Test
683     fun showNoteTask_copeDevices_quickAffordanceEntryPoint_managedProfileNotFound_shouldStartBubbleInTheMainProfile() {
684         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
685         userTracker.set(listOf(mainUserInfo), mainAndWorkProfileUsers.indexOf(mainUserInfo))
686 
687         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
688 
689         verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
690     }
691 
692     @Test
693     fun showNoteTask_copeDevices_quickAffordanceEntryPoint_shouldStartBubbleInWorkProfile() {
694         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
695         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
696 
697         createNoteTaskController().showNoteTask(entryPoint = QUICK_AFFORDANCE)
698 
699         verifyNoteTaskOpenInBubbleInUser(workUserInfo.userHandle)
700     }
701 
702     @Test
703     fun showNoteTask_copeDevices_tailButtonEntryPoint_shouldStartBubbleInTheUserSelectedUser() {
704         secureSettings.putIntForUser(
705             /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
706             /* value= */ mainUserInfo.id,
707             /* userHandle= */ userTracker.userId,
708         )
709         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
710         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
711 
712         createNoteTaskController().showNoteTask(entryPoint = TAIL_BUTTON)
713 
714         verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
715     }
716 
717     @Test
718     fun showNoteTask_copeDevices_shortcutsEntryPoint_shouldStartBubbleInTheSelectedUser() {
719         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
720         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
721 
722         createNoteTaskController().showNoteTask(entryPoint = WIDGET_PICKER_SHORTCUT)
723 
724         verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
725     }
726 
727     @Test
728     fun showNoteTask_copeDevices_appClipsEntryPoint_shouldStartBubbleInTheSelectedUser() {
729         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
730         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
731 
732         createNoteTaskController().showNoteTask(entryPoint = APP_CLIPS)
733 
734         verifyNoteTaskOpenInBubbleInUser(mainUserInfo.userHandle)
735     }
736 
737     // endregion
738 
739     private fun verifyNoteTaskOpenInBubbleInUser(userHandle: UserHandle) {
740         val intentCaptor = argumentCaptor<Intent>()
741         val iconCaptor = argumentCaptor<Icon>()
742         verify(bubbles)
743             .showOrHideAppBubble(capture(intentCaptor), eq(userHandle), capture(iconCaptor))
744         assertThat(intentCaptor.value).run {
745             hasAction(ACTION_CREATE_NOTE)
746             hasPackage(NOTE_TASK_PACKAGE_NAME)
747             hasFlags(FLAG_ACTIVITY_NEW_TASK)
748             extras().bool(EXTRA_USE_STYLUS_MODE).isTrue()
749         }
750         iconCaptor.value?.let { icon ->
751             assertNotNull(icon)
752             assertThat(icon.resId).isEqualTo(R.drawable.ic_note_task_shortcut_widget)
753         }
754     }
755 
756     // region onRoleHoldersChanged
757     @Test
758     fun onRoleHoldersChanged_notNotesRole_doNothing() {
759         val user = UserHandle.of(0)
760 
761         createNoteTaskController(isEnabled = true).onRoleHoldersChanged("NOT_NOTES", user)
762 
763         verify(context, never()).startActivityAsUser(any(), any())
764     }
765 
766     @Test
767     fun onRoleHoldersChanged_notesRole_shouldUpdateShortcuts() {
768         val user = userTracker.userHandle
769         val controller = spy(createNoteTaskController())
770         doNothing().whenever(controller).updateNoteTaskAsUser(any())
771 
772         controller.onRoleHoldersChanged(ROLE_NOTES, user)
773 
774         verify(controller).updateNoteTaskAsUser(user)
775     }
776 
777     // endregion
778 
779     // region updateNoteTaskAsUser
780     @Test
781     fun updateNoteTaskAsUser_sameUser_shouldUpdateShortcuts() {
782         val user = UserHandle.CURRENT
783         val controller = spy(createNoteTaskController())
784         doNothing().whenever(controller).launchUpdateNoteTaskAsUser(any())
785         whenever(controller.getCurrentRunningUser()).thenReturn(user)
786 
787         controller.updateNoteTaskAsUser(user)
788 
789         verify(controller).launchUpdateNoteTaskAsUser(user)
790         verify(context, never()).startServiceAsUser(any(), any())
791     }
792 
793     @Test
794     fun updateNoteTaskAsUser_differentUser_shouldUpdateShortcutsInUserProcess() {
795         val user = UserHandle.CURRENT
796         val controller = spy(createNoteTaskController(isEnabled = true))
797         doNothing().whenever(controller).launchUpdateNoteTaskAsUser(any())
798         whenever(controller.getCurrentRunningUser()).thenReturn(UserHandle.SYSTEM)
799 
800         controller.updateNoteTaskAsUser(user)
801 
802         verify(controller, never()).launchUpdateNoteTaskAsUser(any())
803         val intent = withArgCaptor { verify(context).startServiceAsUser(capture(), eq(user)) }
804         assertThat(intent).hasComponentClass(NoteTaskControllerUpdateService::class.java)
805     }
806 
807     // endregion
808 
809     // region internalUpdateNoteTaskAsUser
810     @Test
811     fun updateNoteTaskAsUserInternal_withNotesRole_withShortcuts_shouldUpdateShortcuts() {
812         createNoteTaskController(isEnabled = true)
813             .launchUpdateNoteTaskAsUser(userTracker.userHandle)
814         testScope.runCurrent()
815 
816         val actualComponent = argumentCaptor<ComponentName>()
817         verify(context.packageManager)
818             .setComponentEnabledSetting(
819                 actualComponent.capture(),
820                 eq(COMPONENT_ENABLED_STATE_ENABLED),
821                 eq(PackageManager.DONT_KILL_APP),
822             )
823         assertThat(actualComponent.value.className)
824             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
825         verify(shortcutManager, never()).disableShortcuts(any())
826         verify(shortcutManager).enableShortcuts(listOf(SHORTCUT_ID))
827         val shortcutInfo = withArgCaptor { verify(shortcutManager).updateShortcuts(capture()) }
828         with(shortcutInfo.first()) {
829             assertThat(id).isEqualTo(SHORTCUT_ID)
830             assertThat(intent).run {
831                 hasComponentClass(LaunchNoteTaskActivity::class.java)
832                 hasAction(ACTION_CREATE_NOTE)
833             }
834             assertThat(shortLabel).isEqualTo(NOTE_TASK_SHORT_LABEL)
835             assertThat(longLabel).isEqualTo(NOTE_TASK_LONG_LABEL)
836             assertThat(isLongLived).isEqualTo(true)
837             assertThat(icon?.resId).isEqualTo(R.drawable.ic_note_task_shortcut_widget)
838             assertThat(extras?.getString(EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE))
839                 .isEqualTo(NOTE_TASK_PACKAGE_NAME)
840         }
841     }
842 
843     @Test
844     fun updateNoteTaskAsUserInternal_noNotesRole_shouldDisableShortcuts() {
845         whenever(roleManager.getRoleHoldersAsUser(ROLE_NOTES, userTracker.userHandle))
846             .thenReturn(emptyList())
847 
848         createNoteTaskController(isEnabled = true)
849             .launchUpdateNoteTaskAsUser(userTracker.userHandle)
850         testScope.runCurrent()
851 
852         val argument = argumentCaptor<ComponentName>()
853         verify(context.packageManager)
854             .setComponentEnabledSetting(
855                 argument.capture(),
856                 eq(COMPONENT_ENABLED_STATE_DISABLED),
857                 eq(PackageManager.DONT_KILL_APP),
858             )
859         assertThat(argument.value.className)
860             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
861         verify(shortcutManager).disableShortcuts(listOf(SHORTCUT_ID))
862         verify(shortcutManager, never()).enableShortcuts(any())
863         verify(shortcutManager, never()).updateShortcuts(any())
864     }
865 
866     @Test
867     fun updateNoteTaskAsUserInternal_flagDisabled_shouldDisableShortcuts() {
868         createNoteTaskController(isEnabled = false)
869             .launchUpdateNoteTaskAsUser(userTracker.userHandle)
870         testScope.runCurrent()
871 
872         val argument = argumentCaptor<ComponentName>()
873         verify(context.packageManager)
874             .setComponentEnabledSetting(
875                 argument.capture(),
876                 eq(COMPONENT_ENABLED_STATE_DISABLED),
877                 eq(PackageManager.DONT_KILL_APP),
878             )
879         assertThat(argument.value.className)
880             .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
881         verify(shortcutManager).disableShortcuts(listOf(SHORTCUT_ID))
882         verify(shortcutManager, never()).enableShortcuts(any())
883         verify(shortcutManager, never()).updateShortcuts(any())
884     }
885 
886     // endregion
887 
888     // startregion updateNoteTaskForAllUsers
889     @Test
890     fun updateNoteTaskForAllUsers_shouldRunUpdateForCurrentUserAndProfiles() {
891         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
892         val controller = spy(createNoteTaskController())
893         doNothing().whenever(controller).updateNoteTaskAsUser(any())
894 
895         controller.updateNoteTaskForCurrentUserAndManagedProfiles()
896 
897         verify(controller).updateNoteTaskAsUser(mainUserInfo.userHandle)
898         verify(controller).updateNoteTaskAsUser(workUserInfo.userHandle)
899     }
900 
901     // endregion
902 
903     // region getUserForHandlingNotesTaking
904     @Test
905     fun getUserForHandlingNotesTaking_cope_quickAffordance_shouldReturnWorkProfileUser() {
906         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
907         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
908 
909         val user = createNoteTaskController().getUserForHandlingNotesTaking(QUICK_AFFORDANCE)
910 
911         assertThat(user).isEqualTo(UserHandle.of(workUserInfo.id))
912     }
913 
914     @Suppress("ktlint:standard:max-line-length")
915     @Test
916     fun getUserForHandlingNotesTaking_cope_userSelectedWorkProfile_tailButton_shouldReturnWorkProfileUser() {
917         secureSettings.putIntForUser(
918             /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
919             /* value= */ workUserInfo.id,
920             /* userHandle= */ userTracker.userId,
921         )
922         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
923         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
924 
925         val user = createNoteTaskController().getUserForHandlingNotesTaking(TAIL_BUTTON)
926 
927         assertThat(user).isEqualTo(UserHandle.of(workUserInfo.id))
928     }
929 
930     @Suppress("ktlint:standard:max-line-length")
931     @Test
932     fun getUserForHandlingNotesTaking_cope_userSelectedMainProfile_tailButton_shouldReturnMainProfileUser() {
933         secureSettings.putIntForUser(
934             /* name= */ Settings.Secure.DEFAULT_NOTE_TASK_PROFILE,
935             /* value= */ mainUserInfo.id,
936             /* userHandle= */ userTracker.userId,
937         )
938         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
939         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
940 
941         val user = createNoteTaskController().getUserForHandlingNotesTaking(TAIL_BUTTON)
942 
943         assertThat(user).isEqualTo(UserHandle.of(mainUserInfo.id))
944     }
945 
946     @Test
947     fun getUserForHandlingNotesTaking_cope_appClip_shouldReturnCurrentUser() {
948         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
949         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
950 
951         val user = createNoteTaskController().getUserForHandlingNotesTaking(APP_CLIPS)
952 
953         assertThat(user).isEqualTo(UserHandle.of(mainUserInfo.id))
954     }
955 
956     @Test
957     fun getUserForHandlingNotesTaking_noManagement_quickAffordance_shouldReturnCurrentUser() {
958         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
959 
960         val user = createNoteTaskController().getUserForHandlingNotesTaking(QUICK_AFFORDANCE)
961 
962         assertThat(user).isEqualTo(UserHandle.of(mainUserInfo.id))
963     }
964 
965     @Test
966     fun getUserForHandlingNotesTaking_noManagement_tailButton_shouldReturnCurrentUser() {
967         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
968 
969         val user = createNoteTaskController().getUserForHandlingNotesTaking(TAIL_BUTTON)
970 
971         assertThat(user).isEqualTo(UserHandle.of(mainUserInfo.id))
972     }
973 
974     @Test
975     fun getUserForHandlingNotesTaking_noManagement_appClip_shouldReturnCurrentUser() {
976         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
977 
978         val user = createNoteTaskController().getUserForHandlingNotesTaking(APP_CLIPS)
979 
980         assertThat(user).isEqualTo(UserHandle.of(mainUserInfo.id))
981     }
982 
983     // endregion
984 
985     // startregion startNotesRoleSetting
986     @Test
987     fun startNotesRoleSetting_cope_quickAffordance_shouldStartNoteRoleIntentWithWorkProfileUser() {
988         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
989         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
990 
991         createNoteTaskController().startNotesRoleSetting(context, QUICK_AFFORDANCE)
992 
993         val intentCaptor = argumentCaptor<Intent>()
994         val userCaptor = argumentCaptor<UserHandle>()
995         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
996         assertThat(intentCaptor.value).hasAction(ACTION_MANAGE_DEFAULT_APP)
997         assertThat(userCaptor.value).isEqualTo(UserHandle.of(workUserInfo.id))
998     }
999 
1000     @Test
1001     fun startNotesRoleSetting_cope_nullEntryPoint_shouldStartNoteRoleIntentWithCurrentUser() {
1002         whenever(devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile).thenReturn(true)
1003         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
1004 
1005         createNoteTaskController().startNotesRoleSetting(context, entryPoint = null)
1006 
1007         val intentCaptor = argumentCaptor<Intent>()
1008         val userCaptor = argumentCaptor<UserHandle>()
1009         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
1010         assertThat(intentCaptor.value).hasAction(ACTION_MANAGE_DEFAULT_APP)
1011         assertThat(userCaptor.value).isEqualTo(UserHandle.of(mainUserInfo.id))
1012     }
1013 
1014     @Suppress("ktlint:standard:max-line-length")
1015     @Test
1016     fun startNotesRoleSetting_noManagement_quickAffordance_shouldStartNoteRoleIntentWithCurrentUser() {
1017         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
1018 
1019         createNoteTaskController().startNotesRoleSetting(context, QUICK_AFFORDANCE)
1020 
1021         val intentCaptor = argumentCaptor<Intent>()
1022         val userCaptor = argumentCaptor<UserHandle>()
1023         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
1024         assertThat(intentCaptor.value).hasAction(ACTION_MANAGE_DEFAULT_APP)
1025         assertThat(userCaptor.value).isEqualTo(UserHandle.of(mainUserInfo.id))
1026     }
1027 
1028     @Suppress("ktlint:standard:max-line-length")
1029     @Test
1030     fun startNotesRoleSetting_noManagement_nullEntryPoint_shouldStartNoteRoleIntentWithCurrentUser() {
1031         userTracker.set(mainAndWorkProfileUsers, mainAndWorkProfileUsers.indexOf(mainUserInfo))
1032 
1033         createNoteTaskController().startNotesRoleSetting(context, entryPoint = null)
1034 
1035         val intentCaptor = argumentCaptor<Intent>()
1036         val userCaptor = argumentCaptor<UserHandle>()
1037         verify(context).startActivityAsUser(capture(intentCaptor), capture(userCaptor))
1038         assertThat(intentCaptor.value).hasAction(ACTION_MANAGE_DEFAULT_APP)
1039         assertThat(userCaptor.value).isEqualTo(UserHandle.of(mainUserInfo.id))
1040     }
1041 
1042     // endregion
1043 
1044     private companion object {
1045         const val NOTE_TASK_SHORT_LABEL = "Note-taking"
1046         const val NOTE_TASK_LONG_LABEL = "Note-taking, App"
1047         const val NOTE_TASK_ACTIVITY_NAME = "NoteTaskActivity"
1048         const val NOTE_TASK_PACKAGE_NAME = "com.android.note.app"
1049         const val NOTE_TASK_UID = 123456
1050 
1051         private val NOTE_TASK_INFO =
1052             NoteTaskInfo(
1053                 packageName = NOTE_TASK_PACKAGE_NAME,
1054                 uid = NOTE_TASK_UID,
1055                 user = UserHandle.of(0),
1056             )
1057         private val NOTE_RUNNING_TASK_INFO =
1058             ActivityManager.RunningTaskInfo().apply {
1059                 topActivity = ComponentName(NOTE_TASK_PACKAGE_NAME, NOTE_TASK_ACTIVITY_NAME)
1060             }
1061 
1062         val mainUserInfo =
1063             UserInfo(/* id= */ 0, /* name= */ "primary", /* flags= */ UserInfo.FLAG_MAIN)
1064         val workUserInfo =
1065             UserInfo(/* id= */ 10, /* name= */ "work", /* flags= */ UserInfo.FLAG_PROFILE)
1066         val mainAndWorkProfileUsers = listOf(mainUserInfo, workUserInfo)
1067     }
1068 }
1069