1 /* 2 * Copyright (C) 2018 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.server.backup; 18 19 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThread; 20 import static com.android.server.backup.testing.TransportData.backupTransport; 21 import static com.android.server.backup.testing.TransportData.d2dTransport; 22 import static com.android.server.backup.testing.TransportData.localTransport; 23 import static com.android.server.backup.testing.TransportTestUtils.setUpCurrentTransport; 24 import static com.android.server.backup.testing.TransportTestUtils.setUpTransports; 25 import static com.google.common.truth.Truth.assertThat; 26 import static org.mockito.ArgumentMatchers.any; 27 import static org.mockito.ArgumentMatchers.anyInt; 28 import static org.mockito.ArgumentMatchers.eq; 29 import static org.mockito.Mockito.mock; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 import static org.robolectric.Shadows.shadowOf; 34 import static org.testng.Assert.expectThrows; 35 36 import android.app.backup.BackupManager; 37 import android.app.backup.ISelectBackupTransportCallback; 38 import android.content.ComponentName; 39 import android.content.Context; 40 import android.content.ContextWrapper; 41 import android.content.Intent; 42 import android.os.HandlerThread; 43 import android.platform.test.annotations.Presubmit; 44 import android.provider.Settings; 45 46 import com.android.server.testing.shadows.ShadowAppBackupUtils; 47 import com.android.server.testing.shadows.ShadowBackupPolicyEnforcer; 48 import com.android.server.backup.testing.TransportData; 49 import com.android.server.backup.testing.TransportTestUtils.TransportMock; 50 import com.android.server.backup.transport.TransportNotRegisteredException; 51 import com.android.server.testing.FrameworkRobolectricTestRunner; 52 import com.android.server.testing.SystemLoaderPackages; 53 54 import java.io.File; 55 import java.util.HashMap; 56 import java.util.List; 57 import java.util.Map; 58 import org.junit.After; 59 import org.junit.Before; 60 import org.junit.Test; 61 import org.junit.runner.RunWith; 62 import org.mockito.Mock; 63 import org.mockito.MockitoAnnotations; 64 import org.robolectric.RuntimeEnvironment; 65 import org.robolectric.annotation.Config; 66 import org.robolectric.shadows.ShadowContextWrapper; 67 import org.robolectric.shadows.ShadowLog; 68 import org.robolectric.shadows.ShadowLooper; 69 import org.robolectric.shadows.ShadowPackageManager; 70 import org.robolectric.shadows.ShadowSettings; 71 import org.robolectric.shadows.ShadowSystemClock; 72 73 @RunWith(FrameworkRobolectricTestRunner.class) 74 @Config( 75 manifest = Config.NONE, 76 sdk = 26, 77 shadows = {ShadowAppBackupUtils.class, ShadowBackupPolicyEnforcer.class} 78 ) 79 @SystemLoaderPackages({"com.android.server.backup"}) 80 @Presubmit 81 public class BackupManagerServiceTest { 82 private static final String TAG = "BMSTest"; 83 84 @Mock private TransportManager mTransportManager; 85 private HandlerThread mBackupThread; 86 private ShadowLooper mShadowBackupLooper; 87 private File mBaseStateDir; 88 private File mDataDir; 89 private ShadowContextWrapper mShadowContext; 90 private Context mContext; 91 private TransportData mTransport; 92 private String mTransportName; 93 94 @Before 95 public void setUp() throws Exception { 96 MockitoAnnotations.initMocks(this); 97 98 mTransport = backupTransport(); 99 mTransportName = mTransport.transportName; 100 101 mBackupThread = startBackupThread(this::uncaughtException); 102 mShadowBackupLooper = shadowOf(mBackupThread.getLooper()); 103 104 ContextWrapper context = RuntimeEnvironment.application; 105 mContext = context; 106 mShadowContext = shadowOf(context); 107 108 File cacheDir = mContext.getCacheDir(); 109 mBaseStateDir = new File(cacheDir, "base_state_dir"); 110 mDataDir = new File(cacheDir, "data_dir"); 111 112 ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null); 113 } 114 115 @After 116 public void tearDown() throws Exception { 117 mBackupThread.quit(); 118 ShadowAppBackupUtils.reset(); 119 ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(null); 120 } 121 122 private void uncaughtException(Thread thread, Throwable e) { 123 // Unrelated exceptions are thrown in the backup thread. Until we mock everything properly 124 // we should not fail tests because of this. This is not flakiness, the exceptions thrown 125 // don't interfere with the tests. 126 ShadowLog.e(TAG, "Uncaught exception in test thread " + thread.getName(), e); 127 } 128 129 /* Tests for destination string */ 130 131 @Test 132 public void testDestinationString() throws Exception { 133 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 134 when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName))) 135 .thenReturn("destinationString"); 136 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 137 138 String destination = backupManagerService.getDestinationString(mTransportName); 139 140 assertThat(destination).isEqualTo("destinationString"); 141 } 142 143 @Test 144 public void testDestinationString_whenTransportNotRegistered() throws Exception { 145 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 146 when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName))) 147 .thenThrow(TransportNotRegisteredException.class); 148 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 149 150 String destination = backupManagerService.getDestinationString(mTransportName); 151 152 assertThat(destination).isNull(); 153 } 154 155 @Test 156 public void testDestinationString_withoutPermission() throws Exception { 157 mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); 158 when(mTransportManager.getTransportCurrentDestinationString(eq(mTransportName))) 159 .thenThrow(TransportNotRegisteredException.class); 160 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 161 162 expectThrows( 163 SecurityException.class, 164 () -> backupManagerService.getDestinationString(mTransportName)); 165 } 166 167 /* Tests for app eligibility */ 168 169 @Test 170 public void testIsAppEligibleForBackup_whenAppEligible() throws Exception { 171 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 172 TransportMock transportMock = setUpCurrentTransport(mTransportManager, backupTransport()); 173 ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> true; 174 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 175 176 boolean result = backupManagerService.isAppEligibleForBackup("app.package"); 177 178 assertThat(result).isTrue(); 179 180 verify(mTransportManager) 181 .disposeOfTransportClient(eq(transportMock.transportClient), any()); 182 } 183 184 @Test 185 public void testIsAppEligibleForBackup_whenAppNotEligible() throws Exception { 186 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 187 setUpCurrentTransport(mTransportManager, mTransport); 188 ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false; 189 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 190 191 boolean result = backupManagerService.isAppEligibleForBackup("app.package"); 192 193 assertThat(result).isFalse(); 194 } 195 196 @Test 197 public void testIsAppEligibleForBackup_withoutPermission() throws Exception { 198 mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); 199 setUpCurrentTransport(mTransportManager, mTransport); 200 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 201 202 expectThrows( 203 SecurityException.class, 204 () -> backupManagerService.isAppEligibleForBackup("app.package")); 205 } 206 207 @Test 208 public void testFilterAppsEligibleForBackup() throws Exception { 209 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 210 TransportMock transportMock = setUpCurrentTransport(mTransportManager, mTransport); 211 Map<String, Boolean> packagesMap = new HashMap<>(); 212 packagesMap.put("package.a", true); 213 packagesMap.put("package.b", false); 214 ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = packagesMap::get; 215 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 216 String[] packages = packagesMap.keySet().toArray(new String[packagesMap.size()]); 217 218 String[] filtered = backupManagerService.filterAppsEligibleForBackup(packages); 219 220 assertThat(filtered).asList().containsExactly("package.a"); 221 verify(mTransportManager) 222 .disposeOfTransportClient(eq(transportMock.transportClient), any()); 223 } 224 225 @Test 226 public void testFilterAppsEligibleForBackup_whenNoneIsEligible() throws Exception { 227 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 228 ShadowAppBackupUtils.sAppIsRunningAndEligibleForBackupWithTransport = p -> false; 229 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 230 231 String[] filtered = 232 backupManagerService.filterAppsEligibleForBackup( 233 new String[] {"package.a", "package.b"}); 234 235 assertThat(filtered).isEmpty(); 236 } 237 238 @Test 239 public void testFilterAppsEligibleForBackup_withoutPermission() throws Exception { 240 mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); 241 setUpCurrentTransport(mTransportManager, mTransport); 242 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 243 244 expectThrows( 245 SecurityException.class, 246 () -> 247 backupManagerService.filterAppsEligibleForBackup( 248 new String[] {"package.a", "package.b"})); 249 } 250 251 /* Tests for select transport */ 252 253 private ComponentName mNewTransportComponent; 254 private TransportData mNewTransport; 255 private TransportMock mNewTransportMock; 256 private ComponentName mOldTransportComponent; 257 private TransportData mOldTransport; 258 private TransportMock mOldTransportMock; 259 260 private void setUpForSelectTransport() throws Exception { 261 mNewTransport = backupTransport(); 262 mNewTransportComponent = mNewTransport.getTransportComponent(); 263 mOldTransport = d2dTransport(); 264 mOldTransportComponent = mOldTransport.getTransportComponent(); 265 List<TransportMock> transportMocks = 266 setUpTransports(mTransportManager, mNewTransport, mOldTransport, localTransport()); 267 mNewTransportMock = transportMocks.get(0); 268 mOldTransportMock = transportMocks.get(1); 269 when(mTransportManager.selectTransport(eq(mNewTransport.transportName))) 270 .thenReturn(mOldTransport.transportName); 271 } 272 273 @Test 274 public void testSelectBackupTransport() throws Exception { 275 setUpForSelectTransport(); 276 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 277 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 278 279 String oldTransport = 280 backupManagerService.selectBackupTransport(mNewTransport.transportName); 281 282 assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName); 283 assertThat(oldTransport).isEqualTo(mOldTransport.transportName); 284 verify(mTransportManager) 285 .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any()); 286 } 287 288 @Test 289 public void testSelectBackupTransport_withoutPermission() throws Exception { 290 setUpForSelectTransport(); 291 mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); 292 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 293 294 expectThrows( 295 SecurityException.class, 296 () -> backupManagerService.selectBackupTransport(mNewTransport.transportName)); 297 } 298 299 @Test 300 public void testSelectBackupTransportAsync() throws Exception { 301 setUpForSelectTransport(); 302 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 303 when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent))) 304 .thenReturn(BackupManager.SUCCESS); 305 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 306 ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class); 307 308 backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback); 309 310 mShadowBackupLooper.runToEndOfTasks(); 311 assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName); 312 verify(callback).onSuccess(eq(mNewTransport.transportName)); 313 verify(mTransportManager) 314 .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any()); 315 } 316 317 @Test 318 public void testSelectBackupTransportAsync_whenMandatoryTransport() throws Exception { 319 setUpForSelectTransport(); 320 ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(mNewTransportComponent); 321 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 322 when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent))) 323 .thenReturn(BackupManager.SUCCESS); 324 ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class); 325 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 326 327 backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback); 328 329 mShadowBackupLooper.runToEndOfTasks(); 330 assertThat(getSettingsTransport()).isEqualTo(mNewTransport.transportName); 331 verify(callback).onSuccess(eq(mNewTransport.transportName)); 332 verify(mTransportManager) 333 .disposeOfTransportClient(eq(mNewTransportMock.transportClient), any()); 334 } 335 336 @Test 337 public void testSelectBackupTransportAsync_whenOtherThanMandatoryTransport() throws Exception { 338 setUpForSelectTransport(); 339 ShadowBackupPolicyEnforcer.setMandatoryBackupTransport(mOldTransportComponent); 340 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 341 when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent))) 342 .thenReturn(BackupManager.SUCCESS); 343 ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class); 344 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 345 346 backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback); 347 348 mShadowBackupLooper.runToEndOfTasks(); 349 assertThat(getSettingsTransport()).isNotEqualTo(mNewTransport.transportName); 350 verify(callback).onFailure(eq(BackupManager.ERROR_BACKUP_NOT_ALLOWED)); 351 } 352 353 @Test 354 public void testSelectBackupTransportAsync_whenRegistrationFails() throws Exception { 355 setUpForSelectTransport(); 356 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 357 when(mTransportManager.registerAndSelectTransport(eq(mNewTransportComponent))) 358 .thenReturn(BackupManager.ERROR_TRANSPORT_UNAVAILABLE); 359 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 360 ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class); 361 362 backupManagerService.selectBackupTransportAsync(mNewTransportComponent, callback); 363 364 mShadowBackupLooper.runToEndOfTasks(); 365 assertThat(getSettingsTransport()).isNotEqualTo(mNewTransport.transportName); 366 verify(callback).onFailure(anyInt()); 367 } 368 369 @Test 370 public void testSelectBackupTransportAsync_whenTransportGetsUnregistered() throws Exception { 371 setUpTransports(mTransportManager, mTransport.unregistered()); 372 ComponentName newTransportComponent = mTransport.getTransportComponent(); 373 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 374 when(mTransportManager.registerAndSelectTransport(eq(newTransportComponent))) 375 .thenReturn(BackupManager.SUCCESS); 376 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 377 ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class); 378 379 backupManagerService.selectBackupTransportAsync(newTransportComponent, callback); 380 381 mShadowBackupLooper.runToEndOfTasks(); 382 assertThat(getSettingsTransport()).isNotEqualTo(mTransportName); 383 verify(callback).onFailure(anyInt()); 384 } 385 386 @Test 387 public void testSelectBackupTransportAsync_withoutPermission() throws Exception { 388 setUpForSelectTransport(); 389 mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); 390 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 391 ComponentName newTransportComponent = mNewTransport.getTransportComponent(); 392 393 expectThrows( 394 SecurityException.class, 395 () -> 396 backupManagerService.selectBackupTransportAsync( 397 newTransportComponent, mock(ISelectBackupTransportCallback.class))); 398 } 399 400 private String getSettingsTransport() { 401 return ShadowSettings.ShadowSecure.getString( 402 mContext.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT); 403 } 404 405 /* Tests for updating transport attributes */ 406 407 private static final int PACKAGE_UID = 10; 408 private ComponentName mTransportComponent; 409 private int mTransportUid; 410 411 private void setUpForUpdateTransportAttributes() throws Exception { 412 mTransportComponent = mTransport.getTransportComponent(); 413 String transportPackage = mTransportComponent.getPackageName(); 414 415 ShadowPackageManager shadowPackageManager = shadowOf(mContext.getPackageManager()); 416 shadowPackageManager.addPackage(transportPackage); 417 shadowPackageManager.setPackagesForUid(PACKAGE_UID, transportPackage); 418 419 mTransportUid = mContext.getPackageManager().getPackageUid(transportPackage, 0); 420 } 421 422 @Test 423 public void 424 testUpdateTransportAttributes_whenTransportUidEqualsToCallingUid_callsThroughToTransportManager() 425 throws Exception { 426 setUpForUpdateTransportAttributes(); 427 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 428 Intent configurationIntent = new Intent(); 429 Intent dataManagementIntent = new Intent(); 430 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 431 432 backupManagerService.updateTransportAttributes( 433 mTransportUid, 434 mTransportComponent, 435 mTransportName, 436 configurationIntent, 437 "currentDestinationString", 438 dataManagementIntent, 439 "dataManagementLabel"); 440 441 verify(mTransportManager) 442 .updateTransportAttributes( 443 eq(mTransportComponent), 444 eq(mTransportName), 445 eq(configurationIntent), 446 eq("currentDestinationString"), 447 eq(dataManagementIntent), 448 eq("dataManagementLabel")); 449 } 450 451 @Test 452 public void testUpdateTransportAttributes_whenTransportUidNotEqualToCallingUid_throwsException() 453 throws Exception { 454 setUpForUpdateTransportAttributes(); 455 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 456 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 457 458 expectThrows( 459 SecurityException.class, 460 () -> 461 backupManagerService.updateTransportAttributes( 462 mTransportUid + 1, 463 mTransportComponent, 464 mTransportName, 465 new Intent(), 466 "currentDestinationString", 467 new Intent(), 468 "dataManagementLabel")); 469 } 470 471 @Test 472 public void testUpdateTransportAttributes_whenTransportComponentNull_throwsException() 473 throws Exception { 474 setUpForUpdateTransportAttributes(); 475 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 476 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 477 478 expectThrows( 479 RuntimeException.class, 480 () -> 481 backupManagerService.updateTransportAttributes( 482 mTransportUid, 483 null, 484 mTransportName, 485 new Intent(), 486 "currentDestinationString", 487 new Intent(), 488 "dataManagementLabel")); 489 } 490 491 @Test 492 public void testUpdateTransportAttributes_whenNameNull_throwsException() throws Exception { 493 setUpForUpdateTransportAttributes(); 494 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 495 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 496 497 expectThrows( 498 RuntimeException.class, 499 () -> 500 backupManagerService.updateTransportAttributes( 501 mTransportUid, 502 mTransportComponent, 503 null, 504 new Intent(), 505 "currentDestinationString", 506 new Intent(), 507 "dataManagementLabel")); 508 } 509 510 @Test 511 public void testUpdateTransportAttributes_whenCurrentDestinationStringNull_throwsException() 512 throws Exception { 513 setUpForUpdateTransportAttributes(); 514 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 515 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 516 517 expectThrows( 518 RuntimeException.class, 519 () -> 520 backupManagerService.updateTransportAttributes( 521 mTransportUid, 522 mTransportComponent, 523 mTransportName, 524 new Intent(), 525 null, 526 new Intent(), 527 "dataManagementLabel")); 528 } 529 530 @Test 531 public void 532 testUpdateTransportAttributes_whenDataManagementArgumentsNullityDontMatch_throwsException() 533 throws Exception { 534 setUpForUpdateTransportAttributes(); 535 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 536 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 537 538 expectThrows( 539 RuntimeException.class, 540 () -> 541 backupManagerService.updateTransportAttributes( 542 mTransportUid, 543 mTransportComponent, 544 mTransportName, 545 new Intent(), 546 "currentDestinationString", 547 null, 548 "dataManagementLabel")); 549 550 expectThrows( 551 RuntimeException.class, 552 () -> 553 backupManagerService.updateTransportAttributes( 554 mTransportUid, 555 mTransportComponent, 556 mTransportName, 557 new Intent(), 558 "currentDestinationString", 559 new Intent(), 560 null)); 561 } 562 563 @Test 564 public void testUpdateTransportAttributes_whenPermissionGranted_callsThroughToTransportManager() 565 throws Exception { 566 setUpForUpdateTransportAttributes(); 567 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 568 Intent configurationIntent = new Intent(); 569 Intent dataManagementIntent = new Intent(); 570 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 571 572 backupManagerService.updateTransportAttributes( 573 mTransportUid, 574 mTransportComponent, 575 mTransportName, 576 configurationIntent, 577 "currentDestinationString", 578 dataManagementIntent, 579 "dataManagementLabel"); 580 581 verify(mTransportManager) 582 .updateTransportAttributes( 583 eq(mTransportComponent), 584 eq(mTransportName), 585 eq(configurationIntent), 586 eq("currentDestinationString"), 587 eq(dataManagementIntent), 588 eq("dataManagementLabel")); 589 } 590 591 @Test 592 public void testUpdateTransportAttributes_whenPermissionDenied_throwsSecurityException() 593 throws Exception { 594 setUpForUpdateTransportAttributes(); 595 mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); 596 BackupManagerService backupManagerService = createInitializedBackupManagerService(); 597 598 expectThrows( 599 SecurityException.class, 600 () -> 601 backupManagerService.updateTransportAttributes( 602 mTransportUid, 603 mTransportComponent, 604 mTransportName, 605 new Intent(), 606 "currentDestinationString", 607 new Intent(), 608 "dataManagementLabel")); 609 } 610 611 /* Miscellaneous tests */ 612 613 @Test 614 public void testConstructor_postRegisterTransports() { 615 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 616 617 createBackupManagerService(); 618 619 mShadowBackupLooper.runToEndOfTasks(); 620 verify(mTransportManager).registerTransports(); 621 } 622 623 @Test 624 public void testConstructor_doesNotRegisterTransportsSynchronously() { 625 mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); 626 627 createBackupManagerService(); 628 629 // Operations posted to mBackupThread only run with mShadowBackupLooper.runToEndOfTasks() 630 verify(mTransportManager, never()).registerTransports(); 631 } 632 633 private BackupManagerService createBackupManagerService() { 634 return new BackupManagerService( 635 mContext, 636 new Trampoline(mContext), 637 mBackupThread, 638 mBaseStateDir, 639 mDataDir, 640 mTransportManager); 641 } 642 643 private BackupManagerService createInitializedBackupManagerService() { 644 BackupManagerService backupManagerService = 645 new BackupManagerService( 646 mContext, 647 new Trampoline(mContext), 648 mBackupThread, 649 mBaseStateDir, 650 mDataDir, 651 mTransportManager); 652 mShadowBackupLooper.runToEndOfTasks(); 653 // Handler instances have their own clock, so advancing looper (with runToEndOfTasks()) 654 // above does NOT advance the handlers' clock, hence whenever a handler post messages with 655 // specific time to the looper the time of those messages will be before the looper's time. 656 // To fix this we advance SystemClock as well since that is from where the handlers read 657 // time. 658 ShadowSystemClock.setCurrentTimeMillis(mShadowBackupLooper.getScheduler().getCurrentTime()); 659 return backupManagerService; 660 } 661 } 662