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 com.google.common.truth.Truth.assertThat;
20
21import static org.mockito.Mockito.doReturn;
22import static org.mockito.Mockito.mock;
23import static org.mockito.Mockito.when;
24
25import android.content.pm.ApplicationInfo;
26import android.content.pm.PackageInfo;
27import android.content.pm.PackageManager;
28import android.content.pm.PackageManagerInternal;
29import android.content.pm.PackageParser;
30import android.content.pm.Signature;
31import android.content.pm.SigningInfo;
32import android.os.Process;
33import android.platform.test.annotations.Presubmit;
34import android.support.test.filters.SmallTest;
35import android.support.test.runner.AndroidJUnit4;
36
37import com.android.server.backup.BackupManagerService;
38import com.android.server.backup.testutils.PackageManagerStub;
39
40import org.junit.Before;
41import org.junit.Test;
42import org.junit.runner.RunWith;
43
44@SmallTest
45@Presubmit
46@RunWith(AndroidJUnit4.class)
47public class AppBackupUtilsTest {
48    private static final String CUSTOM_BACKUP_AGENT_NAME = "custom.backup.agent";
49    private static final String TEST_PACKAGE_NAME = "test_package";
50
51    private static final Signature SIGNATURE_1 = generateSignature((byte) 1);
52    private static final Signature SIGNATURE_2 = generateSignature((byte) 2);
53    private static final Signature SIGNATURE_3 = generateSignature((byte) 3);
54    private static final Signature SIGNATURE_4 = generateSignature((byte) 4);
55
56    private PackageManagerStub mPackageManagerStub;
57    private PackageManagerInternal mMockPackageManagerInternal;
58
59    @Before
60    public void setUp() throws Exception {
61        mPackageManagerStub = new PackageManagerStub();
62        mMockPackageManagerInternal = mock(PackageManagerInternal.class);
63    }
64
65    @Test
66    public void appIsEligibleForBackup_backupNotAllowed_returnsFalse() throws Exception {
67        ApplicationInfo applicationInfo = new ApplicationInfo();
68        applicationInfo.flags = 0;
69        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
70        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
71        applicationInfo.packageName = TEST_PACKAGE_NAME;
72
73        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
74                mPackageManagerStub);
75
76        assertThat(isEligible).isFalse();
77    }
78
79    @Test
80    public void appIsEligibleForBackup_systemAppWithoutCustomBackupAgent_returnsFalse()
81            throws Exception {
82        ApplicationInfo applicationInfo = new ApplicationInfo();
83        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
84        applicationInfo.uid = Process.SYSTEM_UID;
85        applicationInfo.backupAgentName = null;
86        applicationInfo.packageName = TEST_PACKAGE_NAME;
87
88        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
89                mPackageManagerStub);
90
91        assertThat(isEligible).isFalse();
92    }
93
94    @Test
95    public void appIsEligibleForBackup_sharedStorageBackupPackage_returnsFalse() throws Exception {
96        ApplicationInfo applicationInfo = new ApplicationInfo();
97        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
98        applicationInfo.uid = Process.SYSTEM_UID;
99        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
100        applicationInfo.packageName = BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
101
102        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
103                mPackageManagerStub);
104
105        assertThat(isEligible).isFalse();
106    }
107
108    @Test
109    public void appIsEligibleForBackup_systemAppWithCustomBackupAgentAndEnabled_returnsTrue()
110            throws Exception {
111        ApplicationInfo applicationInfo = new ApplicationInfo();
112        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
113        applicationInfo.uid = Process.SYSTEM_UID;
114        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
115        applicationInfo.packageName = TEST_PACKAGE_NAME;
116
117        PackageManagerStub.sApplicationEnabledSetting =
118                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
119
120        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
121                mPackageManagerStub);
122
123        assertThat(isEligible).isTrue();
124    }
125
126    @Test
127    public void appIsEligibleForBackup_nonSystemAppWithoutCustomBackupAgentAndEnabled_returnsTrue()
128            throws Exception {
129        ApplicationInfo applicationInfo = new ApplicationInfo();
130        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
131        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
132        applicationInfo.backupAgentName = null;
133        applicationInfo.packageName = TEST_PACKAGE_NAME;
134
135        PackageManagerStub.sApplicationEnabledSetting =
136                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
137
138        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
139                mPackageManagerStub);
140
141        assertThat(isEligible).isTrue();
142    }
143
144    @Test
145    public void appIsEligibleForBackup_nonSystemAppWithCustomBackupAgentAndEnabled_returnsTrue()
146            throws Exception {
147        ApplicationInfo applicationInfo = new ApplicationInfo();
148        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
149        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
150        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
151        applicationInfo.packageName = TEST_PACKAGE_NAME;
152
153        PackageManagerStub.sApplicationEnabledSetting =
154                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
155
156        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
157                mPackageManagerStub);
158
159        assertThat(isEligible).isTrue();
160    }
161
162    @Test
163    public void appIsEligibleForBackup_systemAppWithCustomBackupAgentAndDisabled_returnsFalse()
164            throws Exception {
165        ApplicationInfo applicationInfo = new ApplicationInfo();
166        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
167        applicationInfo.uid = Process.SYSTEM_UID;
168        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
169        applicationInfo.packageName = TEST_PACKAGE_NAME;
170
171        PackageManagerStub.sApplicationEnabledSetting =
172                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
173
174        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
175                mPackageManagerStub);
176
177        assertThat(isEligible).isFalse();
178    }
179
180    @Test
181    public void appIsEligibleForBackup_nonSystemAppWithoutCustomBackupAgentAndDisabled_returnsFalse()
182            throws Exception {
183        ApplicationInfo applicationInfo = new ApplicationInfo();
184        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
185        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
186        applicationInfo.backupAgentName = null;
187        applicationInfo.packageName = TEST_PACKAGE_NAME;
188
189        PackageManagerStub.sApplicationEnabledSetting =
190                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
191
192        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
193                mPackageManagerStub);
194
195        assertThat(isEligible).isFalse();
196    }
197
198    @Test
199    public void appIsEligibleForBackup_nonSystemAppWithCustomBackupAgentAndDisbled_returnsFalse()
200            throws Exception {
201        ApplicationInfo applicationInfo = new ApplicationInfo();
202        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
203        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
204        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
205        applicationInfo.packageName = TEST_PACKAGE_NAME;
206
207        PackageManagerStub.sApplicationEnabledSetting =
208                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
209
210        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo,
211                mPackageManagerStub);
212
213        assertThat(isEligible).isFalse();
214    }
215
216    @Test
217    public void appIsDisabled_stateEnabled_returnsFalse() throws Exception {
218        ApplicationInfo applicationInfo = new ApplicationInfo();
219        applicationInfo.flags = 0;
220        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
221        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
222        applicationInfo.packageName = TEST_PACKAGE_NAME;
223
224        PackageManagerStub.sApplicationEnabledSetting =
225                PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
226
227        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub);
228
229        assertThat(isDisabled).isFalse();
230    }
231
232    @Test
233    public void appIsDisabled_stateDisabled_returnsTrue() throws Exception {
234        ApplicationInfo applicationInfo = new ApplicationInfo();
235        applicationInfo.flags = 0;
236        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
237        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
238        applicationInfo.packageName = TEST_PACKAGE_NAME;
239
240        PackageManagerStub.sApplicationEnabledSetting =
241                PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
242
243        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub);
244
245        assertThat(isDisabled).isTrue();
246    }
247
248    @Test
249    public void appIsDisabled_stateDisabledUser_returnsTrue() throws Exception {
250        ApplicationInfo applicationInfo = new ApplicationInfo();
251        applicationInfo.flags = 0;
252        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
253        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
254        applicationInfo.packageName = TEST_PACKAGE_NAME;
255
256        PackageManagerStub.sApplicationEnabledSetting =
257                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
258
259        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub);
260
261        assertThat(isDisabled).isTrue();
262    }
263
264    @Test
265    public void appIsDisabled_stateDisabledUntilUsed_returnsTrue() throws Exception {
266        ApplicationInfo applicationInfo = new ApplicationInfo();
267        applicationInfo.flags = 0;
268        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
269        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
270        applicationInfo.packageName = TEST_PACKAGE_NAME;
271
272        PackageManagerStub.sApplicationEnabledSetting =
273                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
274
275        boolean isDisabled = AppBackupUtils.appIsDisabled(applicationInfo, mPackageManagerStub);
276
277        assertThat(isDisabled).isTrue();
278    }
279
280    @Test
281    public void appIsStopped_returnsTrue() throws Exception {
282        ApplicationInfo applicationInfo = new ApplicationInfo();
283        applicationInfo.flags |= ApplicationInfo.FLAG_STOPPED;
284
285        boolean isStopped = AppBackupUtils.appIsStopped(applicationInfo);
286
287        assertThat(isStopped).isTrue();
288    }
289
290    @Test
291    public void appIsStopped_returnsFalse() throws Exception {
292        ApplicationInfo applicationInfo = new ApplicationInfo();
293        applicationInfo.flags = ~ApplicationInfo.FLAG_STOPPED;
294
295        boolean isStopped = AppBackupUtils.appIsStopped(applicationInfo);
296
297        assertThat(isStopped).isFalse();
298    }
299
300    @Test
301    public void appGetsFullBackup_noCustomBackupAgent_returnsTrue() throws Exception {
302        PackageInfo packageInfo = new PackageInfo();
303        packageInfo.applicationInfo = new ApplicationInfo();
304        packageInfo.applicationInfo.backupAgentName = null;
305
306        boolean result = AppBackupUtils.appGetsFullBackup(packageInfo);
307
308        assertThat(result).isTrue();
309    }
310
311    @Test
312    public void appGetsFullBackup_withCustomBackupAgentAndFullBackupOnlyFlag_returnsTrue()
313            throws Exception {
314        PackageInfo packageInfo = new PackageInfo();
315        packageInfo.applicationInfo = new ApplicationInfo();
316        packageInfo.applicationInfo.backupAgentName = "backup.agent";
317        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
318
319        boolean result = AppBackupUtils.appGetsFullBackup(packageInfo);
320
321        assertThat(result).isTrue();
322    }
323
324    @Test
325    public void appGetsFullBackup_withCustomBackupAgentAndWithoutFullBackupOnlyFlag_returnsFalse()
326            throws Exception {
327        PackageInfo packageInfo = new PackageInfo();
328        packageInfo.applicationInfo = new ApplicationInfo();
329        packageInfo.applicationInfo.backupAgentName = "backup.agent";
330        packageInfo.applicationInfo.flags = ~ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
331
332        boolean result = AppBackupUtils.appGetsFullBackup(packageInfo);
333
334        assertThat(result).isFalse();
335    }
336
337    @Test
338    public void appIsKeyValueOnly_noCustomBackupAgent_returnsTrue() throws Exception {
339        PackageInfo packageInfo = new PackageInfo();
340        packageInfo.applicationInfo = new ApplicationInfo();
341        packageInfo.applicationInfo.backupAgentName = null;
342
343        boolean result = AppBackupUtils.appIsKeyValueOnly(packageInfo);
344
345        assertThat(result).isFalse();
346    }
347
348    @Test
349    public void appIsKeyValueOnly_withCustomBackupAgentAndFullBackupOnlyFlag_returnsTrue()
350            throws Exception {
351        PackageInfo packageInfo = new PackageInfo();
352        packageInfo.applicationInfo = new ApplicationInfo();
353        packageInfo.applicationInfo.backupAgentName = "backup.agent";
354        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
355
356        boolean result = AppBackupUtils.appIsKeyValueOnly(packageInfo);
357
358        assertThat(result).isFalse();
359    }
360
361    @Test
362    public void appIsKeyValueOnly_withCustomBackupAgentAndWithoutFullBackupOnlyFlag_returnsFalse()
363            throws Exception {
364        PackageInfo packageInfo = new PackageInfo();
365        packageInfo.applicationInfo = new ApplicationInfo();
366        packageInfo.applicationInfo.backupAgentName = "backup.agent";
367        packageInfo.applicationInfo.flags = ~ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
368
369        boolean result = AppBackupUtils.appIsKeyValueOnly(packageInfo);
370
371        assertThat(result).isTrue();
372    }
373
374    @Test
375    public void signaturesMatch_targetIsNull_returnsFalse() throws Exception {
376        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, null,
377                mMockPackageManagerInternal);
378
379        assertThat(result).isFalse();
380    }
381
382    @Test
383    public void signaturesMatch_systemApplication_returnsTrue() throws Exception {
384        PackageInfo packageInfo = new PackageInfo();
385        packageInfo.packageName = "test";
386        packageInfo.applicationInfo = new ApplicationInfo();
387        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
388
389        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
390                mMockPackageManagerInternal);
391
392        assertThat(result).isTrue();
393    }
394
395    @Test
396    public void signaturesMatch_disallowsUnsignedApps_storedSignatureNull_returnsFalse()
397            throws Exception {
398        PackageInfo packageInfo = new PackageInfo();
399        packageInfo.packageName = "test";
400        packageInfo.signingInfo = new SigningInfo(
401                new PackageParser.SigningDetails(
402                        new Signature[] {SIGNATURE_1},
403                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
404                        null,
405                        null,
406                        null));
407        packageInfo.applicationInfo = new ApplicationInfo();
408
409        boolean result = AppBackupUtils.signaturesMatch(null, packageInfo,
410                mMockPackageManagerInternal);
411
412        assertThat(result).isFalse();
413    }
414
415    @Test
416    public void signaturesMatch_disallowsUnsignedApps_storedSignatureEmpty_returnsFalse()
417            throws Exception {
418        PackageInfo packageInfo = new PackageInfo();
419        packageInfo.packageName = "test";
420        packageInfo.signingInfo = new SigningInfo(
421                new PackageParser.SigningDetails(
422                        new Signature[] {SIGNATURE_1},
423                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
424                        null,
425                        null,
426                        null));
427        packageInfo.applicationInfo = new ApplicationInfo();
428
429        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
430                mMockPackageManagerInternal);
431
432        assertThat(result).isFalse();
433    }
434
435
436    @Test
437    public void
438    signaturesMatch_disallowsUnsignedApps_targetSignatureEmpty_returnsFalse()
439            throws Exception {
440        PackageInfo packageInfo = new PackageInfo();
441        packageInfo.packageName = "test";
442        packageInfo.signingInfo = null;
443        packageInfo.applicationInfo = new ApplicationInfo();
444
445        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, packageInfo,
446                mMockPackageManagerInternal);
447
448        assertThat(result).isFalse();
449    }
450
451    @Test
452    public void
453    signaturesMatch_disallowsUnsignedApps_targetSignatureNull_returnsFalse()
454            throws Exception {
455        PackageInfo packageInfo = new PackageInfo();
456        packageInfo.packageName = "test";
457        packageInfo.signingInfo = null;
458        packageInfo.applicationInfo = new ApplicationInfo();
459
460        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {SIGNATURE_1}, packageInfo,
461                mMockPackageManagerInternal);
462
463        assertThat(result).isFalse();
464    }
465
466    @Test
467    public void signaturesMatch_disallowsUnsignedApps_bothSignaturesNull_returnsFalse()
468            throws Exception {
469        PackageInfo packageInfo = new PackageInfo();
470        packageInfo.signingInfo = null;
471        packageInfo.applicationInfo = new ApplicationInfo();
472
473        boolean result = AppBackupUtils.signaturesMatch(null, packageInfo,
474                mMockPackageManagerInternal);
475
476        assertThat(result).isFalse();
477    }
478
479    @Test
480    public void signaturesMatch_disallowsUnsignedApps_bothSignaturesEmpty_returnsFalse()
481            throws Exception {
482        PackageInfo packageInfo = new PackageInfo();
483        packageInfo.packageName = "test";
484        packageInfo.signingInfo = null;
485        packageInfo.applicationInfo = new ApplicationInfo();
486
487        boolean result = AppBackupUtils.signaturesMatch(new Signature[0], packageInfo,
488                mMockPackageManagerInternal);
489
490        assertThat(result).isFalse();
491    }
492
493    @Test
494    public void signaturesMatch_equalSignatures_returnsTrue() throws Exception {
495        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
496        Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
497        Signature signature3Copy = new Signature(SIGNATURE_3.toByteArray());
498
499        PackageInfo packageInfo = new PackageInfo();
500        packageInfo.packageName = "test";
501        packageInfo.signingInfo = new SigningInfo(
502                new PackageParser.SigningDetails(
503                        new Signature[] {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3},
504                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
505                        null,
506                        null,
507                        null));
508        packageInfo.applicationInfo = new ApplicationInfo();
509
510        boolean result = AppBackupUtils.signaturesMatch(
511                new Signature[] {signature3Copy, signature1Copy, signature2Copy}, packageInfo,
512                mMockPackageManagerInternal);
513
514        assertThat(result).isTrue();
515    }
516
517    @Test
518    public void signaturesMatch_extraSignatureInTarget_returnsTrue() throws Exception {
519        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
520        Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
521
522        PackageInfo packageInfo = new PackageInfo();
523        packageInfo.packageName = "test";
524        packageInfo.signingInfo = new SigningInfo(
525                new PackageParser.SigningDetails(
526                        new Signature[] {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3},
527                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
528                        null,
529                        null,
530                        null));
531        packageInfo.applicationInfo = new ApplicationInfo();
532
533        boolean result = AppBackupUtils.signaturesMatch(
534                new Signature[]{signature2Copy, signature1Copy}, packageInfo,
535                mMockPackageManagerInternal);
536
537        assertThat(result).isTrue();
538    }
539
540    @Test
541    public void signaturesMatch_extraSignatureInStored_returnsFalse() throws Exception {
542        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
543        Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
544
545        PackageInfo packageInfo = new PackageInfo();
546        packageInfo.packageName = "test";
547        packageInfo.signingInfo = new SigningInfo(
548                new PackageParser.SigningDetails(
549                        new Signature[] {signature1Copy, signature2Copy},
550                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
551                        null,
552                        null,
553                        null));
554        packageInfo.applicationInfo = new ApplicationInfo();
555
556        boolean result = AppBackupUtils.signaturesMatch(
557                new Signature[]{SIGNATURE_1, SIGNATURE_2, SIGNATURE_3}, packageInfo,
558                mMockPackageManagerInternal);
559
560        assertThat(result).isFalse();
561    }
562
563    @Test
564    public void signaturesMatch_oneNonMatchingSignature_returnsFalse() throws Exception {
565        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
566        Signature signature2Copy = new Signature(SIGNATURE_2.toByteArray());
567
568        PackageInfo packageInfo = new PackageInfo();
569        packageInfo.packageName = "test";
570        packageInfo.signingInfo = new SigningInfo(
571                new PackageParser.SigningDetails(
572                        new Signature[] {SIGNATURE_1, SIGNATURE_2, SIGNATURE_3},
573                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
574                        null,
575                        null,
576                        null));
577        packageInfo.applicationInfo = new ApplicationInfo();
578
579        boolean result = AppBackupUtils.signaturesMatch(
580                new Signature[]{signature1Copy, signature2Copy, SIGNATURE_4}, packageInfo,
581                mMockPackageManagerInternal);
582
583        assertThat(result).isFalse();
584    }
585
586    @Test
587    public void signaturesMatch_singleStoredSignatureNoRotation_returnsTrue()
588            throws Exception {
589        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
590
591        PackageInfo packageInfo = new PackageInfo();
592        packageInfo.packageName = "test";
593        packageInfo.signingInfo = new SigningInfo(
594                new PackageParser.SigningDetails(
595                        new Signature[] {SIGNATURE_1},
596                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
597                        null,
598                        null,
599                        null));
600        packageInfo.applicationInfo = new ApplicationInfo();
601
602        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
603                packageInfo.packageName);
604
605        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
606                packageInfo, mMockPackageManagerInternal);
607
608        assertThat(result).isTrue();
609    }
610
611    @Test
612    public void signaturesMatch_singleStoredSignatureWithRotationAssumeDataCapability_returnsTrue()
613            throws Exception {
614        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
615
616        PackageInfo packageInfo = new PackageInfo();
617        packageInfo.packageName = "test";
618        packageInfo.signingInfo = new SigningInfo(
619                new PackageParser.SigningDetails(
620                        new Signature[] {SIGNATURE_2},
621                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
622                        null,
623                        new Signature[] {SIGNATURE_1, SIGNATURE_2},
624                        new int[] {0, 0}));
625        packageInfo.applicationInfo = new ApplicationInfo();
626
627        // we know signature1Copy is in history, and we want to assume it has
628        // SigningDetails.CertCapabilities.INSTALLED_DATA capability
629        doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
630                packageInfo.packageName);
631
632        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
633                packageInfo, mMockPackageManagerInternal);
634
635        assertThat(result).isTrue();
636    }
637
638    @Test
639    public void
640            signaturesMatch_singleStoredSignatureWithRotationAssumeNoDataCapability_returnsFalse()
641            throws Exception {
642        Signature signature1Copy = new Signature(SIGNATURE_1.toByteArray());
643
644        PackageInfo packageInfo = new PackageInfo();
645        packageInfo.packageName = "test";
646        packageInfo.signingInfo = new SigningInfo(
647                new PackageParser.SigningDetails(
648                        new Signature[] {SIGNATURE_2},
649                        PackageParser.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
650                        null,
651                        new Signature[] {SIGNATURE_1, SIGNATURE_2},
652                        new int[] {0, 0}));
653        packageInfo.applicationInfo = new ApplicationInfo();
654
655        // we know signature1Copy is in history, but we want to assume it does not have
656        // SigningDetails.CertCapabilities.INSTALLED_DATA capability
657        doReturn(false).when(mMockPackageManagerInternal).isDataRestoreSafe(signature1Copy,
658                packageInfo.packageName);
659
660        boolean result = AppBackupUtils.signaturesMatch(new Signature[] {signature1Copy},
661                packageInfo, mMockPackageManagerInternal);
662
663        assertThat(result).isFalse();
664    }
665
666    private static Signature generateSignature(byte i) {
667        byte[] signatureBytes = new byte[256];
668        signatureBytes[0] = i;
669        return new Signature(signatureBytes);
670    }
671}
672