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