Add tests for chooseRestorePolicy.

Bug: 38090803
Test: runtest -p com.android.server.backup frameworks-services
Change-Id: Iba0235f00ac0ba3150a8d3c77e27725a481c9c2b
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 63578b0..8784dd5 100644
--- a/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -16,11 +16,30 @@
 
 package com.android.server.backup.utils;
 
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_ID;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_APK_NOT_INSTALLED;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
+
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+
 import android.app.backup.IBackupManagerMonitor;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.Signature;
+import android.os.Bundle;
+import android.os.Process;
 import android.platform.test.annotations.Presubmit;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
@@ -29,16 +48,20 @@
 import com.android.frameworks.servicestests.R;
 import com.android.server.backup.FileMetadata;
 import com.android.server.backup.restore.PerformAdbRestoreTask;
+import com.android.server.backup.restore.RestorePolicy;
+import com.android.server.backup.testutils.PackageManagerStub;
 
 import com.google.common.hash.Hashing;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.io.InputStream;
+import java.util.List;
 
 @SmallTest
 @Presubmit
@@ -48,11 +71,13 @@
     private static final String TELEPHONY_PACKAGE_SIGNATURE_SHA256 =
             "301aa3cb081134501c45f1422abc66c24224fd5ded5fdc8f17e697176fd866aa";
     private static final int TELEPHONY_PACKAGE_VERSION = 25;
+    private static final Signature FAKE_SIGNATURE_1 = new Signature("1234");
+    private static final Signature FAKE_SIGNATURE_2 = new Signature("5678");
 
-    @Mock
-    private BytesReadListener mBytesReadListenerMock;
-    @Mock
-    private IBackupManagerMonitor mBackupManagerMonitorMock;
+    @Mock private BytesReadListener mBytesReadListenerMock;
+    @Mock private IBackupManagerMonitor mBackupManagerMonitorMock;
+
+    private final PackageManagerStub mPackageManagerStub = new PackageManagerStub();
     private Context mContext;
 
     @Before
@@ -137,4 +162,329 @@
         String signatureSha256 = Hashing.sha256().hashBytes(signatures[0].toByteArray()).toString();
         assertThat(signatureSha256).isEqualTo(TELEPHONY_PACKAGE_SIGNATURE_SHA256);
     }
+
+    @Test
+    public void chooseRestorePolicy_signaturesIsNull_returnsIgnore() throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                true /* allowApks */, new FileMetadata(), null /* signatures */);
+
+        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+        verifyZeroInteractions(mBackupManagerMonitorMock);
+    }
+
+    @Test
+    public void chooseRestorePolicy_packageDoesNotExistAndAllowApksAndHasApk_returnsAcceptIfApk()
+            throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        FileMetadata info = new FileMetadata();
+        info.hasApk = true;
+        PackageManagerStub.sPackageInfo = null;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                true /* allowApks */, info, new Signature[0] /* signatures */);
+
+        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_APK_NOT_INSTALLED);
+    }
+
+    @Test
+    public void
+    chooseRestorePolicy_packageDoesNotExistAndAllowApksAndDoesNotHaveApk_returnsAcceptIfApkLogsCannotRestore()
+            throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        FileMetadata info = new FileMetadata();
+        info.hasApk = false;
+        PackageManagerStub.sPackageInfo = null;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                true /* allowApks */, info, new Signature[0] /* signatures */);
+
+        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock, times(2)).onEvent(bundleCaptor.capture());
+        List<Bundle> eventBundles = bundleCaptor.getAllValues();
+        assertThat(eventBundles).hasSize(2);
+        assertThat(eventBundles.get(0).get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_APK_NOT_INSTALLED);
+        assertThat(eventBundles.get(1).get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK);
+    }
+
+    @Test
+    public void chooseRestorePolicy_packageDoesNotExistAndDoesNotAllowApks_returnsIgnore()
+            throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        PackageManagerStub.sPackageInfo = null;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
+
+        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_APK_NOT_INSTALLED);
+    }
+
+    @Test
+    public void chooseRestorePolicy_doesNotAllowsBackup_returnsIgnore() throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags = ~ApplicationInfo.FLAG_ALLOW_BACKUP;
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
+
+        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE);
+    }
+
+    @Test
+    public void chooseRestorePolicy_systemAppWithNoAgent_returnsIgnore() throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        packageInfo.applicationInfo.uid = Process.SYSTEM_UID;
+        packageInfo.applicationInfo.backupAgentName = null;
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, new FileMetadata(), new Signature[0] /* signatures */);
+
+        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_SYSTEM_APP_NO_AGENT);
+    }
+
+    @Test
+    public void chooseRestorePolicy_nonSystemAppSignaturesDoNotMatch_returnsIgnore()
+            throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        packageInfo.applicationInfo.backupAgentName = null;
+        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_2};
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, new FileMetadata(), signatures);
+
+        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH);
+    }
+
+    @Test
+    public void chooseRestorePolicy_systemAppWithBackupAgentAndRestoreAnyVersion_returnsAccept() throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |=
+                ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
+        packageInfo.applicationInfo.uid = Process.SYSTEM_UID;
+        packageInfo.applicationInfo.backupAgentName = "backup.agent";
+        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, new FileMetadata(), signatures);
+
+        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_RESTORE_ANY_VERSION);
+    }
+
+    @Test
+    public void chooseRestorePolicy_restoreAnyVersion_returnsAccept() throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |=
+                ApplicationInfo.FLAG_ALLOW_BACKUP | ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
+        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        packageInfo.applicationInfo.backupAgentName = null;
+        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, new FileMetadata(), signatures);
+
+        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_RESTORE_ANY_VERSION);
+    }
+
+    @Test
+    public void chooseRestorePolicy_notRestoreAnyVersionButVersionMatch_returnsAccept()
+            throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+        FileMetadata info = new FileMetadata();
+        info.version = 1;
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
+        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        packageInfo.applicationInfo.backupAgentName = null;
+        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.versionCode = 2;
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, info, signatures);
+
+        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_VERSIONS_MATCH);
+    }
+
+    @Test
+    public void
+    chooseRestorePolicy_notRestoreAnyVersionAndVersionMismatchButAllowApksAndHasApk_returnsAcceptIfApk()
+            throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+        FileMetadata info = new FileMetadata();
+        info.version = 2;
+        info.hasApk = true;
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
+        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        packageInfo.applicationInfo.backupAgentName = null;
+        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.versionCode = 1;
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                true /* allowApks */, info, signatures);
+
+        assertThat(policy).isEqualTo(RestorePolicy.ACCEPT_IF_APK);
+        verifyNoMoreInteractions(mBackupManagerMonitorMock);
+    }
+
+    @Test
+    public void
+    chooseRestorePolicy_notRestoreAnyVersionAndVersionMismatchAndDoesNotAllowApks_returnsIgnore()
+            throws Exception {
+        InputStream inputStream = mContext.getResources().openRawResource(
+                R.raw.backup_telephony_no_password);
+        InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+                inputStream, null);
+        TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+                mBytesReadListenerMock, mBackupManagerMonitorMock);
+        Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+        FileMetadata info = new FileMetadata();
+        info.version = 2;
+
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.applicationInfo = new ApplicationInfo();
+        packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
+        packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        packageInfo.applicationInfo.backupAgentName = null;
+        packageInfo.signatures = new Signature[]{FAKE_SIGNATURE_1};
+        packageInfo.versionCode = 1;
+        PackageManagerStub.sPackageInfo = packageInfo;
+
+        RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+                false /* allowApks */, info, signatures);
+
+        assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+        assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+                LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
+    }
+
 }
\ No newline at end of file