Merge changes from topic "fsd2d-backup-agent"
* changes:
[FSD2D] Pass @OperationType at agent creation in B&R code
[FSD2D] Adjust backup agent creation for device-to-device migrations
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9b13d25..7a4f11d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -37,6 +37,7 @@
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.backup.BackupAgent;
+import android.app.backup.BackupManager;
import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ActivityLifecycleItem.LifecycleState;
import android.app.servertransaction.ActivityRelaunchItem;
@@ -289,6 +290,8 @@
private final Object mNetworkPolicyLock = new Object();
+ private static final String DEFAULT_FULL_BACKUP_AGENT = "android.app.backup.FullBackupAgent";
+
/**
* Denotes the sequence number of the process state change for which the main thread needs
* to block until the network rules are updated for it.
@@ -737,6 +740,7 @@
CompatibilityInfo compatInfo;
int backupMode;
int userId;
+ int operationType;
public String toString() {
return "CreateBackupAgentData{appInfo=" + appInfo
+ " backupAgent=" + appInfo.backupAgentName
@@ -957,12 +961,13 @@
}
public final void scheduleCreateBackupAgent(ApplicationInfo app,
- CompatibilityInfo compatInfo, int backupMode, int userId) {
+ CompatibilityInfo compatInfo, int backupMode, int userId, int operationType) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
d.compatInfo = compatInfo;
d.backupMode = backupMode;
d.userId = userId;
+ d.operationType = operationType;
sendMessage(H.CREATE_BACKUP_AGENT, d);
}
@@ -4075,12 +4080,7 @@
return;
}
- String classname = data.appInfo.backupAgentName;
- // full backup operation but no app-supplied agent? use the default implementation
- if (classname == null && (data.backupMode == ApplicationThreadConstants.BACKUP_MODE_FULL
- || data.backupMode == ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL)) {
- classname = "android.app.backup.FullBackupAgent";
- }
+ String classname = getBackupAgentName(data);
try {
IBinder binder = null;
@@ -4104,7 +4104,7 @@
context.setOuterContext(agent);
agent.attach(context);
- agent.onCreate(UserHandle.of(data.userId));
+ agent.onCreate(UserHandle.of(data.userId), data.operationType);
binder = agent.onBind();
backupAgents.put(packageName, agent);
} catch (Exception e) {
@@ -4132,6 +4132,23 @@
}
}
+ private String getBackupAgentName(CreateBackupAgentData data) {
+ String agentName = data.appInfo.backupAgentName;
+ if (!UserHandle.isCore(data.appInfo.uid)
+ && data.operationType == BackupManager.OperationType.MIGRATION) {
+ // If this is a migration, use the default backup agent regardless of the app's
+ // preferences.
+ agentName = DEFAULT_FULL_BACKUP_AGENT;
+ } else {
+ // full backup operation but no app-supplied agent? use the default implementation
+ if (agentName == null && (data.backupMode == ApplicationThreadConstants.BACKUP_MODE_FULL
+ || data.backupMode == ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL)) {
+ agentName = DEFAULT_FULL_BACKUP_AGENT;
+ }
+ }
+ return agentName;
+ }
+
// Tear down a BackupAgent
private void handleDestroyBackupAgent(CreateBackupAgentData data) {
if (DEBUG_BACKUP) Slog.v(TAG, "handleDestroyBackupAgent: " + data);
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3b6a7b8..9964011 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -288,7 +288,8 @@
void stopAppSwitches();
@UnsupportedAppUsage
void resumeAppSwitches();
- boolean bindBackupAgent(in String packageName, int backupRestoreMode, int targetUserId);
+ boolean bindBackupAgent(in String packageName, int backupRestoreMode, int targetUserId,
+ int operationType);
void backupAgentCreated(in String packageName, in IBinder agent, int userId);
void unbindBackupAgent(in ApplicationInfo appInfo);
int getUidForIntentSender(in IIntentSender sender);
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index 6e9157e..24da504 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -95,7 +95,7 @@
void profilerControl(boolean start, in ProfilerInfo profilerInfo, int profileType);
void setSchedulingGroup(int group);
void scheduleCreateBackupAgent(in ApplicationInfo app, in CompatibilityInfo compatInfo,
- int backupMode, int userId);
+ int backupMode, int userId, int operationType);
void scheduleDestroyBackupAgent(in ApplicationInfo app,
in CompatibilityInfo compatInfo, int userId);
void scheduleOnNewActivityOptions(IBinder token, in Bundle options);
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index a789169..16ddcd1 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.app.IBackupAgent;
import android.app.QueuedWork;
+import android.app.backup.BackupManager.OperationType;
import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags;
import android.content.Context;
import android.content.ContextWrapper;
@@ -38,6 +39,8 @@
import android.util.ArraySet;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParserException;
@@ -50,6 +53,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -129,6 +133,7 @@
public abstract class BackupAgent extends ContextWrapper {
private static final String TAG = "BackupAgent";
private static final boolean DEBUG = false;
+ private static final int DEFAULT_OPERATION_TYPE = OperationType.BACKUP;
/** @hide */
public static final int RESULT_SUCCESS = 0;
@@ -186,6 +191,9 @@
Handler mHandler = null;
@Nullable private UserHandle mUser;
+ // This field is written from the main thread (in onCreate), and read in a Binder thread (in
+ // onFullBackup that is called from system_server via Binder).
+ @OperationType private volatile int mOperationType = DEFAULT_OPERATION_TYPE;
Handler getHandler() {
if (mHandler == null) {
@@ -229,6 +237,13 @@
}
/**
+ * @hide
+ */
+ public void onCreate(UserHandle user) {
+ onCreate(user, DEFAULT_OPERATION_TYPE);
+ }
+
+ /**
* Provided as a convenience for agent implementations that need an opportunity
* to do one-time initialization before the actual backup or restore operation
* is begun with information about the calling user.
@@ -236,10 +251,11 @@
*
* @hide
*/
- public void onCreate(UserHandle user) {
+ public void onCreate(UserHandle user, @OperationType int operationType) {
onCreate();
mUser = user;
+ mOperationType = operationType;
}
/**
@@ -390,12 +406,9 @@
return;
}
- Map<String, Set<PathWithRequiredFlags>> manifestIncludeMap;
- ArraySet<PathWithRequiredFlags> manifestExcludeSet;
+ IncludeExcludeRules includeExcludeRules;
try {
- manifestIncludeMap =
- backupScheme.maybeParseAndGetCanonicalIncludePaths();
- manifestExcludeSet = backupScheme.maybeParseAndGetCanonicalExcludePaths();
+ includeExcludeRules = getIncludeExcludeRules(backupScheme);
} catch (IOException | XmlPullParserException e) {
if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
Log.v(FullBackup.TAG_XML_PARSER,
@@ -404,6 +417,10 @@
}
return;
}
+ Map<String, Set<PathWithRequiredFlags>> manifestIncludeMap
+ = includeExcludeRules.getIncludeMap();
+ Set<PathWithRequiredFlags> manifestExcludeSet
+ = includeExcludeRules.getExcludeSet();
final String packageName = getPackageName();
final ApplicationInfo appInfo = getApplicationInfo();
@@ -528,6 +545,24 @@
}
}
+ /** @hide */
+ @VisibleForTesting
+ public IncludeExcludeRules getIncludeExcludeRules(FullBackup.BackupScheme backupScheme)
+ throws IOException, XmlPullParserException {
+ if (mOperationType == OperationType.MIGRATION) {
+ return IncludeExcludeRules.emptyRules();
+ }
+
+ Map<String, Set<PathWithRequiredFlags>> manifestIncludeMap;
+ ArraySet<PathWithRequiredFlags> manifestExcludeSet;
+
+ manifestIncludeMap =
+ backupScheme.maybeParseAndGetCanonicalIncludePaths();
+ manifestExcludeSet = backupScheme.maybeParseAndGetCanonicalExcludePaths();
+
+ return new IncludeExcludeRules(manifestIncludeMap, manifestExcludeSet);
+ }
+
/**
* Notification that the application's current backup operation causes it to exceed
* the maximum size permitted by the transport. The ongoing backup operation is
@@ -570,7 +605,7 @@
*/
private void applyXmlFiltersAndDoFullBackupForDomain(String packageName, String domainToken,
Map<String, Set<PathWithRequiredFlags>> includeMap,
- ArraySet<PathWithRequiredFlags> filterSet, ArraySet<String> traversalExcludeSet,
+ Set<PathWithRequiredFlags> filterSet, ArraySet<String> traversalExcludeSet,
FullBackupDataOutput data) throws IOException {
if (includeMap == null || includeMap.size() == 0) {
// Do entire sub-tree for the provided token.
@@ -742,7 +777,7 @@
* @hide
*/
protected final void fullBackupFileTree(String packageName, String domain, String startingPath,
- ArraySet<PathWithRequiredFlags> manifestExcludes,
+ Set<PathWithRequiredFlags> manifestExcludes,
ArraySet<String> systemExcludes,
FullBackupDataOutput output) {
// Pull out the domain and set it aside to use when making the tarball.
@@ -811,7 +846,7 @@
}
private boolean manifestExcludesContainFilePath(
- ArraySet<PathWithRequiredFlags> manifestExcludes, String filePath) {
+ Set<PathWithRequiredFlags> manifestExcludes, String filePath) {
for (PathWithRequiredFlags exclude : manifestExcludes) {
String excludePath = exclude.getPath();
if (excludePath != null && excludePath.equals(filePath)) {
@@ -1265,4 +1300,53 @@
throw new IllegalStateException(mMessage);
}
}
+
+ /** @hide */
+ @VisibleForTesting
+ public static class IncludeExcludeRules {
+ private final Map<String, Set<PathWithRequiredFlags>> mManifestIncludeMap;
+ private final Set<PathWithRequiredFlags> mManifestExcludeSet;
+
+ /** @hide */
+ public IncludeExcludeRules(
+ Map<String, Set<PathWithRequiredFlags>> manifestIncludeMap,
+ Set<PathWithRequiredFlags> manifestExcludeSet) {
+ mManifestIncludeMap = manifestIncludeMap;
+ mManifestExcludeSet = manifestExcludeSet;
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ public static IncludeExcludeRules emptyRules() {
+ return new IncludeExcludeRules(Collections.emptyMap(), new ArraySet<>());
+ }
+
+ private Map<String, Set<PathWithRequiredFlags>> getIncludeMap() {
+ return mManifestIncludeMap;
+ }
+
+ private Set<PathWithRequiredFlags> getExcludeSet() {
+ return mManifestExcludeSet;
+ }
+
+ /** @hide */
+ @Override
+ public int hashCode() {
+ return Objects.hash(mManifestIncludeMap, mManifestExcludeSet);
+ }
+
+ /** @hide */
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+ IncludeExcludeRules that = (IncludeExcludeRules) object;
+ return Objects.equals(mManifestIncludeMap, that.mManifestIncludeMap) &&
+ Objects.equals(mManifestExcludeSet, that.mManifestExcludeSet);
+ }
+ }
}
diff --git a/core/tests/coretests/src/android/app/backup/BackupAgentTest.java b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
new file mode 100644
index 0000000..ea903f2
--- /dev/null
+++ b/core/tests/coretests/src/android/app/backup/BackupAgentTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.app.backup.BackupAgent.IncludeExcludeRules;
+import android.app.backup.BackupManager.OperationType;
+import android.app.backup.FullBackup.BackupScheme.PathWithRequiredFlags;
+import android.os.ParcelFileDescriptor;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class BackupAgentTest {
+ // An arbitrary user.
+ private static final UserHandle USER_HANDLE = new UserHandle(15);
+
+ @Mock FullBackup.BackupScheme mBackupScheme;
+
+ private BackupAgent mBackupAgent;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testGetIncludeExcludeRules_isMigration_returnsEmptyRules() throws Exception {
+ mBackupAgent = getAgentForOperationType(OperationType.MIGRATION);
+
+ IncludeExcludeRules rules = mBackupAgent.getIncludeExcludeRules(mBackupScheme);
+ assertThat(rules).isEqualTo(IncludeExcludeRules.emptyRules());
+ }
+
+ @Test
+ public void testGetIncludeExcludeRules_isNotMigration_returnsRules() throws Exception {
+ PathWithRequiredFlags path = new PathWithRequiredFlags("path", /* requiredFlags */ 0);
+ Map<String, Set<PathWithRequiredFlags>> includePaths = Collections.singletonMap("test",
+ Collections.singleton(path));
+ ArraySet<PathWithRequiredFlags> excludePaths = new ArraySet<>();
+ excludePaths.add(path);
+ IncludeExcludeRules expectedRules = new IncludeExcludeRules(includePaths, excludePaths);
+
+ mBackupAgent = getAgentForOperationType(OperationType.BACKUP);
+ when(mBackupScheme.maybeParseAndGetCanonicalExcludePaths()).thenReturn(excludePaths);
+ when(mBackupScheme.maybeParseAndGetCanonicalIncludePaths()).thenReturn(includePaths);
+
+ IncludeExcludeRules rules = mBackupAgent.getIncludeExcludeRules(mBackupScheme);
+ assertThat(rules).isEqualTo(expectedRules);
+ }
+
+ private BackupAgent getAgentForOperationType(@OperationType int operationType) {
+ BackupAgent agent = new TestFullBackupAgent();
+ agent.onCreate(USER_HANDLE, operationType);
+ return agent;
+ }
+
+ private static class TestFullBackupAgent extends BackupAgent {
+
+ @Override
+ public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+ ParcelFileDescriptor newState) throws IOException {
+ // Left empty as this is a full backup agent.
+ }
+
+ @Override
+ public void onRestore(BackupDataInput data, int appVersionCode,
+ ParcelFileDescriptor newState) throws IOException {
+ // Left empty as this is a full backup agent.
+ }
+ }
+}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index f11adef..e0d702e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -494,7 +494,8 @@
@Override
public void scheduleCreateBackupAgent(ApplicationInfo applicationInfo,
- CompatibilityInfo compatibilityInfo, int i, int userId) throws RemoteException {
+ CompatibilityInfo compatibilityInfo, int i, int userId, int operatioType)
+ throws RemoteException {
}
@Override
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index c9b09e3..0855b9d 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -10,6 +10,7 @@
import android.app.ApplicationThreadConstants;
import android.app.IBackupAgent;
+import android.app.backup.BackupManager;
import android.app.backup.FullBackup;
import android.app.backup.FullBackupDataOutput;
import android.app.backup.IBackupCallback;
@@ -146,7 +147,8 @@
private IBackupAgent bindToAgent(ApplicationInfo targetApp) {
try {
return mBackupManagerService.bindToAgentSynchronous(targetApp,
- ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
+ ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL,
+ BackupManager.OperationType.BACKUP);
} catch (SecurityException e) {
Slog.e(TAG, "error in binding to agent for package " + targetApp.packageName
+ ". " + e);
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 27a280a..29235dd 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -1651,13 +1651,15 @@
/** Fires off a backup agent, blocking until it attaches or times out. */
@Nullable
- public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode) {
+ public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode,
+ @OperationType int operationType) {
IBackupAgent agent = null;
synchronized (mAgentConnectLock) {
mConnecting = true;
mConnectedAgent = null;
try {
- if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId)) {
+ if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId,
+ operationType)) {
Slog.d(TAG, addUserIdToLogMessage(mUserId, "awaiting agent for " + app));
// success; wait for the agent to arrive
diff --git a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
index 846c6a2..fe5497f 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -41,6 +41,7 @@
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.remote.RemoteCall;
+import com.android.server.backup.utils.BackupEligibilityRules;
import com.android.server.backup.utils.FullBackupUtils;
import java.io.File;
@@ -64,6 +65,7 @@
private final int mOpToken;
private final int mTransportFlags;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
+ private final BackupEligibilityRules mBackupEligibilityRules;
class FullBackupRunner implements Runnable {
private final @UserIdInt int mUserId;
@@ -190,7 +192,8 @@
BackupRestoreTask timeoutMonitor,
long quota,
int opToken,
- int transportFlags) {
+ int transportFlags,
+ BackupEligibilityRules backupEligibilityRules) {
this.backupManagerService = backupManagerService;
mOutput = output;
mPreflightHook = preflightHook;
@@ -204,6 +207,7 @@
Objects.requireNonNull(
backupManagerService.getAgentTimeoutParameters(),
"Timeout parameters cannot be null");
+ mBackupEligibilityRules = backupEligibilityRules;
}
public int preflightCheck() throws RemoteException {
@@ -302,7 +306,8 @@
}
mAgent =
backupManagerService.bindToAgentSynchronous(
- mPkg.applicationInfo, ApplicationThreadConstants.BACKUP_MODE_FULL);
+ mPkg.applicationInfo, ApplicationThreadConstants.BACKUP_MODE_FULL,
+ mBackupEligibilityRules.getOperationType());
}
return mAgent != null;
}
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
index 0a11774..448e086 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -421,7 +421,8 @@
this,
Long.MAX_VALUE,
mCurrentOpToken,
- /*transportFlags=*/ 0);
+ /*transportFlags=*/ 0,
+ mBackupEligibilityRules);
sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
// Don't need to check preflight result as there is no preflight hook.
diff --git a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
index 1fa8892..a4d47d4 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -860,7 +860,8 @@
this,
mQuota,
mCurrentOpToken,
- mTransportFlags);
+ mTransportFlags,
+ mBackupEligibilityRules);
try {
try {
if (!mIsCancelled) {
diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
index 6124171..7267cdf 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -731,7 +731,8 @@
try {
agent =
mBackupManagerService.bindToAgentSynchronous(
- packageInfo.applicationInfo, BACKUP_MODE_INCREMENTAL);
+ packageInfo.applicationInfo, BACKUP_MODE_INCREMENTAL,
+ mBackupEligibilityRules.getOperationType());
if (agent == null) {
mReporter.onAgentError(packageName);
throw AgentException.transitory();
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index e42d3bd..6220679 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -49,6 +49,7 @@
import com.android.server.backup.KeyValueAdbRestoreEngine;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.fullbackup.FullBackupObbConnection;
+import com.android.server.backup.utils.BackupEligibilityRules;
import com.android.server.backup.utils.BytesReadListener;
import com.android.server.backup.utils.FullBackupRestoreObserverUtils;
import com.android.server.backup.utils.RestoreUtils;
@@ -129,11 +130,13 @@
private final boolean mIsAdbRestore;
@GuardedBy("mPipesLock")
private boolean mPipesClosed;
+ private final BackupEligibilityRules mBackupEligibilityRules;
public FullRestoreEngine(UserBackupManagerService backupManagerService,
BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer,
IBackupManagerMonitor monitor, PackageInfo onlyPackage, boolean allowApks,
- int ephemeralOpToken, boolean isAdbRestore) {
+ int ephemeralOpToken, boolean isAdbRestore,
+ BackupEligibilityRules backupEligibilityRules) {
mBackupManagerService = backupManagerService;
mEphemeralOpToken = ephemeralOpToken;
mMonitorTask = monitorTask;
@@ -147,6 +150,7 @@
"Timeout parameters cannot be null");
mIsAdbRestore = isAdbRestore;
mUserId = backupManagerService.getUserId();
+ mBackupEligibilityRules = backupEligibilityRules;
}
public IBackupAgent getAgent() {
@@ -365,7 +369,8 @@
mAgent = mBackupManagerService.bindToAgentSynchronous(mTargetApp,
FullBackup.KEY_VALUE_DATA_TOKEN.equals(info.domain)
? ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL
- : ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL);
+ : ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL,
+ mBackupEligibilityRules.getOperationType());
mAgentPackage = pkg;
} catch (IOException | NameNotFoundException e) {
// fall through to error handling
diff --git a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
index 923bb08..c94286f 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformAdbRestoreTask.java
@@ -25,12 +25,15 @@
import static com.android.server.backup.UserBackupManagerService.BACKUP_FILE_VERSION;
import android.app.backup.IFullBackupRestoreObserver;
+import android.content.pm.PackageManagerInternal;
import android.os.ParcelFileDescriptor;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.fullbackup.FullBackupObbConnection;
+import com.android.server.backup.utils.BackupEligibilityRules;
import com.android.server.backup.utils.FullBackupRestoreObserverUtils;
import com.android.server.backup.utils.PasswordUtils;
@@ -102,7 +105,10 @@
}
FullRestoreEngine mEngine = new FullRestoreEngine(mBackupManagerService, null,
- mObserver, null, null, true, 0 /*unused*/, true);
+ mObserver, null, null, true, 0 /*unused*/, true,
+ BackupEligibilityRules.forBackup(mBackupManagerService.getPackageManager(),
+ LocalServices.getService(PackageManagerInternal.class),
+ mBackupManagerService.getUserId()));
FullRestoreEngineThread mEngineThread = new FullRestoreEngineThread(mEngine,
tarInputStream);
mEngineThread.run();
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index a7e3604..7baf559 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -162,6 +162,7 @@
private final int mEphemeralOpToken;
private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
+ private final BackupEligibilityRules mBackupEligibilityRules;
@VisibleForTesting
PerformUnifiedRestoreTask(UserBackupManagerService backupManagerService) {
@@ -171,6 +172,7 @@
mTransportManager = null;
mEphemeralOpToken = 0;
mUserId = 0;
+ mBackupEligibilityRules = null;
this.backupManagerService = backupManagerService;
}
@@ -208,6 +210,7 @@
mAgentTimeoutParameters = Objects.requireNonNull(
backupManagerService.getAgentTimeoutParameters(),
"Timeout parameters cannot be null");
+ mBackupEligibilityRules = backupEligibilityRules;
if (targetPackage != null) {
// Single package restore
@@ -656,7 +659,8 @@
// Good to go! Set up and bind the agent...
mAgent = backupManagerService.bindToAgentSynchronous(
mCurrentPackage.applicationInfo,
- ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
+ ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL,
+ mBackupEligibilityRules.getOperationType());
if (mAgent == null) {
Slog.w(TAG, "Can't find backup agent for " + packageName);
mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
@@ -913,7 +917,8 @@
mCurrentPackage.packageName);
mEngine = new FullRestoreEngine(backupManagerService, this, null,
- mMonitor, mCurrentPackage, false, mEphemeralOpToken, false);
+ mMonitor, mCurrentPackage, false, mEphemeralOpToken, false,
+ mBackupEligibilityRules);
mEngineThread = new FullRestoreEngineThread(mEngine, mEnginePipes[0]);
ParcelFileDescriptor eWriteEnd = mEnginePipes[1];
diff --git a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
index ee05c2b..d659897 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
@@ -318,4 +318,8 @@
return true;
}
}
+
+ public int getOperationType() {
+ return mOperationType;
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 91a1487..71d12ee 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -176,6 +176,8 @@
import android.app.ProcessMemoryState;
import android.app.ProfilerInfo;
import android.app.WaitResult;
+import android.app.backup.BackupManager;
+import android.app.backup.BackupManager.OperationType;
import android.app.backup.IBackupManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
@@ -5374,7 +5376,7 @@
try {
thread.scheduleCreateBackupAgent(backupTarget.appInfo,
compatibilityInfoForPackage(backupTarget.appInfo),
- backupTarget.backupMode, backupTarget.userId);
+ backupTarget.backupMode, backupTarget.userId, backupTarget.operationType);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
badApp = true;
@@ -13776,7 +13778,8 @@
// Cause the target app to be launched if necessary and its backup agent
// instantiated. The backup agent will invoke backupAgentCreated() on the
// activity manager to announce its creation.
- public boolean bindBackupAgent(String packageName, int backupMode, int targetUserId) {
+ public boolean bindBackupAgent(String packageName, int backupMode, int targetUserId,
+ @OperationType int operationType) {
if (DEBUG_BACKUP) {
Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode
+ " targetUserId=" + targetUserId + " callingUid = " + Binder.getCallingUid()
@@ -13819,7 +13822,7 @@
+ app.packageName + ": " + e);
}
- BackupRecord r = new BackupRecord(app, backupMode, targetUserId);
+ BackupRecord r = new BackupRecord(app, backupMode, targetUserId, operationType);
ComponentName hostingName =
(backupMode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL)
? new ComponentName(app.packageName, app.backupAgentName)
@@ -13858,7 +13861,8 @@
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "Agent proc already running: " + proc);
try {
proc.thread.scheduleCreateBackupAgent(app,
- compatibilityInfoForPackage(app), backupMode, targetUserId);
+ compatibilityInfoForPackage(app), backupMode, targetUserId,
+ operationType);
} catch (RemoteException e) {
// Will time out on the backup manager side
}
diff --git a/services/core/java/com/android/server/am/BackupRecord.java b/services/core/java/com/android/server/am/BackupRecord.java
index 37b4be4..d419856 100644
--- a/services/core/java/com/android/server/am/BackupRecord.java
+++ b/services/core/java/com/android/server/am/BackupRecord.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import android.app.backup.BackupManager;
+import android.app.backup.BackupManager.OperationType;
import android.content.pm.ApplicationInfo;
/** @hide */
@@ -30,14 +32,16 @@
final ApplicationInfo appInfo; // information about BackupAgent's app
final int userId; // user for which backup is performed
final int backupMode; // full backup / incremental / restore
+ @OperationType final int operationType; // see BackupManager#OperationType
ProcessRecord app; // where this agent is running or null
// ----- Implementation -----
- BackupRecord(ApplicationInfo _appInfo, int _backupMode, int _userId) {
+ BackupRecord(ApplicationInfo _appInfo, int _backupMode, int _userId, int _operationType) {
appInfo = _appInfo;
backupMode = _backupMode;
userId = _userId;
+ operationType = _operationType;
}
public String toString() {
diff --git a/services/core/java/com/android/server/backup/SystemBackupAgent.java b/services/core/java/com/android/server/backup/SystemBackupAgent.java
index 0a30b76..d98298c 100644
--- a/services/core/java/com/android/server/backup/SystemBackupAgent.java
+++ b/services/core/java/com/android/server/backup/SystemBackupAgent.java
@@ -20,6 +20,7 @@
import android.app.backup.BackupAgentHelper;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupHelper;
+import android.app.backup.BackupManager;
import android.app.backup.FullBackup;
import android.app.backup.FullBackupDataOutput;
import android.app.backup.WallpaperBackupHelper;
@@ -87,8 +88,8 @@
private int mUserId = UserHandle.USER_SYSTEM;
@Override
- public void onCreate(UserHandle user) {
- super.onCreate(user);
+ public void onCreate(UserHandle user, @BackupManager.OperationType int operationType) {
+ super.onCreate(user, operationType);
mUserId = user.getIdentifier();
diff --git a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 6184c4e..09e3bfe 100644
--- a/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -794,7 +794,7 @@
setUpAgent(PACKAGE_1);
doThrow(SecurityException.class)
.when(mBackupManagerService)
- .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt());
+ .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt(), anyInt());
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
runTask(task);
@@ -812,7 +812,7 @@
setUpAgent(PACKAGE_1);
doThrow(SecurityException.class)
.when(mBackupManagerService)
- .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt());
+ .bindToAgentSynchronous(argThat(applicationInfo(PACKAGE_1)), anyInt(), anyInt());
KeyValueBackupTask task = createKeyValueBackupTask(transportMock, true, PACKAGE_1);
runTask(task);
@@ -2593,11 +2593,13 @@
if (packageData.available) {
doReturn(backupAgentBinder)
.when(mBackupManagerService)
- .bindToAgentSynchronous(argThat(applicationInfo(packageData)), anyInt());
+ .bindToAgentSynchronous(argThat(applicationInfo(packageData)), anyInt(),
+ anyInt());
} else {
doReturn(null)
.when(mBackupManagerService)
- .bindToAgentSynchronous(argThat(applicationInfo(packageData)), anyInt());
+ .bindToAgentSynchronous(argThat(applicationInfo(packageData)), anyInt(),
+ anyInt());
}
return new AgentMock(backupAgentBinder, backupAgent);
} catch (RemoteException e) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 1b2711d..82726c7 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -501,7 +501,7 @@
public void testUpdateOomAdj_DoOne_Backup() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true));
- BackupRecord backupTarget = new BackupRecord(null, 0, 0);
+ BackupRecord backupTarget = new BackupRecord(null, 0, 0, 0);
backupTarget.app = app;
doReturn(backupTarget).when(sService.mBackupTargets).get(anyInt());
sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
@@ -803,7 +803,7 @@
ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
bindService(app, client, null, Context.BIND_ABOVE_CLIENT, mock(IBinder.class));
- BackupRecord backupTarget = new BackupRecord(null, 0, 0);
+ BackupRecord backupTarget = new BackupRecord(null, 0, 0, 0);
backupTarget.app = client;
doReturn(backupTarget).when(sService.mBackupTargets).get(anyInt());
sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;