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.createBackupWakeLock; 20 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.setUpBackupManagerServiceBasics; 21 import static com.android.server.backup.testing.BackupManagerServiceTestUtils.startBackupThreadAndGetLooper; 22 23 import static com.android.server.backup.testing.TransportData.backupTransport; 24 25 import static com.google.common.truth.Truth.assertThat; 26 27 import static org.mockito.ArgumentMatchers.any; 28 import static org.mockito.ArgumentMatchers.anyInt; 29 import static org.mockito.ArgumentMatchers.anyLong; 30 import static org.mockito.ArgumentMatchers.argThat; 31 import static org.mockito.ArgumentMatchers.eq; 32 import static org.mockito.Mockito.doAnswer; 33 import static org.mockito.Mockito.doNothing; 34 import static org.mockito.Mockito.never; 35 import static org.mockito.Mockito.spy; 36 import static org.mockito.Mockito.times; 37 import static org.mockito.Mockito.verify; 38 import static org.mockito.Mockito.when; 39 import static org.robolectric.Shadows.shadowOf; 40 41 import static java.util.Collections.emptyList; 42 import static java.util.stream.Collectors.toCollection; 43 import static java.util.stream.Collectors.toList; 44 45 import android.app.Application; 46 import android.app.IBackupAgent; 47 import android.app.backup.BackupAgent; 48 import android.app.backup.BackupDataInput; 49 import android.app.backup.BackupDataOutput; 50 import android.app.backup.BackupManager; 51 import android.app.backup.BackupTransport; 52 import android.app.backup.IBackupManager; 53 import android.app.backup.IBackupManagerMonitor; 54 import android.app.backup.IBackupObserver; 55 import android.content.pm.ApplicationInfo; 56 import android.content.pm.PackageInfo; 57 import android.content.pm.PackageManager; 58 import android.os.Handler; 59 import android.os.Looper; 60 import android.os.Message; 61 import android.os.ParcelFileDescriptor; 62 import android.os.PowerManager; 63 import android.os.RemoteException; 64 import android.platform.test.annotations.Presubmit; 65 import android.util.Pair; 66 67 import com.android.internal.backup.IBackupTransport; 68 import com.android.server.backup.internal.BackupHandler; 69 import com.android.server.backup.internal.BackupRequest; 70 import com.android.server.backup.internal.OnTaskFinishedListener; 71 import com.android.server.backup.internal.PerformBackupTask; 72 import com.android.server.backup.testing.TransportData; 73 import com.android.server.backup.testing.TransportTestUtils; 74 import com.android.server.backup.testing.TransportTestUtils.TransportMock; 75 import com.android.server.backup.transport.TransportClient; 76 import com.android.server.testing.FrameworkRobolectricTestRunner; 77 import com.android.server.testing.SystemLoaderClasses; 78 import com.android.server.testing.SystemLoaderPackages; 79 import com.android.server.testing.shadows.ShadowBackupDataInput; 80 import com.android.server.testing.shadows.ShadowBackupDataOutput; 81 82 import org.junit.Before; 83 import org.junit.Ignore; 84 import org.junit.Test; 85 import org.junit.runner.RunWith; 86 import org.mockito.ArgumentMatcher; 87 import org.mockito.Mock; 88 import org.mockito.MockitoAnnotations; 89 import org.mockito.invocation.InvocationOnMock; 90 import org.mockito.stubbing.Answer; 91 import org.robolectric.RuntimeEnvironment; 92 import org.robolectric.annotation.Config; 93 import org.robolectric.shadows.ShadowLooper; 94 import org.robolectric.shadows.ShadowPackageManager; 95 import org.robolectric.shadows.ShadowQueuedWork; 96 97 import java.io.File; 98 import java.io.IOException; 99 import java.util.ArrayList; 100 import java.util.List; 101 import java.util.stream.Stream; 102 103 @RunWith(FrameworkRobolectricTestRunner.class) 104 @Config( 105 manifest = Config.NONE, 106 sdk = 26, 107 shadows = {ShadowBackupDataInput.class, ShadowBackupDataOutput.class, ShadowQueuedWork.class} 108 ) 109 @SystemLoaderPackages({"com.android.server.backup", "android.app.backup"}) 110 @SystemLoaderClasses({IBackupTransport.class, IBackupAgent.class, PackageInfo.class}) 111 @Presubmit 112 public class PerformBackupTaskTest { 113 private static final String PACKAGE_1 = "com.example.package1"; 114 private static final String PACKAGE_2 = "com.example.package2"; 115 116 @Mock private BackupManagerService mBackupManagerService; 117 @Mock private TransportManager mTransportManager; 118 @Mock private DataChangedJournal mDataChangedJournal; 119 @Mock private IBackupObserver mObserver; 120 @Mock private IBackupManagerMonitor mMonitor; 121 @Mock private OnTaskFinishedListener mListener; 122 private TransportData mTransport; 123 private ShadowLooper mShadowBackupLooper; 124 private BackupHandler mBackupHandler; 125 private PowerManager.WakeLock mWakeLock; 126 private ShadowPackageManager mShadowPackageManager; 127 private FakeIBackupManager mBackupManager; 128 private File mBaseStateDir; 129 130 @Before setUp()131 public void setUp() throws Exception { 132 MockitoAnnotations.initMocks(this); 133 134 mTransport = backupTransport(); 135 136 Application application = RuntimeEnvironment.application; 137 File cacheDir = application.getCacheDir(); 138 mBaseStateDir = new File(cacheDir, "base_state_dir"); 139 File dataDir = new File(cacheDir, "data_dir"); 140 assertThat(mBaseStateDir.mkdir()).isTrue(); 141 assertThat(dataDir.mkdir()).isTrue(); 142 143 PackageManager packageManager = application.getPackageManager(); 144 mShadowPackageManager = shadowOf(packageManager); 145 146 mWakeLock = createBackupWakeLock(application); 147 148 Looper backupLooper = startBackupThreadAndGetLooper(); 149 mShadowBackupLooper = shadowOf(backupLooper); 150 151 Handler mainHandler = new Handler(Looper.getMainLooper()); 152 BackupAgentTimeoutParameters agentTimeoutParameters = 153 new BackupAgentTimeoutParameters(mainHandler, application.getContentResolver()); 154 agentTimeoutParameters.start(); 155 156 // We need to mock BMS timeout parameters before initializing the BackupHandler since 157 // the constructor of BackupHandler relies on the timeout parameters. 158 when(mBackupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters); 159 mBackupHandler = new BackupHandler(mBackupManagerService, backupLooper); 160 161 mBackupManager = spy(FakeIBackupManager.class); 162 163 setUpBackupManagerServiceBasics( 164 mBackupManagerService, 165 application, 166 mTransportManager, 167 packageManager, 168 mBackupHandler, 169 mWakeLock, 170 agentTimeoutParameters); 171 when(mBackupManagerService.getBaseStateDir()).thenReturn(mBaseStateDir); 172 when(mBackupManagerService.getDataDir()).thenReturn(dataDir); 173 when(mBackupManagerService.getBackupManagerBinder()).thenReturn(mBackupManager); 174 } 175 176 @Test testRunTask_whenTransportProvidesFlags_passesThemToTheAgent()177 public void testRunTask_whenTransportProvidesFlags_passesThemToTheAgent() throws Exception { 178 TransportMock transportMock = setUpTransport(mTransport); 179 AgentMock agentMock = setUpAgent(PACKAGE_1); 180 int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED; 181 when(transportMock.transport.getTransportFlags()).thenReturn(flags); 182 PerformBackupTask task = 183 createPerformBackupTask( 184 transportMock.transportClient, 185 mTransport.transportDirName, 186 emptyList(), 187 PACKAGE_1); 188 189 runTask(task); 190 191 verify(agentMock.agent) 192 .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any()); 193 } 194 195 @Test testRunTask_whenTransportDoesNotProvidesFlags()196 public void testRunTask_whenTransportDoesNotProvidesFlags() throws Exception { 197 TransportMock transportMock = setUpTransport(mTransport); 198 AgentMock agentMock = setUpAgent(PACKAGE_1); 199 PerformBackupTask task = 200 createPerformBackupTask( 201 transportMock.transportClient, 202 mTransport.transportDirName, 203 emptyList(), 204 PACKAGE_1); 205 206 runTask(task); 207 208 verify(agentMock.agent).onBackup(any(), argThat(dataOutputWithTransportFlags(0)), any()); 209 } 210 211 @Test testRunTask_whenTransportProvidesFlagsAndMultipleAgents_passesToAll()212 public void testRunTask_whenTransportProvidesFlagsAndMultipleAgents_passesToAll() 213 throws Exception { 214 TransportMock transportMock = setUpTransport(mTransport); 215 List<AgentMock> agentMocks = setUpAgents(PACKAGE_1, PACKAGE_2); 216 BackupAgent agent1 = agentMocks.get(0).agent; 217 BackupAgent agent2 = agentMocks.get(1).agent; 218 int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED; 219 when(transportMock.transport.getTransportFlags()).thenReturn(flags); 220 PerformBackupTask task = 221 createPerformBackupTask( 222 transportMock.transportClient, 223 mTransport.transportDirName, 224 emptyList(), 225 PACKAGE_1, 226 PACKAGE_2); 227 228 runTask(task); 229 230 verify(agent1).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any()); 231 verify(agent2).onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any()); 232 } 233 234 @Test testRunTask_whenTransportChangeFlagsAfterTaskCreation()235 public void testRunTask_whenTransportChangeFlagsAfterTaskCreation() throws Exception { 236 TransportMock transportMock = setUpTransport(mTransport); 237 AgentMock agentMock = setUpAgent(PACKAGE_1); 238 PerformBackupTask task = 239 createPerformBackupTask( 240 transportMock.transportClient, 241 mTransport.transportDirName, 242 emptyList(), 243 PACKAGE_1); 244 int flags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED; 245 when(transportMock.transport.getTransportFlags()).thenReturn(flags); 246 247 runTask(task); 248 249 verify(agentMock.agent) 250 .onBackup(any(), argThat(dataOutputWithTransportFlags(flags)), any()); 251 } 252 253 @Test testRunTask_callsListenerAndObserver()254 public void testRunTask_callsListenerAndObserver() throws Exception { 255 TransportMock transportMock = setUpTransport(mTransport); 256 setUpAgent(PACKAGE_1); 257 PerformBackupTask task = 258 createPerformBackupTask( 259 transportMock.transportClient, 260 mTransport.transportDirName, 261 emptyList(), 262 PACKAGE_1); 263 264 runTask(task); 265 266 verify(mListener).onFinished(any()); 267 verify(mObserver).backupFinished(eq(BackupManager.SUCCESS)); 268 } 269 270 @Test testRunTask_releasesWakeLock()271 public void testRunTask_releasesWakeLock() throws Exception { 272 TransportMock transportMock = setUpTransport(mTransport); 273 setUpAgent(PACKAGE_1); 274 PerformBackupTask task = 275 createPerformBackupTask( 276 transportMock.transportClient, 277 mTransport.transportDirName, 278 emptyList(), 279 PACKAGE_1); 280 281 runTask(task); 282 283 assertThat(mWakeLock.isHeld()).isFalse(); 284 } 285 286 @Test testRunTask_callsTransportPerformBackupWithAgentData()287 public void testRunTask_callsTransportPerformBackupWithAgentData() throws Exception { 288 TransportMock transportMock = setUpTransport(mTransport); 289 IBackupTransport transportBinder = transportMock.transport; 290 AgentMock agentMock = setUpAgent(PACKAGE_1); 291 agentOnBackupDo( 292 agentMock.agent, 293 (oldState, dataOutput, newState) -> { 294 writeData(dataOutput, "key1", "foo".getBytes()); 295 writeData(dataOutput, "key2", "bar".getBytes()); 296 }); 297 PerformBackupTask task = 298 createPerformBackupTask( 299 transportMock.transportClient, 300 mTransport.transportDirName, 301 emptyList(), 302 PACKAGE_1); 303 // We need to verify at call time because the file is deleted right after 304 when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt())) 305 .then(this::mockAndVerifyTransportPerformBackupData); 306 307 runTask(task); 308 309 // Already verified data in mockAndVerifyPerformBackupData 310 verify(transportBinder).performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt()); 311 } 312 mockAndVerifyTransportPerformBackupData(InvocationOnMock invocation)313 private int mockAndVerifyTransportPerformBackupData(InvocationOnMock invocation) 314 throws IOException { 315 ParcelFileDescriptor data = invocation.getArgument(1); 316 317 // Verifying that what we passed to the transport is what the agent wrote 318 BackupDataInput dataInput = new BackupDataInput(data.getFileDescriptor()); 319 320 // "key1" => "foo" 321 assertThat(dataInput.readNextHeader()).isTrue(); 322 assertThat(dataInput.getKey()).isEqualTo("key1"); 323 int size1 = dataInput.getDataSize(); 324 byte[] data1 = new byte[size1]; 325 dataInput.readEntityData(data1, 0, size1); 326 assertThat(data1).isEqualTo("foo".getBytes()); 327 328 // "key2" => "bar" 329 assertThat(dataInput.readNextHeader()).isTrue(); 330 assertThat(dataInput.getKey()).isEqualTo("key2"); 331 int size2 = dataInput.getDataSize(); 332 byte[] data2 = new byte[size2]; 333 dataInput.readEntityData(data2, 0, size2); 334 assertThat(data2).isEqualTo("bar".getBytes()); 335 336 // No more 337 assertThat(dataInput.readNextHeader()).isFalse(); 338 339 return BackupTransport.TRANSPORT_OK; 340 } 341 342 @Test testRunTask_whenPerformBackupSucceeds_callsTransportFinishBackup()343 public void testRunTask_whenPerformBackupSucceeds_callsTransportFinishBackup() 344 throws Exception { 345 TransportMock transportMock = setUpTransport(mTransport); 346 IBackupTransport transportBinder = transportMock.transport; 347 setUpAgent(PACKAGE_1); 348 PerformBackupTask task = 349 createPerformBackupTask( 350 transportMock.transportClient, 351 mTransport.transportDirName, 352 emptyList(), 353 PACKAGE_1); 354 when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt())) 355 .thenReturn(BackupTransport.TRANSPORT_OK); 356 357 runTask(task); 358 359 verify(transportBinder).finishBackup(); 360 } 361 362 @Test testRunTask_whenProhibitedKey_failsAgent()363 public void testRunTask_whenProhibitedKey_failsAgent() throws Exception { 364 TransportMock transportMock = setUpTransport(mTransport); 365 AgentMock agentMock = setUpAgent(PACKAGE_1); 366 agentOnBackupDo( 367 agentMock.agent, 368 (oldState, dataOutput, newState) -> { 369 char prohibitedChar = 0xff00; 370 writeData(dataOutput, prohibitedChar + "key", "foo".getBytes()); 371 }); 372 PerformBackupTask task = 373 createPerformBackupTask( 374 transportMock.transportClient, 375 mTransport.transportDirName, 376 emptyList(), 377 PACKAGE_1); 378 379 runTask(task); 380 381 // TODO: Should it not call mListener.onFinished()? PerformBackupTask:891 return? 382 // verify(mListener).onFinished(any()); 383 verify(mObserver).onResult(eq(PACKAGE_1), eq(BackupManager.ERROR_AGENT_FAILURE)); 384 verify(agentMock.agentBinder).fail(any()); 385 } 386 387 @Test testRunTask_whenTransportUnavailable()388 public void testRunTask_whenTransportUnavailable() throws Exception { 389 TransportMock transportMock = setUpTransport(mTransport.unavailable()); 390 setUpAgent(PACKAGE_1); 391 PerformBackupTask task = 392 createPerformBackupTask( 393 transportMock.transportClient, 394 mTransport.transportDirName, 395 emptyList(), 396 PACKAGE_1); 397 398 runTask(task); 399 400 verify(mListener).onFinished(any()); 401 // TODO: Should it be 2 times? (PBT.beginBackup() and PBT.finalizeBackup()) 402 verify(mObserver, times(2)).backupFinished(eq(BackupManager.ERROR_TRANSPORT_ABORTED)); 403 } 404 405 @Test testRunTask_whenTransportRejectsPackage()406 public void testRunTask_whenTransportRejectsPackage() throws Exception { 407 TransportMock transportMock = setUpTransport(mTransport); 408 setUpAgent(PACKAGE_1); 409 when(transportMock.transport.performBackup( 410 argThat(packageInfo(PACKAGE_1)), any(), anyInt())) 411 .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED); 412 PerformBackupTask task = 413 createPerformBackupTask( 414 transportMock.transportClient, 415 mTransport.transportDirName, 416 emptyList(), 417 PACKAGE_1); 418 419 runTask(task); 420 421 verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED); 422 verify(mObserver).backupFinished(BackupManager.SUCCESS); 423 } 424 425 @Test testRunTask_whenTransportRejectsFirstPackageButLastSucceeds()426 public void testRunTask_whenTransportRejectsFirstPackageButLastSucceeds() throws Exception { 427 TransportMock transportMock = setUpTransport(mTransport); 428 IBackupTransport transportBinder = transportMock.transport; 429 setUpAgents(PACKAGE_1, PACKAGE_2); 430 when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt())) 431 .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED); 432 when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt())) 433 .thenReturn(BackupTransport.TRANSPORT_OK); 434 PerformBackupTask task = 435 createPerformBackupTask( 436 transportMock.transportClient, 437 mTransport.transportDirName, 438 emptyList(), 439 PACKAGE_1, 440 PACKAGE_2); 441 442 runTask(task); 443 444 verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED); 445 verify(mObserver).onResult(PACKAGE_2, BackupManager.SUCCESS); 446 verify(mObserver).backupFinished(BackupManager.SUCCESS); 447 } 448 449 @Test testRunTask_whenTransportRejectsLastPackageButFirstSucceeds()450 public void testRunTask_whenTransportRejectsLastPackageButFirstSucceeds() throws Exception { 451 TransportMock transportMock = setUpTransport(mTransport); 452 IBackupTransport transportBinder = transportMock.transport; 453 setUpAgents(PACKAGE_1, PACKAGE_2); 454 when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_1)), any(), anyInt())) 455 .thenReturn(BackupTransport.TRANSPORT_OK); 456 when(transportBinder.performBackup(argThat(packageInfo(PACKAGE_2)), any(), anyInt())) 457 .thenReturn(BackupTransport.TRANSPORT_PACKAGE_REJECTED); 458 PerformBackupTask task = 459 createPerformBackupTask( 460 transportMock.transportClient, 461 mTransport.transportDirName, 462 emptyList(), 463 PACKAGE_1, 464 PACKAGE_2); 465 466 runTask(task); 467 468 verify(mObserver).onResult(PACKAGE_1, BackupManager.SUCCESS); 469 verify(mObserver).onResult(PACKAGE_2, BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED); 470 verify(mObserver).backupFinished(BackupManager.SUCCESS); 471 } 472 473 @Test testRunTask_whenTransportReturnsQuotaExceeded()474 public void testRunTask_whenTransportReturnsQuotaExceeded() throws Exception { 475 TransportMock transportMock = setUpTransport(mTransport); 476 AgentMock agentMock = setUpAgent(PACKAGE_1); 477 when(transportMock.transport.performBackup( 478 argThat(packageInfo(PACKAGE_1)), any(), anyInt())) 479 .thenReturn(BackupTransport.TRANSPORT_QUOTA_EXCEEDED); 480 PerformBackupTask task = 481 createPerformBackupTask( 482 transportMock.transportClient, 483 mTransport.transportDirName, 484 emptyList(), 485 PACKAGE_1); 486 487 runTask(task); 488 489 verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED); 490 verify(mObserver).backupFinished(BackupManager.SUCCESS); 491 verify(agentMock.agent).onQuotaExceeded(anyLong(), anyLong()); 492 } 493 494 @Test testRunTask_whenAgentUnknown()495 public void testRunTask_whenAgentUnknown() throws Exception { 496 // Not calling setUpAgent() 497 TransportMock transportMock = setUpTransport(mTransport); 498 PerformBackupTask task = 499 createPerformBackupTask( 500 transportMock.transportClient, 501 mTransport.transportDirName, 502 emptyList(), 503 PACKAGE_1); 504 505 runTask(task); 506 507 verify(transportMock.transport, never()).performBackup(any(), any(), anyInt()); 508 verify(mObserver).onResult(PACKAGE_1, BackupManager.ERROR_PACKAGE_NOT_FOUND); 509 verify(mObserver).backupFinished(BackupManager.SUCCESS); 510 } 511 runTask(PerformBackupTask task)512 private void runTask(PerformBackupTask task) { 513 Message message = mBackupHandler.obtainMessage(BackupHandler.MSG_BACKUP_RESTORE_STEP, task); 514 mBackupHandler.sendMessage(message); 515 while (mShadowBackupLooper.getScheduler().areAnyRunnable()) { 516 mShadowBackupLooper.runToEndOfTasks(); 517 } 518 } 519 setUpTransport(TransportData transport)520 private TransportMock setUpTransport(TransportData transport) throws Exception { 521 TransportMock transportMock = 522 TransportTestUtils.setUpTransport(mTransportManager, transport); 523 File stateDir = new File(mBaseStateDir, transport.transportDirName); 524 assertThat(stateDir.mkdir()).isTrue(); 525 return transportMock; 526 } 527 setUpAgents(String... packageNames)528 private List<AgentMock> setUpAgents(String... packageNames) { 529 return Stream.of(packageNames).map(this::setUpAgent).collect(toList()); 530 } 531 setUpAgent(String packageName)532 private AgentMock setUpAgent(String packageName) { 533 try { 534 PackageInfo packageInfo = new PackageInfo(); 535 packageInfo.packageName = packageName; 536 packageInfo.applicationInfo = new ApplicationInfo(); 537 packageInfo.applicationInfo.flags = ApplicationInfo.FLAG_ALLOW_BACKUP; 538 packageInfo.applicationInfo.backupAgentName = "BackupAgent" + packageName; 539 packageInfo.applicationInfo.packageName = packageName; 540 mShadowPackageManager.setApplicationEnabledSetting( 541 packageName, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0); 542 mShadowPackageManager.addPackage(packageInfo); 543 BackupAgent backupAgent = spy(BackupAgent.class); 544 IBackupAgent backupAgentBinder = 545 spy(IBackupAgent.Stub.asInterface(backupAgent.onBind())); 546 // Don't crash our only process (in production code this would crash the app, not us) 547 doNothing().when(backupAgentBinder).fail(any()); 548 when(mBackupManagerService.bindToAgentSynchronous( 549 eq(packageInfo.applicationInfo), anyInt())) 550 .thenReturn(backupAgentBinder); 551 return new AgentMock(backupAgentBinder, backupAgent); 552 } catch (RemoteException e) { 553 // Never happens, compiler happy 554 throw new AssertionError(e); 555 } 556 } 557 createPerformBackupTask( TransportClient transportClient, String transportDirName, List<String> pendingFullBackups, String... packages)558 private PerformBackupTask createPerformBackupTask( 559 TransportClient transportClient, 560 String transportDirName, 561 List<String> pendingFullBackups, 562 String... packages) { 563 ArrayList<BackupRequest> backupRequests = 564 Stream.of(packages).map(BackupRequest::new).collect(toCollection(ArrayList::new)); 565 mWakeLock.acquire(); 566 PerformBackupTask task = 567 new PerformBackupTask( 568 mBackupManagerService, 569 transportClient, 570 transportDirName, 571 backupRequests, 572 mDataChangedJournal, 573 mObserver, 574 mMonitor, 575 mListener, 576 pendingFullBackups, 577 /* userInitiated */ false, 578 /* nonIncremental */ true); 579 mBackupManager.setUp(mBackupHandler, task); 580 return task; 581 } 582 583 /** Matches {@link PackageInfo} whose package name is {@code packageName}. */ packageInfo(String packageName)584 private static ArgumentMatcher<PackageInfo> packageInfo(String packageName) { 585 // We have to test for packageInfo nulity because of Mockito's own stubbing with argThat(). 586 // E.g. if you do: 587 // 588 // 1. when(object.method(argThat(str -> str.equals("foo")))).thenReturn(0) 589 // 2. when(object.method(argThat(str -> str.equals("bar")))).thenReturn(2) 590 // 591 // The second line will throw NPE because it will call lambda 1 with null, since argThat() 592 // returns null. So we guard against that by checking for null. 593 return packageInfo -> packageInfo != null && packageName.equals(packageInfo.packageName); 594 } 595 dataOutputWithTransportFlags(int flags)596 private static ArgumentMatcher<BackupDataOutput> dataOutputWithTransportFlags(int flags) { 597 return dataOutput -> dataOutput.getTransportFlags() == flags; 598 } 599 writeData(BackupDataOutput dataOutput, String key, byte[] data)600 private static void writeData(BackupDataOutput dataOutput, String key, byte[] data) 601 throws IOException { 602 dataOutput.writeEntityHeader(key, data.length); 603 dataOutput.writeEntityData(data, data.length); 604 } 605 agentOnBackupDo(BackupAgent agent, BackupAgentOnBackup function)606 private static void agentOnBackupDo(BackupAgent agent, BackupAgentOnBackup function) 607 throws Exception { 608 doAnswer(function).when(agent).onBackup(any(), any(), any()); 609 } 610 611 @FunctionalInterface 612 private interface BackupAgentOnBackup extends Answer<Void> { onBackup( ParcelFileDescriptor oldState, BackupDataOutput dataOutput, ParcelFileDescriptor newState)613 void onBackup( 614 ParcelFileDescriptor oldState, 615 BackupDataOutput dataOutput, 616 ParcelFileDescriptor newState) 617 throws IOException; 618 619 @Override answer(InvocationOnMock invocation)620 default Void answer(InvocationOnMock invocation) throws Throwable { 621 onBackup( 622 invocation.getArgument(0), 623 invocation.getArgument(1), 624 invocation.getArgument(2)); 625 return null; 626 } 627 } 628 629 private static class AgentMock { 630 private final IBackupAgent agentBinder; 631 private final BackupAgent agent; 632 AgentMock(IBackupAgent agentBinder, BackupAgent agent)633 private AgentMock(IBackupAgent agentBinder, BackupAgent agent) { 634 this.agentBinder = agentBinder; 635 this.agent = agent; 636 } 637 } 638 639 private abstract static class FakeIBackupManager extends IBackupManager.Stub { 640 private Handler mBackupHandler; 641 private BackupRestoreTask mTask; 642 FakeIBackupManager()643 public FakeIBackupManager() {} 644 setUp(Handler backupHandler, BackupRestoreTask task)645 private void setUp(Handler backupHandler, BackupRestoreTask task) { 646 mBackupHandler = backupHandler; 647 mTask = task; 648 } 649 650 @Override opComplete(int token, long result)651 public void opComplete(int token, long result) throws RemoteException { 652 assertThat(mTask).isNotNull(); 653 Message message = 654 mBackupHandler.obtainMessage( 655 BackupHandler.MSG_OP_COMPLETE, Pair.create(mTask, result)); 656 mBackupHandler.sendMessage(message); 657 } 658 } 659 } 660