2 * Copyright (C) 2018 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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
17 package com.android.server.backup.testing;
19 import static com.android.server.backup.testing.TestUtils.runToEndOfTasks;
21 import static org.mockito.ArgumentMatchers.anyBoolean;
22 import static org.mockito.Mockito.doAnswer;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.when;
25 import static org.robolectric.Shadows.shadowOf;
27 import android.annotation.Nullable;
28 import android.app.Application;
29 import android.app.IActivityManager;
30 import android.content.Context;
31 import android.content.pm.PackageManager;
32 import android.os.Handler;
33 import android.os.HandlerThread;
34 import android.os.Looper;
35 import android.os.PowerManager;
36 import android.os.Process;
37 import android.util.Log;
39 import com.android.server.backup.BackupAgentTimeoutParameters;
40 import com.android.server.backup.Trampoline;
41 import com.android.server.backup.TransportManager;
42 import com.android.server.backup.UserBackupManagerService;
44 import org.mockito.stubbing.Answer;
45 import org.robolectric.shadows.ShadowApplication;
46 import org.robolectric.shadows.ShadowBinder;
49 import java.lang.Thread.UncaughtExceptionHandler;
50 import java.util.concurrent.atomic.AtomicReference;
52 /** Test utils for {@link UserBackupManagerService} and friends. */
53 public class BackupManagerServiceTestUtils {
55 * Creates an instance of {@link UserBackupManagerService} with a new backup thread and runs
56 * tasks that were posted to it during instantiation.
58 * <p>If the class-under-test is going to execute methods as the system, it's a good idea to
59 * also call {@link #setUpBinderCallerAndApplicationAsSystem(Application)} before this method.
61 * @see #createUserBackupManagerServiceAndRunTasks(int, Context, HandlerThread, File, File,
64 public static UserBackupManagerService createUserBackupManagerServiceAndRunTasks(
69 TransportManager transportManager) {
70 return createUserBackupManagerServiceAndRunTasks(
71 userId, context, startBackupThread(null), baseStateDir, dataDir, transportManager);
75 * Creates an instance of {@link UserBackupManagerService} with the supplied backup thread
76 * {@code backupThread} and runs tasks that were posted to it during instantiation.
78 * <p>If the class-under-test is going to execute methods as the system, it's a good idea to
79 * also call {@link #setUpBinderCallerAndApplicationAsSystem(Application)} before this method.
81 public static UserBackupManagerService createUserBackupManagerServiceAndRunTasks(
84 HandlerThread backupThread,
87 TransportManager transportManager) {
88 UserBackupManagerService backupManagerService =
89 UserBackupManagerService.createAndInitializeService(
92 new Trampoline(context),
97 runToEndOfTasks(backupThread.getLooper());
98 return backupManagerService;
102 * Sets up basic mocks for {@link UserBackupManagerService} mock. If {@code
103 * backupManagerService} is a spy, make sure you provide in the arguments the same objects that
104 * the original object uses.
106 * <p>If the class-under-test is going to execute methods as the system, it's a good idea to
107 * also call {@link #setUpBinderCallerAndApplicationAsSystem(Application)}.
109 @SuppressWarnings("ResultOfMethodCallIgnored")
110 public static void setUpBackupManagerServiceBasics(
111 UserBackupManagerService backupManagerService,
112 Application application,
113 TransportManager transportManager,
114 PackageManager packageManager,
115 Handler backupHandler,
116 PowerManager.WakeLock wakeLock,
117 BackupAgentTimeoutParameters agentTimeoutParameters) {
119 when(backupManagerService.getContext()).thenReturn(application);
120 when(backupManagerService.getTransportManager()).thenReturn(transportManager);
121 when(backupManagerService.getPackageManager()).thenReturn(packageManager);
122 when(backupManagerService.getBackupHandler()).thenReturn(backupHandler);
123 when(backupManagerService.getCurrentOpLock()).thenReturn(new Object());
124 when(backupManagerService.getQueueLock()).thenReturn(new Object());
125 when(backupManagerService.getActivityManager()).thenReturn(mock(IActivityManager.class));
126 when(backupManagerService.getWakelock()).thenReturn(wakeLock);
127 when(backupManagerService.getAgentTimeoutParameters()).thenReturn(agentTimeoutParameters);
129 AccessorMock backupEnabled = mockAccessor(false);
130 doAnswer(backupEnabled.getter).when(backupManagerService).isBackupEnabled();
131 doAnswer(backupEnabled.setter).when(backupManagerService).setBackupEnabled(anyBoolean());
133 AccessorMock backupRunning = mockAccessor(false);
134 doAnswer(backupEnabled.getter).when(backupManagerService).isBackupRunning();
135 doAnswer(backupRunning.setter).when(backupManagerService).setBackupRunning(anyBoolean());
138 public static void setUpBinderCallerAndApplicationAsSystem(Application application) {
139 final int uid = Process.SYSTEM_UID;
140 final int pid = 1211;
141 ShadowBinder.setCallingUid(uid);
142 ShadowBinder.setCallingPid(pid);
143 ShadowApplication shadowApplication = shadowOf(application);
144 shadowApplication.grantPermissions(pid, uid, "android.permission.BACKUP");
145 shadowApplication.grantPermissions(pid, uid, "android.permission.CONFIRM_FULL_BACKUP");
149 * Returns one getter {@link Answer<T>} and one setter {@link Answer<T>} to be easily passed to
150 * Mockito mocking facilities.
152 * @param defaultValue Value returned by the getter if there was no setter call until then.
154 public static <T> AccessorMock<T> mockAccessor(T defaultValue) {
155 AtomicReference<T> holder = new AtomicReference<>(defaultValue);
156 return new AccessorMock<>(
157 invocation -> holder.get(),
159 holder.set(invocation.getArgument(0));
164 public static PowerManager.WakeLock createBackupWakeLock(Application application) {
165 PowerManager powerManager =
166 (PowerManager) application.getSystemService(Context.POWER_SERVICE);
167 return powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*backup*");
171 * Creates a backup thread associated with a looper, starts it and returns its looper for
172 * shadowing and creation of the backup handler.
174 * <p>Note that Robolectric simulates multi-thread in a single-thread to avoid flakiness, so
175 * even though we started the thread, you should control its execution via the shadow of the
178 * @return The {@link Looper} for the backup thread.
180 public static Looper startBackupThreadAndGetLooper() {
181 HandlerThread backupThread = new HandlerThread("backup");
182 backupThread.start();
183 return backupThread.getLooper();
187 * Similar to {@link #startBackupThreadAndGetLooper()} but with a custom exception handler and
188 * returning the thread instead of the looper associated with it.
190 * @param exceptionHandler Uncaught exception handler for backup thread.
191 * @return The backup thread.
192 * @see #startBackupThreadAndGetLooper()
194 public static HandlerThread startBackupThread(
195 @Nullable UncaughtExceptionHandler exceptionHandler) {
196 HandlerThread backupThread = new HandlerThread("backup");
197 backupThread.setUncaughtExceptionHandler(exceptionHandler);
198 backupThread.start();
203 * Similar to {@link #startBackupThread(UncaughtExceptionHandler)} but logging uncaught
204 * exceptions to logcat.
206 * @param tag Tag used for logging exceptions.
207 * @return The backup thread.
208 * @see #startBackupThread(UncaughtExceptionHandler)
210 public static HandlerThread startSilentBackupThread(String tag) {
211 return startBackupThread(
213 Log.e(tag, "Uncaught exception in test thread " + thread.getName(), e));
216 private BackupManagerServiceTestUtils() {}
218 public static class AccessorMock<T> {
219 public Answer<T> getter;
220 public Answer<T> setter;
222 private AccessorMock(Answer<T> getter, Answer<T> setter) {
223 this.getter = getter;
224 this.setter = setter;