1 /* 2 * Copyright (C) 2023 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 android.backup.cts; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.Manifest; 22 import android.app.UiAutomation; 23 import android.app.backup.BackupManager; 24 import android.app.backup.BackupManagerMonitor; 25 import android.app.backup.BackupObserver; 26 import android.app.backup.BackupRestoreEventLogger.DataTypeResult; 27 import android.app.backup.RestoreObserver; 28 import android.app.backup.RestoreSession; 29 import android.content.Context; 30 import android.os.Bundle; 31 32 import androidx.test.runner.AndroidJUnit4; 33 34 import org.junit.After; 35 import org.junit.Before; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 import java.util.List; 40 import java.util.concurrent.CountDownLatch; 41 import java.util.concurrent.TimeUnit; 42 43 @RunWith(AndroidJUnit4.class) 44 public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest { 45 private static final String BACKUP_APP_PACKAGE 46 = "android.cts.backup.backuprestoreeventloggerapp"; 47 private static final int OPERATION_TIMEOUT_SECONDS = 30; 48 private static final int BACKUP_APP_RESTART_SLEEP_MS = 3_000; 49 50 51 // Copied from LoggingFullBackupAgent.java 52 private static final String DATA_TYPE = "data_type"; 53 private static final String ERROR = "error"; 54 private static final String METADATA = "metadata"; 55 private static final int SUCCESS_COUNT = 1; 56 private static final int FAIL_COUNT = 2; 57 58 private final TestBackupManagerMonitor mBackupMonitor = new TestBackupManagerMonitor(); 59 private final TestBackupManagerMonitor mRestoreMonitor = new TestBackupManagerMonitor(); 60 61 private UiAutomation mUiAutomation; 62 private BackupManager mBackupManager; 63 private BackupObserver mBackupObserver; 64 private RestoreObserver mRestoreObserver; 65 private CountDownLatch mOperationLatch; 66 private RestoreSession mRestoreSession; 67 68 @Before setUp()69 public void setUp() throws Exception { 70 super.setUp(); 71 72 Context context = mInstrumentation.getTargetContext(); 73 74 mUiAutomation = mInstrumentation.getUiAutomation(); 75 mBackupManager = new BackupManager(context); 76 mBackupObserver = new TestBackupObserver(); 77 mRestoreObserver = new TestRestoreObserver(); 78 79 mUiAutomation.adoptShellPermissionIdentity(Manifest.permission.BACKUP); 80 } 81 82 @After tearDown()83 public void tearDown() throws Exception { 84 85 if (mRestoreSession != null){ 86 mRestoreSession.endRestoreSession(); 87 } 88 mUiAutomation.dropShellPermissionIdentity(); 89 } 90 91 @Test testBackupRestoreRoundTrip_logsSentToMonitor()92 public void testBackupRestoreRoundTrip_logsSentToMonitor() throws Exception { 93 if (!isBackupSupported()) { 94 return; 95 } 96 97 // Ensure the app is not in stopped state. 98 createTestFileOfSize(BACKUP_APP_PACKAGE, /* size */ 1); 99 100 // Run a backup. 101 mOperationLatch = new CountDownLatch(/* count */ 1); 102 mBackupManager.requestBackup(new String[] { BACKUP_APP_PACKAGE }, 103 /* observer */ mBackupObserver, mBackupMonitor, /* flags */ 0); 104 boolean backupFinished = mOperationLatch.await(OPERATION_TIMEOUT_SECONDS, 105 TimeUnit.SECONDS); 106 107 // Sleep to allow the app to be killed, so that this doesn't disrupt the restore operation 108 Thread.sleep(BACKUP_APP_RESTART_SLEEP_MS); 109 110 // Run a restore. 111 mOperationLatch = new CountDownLatch(/* count */ 1); 112 mRestoreSession = mBackupManager.beginRestoreSession(); 113 mRestoreSession.restorePackage(BACKUP_APP_PACKAGE, mRestoreObserver, mRestoreMonitor); 114 boolean restoreFinished = mOperationLatch.await(OPERATION_TIMEOUT_SECONDS, 115 TimeUnit.SECONDS); 116 117 118 assertThat(backupFinished).isTrue(); 119 assertThat(restoreFinished).isTrue(); 120 assertLoggingResultsAreCorrect(mBackupMonitor); 121 assertLoggingResultsAreCorrect(mRestoreMonitor); 122 } 123 124 /** 125 * Assert the logging results are consistent with what is logged in LoggingFullBackupAgent.java. 126 */ assertLoggingResultsAreCorrect(TestBackupManagerMonitor monitor)127 private void assertLoggingResultsAreCorrect(TestBackupManagerMonitor monitor) { 128 assertThat(monitor.mAgentBundle).isNotNull(); 129 List<DataTypeResult> dataTypeList = monitor.mAgentBundle.getParcelableArrayList( 130 BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS, 131 DataTypeResult.class); 132 assertThat(dataTypeList.size()).isEqualTo(/* expected */ 1); 133 DataTypeResult dataTypeResult = dataTypeList.get(/* index */ 0); 134 assertThat(dataTypeResult.getDataType()).isEqualTo(DATA_TYPE); 135 assertThat(dataTypeResult.getSuccessCount()).isEqualTo(SUCCESS_COUNT); 136 assertThat(dataTypeResult.getErrors().get(ERROR)).isEqualTo(FAIL_COUNT); 137 } 138 139 private static class TestBackupManagerMonitor extends BackupManagerMonitor { 140 private Bundle mAgentBundle = null; 141 142 @Override onEvent(Bundle event)143 public void onEvent(Bundle event) { 144 if (event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID) 145 == BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS) { 146 mAgentBundle = event; 147 } 148 } 149 } 150 151 private class TestBackupObserver extends BackupObserver { 152 @Override backupFinished(int status)153 public void backupFinished(int status) { 154 assertThat(status).isEqualTo(/* expected */ 0); 155 mOperationLatch.countDown(); 156 } 157 } 158 159 private class TestRestoreObserver extends RestoreObserver { 160 161 @Override restoreFinished(int error)162 public void restoreFinished(int error) { 163 assertThat(error).isEqualTo(/* expected */ 0); 164 mOperationLatch.countDown(); 165 } 166 } 167 } 168