• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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