Home | History | Annotate | Download | only in backup
      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
    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
    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
    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
    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
    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
    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
    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
    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 
    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
    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
    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
    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
    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
    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
    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
    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
    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 
    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 
    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 
    528     private List<AgentMock> setUpAgents(String... packageNames) {
    529         return Stream.of(packageNames).map(this::setUpAgent).collect(toList());
    530     }
    531 
    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 
    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}. */
    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 
    596     private static ArgumentMatcher<BackupDataOutput> dataOutputWithTransportFlags(int flags) {
    597         return dataOutput -> dataOutput.getTransportFlags() == flags;
    598     }
    599 
    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 
    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> {
    613         void onBackup(
    614                 ParcelFileDescriptor oldState,
    615                 BackupDataOutput dataOutput,
    616                 ParcelFileDescriptor newState)
    617                 throws IOException;
    618 
    619         @Override
    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 
    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 
    643         public FakeIBackupManager() {}
    644 
    645         private void setUp(Handler backupHandler, BackupRestoreTask task) {
    646             mBackupHandler = backupHandler;
    647             mTask = task;
    648         }
    649 
    650         @Override
    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