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