1 /* 2 * 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 17 package com.android.systemui.qs; 18 19 import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.argThat; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.ArgumentMatchers.isNull; 26 import static org.mockito.Mockito.mock; 27 import static org.mockito.Mockito.never; 28 import static org.mockito.Mockito.times; 29 import static org.mockito.Mockito.verify; 30 31 import android.app.IActivityManager; 32 import android.app.IForegroundServiceObserver; 33 import android.app.job.IUserVisibleJobObserver; 34 import android.app.job.JobScheduler; 35 import android.app.job.UserVisibleJobSummary; 36 import android.content.BroadcastReceiver; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.content.pm.PackageManager; 40 import android.content.pm.UserInfo; 41 import android.os.Binder; 42 import android.os.RemoteException; 43 import android.os.UserHandle; 44 import android.provider.DeviceConfig; 45 import android.testing.AndroidTestingRunner; 46 import android.testing.TestableLooper; 47 48 import androidx.test.filters.SmallTest; 49 50 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; 51 import com.android.systemui.SysuiTestCase; 52 import com.android.systemui.animation.DialogLaunchAnimator; 53 import com.android.systemui.broadcast.BroadcastDispatcher; 54 import com.android.systemui.dump.DumpManager; 55 import com.android.systemui.settings.UserTracker; 56 import com.android.systemui.util.DeviceConfigProxyFake; 57 import com.android.systemui.util.concurrency.FakeExecutor; 58 import com.android.systemui.util.time.FakeSystemClock; 59 60 import org.junit.Assert; 61 import org.junit.Before; 62 import org.junit.Test; 63 import org.junit.runner.RunWith; 64 import org.mockito.ArgumentCaptor; 65 import org.mockito.ArgumentMatchers; 66 import org.mockito.InOrder; 67 import org.mockito.Mock; 68 import org.mockito.Mockito; 69 import org.mockito.MockitoAnnotations; 70 71 import java.util.ArrayList; 72 import java.util.List; 73 74 @RunWith(AndroidTestingRunner.class) 75 @TestableLooper.RunWithLooper 76 @SmallTest 77 public class FgsManagerControllerTest extends SysuiTestCase { 78 79 FakeSystemClock mSystemClock; 80 FakeExecutor mMainExecutor; 81 FakeExecutor mBackgroundExecutor; 82 DeviceConfigProxyFake mDeviceConfigProxyFake; 83 84 @Mock 85 IActivityManager mIActivityManager; 86 @Mock 87 JobScheduler mJobScheduler; 88 @Mock 89 PackageManager mPackageManager; 90 @Mock 91 UserTracker mUserTracker; 92 @Mock 93 DialogLaunchAnimator mDialogLaunchAnimator; 94 @Mock 95 BroadcastDispatcher mBroadcastDispatcher; 96 @Mock 97 DumpManager mDumpManager; 98 99 private FgsManagerController mFmc; 100 101 private IForegroundServiceObserver mIForegroundServiceObserver; 102 private IUserVisibleJobObserver mIUserVisibleJobObserver; 103 private UserTracker.Callback mUserTrackerCallback; 104 private BroadcastReceiver mShowFgsManagerReceiver; 105 private InOrder mJobSchedulerInOrder; 106 107 private List<UserInfo> mUserProfiles; 108 109 @Before setUp()110 public void setUp() throws RemoteException { 111 MockitoAnnotations.initMocks(this); 112 113 mDeviceConfigProxyFake = new DeviceConfigProxyFake(); 114 mSystemClock = new FakeSystemClock(); 115 mMainExecutor = new FakeExecutor(mSystemClock); 116 mBackgroundExecutor = new FakeExecutor(mSystemClock); 117 118 mUserProfiles = new ArrayList<>(); 119 Mockito.doReturn(mUserProfiles).when(mUserTracker).getUserProfiles(); 120 121 mJobSchedulerInOrder = Mockito.inOrder(mJobScheduler); 122 123 mFmc = createFgsManagerController(); 124 } 125 126 @Test testNumPackages()127 public void testNumPackages() throws RemoteException { 128 setUserProfiles(0); 129 130 Binder b1 = new Binder(); 131 Binder b2 = new Binder(); 132 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 133 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, true); 134 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 135 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, true); 136 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 137 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, false); 138 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 139 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, false); 140 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 141 } 142 143 @Test testNumPackages_jobs()144 public void testNumPackages_jobs() throws RemoteException { 145 setUserProfiles(0); 146 setShowUserVisibleJobs(true); 147 148 UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, "pkg1", 0, "pkg1", null, 0); 149 UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, "pkg2", 0, "pkg2", null, 1); 150 // pkg2 is performing work on behalf of pkg3. Since pkg2 will show the notification 151 // It should be the one shown in TaskManager. 152 UserVisibleJobSummary j3 = new UserVisibleJobSummary(1, "pkg2", 0, "pkg3", null, 3); 153 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 154 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true); 155 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 156 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, true); 157 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 158 // Job3 starts running. The source package (pkg3) shouldn't matter. Since pkg2 is 159 // already running, the running package count shouldn't increase. 160 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, true); 161 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 162 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, false); 163 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 164 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, false); 165 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 166 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, false); 167 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 168 } 169 170 @Test testNumPackages_FgsAndJobs()171 public void testNumPackages_FgsAndJobs() throws RemoteException { 172 setUserProfiles(0); 173 setShowUserVisibleJobs(true); 174 175 Binder b1 = new Binder(); 176 Binder b2 = new Binder(); 177 UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, "pkg1", 0, "pkg1", null, 0); 178 UserVisibleJobSummary j3 = new UserVisibleJobSummary(1, "pkg3", 0, "pkg3", null, 1); 179 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 180 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, true); 181 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 182 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, true); 183 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 184 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true); 185 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 186 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, true); 187 Assert.assertEquals(3, mFmc.getNumRunningPackages()); 188 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, false); 189 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 190 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j3, false); 191 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 192 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, false); 193 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 194 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, false); 195 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 196 } 197 198 @Test testNumPackagesDoesNotChangeWhenSecondFgsIsStarted()199 public void testNumPackagesDoesNotChangeWhenSecondFgsIsStarted() throws RemoteException { 200 setUserProfiles(0); 201 202 // Different tokens == different services 203 Binder b1 = new Binder(); 204 Binder b2 = new Binder(); 205 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 206 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, true); 207 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 208 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg1", 0, true); 209 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 210 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, false); 211 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 212 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg1", 0, false); 213 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 214 } 215 216 @Test testNumPackagesListener()217 public void testNumPackagesListener() throws RemoteException { 218 setUserProfiles(0); 219 220 FgsManagerController.OnNumberOfPackagesChangedListener onNumberOfPackagesChangedListener = 221 Mockito.mock(FgsManagerController.OnNumberOfPackagesChangedListener.class); 222 223 mFmc.addOnNumberOfPackagesChangedListener(onNumberOfPackagesChangedListener); 224 225 Binder b1 = new Binder(); 226 Binder b2 = new Binder(); 227 228 verify(onNumberOfPackagesChangedListener, never()).onNumberOfPackagesChanged(anyInt()); 229 230 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, true); 231 mBackgroundExecutor.advanceClockToLast(); 232 mBackgroundExecutor.runAllReady(); 233 verify(onNumberOfPackagesChangedListener).onNumberOfPackagesChanged(1); 234 235 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, true); 236 mBackgroundExecutor.advanceClockToLast(); 237 mBackgroundExecutor.runAllReady(); 238 verify(onNumberOfPackagesChangedListener).onNumberOfPackagesChanged(2); 239 240 mIForegroundServiceObserver.onForegroundStateChanged(b1, "pkg1", 0, false); 241 mBackgroundExecutor.advanceClockToLast(); 242 mBackgroundExecutor.runAllReady(); 243 verify(onNumberOfPackagesChangedListener, times(2)).onNumberOfPackagesChanged(1); 244 245 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, false); 246 mBackgroundExecutor.advanceClockToLast(); 247 mBackgroundExecutor.runAllReady(); 248 verify(onNumberOfPackagesChangedListener).onNumberOfPackagesChanged(0); 249 } 250 251 @Test testChangesSinceLastDialog()252 public void testChangesSinceLastDialog() throws RemoteException { 253 setUserProfiles(0); 254 255 Assert.assertFalse(mFmc.getNewChangesSinceDialogWasDismissed()); 256 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg", 0, true); 257 Assert.assertTrue(mFmc.getNewChangesSinceDialogWasDismissed()); 258 } 259 260 @Test testProfilePackagesCounted()261 public void testProfilePackagesCounted() throws RemoteException { 262 setUserProfiles(0, 10); 263 264 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg1", 0, true); 265 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg2", 10, true); 266 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 267 } 268 269 @Test testSecondaryUserPackagesAreNotCounted()270 public void testSecondaryUserPackagesAreNotCounted() throws RemoteException { 271 setUserProfiles(0); 272 273 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg1", 0, true); 274 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg2", 10, true); 275 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 276 } 277 278 @Test testSecondaryUserPackagesAreCountedWhenUserSwitch()279 public void testSecondaryUserPackagesAreCountedWhenUserSwitch() throws RemoteException { 280 setUserProfiles(0); 281 282 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg1", 0, true); 283 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg2", 10, true); 284 mIForegroundServiceObserver.onForegroundStateChanged(new Binder(), "pkg3", 10, true); 285 286 Assert.assertEquals(1, mFmc.getNumRunningPackages()); 287 288 setUserProfiles(10); 289 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 290 } 291 292 @Test testButtonVisibilityOnShowAllowlistButtonFlagChange()293 public void testButtonVisibilityOnShowAllowlistButtonFlagChange() throws Exception { 294 setUserProfiles(0); 295 setBackgroundRestrictionExemptionReason("pkg", 12345, REASON_ALLOWLISTED_PACKAGE); 296 297 final Binder binder = new Binder(); 298 setShowStopButtonForUserAllowlistedApps(true); 299 mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true); 300 Assert.assertEquals(1, mFmc.visibleButtonsCount()); 301 302 mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, false); 303 Assert.assertEquals(0, mFmc.visibleButtonsCount()); 304 305 setShowStopButtonForUserAllowlistedApps(false); 306 mIForegroundServiceObserver.onForegroundStateChanged(binder, "pkg", 0, true); 307 Assert.assertEquals(0, mFmc.visibleButtonsCount()); 308 } 309 310 @Test testShowUserVisibleJobsOnCreation()311 public void testShowUserVisibleJobsOnCreation() { 312 // Test when the default is on. 313 mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 314 SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, 315 "true", false); 316 FgsManagerController fmc = new FgsManagerControllerImpl( 317 mContext, 318 mMainExecutor, 319 mBackgroundExecutor, 320 mSystemClock, 321 mIActivityManager, 322 mJobScheduler, 323 mPackageManager, 324 mUserTracker, 325 mDeviceConfigProxyFake, 326 mDialogLaunchAnimator, 327 mBroadcastDispatcher, 328 mDumpManager 329 ); 330 fmc.init(); 331 Assert.assertTrue(fmc.getIncludesUserVisibleJobs()); 332 ArgumentCaptor<IUserVisibleJobObserver> iUserVisibleJobObserverArgumentCaptor = 333 ArgumentCaptor.forClass(IUserVisibleJobObserver.class); 334 mJobSchedulerInOrder.verify(mJobScheduler) 335 .registerUserVisibleJobObserver(iUserVisibleJobObserverArgumentCaptor.capture()); 336 Assert.assertNotNull(iUserVisibleJobObserverArgumentCaptor.getValue()); 337 338 // Test when the default is off. 339 mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 340 SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, 341 "false", false); 342 fmc = new FgsManagerControllerImpl( 343 mContext, 344 mMainExecutor, 345 mBackgroundExecutor, 346 mSystemClock, 347 mIActivityManager, 348 mJobScheduler, 349 mPackageManager, 350 mUserTracker, 351 mDeviceConfigProxyFake, 352 mDialogLaunchAnimator, 353 mBroadcastDispatcher, 354 mDumpManager 355 ); 356 fmc.init(); 357 Assert.assertFalse(fmc.getIncludesUserVisibleJobs()); 358 mJobSchedulerInOrder.verify(mJobScheduler, never()).registerUserVisibleJobObserver(any()); 359 } 360 361 @Test testShowUserVisibleJobsToggling()362 public void testShowUserVisibleJobsToggling() throws Exception { 363 setUserProfiles(0); 364 setShowUserVisibleJobs(true); 365 366 // pkg1 has only job 367 // pkg2 has both job and fgs 368 // pkg3 has only fgs 369 UserVisibleJobSummary j1 = new UserVisibleJobSummary(0, "pkg1", 0, "pkg1", null, 0); 370 UserVisibleJobSummary j2 = new UserVisibleJobSummary(1, "pkg2", 0, "pkg2", null, 1); 371 Binder b2 = new Binder(); 372 Binder b3 = new Binder(); 373 374 Assert.assertEquals(0, mFmc.getNumRunningPackages()); 375 mIForegroundServiceObserver.onForegroundStateChanged(b2, "pkg2", 0, true); 376 mIForegroundServiceObserver.onForegroundStateChanged(b3, "pkg3", 0, true); 377 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 378 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true); 379 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, true); 380 Assert.assertEquals(3, mFmc.getNumRunningPackages()); 381 382 // Turn off the flag, confirm the number of packages is updated properly. 383 setShowUserVisibleJobs(false); 384 // Only pkg1 should be removed since the other two have fgs 385 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 386 387 setShowUserVisibleJobs(true); 388 389 Assert.assertEquals(2, mFmc.getNumRunningPackages()); 390 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j1, true); 391 mIUserVisibleJobObserver.onUserVisibleJobStateChanged(j2, true); 392 Assert.assertEquals(3, mFmc.getNumRunningPackages()); 393 } 394 setShowStopButtonForUserAllowlistedApps(boolean enable)395 private void setShowStopButtonForUserAllowlistedApps(boolean enable) { 396 mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 397 SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_STOP_BUTTON_FOR_USER_ALLOWLISTED_APPS, 398 enable ? "true" : "false", false); 399 mBackgroundExecutor.advanceClockToLast(); 400 mBackgroundExecutor.runAllReady(); 401 } 402 setShowUserVisibleJobs(boolean enable)403 private void setShowUserVisibleJobs(boolean enable) { 404 if (mFmc.getIncludesUserVisibleJobs() == enable) { 405 // No change. 406 return; 407 } 408 409 mDeviceConfigProxyFake.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, 410 SystemUiDeviceConfigFlags.TASK_MANAGER_SHOW_USER_VISIBLE_JOBS, 411 enable ? "true" : "false", false); 412 mBackgroundExecutor.advanceClockToLast(); 413 mBackgroundExecutor.runAllReady(); 414 415 ArgumentCaptor<IUserVisibleJobObserver> iUserVisibleJobObserverArgumentCaptor = 416 ArgumentCaptor.forClass(IUserVisibleJobObserver.class); 417 if (enable) { 418 mJobSchedulerInOrder.verify(mJobScheduler).registerUserVisibleJobObserver( 419 iUserVisibleJobObserverArgumentCaptor.capture() 420 ); 421 mIUserVisibleJobObserver = iUserVisibleJobObserverArgumentCaptor.getValue(); 422 } else { 423 mJobSchedulerInOrder.verify(mJobScheduler).unregisterUserVisibleJobObserver( 424 eq(mIUserVisibleJobObserver) 425 ); 426 mIUserVisibleJobObserver = null; 427 } 428 } 429 setBackgroundRestrictionExemptionReason(String pkgName, int uid, int reason)430 private void setBackgroundRestrictionExemptionReason(String pkgName, int uid, int reason) 431 throws Exception { 432 Mockito.doReturn(uid) 433 .when(mPackageManager) 434 .getPackageUidAsUser(pkgName, UserHandle.getUserId(uid)); 435 Mockito.doReturn(reason) 436 .when(mIActivityManager) 437 .getBackgroundRestrictionExemptionReason(uid); 438 } 439 createFgsManagerController()440 FgsManagerController createFgsManagerController() throws RemoteException { 441 ArgumentCaptor<IForegroundServiceObserver> iForegroundServiceObserverArgumentCaptor = 442 ArgumentCaptor.forClass(IForegroundServiceObserver.class); 443 ArgumentCaptor<UserTracker.Callback> userTrackerCallbackArgumentCaptor = 444 ArgumentCaptor.forClass(UserTracker.Callback.class); 445 ArgumentCaptor<BroadcastReceiver> showFgsManagerReceiverArgumentCaptor = 446 ArgumentCaptor.forClass(BroadcastReceiver.class); 447 448 FgsManagerController result = new FgsManagerControllerImpl( 449 mContext, 450 mMainExecutor, 451 mBackgroundExecutor, 452 mSystemClock, 453 mIActivityManager, 454 mJobScheduler, 455 mPackageManager, 456 mUserTracker, 457 mDeviceConfigProxyFake, 458 mDialogLaunchAnimator, 459 mBroadcastDispatcher, 460 mDumpManager 461 ); 462 result.init(); 463 464 verify(mIActivityManager).registerForegroundServiceObserver( 465 iForegroundServiceObserverArgumentCaptor.capture() 466 ); 467 verify(mUserTracker).addCallback( 468 userTrackerCallbackArgumentCaptor.capture(), 469 ArgumentMatchers.eq(mBackgroundExecutor) 470 ); 471 verify(mBroadcastDispatcher).registerReceiver( 472 showFgsManagerReceiverArgumentCaptor.capture(), 473 argThat(fltr -> fltr.matchAction(Intent.ACTION_SHOW_FOREGROUND_SERVICE_MANAGER)), 474 eq(mMainExecutor), 475 isNull(), 476 eq(Context.RECEIVER_NOT_EXPORTED), 477 isNull() 478 ); 479 480 mIForegroundServiceObserver = iForegroundServiceObserverArgumentCaptor.getValue(); 481 mUserTrackerCallback = userTrackerCallbackArgumentCaptor.getValue(); 482 mShowFgsManagerReceiver = showFgsManagerReceiverArgumentCaptor.getValue(); 483 484 if (result.getIncludesUserVisibleJobs()) { 485 ArgumentCaptor<IUserVisibleJobObserver> iUserVisibleJobObserverArgumentCaptor = 486 ArgumentCaptor.forClass(IUserVisibleJobObserver.class); 487 mJobSchedulerInOrder.verify(mJobScheduler).registerUserVisibleJobObserver( 488 iUserVisibleJobObserverArgumentCaptor.capture() 489 ); 490 mIUserVisibleJobObserver = iUserVisibleJobObserverArgumentCaptor.getValue(); 491 } 492 493 return result; 494 } 495 setUserProfiles(int current, int... profileUserIds)496 private void setUserProfiles(int current, int... profileUserIds) { 497 mUserProfiles.clear(); 498 mUserProfiles.add(new UserInfo(current, "current:" + current, 0)); 499 for (int id : profileUserIds) { 500 mUserProfiles.add(new UserInfo(id, "profile:" + id, 0)); 501 } 502 503 if (mUserTrackerCallback != null) { 504 mUserTrackerCallback.onUserChanged(current, mock(Context.class)); 505 mUserTrackerCallback.onProfilesChanged(mUserProfiles); 506 } 507 } 508 } 509