1/*
2 * Copyright (C) 2017 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
17package com.android.server.backup.utils;
18
19import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_ID;
20import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_APK_NOT_INSTALLED;
21import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK;
22import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE;
23import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH;
24import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION;
25import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT;
26import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
27import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
28
29import static com.google.common.truth.Truth.assertThat;
30
31import static org.mockito.Mockito.doReturn;
32import static org.mockito.Mockito.mock;
33import static org.mockito.Mockito.when;
34import static org.mockito.Mockito.verify;
35import static org.mockito.Mockito.verifyNoMoreInteractions;
36import static org.mockito.Mockito.verifyZeroInteractions;
37import static org.mockito.internal.verification.VerificationModeFactory.times;
38
39import android.app.backup.IBackupManagerMonitor;
40import android.content.Context;
41import android.content.pm.ApplicationInfo;
42import android.content.pm.PackageInfo;
43import android.content.pm.PackageManagerInternal;
44import android.content.pm.PackageParser;
45import android.content.pm.Signature;
46import android.content.pm.SigningInfo;
47import android.os.Bundle;
48import android.os.Process;
49import android.platform.test.annotations.Presubmit;
50import android.support.test.InstrumentationRegistry;
51import android.support.test.filters.SmallTest;
52import android.support.test.runner.AndroidJUnit4;
53
54import com.android.frameworks.servicestests.R;
55import com.android.server.backup.FileMetadata;
56import com.android.server.backup.BackupManagerService;
57import com.android.server.backup.restore.PerformAdbRestoreTask;
58import com.android.server.backup.restore.RestorePolicy;
59import com.android.server.backup.testutils.PackageManagerStub;
60
61import com.google.common.hash.Hashing;
62
63import org.junit.Before;
64import org.junit.Test;
65import org.junit.runner.RunWith;
66import org.mockito.ArgumentCaptor;
67import org.mockito.Mock;
68import org.mockito.MockitoAnnotations;
69
70import java.io.InputStream;
71import java.util.Arrays;
72import java.util.List;
73
74@SmallTest
75@Presubmit
76@RunWith(AndroidJUnit4.class)
77public class TarBackupReaderTest {
78    private static final String TELEPHONY_PACKAGE_NAME = "com.android.providers.telephony";
79    private static final String TELEPHONY_PACKAGE_SIGNATURE_SHA256 =
80            "301aa3cb081134501c45f1422abc66c24224fd5ded5fdc8f17e697176fd866aa";
81    private static final int TELEPHONY_PACKAGE_VERSION = 25;
82    private static final String TEST_PACKAGE_NAME = "com.android.backup.testing";
83    private static final Signature FAKE_SIGNATURE_1 = new Signature("1234");
84    private static final Signature FAKE_SIGNATURE_2 = new Signature("5678");
85
86    @Mock private BytesReadListener mBytesReadListenerMock;
87    @Mock private IBackupManagerMonitor mBackupManagerMonitorMock;
88    @Mock private PackageManagerInternal mMockPackageManagerInternal;
89
90    private final PackageManagerStub mPackageManagerStub = new PackageManagerStub();
91    private Context mContext;
92
93    @Before
94    public void setUp() throws Exception {
95        MockitoAnnotations.initMocks(this);
96
97        mContext = InstrumentationRegistry.getContext();
98    }
99
100    @Test
101    public void readTarHeaders_backupEncrypted_correctlyParsesFileMetadata() throws Exception {
102        InputStream inputStream = mContext.getResources().openRawResource(
103                R.raw.backup_telephony_with_password);
104        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
105                inputStream, "123");
106        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
107                mBytesReadListenerMock, mBackupManagerMonitorMock);
108        FileMetadata fileMetadata = tarBackupReader.readTarHeaders();
109
110        assertThat(fileMetadata.packageName).isEqualTo(TELEPHONY_PACKAGE_NAME);
111        assertThat(fileMetadata.mode).isEqualTo(0600);
112        assertThat(fileMetadata.size).isEqualTo(2438);
113        assertThat(fileMetadata.domain).isEqualTo(null);
114        assertThat(fileMetadata.path).isEqualTo("_manifest");
115    }
116
117    @Test
118    public void readTarHeaders_backupNotEncrypted_correctlyParsesFileMetadata() throws Exception {
119        InputStream inputStream = mContext.getResources().openRawResource(
120                R.raw.backup_telephony_no_password);
121        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
122                inputStream, null);
123        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
124                mBytesReadListenerMock, mBackupManagerMonitorMock);
125        FileMetadata fileMetadata = tarBackupReader.readTarHeaders();
126
127        assertThat(fileMetadata.packageName).isEqualTo(TELEPHONY_PACKAGE_NAME);
128        assertThat(fileMetadata.mode).isEqualTo(0600);
129        assertThat(fileMetadata.size).isEqualTo(2438);
130        assertThat(fileMetadata.domain).isEqualTo(null);
131        assertThat(fileMetadata.path).isEqualTo("_manifest");
132    }
133
134    @Test
135    public void readTarHeaders_backupNotEncrypted_correctlyReadsPaxHeader() throws Exception {
136        // Files with long names (>100 chars) will force backup to add PAX header.
137        InputStream inputStream = mContext.getResources().openRawResource(
138                R.raw.backup_file_with_long_name);
139        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
140                inputStream, null);
141        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
142                mBytesReadListenerMock, mBackupManagerMonitorMock);
143
144        // Read manifest file.
145        FileMetadata fileMetadata = tarBackupReader.readTarHeaders();
146        Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(
147                fileMetadata);
148        RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
149                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
150                mMockPackageManagerInternal);
151
152        assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
153        assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
154        assertThat(fileMetadata.path).isEqualTo(BackupManagerService.BACKUP_MANIFEST_FILENAME);
155
156        tarBackupReader.skipTarPadding(fileMetadata.size);
157
158        // Read actual file (PAX header will only exist here).
159        fileMetadata = tarBackupReader.readTarHeaders();
160        signatures = tarBackupReader.readAppManifestAndReturnSignatures(
161                fileMetadata);
162        restorePolicy = tarBackupReader.chooseRestorePolicy(
163                mPackageManagerStub, false /* allowApks */, fileMetadata, signatures,
164                mMockPackageManagerInternal);
165
166        assertThat(restorePolicy).isEqualTo(RestorePolicy.IGNORE);
167        assertThat(fileMetadata.packageName).isEqualTo(TEST_PACKAGE_NAME);
168        char[] expectedFileNameChars = new char[200];
169        Arrays.fill(expectedFileNameChars, '1');
170        String expectedFileName = new String(expectedFileNameChars);
171        assertThat(fileMetadata.path).isEqualTo(expectedFileName);
172    }
173
174    @Test
175    public void readAppManifest_backupEncrypted_correctlyParsesAppManifest() throws Exception {
176        InputStream inputStream = mContext.getResources().openRawResource(
177                R.raw.backup_telephony_with_password);
178        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
179                inputStream, "123");
180        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
181                mBytesReadListenerMock, mBackupManagerMonitorMock);
182        FileMetadata fileMetadata = tarBackupReader.readTarHeaders();
183
184        Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(fileMetadata);
185
186        assertThat(fileMetadata.version).isEqualTo(TELEPHONY_PACKAGE_VERSION);
187        assertThat(fileMetadata.hasApk).isFalse();
188        assertThat(signatures).isNotNull();
189        assertThat(signatures).hasLength(1);
190
191        String signatureSha256 = Hashing.sha256().hashBytes(signatures[0].toByteArray()).toString();
192        assertThat(signatureSha256).isEqualTo(TELEPHONY_PACKAGE_SIGNATURE_SHA256);
193    }
194
195    @Test
196    public void readAppManifest_backupNotEncrypted_correctlyParsesAppManifest() throws Exception {
197        InputStream inputStream = mContext.getResources().openRawResource(
198                R.raw.backup_telephony_no_password);
199        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
200                inputStream, null);
201        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
202                mBytesReadListenerMock, mBackupManagerMonitorMock);
203        FileMetadata fileMetadata = tarBackupReader.readTarHeaders();
204
205        Signature[] signatures = tarBackupReader.readAppManifestAndReturnSignatures(fileMetadata);
206
207        assertThat(fileMetadata.version).isEqualTo(TELEPHONY_PACKAGE_VERSION);
208        assertThat(fileMetadata.hasApk).isFalse();
209        assertThat(signatures).isNotNull();
210        assertThat(signatures).hasLength(1);
211
212        String signatureSha256 = Hashing.sha256().hashBytes(signatures[0].toByteArray()).toString();
213        assertThat(signatureSha256).isEqualTo(TELEPHONY_PACKAGE_SIGNATURE_SHA256);
214    }
215
216    @Test
217    public void chooseRestorePolicy_signaturesIsNull_returnsIgnore() throws Exception {
218        InputStream inputStream = mContext.getResources().openRawResource(
219                R.raw.backup_telephony_no_password);
220        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
221                inputStream, null);
222        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
223                mBytesReadListenerMock, mBackupManagerMonitorMock);
224
225        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
226                true /* allowApks */, new FileMetadata(), null /* signatures */,
227                mMockPackageManagerInternal);
228
229        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
230        verifyZeroInteractions(mBackupManagerMonitorMock);
231    }
232
233    @Test
234    public void chooseRestorePolicy_packageDoesNotExistAndAllowApksAndHasApk_returnsAcceptIfApk()
235            throws Exception {
236        InputStream inputStream = mContext.getResources().openRawResource(
237                R.raw.backup_telephony_no_password);
238        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
239                inputStream, null);
240        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
241                mBytesReadListenerMock, mBackupManagerMonitorMock);
242        FileMetadata info = new FileMetadata();
243        info.hasApk = true;
244        PackageManagerStub.sPackageInfo = null;
245
246        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
247                true /* allowApks */, info, new Signature[0] /* signatures */,
248                mMockPackageManagerInternal);
249
250        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
251        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
252        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
253        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
254                LOG_EVENT_ID_APK_NOT_INSTALLED);
255    }
256
257    @Test
258    public void
259    chooseRestorePolicy_packageDoesNotExistAndAllowApksAndDoesNotHaveApk_returnsAcceptIfApkLogsCannotRestore()
260            throws Exception {
261        InputStream inputStream = mContext.getResources().openRawResource(
262                R.raw.backup_telephony_no_password);
263        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
264                inputStream, null);
265        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
266                mBytesReadListenerMock, mBackupManagerMonitorMock);
267        FileMetadata info = new FileMetadata();
268        info.hasApk = false;
269        PackageManagerStub.sPackageInfo = null;
270
271        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
272                true /* allowApks */, info, new Signature[0] /* signatures */,
273                mMockPackageManagerInternal);
274
275        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
276        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
277        verify(mBackupManagerMonitorMock, times(2)).onEvent(bundleCaptor.capture());
278        List<Bundle> eventBundles = bundleCaptor.getAllValues();
279        assertThat(eventBundles).hasSize(2);
280        assertThat(eventBundles.get(0).get(EXTRA_LOG_EVENT_ID)).isEqualTo(
281                LOG_EVENT_ID_APK_NOT_INSTALLED);
282        assertThat(eventBundles.get(1).get(EXTRA_LOG_EVENT_ID)).isEqualTo(
283                LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK);
284    }
285
286    @Test
287    public void chooseRestorePolicy_packageDoesNotExistAndDoesNotAllowApks_returnsIgnore()
288            throws Exception {
289        InputStream inputStream = mContext.getResources().openRawResource(
290                R.raw.backup_telephony_no_password);
291        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
292                inputStream, null);
293        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
294                mBytesReadListenerMock, mBackupManagerMonitorMock);
295        PackageManagerStub.sPackageInfo = null;
296
297        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
298                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
299                mMockPackageManagerInternal);
300
301        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
302        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
303        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
304        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
305                LOG_EVENT_ID_APK_NOT_INSTALLED);
306    }
307
308    @Test
309    public void chooseRestorePolicy_doesNotAllowsBackup_returnsIgnore() throws Exception {
310        InputStream inputStream = mContext.getResources().openRawResource(
311                R.raw.backup_telephony_no_password);
312        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
313                inputStream, null);
314        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
315                mBytesReadListenerMock, mBackupManagerMonitorMock);
316
317        PackageInfo packageInfo = new PackageInfo();
318        packageInfo.applicationInfo = new ApplicationInfo();
319        packageInfo.applicationInfo.flags = ~ApplicationInfo.FLAG_ALLOW_BACKUP;
320        PackageManagerStub.sPackageInfo = packageInfo;
321
322        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
323                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
324                mMockPackageManagerInternal);
325
326        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
327        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
328        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
329        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
330                LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE);
331    }
332
333    @Test
334    public void chooseRestorePolicy_systemAppWithNoAgent_returnsIgnore() throws Exception {
335        InputStream inputStream = mContext.getResources().openRawResource(
336                R.raw.backup_telephony_no_password);
337        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
338                inputStream, null);
339        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
340                mBytesReadListenerMock, mBackupManagerMonitorMock);
341
342        PackageInfo packageInfo = new PackageInfo();
343        packageInfo.applicationInfo = new ApplicationInfo();
344        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
345        packageInfo.applicationInfo.uid = Process.SYSTEM_UID;
346        packageInfo.applicationInfo.backupAgentName = null;
347        PackageManagerStub.sPackageInfo = packageInfo;
348
349        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
350                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */,
351                mMockPackageManagerInternal);
352
353        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
354        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
355        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
356        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
357                LOG_EVENT_ID_SYSTEM_APP_NO_AGENT);
358    }
359
360    @Test
361    public void chooseRestorePolicy_nonSystemAppSignaturesDoNotMatch_returnsIgnore()
362            throws Exception {
363        InputStream inputStream = mContext.getResources().openRawResource(
364                R.raw.backup_telephony_no_password);
365        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
366                inputStream, null);
367        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
368                mBytesReadListenerMock, mBackupManagerMonitorMock);
369        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
370
371        PackageInfo packageInfo = new PackageInfo();
372        packageInfo.applicationInfo = new ApplicationInfo();
373        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
374        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
375        packageInfo.applicationInfo.backupAgentName = null;
376        packageInfo.signingInfo = new SigningInfo(
377                new PackageParser.SigningDetails(
378                        new Signature[] {FAKE_SIGNATURE_2},
379                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
380                        null,
381                        null,
382                        null));
383        PackageManagerStub.sPackageInfo = packageInfo;
384
385        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
386                false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
387
388        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
389        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
390        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
391        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
392                LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH);
393    }
394
395    @Test
396    public void chooseRestorePolicy_systemAppWithBackupAgentAndRestoreAnyVersion_returnsAccept()
397            throws Exception {
398        InputStream inputStream = mContext.getResources().openRawResource(
399                R.raw.backup_telephony_no_password);
400        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
401                inputStream, null);
402        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
403                mBytesReadListenerMock, mBackupManagerMonitorMock);
404        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
405
406        PackageInfo packageInfo = new PackageInfo();
407        packageInfo.packageName = "test";
408        packageInfo.applicationInfo = new ApplicationInfo();
409        packageInfo.applicationInfo.flags |=
410                ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
411        packageInfo.applicationInfo.uid = Process.SYSTEM_UID;
412        packageInfo.applicationInfo.backupAgentName = "backup.agent";
413        packageInfo.signingInfo = new SigningInfo(
414                new PackageParser.SigningDetails(
415                        new Signature[] {FAKE_SIGNATURE_1},
416                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
417                        null,
418                        null,
419                        null));
420        PackageManagerStub.sPackageInfo = packageInfo;
421
422        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
423                packageInfo.packageName);
424        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
425                false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
426
427        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
428        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
429        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
430        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
431                LOG_EVENT_ID_RESTORE_ANY_VERSION);
432    }
433
434    @Test
435    public void chooseRestorePolicy_restoreAnyVersion_returnsAccept() throws Exception {
436        InputStream inputStream = mContext.getResources().openRawResource(
437                R.raw.backup_telephony_no_password);
438        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
439                inputStream, null);
440        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
441                mBytesReadListenerMock, mBackupManagerMonitorMock);
442        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
443
444        PackageInfo packageInfo = new PackageInfo();
445        packageInfo.packageName = "test";
446        packageInfo.applicationInfo = new ApplicationInfo();
447        packageInfo.applicationInfo.flags |=
448                ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
449        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
450        packageInfo.applicationInfo.backupAgentName = null;
451        packageInfo.signingInfo = new SigningInfo(
452                new PackageParser.SigningDetails(
453                        new Signature[] {FAKE_SIGNATURE_1},
454                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
455                        null,
456                        null,
457                        null));
458        PackageManagerStub.sPackageInfo = packageInfo;
459
460        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
461                packageInfo.packageName);
462        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
463                false /* allowApks */, new FileMetadata(), signatures, mMockPackageManagerInternal);
464
465        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
466        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
467        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
468        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
469                LOG_EVENT_ID_RESTORE_ANY_VERSION);
470    }
471
472    @Test
473    public void chooseRestorePolicy_notRestoreAnyVersionButVersionMatch_returnsAccept()
474            throws Exception {
475        InputStream inputStream = mContext.getResources().openRawResource(
476                R.raw.backup_telephony_no_password);
477        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
478                inputStream, null);
479        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
480                mBytesReadListenerMock, mBackupManagerMonitorMock);
481        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
482        FileMetadata info = new FileMetadata();
483        info.version = 1;
484
485        PackageInfo packageInfo = new PackageInfo();
486        packageInfo.packageName = "test";
487        packageInfo.applicationInfo = new ApplicationInfo();
488        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
489        packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
490        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
491        packageInfo.applicationInfo.backupAgentName = null;
492        packageInfo.signingInfo = new SigningInfo(
493                new PackageParser.SigningDetails(
494                        new Signature[] {FAKE_SIGNATURE_1},
495                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
496                        null,
497                        null,
498                        null));
499        packageInfo.versionCode = 2;
500        PackageManagerStub.sPackageInfo = packageInfo;
501
502        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
503                packageInfo.packageName);
504        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
505                false /* allowApks */, info, signatures, mMockPackageManagerInternal);
506
507        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
508        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
509        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
510        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
511                LOG_EVENT_ID_VERSIONS_MATCH);
512    }
513
514    @Test
515    public void
516    chooseRestorePolicy_notRestoreAnyVersionAndVersionMismatchButAllowApksAndHasApk_returnsAcceptIfApk()
517            throws Exception {
518        InputStream inputStream = mContext.getResources().openRawResource(
519                R.raw.backup_telephony_no_password);
520        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
521                inputStream, null);
522        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
523                mBytesReadListenerMock, mBackupManagerMonitorMock);
524        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
525        FileMetadata info = new FileMetadata();
526        info.version = 2;
527        info.hasApk = true;
528
529        PackageInfo packageInfo = new PackageInfo();
530        packageInfo.packageName = "test";
531        packageInfo.applicationInfo = new ApplicationInfo();
532        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
533        packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
534        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
535        packageInfo.applicationInfo.backupAgentName = null;
536        packageInfo.signingInfo = new SigningInfo(
537                new PackageParser.SigningDetails(
538                        new Signature[] {FAKE_SIGNATURE_1},
539                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
540                        null,
541                        null,
542                        null));
543        packageInfo.versionCode = 1;
544        PackageManagerStub.sPackageInfo = packageInfo;
545
546        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
547                packageInfo.packageName);
548        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
549                true /* allowApks */, info, signatures, mMockPackageManagerInternal);
550
551        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
552        verifyNoMoreInteractions(mBackupManagerMonitorMock);
553    }
554
555    @Test
556    public void
557    chooseRestorePolicy_notRestoreAnyVersionAndVersionMismatchAndDoesNotAllowApks_returnsIgnore()
558            throws Exception {
559        InputStream inputStream = mContext.getResources().openRawResource(
560                R.raw.backup_telephony_no_password);
561        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
562                inputStream, null);
563        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
564                mBytesReadListenerMock, mBackupManagerMonitorMock);
565        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
566        FileMetadata info = new FileMetadata();
567        info.version = 2;
568
569        PackageInfo packageInfo = new PackageInfo();
570        packageInfo.packageName = "test";
571        packageInfo.applicationInfo = new ApplicationInfo();
572        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
573        packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
574        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
575        packageInfo.applicationInfo.backupAgentName = null;
576        packageInfo.signingInfo = new SigningInfo(
577                new PackageParser.SigningDetails(
578                        new Signature[] {FAKE_SIGNATURE_1},
579                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
580                        null,
581                        null,
582                        null));
583        packageInfo.versionCode = 1;
584        PackageManagerStub.sPackageInfo = packageInfo;
585
586        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
587                packageInfo.packageName);
588        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
589                false /* allowApks */, info, signatures, mMockPackageManagerInternal);
590
591        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
592        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
593        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
594        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
595                LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
596    }
597}
598
599