summaryrefslogtreecommitdiff
path: root/services/backup
diff options
context:
space:
mode:
author Sarp Misoglu <sarpm@google.com> 2024-11-18 14:38:32 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-18 14:38:32 +0000
commit1ba241bebb4bd6ea766468f7568eb00f92d1dad4 (patch)
tree3236eaf0e1d7a55838514ec23c619035d95961ab /services/backup
parent280d19b92ae749f11f3ac0edd168b42e42df3097 (diff)
parentf658e37095197043246f4ae177d441fb73cf2da2 (diff)
Merge "Move BackupAgent connection to a helper class" into main
Diffstat (limited to 'services/backup')
-rw-r--r--services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java318
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java6
-rw-r--r--services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java3
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java266
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java2
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java6
-rw-r--r--services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java5
-rw-r--r--services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java23
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java7
9 files changed, 353 insertions, 283 deletions
diff --git a/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
new file mode 100644
index 000000000000..5e4bab15952d
--- /dev/null
+++ b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2017 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 com.android.server.backup;
+
+import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
+import static com.android.server.backup.BackupManagerService.TAG;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.ApplicationThreadConstants;
+import android.app.IActivityManager;
+import android.app.IBackupAgent;
+import android.app.backup.BackupAnnotations;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Binder;
+import android.os.Build;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.LocalServices;
+import com.android.server.backup.internal.LifecycleOperationStorage;
+
+import java.util.Set;
+
+/**
+ * Handles the lifecycle of {@link IBackupAgent}s that the {@link UserBackupManagerService}
+ * communicates with.
+ *
+ * <p>There can only be one agent that's connected to at a time.
+ *
+ * <p>There should be only one instance of this class per {@link UserBackupManagerService}.
+ */
+public class BackupAgentConnectionManager {
+
+ /**
+ * Enables the OS making a decision on whether backup restricted mode should be used for apps
+ * that haven't explicitly opted in or out. See
+ * {@link android.content.pm.PackageManager#PROPERTY_USE_RESTRICTED_BACKUP_MODE} for details.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.BAKLAVA)
+ public static final long OS_DECIDES_BACKUP_RESTRICTED_MODE = 376661510;
+
+ // The thread performing the sequence of queued backups binds to each app's agent
+ // in succession. Bind notifications are asynchronously delivered through the
+ // Activity Manager; use this lock object to signal when a requested binding has
+ // completed.
+ private final Object mAgentConnectLock = new Object();
+ private IBackupAgent mConnectedAgent;
+ private volatile boolean mConnecting;
+ private final ArraySet<String> mRestoreNoRestrictedModePackages = new ArraySet<>();
+ private final ArraySet<String> mBackupNoRestrictedModePackages = new ArraySet<>();
+
+ private final IActivityManager mActivityManager;
+ private final ActivityManagerInternal mActivityManagerInternal;
+ private final LifecycleOperationStorage mOperationStorage;
+ private final PackageManager mPackageManager;
+ private final UserBackupManagerService mUserBackupManagerService;
+ private final int mUserId;
+ private final String mUserIdMsg;
+
+ BackupAgentConnectionManager(LifecycleOperationStorage operationStorage,
+ PackageManager packageManager, UserBackupManagerService userBackupManagerService,
+ int userId) {
+ mActivityManager = ActivityManager.getService();
+ mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+ mOperationStorage = operationStorage;
+ mPackageManager = packageManager;
+ mUserBackupManagerService = userBackupManagerService;
+ mUserId = userId;
+ mUserIdMsg = "[UserID:" + userId + "] ";
+ }
+
+ /**
+ * Fires off a backup agent, blocking until it attaches (and ActivityManager will call
+ * {@link #agentConnected(String, IBinder)}) or until this operation times out.
+ *
+ * @param mode a {@code BACKUP_MODE} from {@link android.app.ApplicationThreadConstants}.
+ */
+ @Nullable
+ public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode,
+ @BackupAnnotations.BackupDestination int backupDestination) {
+ IBackupAgent agent = null;
+ synchronized (mAgentConnectLock) {
+ mConnecting = true;
+ mConnectedAgent = null;
+ boolean useRestrictedMode = shouldUseRestrictedBackupModeForPackage(mode,
+ app.packageName);
+ try {
+ if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId,
+ backupDestination, useRestrictedMode)) {
+ Slog.d(TAG, mUserIdMsg + "awaiting agent for " + app);
+
+ // success; wait for the agent to arrive
+ // only wait 10 seconds for the bind to happen
+ long timeoutMark = System.currentTimeMillis() + 10 * 1000;
+ while (mConnecting && mConnectedAgent == null && (System.currentTimeMillis()
+ < timeoutMark)) {
+ try {
+ mAgentConnectLock.wait(5000);
+ } catch (InterruptedException e) {
+ // just bail
+ Slog.w(TAG, mUserIdMsg + "Interrupted: " + e);
+ mConnecting = false;
+ mConnectedAgent = null;
+ }
+ }
+
+ // if we timed out with no connect, abort and move on
+ if (mConnecting) {
+ Slog.w(TAG, mUserIdMsg + "Timeout waiting for agent " + app);
+ mConnectedAgent = null;
+ }
+ Slog.i(TAG, mUserIdMsg + "got agent " + mConnectedAgent);
+ agent = mConnectedAgent;
+ }
+ } catch (RemoteException e) {
+ // can't happen - ActivityManager is local
+ }
+ }
+ if (agent == null) {
+ mActivityManagerInternal.clearPendingBackup(mUserId);
+ }
+ return agent;
+ }
+
+ /**
+ * Tell the ActivityManager that we are done with the {@link IBackupAgent} of this {@code app}.
+ * It will tell the app to destroy the agent.
+ */
+ public void unbindAgent(ApplicationInfo app) {
+ try {
+ mActivityManager.unbindBackupAgent(app);
+ } catch (RemoteException e) {
+ // Can't happen - activity manager is local
+ }
+ }
+
+ /**
+ * Callback: a requested backup agent has been instantiated. This should only be called from
+ * the
+ * {@link ActivityManager} when it's telling us that an agent is ready after a call to
+ * {@link #bindToAgentSynchronous(ApplicationInfo, int, int)}.
+ */
+ public void agentConnected(String packageName, IBinder agentBinder) {
+ synchronized (mAgentConnectLock) {
+ if (getCallingUid() == android.os.Process.SYSTEM_UID) {
+ Slog.d(TAG,
+ mUserIdMsg + "agentConnected pkg=" + packageName + " agent=" + agentBinder);
+ mConnectedAgent = IBackupAgent.Stub.asInterface(agentBinder);
+ mConnecting = false;
+ } else {
+ Slog.w(TAG, mUserIdMsg + "Non-system process uid=" + getCallingUid()
+ + " claiming agent connected");
+ }
+ mAgentConnectLock.notifyAll();
+ }
+ }
+
+ /**
+ * Callback: a backup agent has failed to come up, or has unexpectedly quit. If the agent failed
+ * to come up in the first place, the agentBinder argument will be {@code null}. This should
+ * only be called from the {@link ActivityManager}.
+ */
+ public void agentDisconnected(String packageName) {
+ synchronized (mAgentConnectLock) {
+ if (getCallingUid() == Process.SYSTEM_UID) {
+ mConnectedAgent = null;
+ mConnecting = false;
+ } else {
+ Slog.w(TAG, mUserIdMsg + "Non-system process uid=" + getCallingUid()
+ + " claiming agent disconnected");
+ }
+ Slog.w(TAG, mUserIdMsg + "agentDisconnected: the backup agent for " + packageName
+ + " died: cancel current operations");
+
+ // Offload operation cancellation off the main thread as the cancellation callbacks
+ // might call out to BackupTransport. Other operations started on the same package
+ // before the cancellation callback has executed will also be cancelled by the callback.
+ Runnable cancellationRunnable = () -> {
+ // handleCancel() causes the PerformFullTransportBackupTask to go on to
+ // tearDownAgentAndKill: that will unbindBackupAgent in the Activity Manager, so
+ // that the package being backed up doesn't get stuck in restricted mode until the
+ // backup time-out elapses.
+ for (int token : mOperationStorage.operationTokensForPackage(packageName)) {
+ if (MORE_DEBUG) {
+ Slog.d(TAG,
+ mUserIdMsg + "agentDisconnected: will handleCancel(all) for token:"
+ + Integer.toHexString(token));
+ }
+ mUserBackupManagerService.handleCancel(token, true /* cancelAll */);
+ }
+ };
+ getThreadForCancellation(cancellationRunnable).start();
+
+ mAgentConnectLock.notifyAll();
+ }
+ }
+
+ /**
+ * Marks the given set of packages as packages that should not be put into restricted mode if
+ * they are started for the given {@link BackupAnnotations.OperationType}.
+ */
+ public void setNoRestrictedModePackages(Set<String> packageNames,
+ @BackupAnnotations.OperationType int opType) {
+ if (opType == BackupAnnotations.OperationType.BACKUP) {
+ mBackupNoRestrictedModePackages.clear();
+ mBackupNoRestrictedModePackages.addAll(packageNames);
+ } else if (opType == BackupAnnotations.OperationType.RESTORE) {
+ mRestoreNoRestrictedModePackages.clear();
+ mRestoreNoRestrictedModePackages.addAll(packageNames);
+ } else {
+ throw new IllegalArgumentException("opType must be BACKUP or RESTORE");
+ }
+ }
+
+ /**
+ * Clears the list of packages that should not be put into restricted mode for either backup or
+ * restore.
+ */
+ public void clearNoRestrictedModePackages() {
+ mBackupNoRestrictedModePackages.clear();
+ mRestoreNoRestrictedModePackages.clear();
+ }
+
+ /**
+ * If the app has specified {@link PackageManager#PROPERTY_USE_RESTRICTED_BACKUP_MODE}, then
+ * its value is returned. If it hasn't and it targets an SDK below
+ * {@link Build.VERSION_CODES#BAKLAVA} then returns true. If it targets a newer SDK, then
+ * returns the decision made by the {@link android.app.backup.BackupTransport}.
+ *
+ * <p>When this method is called, we should have already asked the transport and cached its
+ * response in {@link #mBackupNoRestrictedModePackages} or
+ * {@link #mRestoreNoRestrictedModePackages} so this method will immediately return without
+ * any IPC to the transport.
+ */
+ private boolean shouldUseRestrictedBackupModeForPackage(
+ @BackupAnnotations.OperationType int mode, String packageName) {
+ if (!Flags.enableRestrictedModeChanges()) {
+ return true;
+ }
+
+ // Key/Value apps are never put in restricted mode.
+ if (mode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL
+ || mode == ApplicationThreadConstants.BACKUP_MODE_RESTORE) {
+ return false;
+ }
+
+ try {
+ PackageManager.Property property = mPackageManager.getPropertyAsUser(
+ PackageManager.PROPERTY_USE_RESTRICTED_BACKUP_MODE,
+ packageName, /* className= */ null, mUserId);
+ if (property.isBoolean()) {
+ // If the package has explicitly specified, we won't ask the transport.
+ return property.getBoolean();
+ } else {
+ Slog.w(TAG,
+ PackageManager.PROPERTY_USE_RESTRICTED_BACKUP_MODE + "must be a boolean.");
+ }
+ } catch (NameNotFoundException e) {
+ // This is expected when the package has not defined the property in its manifest.
+ }
+
+ // The package has not specified the property. The behavior depends on the package's
+ // targetSdk.
+ // <36 gets the old behavior of always using restricted mode.
+ if (!CompatChanges.isChangeEnabled(OS_DECIDES_BACKUP_RESTRICTED_MODE, packageName,
+ UserHandle.of(mUserId))) {
+ return true;
+ }
+
+ // Apps targeting >=36 get the behavior decided by the transport.
+ // By this point, we should have asked the transport and cached its decision.
+ if ((mode == ApplicationThreadConstants.BACKUP_MODE_FULL
+ && mBackupNoRestrictedModePackages.contains(packageName)) || (
+ mode == ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL
+ && mRestoreNoRestrictedModePackages.contains(packageName))) {
+ Slog.d(TAG, "Transport requested no restricted mode for: " + packageName);
+ return false;
+ }
+ return true;
+ }
+
+ @VisibleForTesting
+ Thread getThreadForCancellation(Runnable operation) {
+ return new Thread(operation, /* operationName */ "agent-disconnected");
+ }
+
+ @VisibleForTesting
+ int getCallingUid() {
+ return Binder.getCallingUid();
+ }
+}
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 5f0071d47c89..3f6ede95eaf9 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -658,7 +658,8 @@ public class BackupManagerService extends IBackupManager.Stub {
getServiceForUserIfCallerHasPermission(userId, "agentConnected()");
if (userBackupManagerService != null) {
- userBackupManagerService.agentConnected(packageName, agentBinder);
+ userBackupManagerService.getBackupAgentConnectionManager().agentConnected(packageName,
+ agentBinder);
}
}
@@ -683,7 +684,8 @@ public class BackupManagerService extends IBackupManager.Stub {
getServiceForUserIfCallerHasPermission(userId, "agentDisconnected()");
if (userBackupManagerService != null) {
- userBackupManagerService.agentDisconnected(packageName);
+ userBackupManagerService.getBackupAgentConnectionManager().agentDisconnected(
+ packageName);
}
}
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index f5d68362c70a..136bacdd6399 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -146,7 +146,8 @@ public class KeyValueAdbBackupEngine {
private IBackupAgent bindToAgent(ApplicationInfo targetApp) {
try {
- return mBackupManagerService.bindToAgentSynchronous(targetApp,
+ return mBackupManagerService.getBackupAgentConnectionManager().bindToAgentSynchronous(
+ targetApp,
ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL,
BackupAnnotations.BackupDestination.CLOUD);
} catch (SecurityException e) {
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 5de2fb30ac78..e085f6e63067 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -43,9 +43,7 @@ import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
import android.app.AppGlobals;
-import android.app.ApplicationThreadConstants;
import android.app.IActivityManager;
-import android.app.IBackupAgent;
import android.app.PendingIntent;
import android.app.backup.BackupAgent;
import android.app.backup.BackupAnnotations;
@@ -60,9 +58,6 @@ import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
-import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -83,7 +78,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
-import android.os.IBinder;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
@@ -302,21 +296,10 @@ public class UserBackupManagerService {
private static final String BACKUP_FINISHED_ACTION = "android.intent.action.BACKUP_FINISHED";
private static final String BACKUP_FINISHED_PACKAGE_EXTRA = "packageName";
- /**
- * Enables the OS making a decision on whether backup restricted mode should be used for apps
- * that haven't explicitly opted in or out. See
- * {@link PackageManager#PROPERTY_USE_RESTRICTED_BACKUP_MODE} for details.
- */
- @ChangeId
- @EnabledSince(targetSdkVersion = Build.VERSION_CODES.BAKLAVA)
- public static final long OS_DECIDES_BACKUP_RESTRICTED_MODE = 376661510;
-
// Time delay for initialization operations that can be delayed so as not to consume too much
// CPU on bring-up and increase time-to-UI.
private static final long INITIALIZATION_DELAY_MILLIS = 3000;
- // Timeout interval for deciding that a bind has taken too long.
- private static final long BIND_TIMEOUT_INTERVAL = 10 * 1000;
// Timeout interval for deciding that a clear-data has taken too long.
private static final long CLEAR_DATA_TIMEOUT_INTERVAL = 30 * 1000;
@@ -365,22 +348,9 @@ public class UserBackupManagerService {
// Backups that we haven't started yet. Keys are package names.
private final HashMap<String, BackupRequest> mPendingBackups = new HashMap<>();
- private final ArraySet<String> mRestoreNoRestrictedModePackages = new ArraySet<>();
- private final ArraySet<String> mBackupNoRestrictedModePackages = new ArraySet<>();
-
// locking around the pending-backup management
private final Object mQueueLock = new Object();
-
private final UserBackupPreferences mBackupPreferences;
-
- // The thread performing the sequence of queued backups binds to each app's agent
- // in succession. Bind notifications are asynchronously delivered through the
- // Activity Manager; use this lock object to signal when a requested binding has
- // completed.
- private final Object mAgentConnectLock = new Object();
- private IBackupAgent mConnectedAgent;
- private volatile boolean mConnecting;
-
private volatile boolean mBackupRunning;
private volatile long mLastBackupPass;
@@ -410,6 +380,7 @@ public class UserBackupManagerService {
private ActiveRestoreSession mActiveRestoreSession;
+ private final BackupAgentConnectionManager mBackupAgentConnectionManager;
private final LifecycleOperationStorage mOperationStorage;
private final Random mTokenGenerator = new Random();
@@ -547,6 +518,8 @@ public class UserBackupManagerService {
mRegisterTransportsRequestedTime = 0;
mPackageManager = packageManager;
mOperationStorage = operationStorage;
+ mBackupAgentConnectionManager = new BackupAgentConnectionManager(mOperationStorage,
+ mPackageManager, this, mUserId);
mTransportManager = transportManager;
mFullBackupQueue = new ArrayList<>();
mBackupHandler = backupHandler;
@@ -599,6 +572,8 @@ public class UserBackupManagerService {
mAgentTimeoutParameters.start();
mOperationStorage = new LifecycleOperationStorage(mUserId);
+ mBackupAgentConnectionManager = new BackupAgentConnectionManager(mOperationStorage,
+ mPackageManager, this, mUserId);
Objects.requireNonNull(userBackupThread, "userBackupThread cannot be null");
mBackupHandler = new BackupHandler(this, mOperationStorage, userBackupThread);
@@ -1660,67 +1635,6 @@ public class UserBackupManagerService {
}
}
- /** Fires off a backup agent, blocking until it attaches or times out. */
- @Nullable
- public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode,
- @BackupDestination int backupDestination) {
- IBackupAgent agent = null;
- synchronized (mAgentConnectLock) {
- mConnecting = true;
- mConnectedAgent = null;
- boolean useRestrictedMode = shouldUseRestrictedBackupModeForPackage(mode,
- app.packageName);
- try {
- if (mActivityManager.bindBackupAgent(app.packageName, mode, mUserId,
- backupDestination, useRestrictedMode)) {
- Slog.d(TAG, addUserIdToLogMessage(mUserId, "awaiting agent for " + app));
-
- // success; wait for the agent to arrive
- // only wait 10 seconds for the bind to happen
- long timeoutMark = System.currentTimeMillis() + BIND_TIMEOUT_INTERVAL;
- while (mConnecting && mConnectedAgent == null
- && (System.currentTimeMillis() < timeoutMark)) {
- try {
- mAgentConnectLock.wait(5000);
- } catch (InterruptedException e) {
- // just bail
- Slog.w(TAG, addUserIdToLogMessage(mUserId, "Interrupted: " + e));
- mConnecting = false;
- mConnectedAgent = null;
- }
- }
-
- // if we timed out with no connect, abort and move on
- if (mConnecting) {
- Slog.w(
- TAG,
- addUserIdToLogMessage(mUserId, "Timeout waiting for agent " + app));
- mConnectedAgent = null;
- }
- if (DEBUG) {
- Slog.i(TAG, addUserIdToLogMessage(mUserId, "got agent " + mConnectedAgent));
- }
- agent = mConnectedAgent;
- }
- } catch (RemoteException e) {
- // can't happen - ActivityManager is local
- }
- }
- if (agent == null) {
- mActivityManagerInternal.clearPendingBackup(mUserId);
- }
- return agent;
- }
-
- /** Unbind from a backup agent. */
- public void unbindAgent(ApplicationInfo app) {
- try {
- mActivityManager.unbindBackupAgent(app);
- } catch (RemoteException e) {
- // Can't happen - activity manager is local
- }
- }
-
/**
* Clear an application's data after a failed restore, blocking until the operation completes or
* times out.
@@ -2493,10 +2407,6 @@ public class UserBackupManagerService {
AppWidgetBackupBridge.restoreWidgetState(packageName, widgetData, mUserId);
}
- // *****************************
- // NEW UNIFIED RESTORE IMPLEMENTATION
- // *****************************
-
/** Schedule a backup pass for {@code packageName}. */
public void dataChangedImpl(String packageName) {
HashSet<String> targets = dataChangedTargets(packageName);
@@ -3122,91 +3032,6 @@ public class UserBackupManagerService {
}
}
- /**
- * Marks the given set of packages as packages that should not be put into restricted mode if
- * they are started for the given {@link BackupAnnotations.OperationType}.
- */
- public void setNoRestrictedModePackages(Set<String> packageNames,
- @BackupAnnotations.OperationType int opType) {
- if (opType == BackupAnnotations.OperationType.BACKUP) {
- mBackupNoRestrictedModePackages.clear();
- mBackupNoRestrictedModePackages.addAll(packageNames);
- } else if (opType == BackupAnnotations.OperationType.RESTORE) {
- mRestoreNoRestrictedModePackages.clear();
- mRestoreNoRestrictedModePackages.addAll(packageNames);
- } else {
- throw new IllegalArgumentException("opType must be BACKUP or RESTORE");
- }
- }
-
- /**
- * Clears the list of packages that should not be put into restricted mode for either backup or
- * restore.
- */
- public void clearNoRestrictedModePackages() {
- mBackupNoRestrictedModePackages.clear();
- mRestoreNoRestrictedModePackages.clear();
- }
-
- /**
- * If the app has specified {@link PackageManager#PROPERTY_USE_RESTRICTED_BACKUP_MODE}, then
- * its value is returned. If it hasn't and it targets an SDK below
- * {@link Build.VERSION_CODES#BAKLAVA} then returns true. If it targets a newer SDK, then
- * returns the decision made by the {@link android.app.backup.BackupTransport}.
- *
- * <p>When this method is called, we should have already asked the transport and cached its
- * response in {@link #mBackupNoRestrictedModePackages} or
- * {@link #mRestoreNoRestrictedModePackages} so this method will immediately return without
- * any IPC to the transport.
- */
- private boolean shouldUseRestrictedBackupModeForPackage(
- @BackupAnnotations.OperationType int mode, String packageName) {
- if (!Flags.enableRestrictedModeChanges()) {
- return true;
- }
-
- // Key/Value apps are never put in restricted mode.
- if (mode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL
- || mode == ApplicationThreadConstants.BACKUP_MODE_RESTORE) {
- return false;
- }
-
- try {
- PackageManager.Property property = mPackageManager.getPropertyAsUser(
- PackageManager.PROPERTY_USE_RESTRICTED_BACKUP_MODE,
- packageName, /* className= */ null,
- mUserId);
- if (property.isBoolean()) {
- // If the package has explicitly specified, we won't ask the transport.
- return property.getBoolean();
- } else {
- Slog.w(TAG, PackageManager.PROPERTY_USE_RESTRICTED_BACKUP_MODE
- + "must be a boolean.");
- }
- } catch (NameNotFoundException e) {
- // This is expected when the package has not defined the property in its manifest.
- }
-
- // The package has not specified the property. The behavior depends on the package's
- // targetSdk.
- // <36 gets the old behavior of always using restricted mode.
- if (!CompatChanges.isChangeEnabled(OS_DECIDES_BACKUP_RESTRICTED_MODE, packageName,
- UserHandle.of(mUserId))) {
- return true;
- }
-
- // Apps targeting >=36 get the behavior decided by the transport.
- // By this point, we should have asked the transport and cached its decision.
- if ((mode == ApplicationThreadConstants.BACKUP_MODE_FULL
- && mBackupNoRestrictedModePackages.contains(packageName))
- || (mode == ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL
- && mRestoreNoRestrictedModePackages.contains(packageName))) {
- Slog.d(TAG, "Transport requested no restricted mode for: " + packageName);
- return false;
- }
- return true;
- }
-
private boolean startConfirmationUi(int token, String action) {
try {
Intent confIntent = new Intent(action);
@@ -3898,83 +3723,6 @@ public class UserBackupManagerService {
}
/**
- * Callback: a requested backup agent has been instantiated. This should only be called from the
- * {@link ActivityManager}.
- */
- public void agentConnected(String packageName, IBinder agentBinder) {
- synchronized (mAgentConnectLock) {
- if (Binder.getCallingUid() == Process.SYSTEM_UID) {
- Slog.d(
- TAG,
- addUserIdToLogMessage(
- mUserId,
- "agentConnected pkg=" + packageName + " agent=" + agentBinder));
- mConnectedAgent = IBackupAgent.Stub.asInterface(agentBinder);
- mConnecting = false;
- } else {
- Slog.w(
- TAG,
- addUserIdToLogMessage(
- mUserId,
- "Non-system process uid="
- + Binder.getCallingUid()
- + " claiming agent connected"));
- }
- mAgentConnectLock.notifyAll();
- }
- }
-
- /**
- * Callback: a backup agent has failed to come up, or has unexpectedly quit. If the agent failed
- * to come up in the first place, the agentBinder argument will be {@code null}. This should
- * only be called from the {@link ActivityManager}.
- */
- public void agentDisconnected(String packageName) {
- synchronized (mAgentConnectLock) {
- if (Binder.getCallingUid() == Process.SYSTEM_UID) {
- mConnectedAgent = null;
- mConnecting = false;
- } else {
- Slog.w(
- TAG,
- addUserIdToLogMessage(
- mUserId,
- "Non-system process uid="
- + Binder.getCallingUid()
- + " claiming agent disconnected"));
- }
- Slog.w(TAG, "agentDisconnected: the backup agent for " + packageName
- + " died: cancel current operations");
-
- // Offload operation cancellation off the main thread as the cancellation callbacks
- // might call out to BackupTransport. Other operations started on the same package
- // before the cancellation callback has executed will also be cancelled by the callback.
- Runnable cancellationRunnable = () -> {
- // handleCancel() causes the PerformFullTransportBackupTask to go on to
- // tearDownAgentAndKill: that will unbindBackupAgent in the Activity Manager, so
- // that the package being backed up doesn't get stuck in restricted mode until the
- // backup time-out elapses.
- for (int token : mOperationStorage.operationTokensForPackage(packageName)) {
- if (MORE_DEBUG) {
- Slog.d(TAG, "agentDisconnected: will handleCancel(all) for token:"
- + Integer.toHexString(token));
- }
- handleCancel(token, true /* cancelAll */);
- }
- };
- getThreadForAsyncOperation(/* operationName */ "agent-disconnected",
- cancellationRunnable).start();
-
- mAgentConnectLock.notifyAll();
- }
- }
-
- @VisibleForTesting
- Thread getThreadForAsyncOperation(String operationName, Runnable operation) {
- return new Thread(operation, operationName);
- }
-
- /**
* An application being installed will need a restore pass, then the {@link PackageManager} will
* need to be told when the restore is finished.
*/
@@ -4521,4 +4269,8 @@ public class UserBackupManagerService {
public IBackupManager getBackupManagerBinder() {
return mBackupManagerBinder;
}
+
+ public BackupAgentConnectionManager getBackupAgentConnectionManager() {
+ return mBackupAgentConnectionManager;
+ }
}
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 12712063e344..b98cb1086680 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -314,7 +314,7 @@ public class FullBackupEngine {
Slog.d(TAG, "Binding to full backup agent : " + mPkg.packageName);
}
mAgent =
- backupManagerService.bindToAgentSynchronous(
+ backupManagerService.getBackupAgentConnectionManager().bindToAgentSynchronous(
mPkg.applicationInfo, ApplicationThreadConstants.BACKUP_MODE_FULL,
mBackupEligibilityRules.getBackupDestination());
}
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 be9cdc8692cb..65730c9591a8 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -702,7 +702,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
// Clear this to avoid using the memory until reboot.
- mUserBackupManagerService.clearNoRestrictedModePackages();
+ mUserBackupManagerService
+ .getBackupAgentConnectionManager().clearNoRestrictedModePackages();
Slog.i(TAG, "Full data backup pass finished.");
mUserBackupManagerService.getWakelock().release();
@@ -741,7 +742,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
}
packageNames = transport.getPackagesThatShouldNotUseRestrictedMode(packageNames,
BACKUP);
- mUserBackupManagerService.setNoRestrictedModePackages(packageNames, BACKUP);
+ mUserBackupManagerService.getBackupAgentConnectionManager().setNoRestrictedModePackages(
+ packageNames, BACKUP);
} catch (RemoteException e) {
Slog.i(TAG, "Failed to retrieve no restricted mode packages from transport");
}
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 3a6e1cafa505..82232a653858 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -741,7 +741,7 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
final IBackupAgent agent;
try {
agent =
- mBackupManagerService.bindToAgentSynchronous(
+ mBackupManagerService.getBackupAgentConnectionManager().bindToAgentSynchronous(
packageInfo.applicationInfo, BACKUP_MODE_INCREMENTAL,
mBackupEligibilityRules.getBackupDestination());
if (agent == null) {
@@ -1302,7 +1302,8 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable {
// For PM metadata (for which applicationInfo is null) there is no agent-bound state.
if (mCurrentPackage.applicationInfo != null) {
- mBackupManagerService.unbindAgent(mCurrentPackage.applicationInfo);
+ mBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ mCurrentPackage.applicationInfo);
}
mAgent = null;
}
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 2d99c96452da..b59e860f81fe 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -410,11 +410,7 @@ public class FullRestoreEngine extends RestoreEngine {
// All set; now set up the IPC and launch the agent
setUpPipes();
- mAgent = mBackupManagerService.bindToAgentSynchronous(mTargetApp,
- FullBackup.KEY_VALUE_DATA_TOKEN.equals(info.domain)
- ? ApplicationThreadConstants.BACKUP_MODE_RESTORE
- : ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL,
- mBackupEligibilityRules.getBackupDestination());
+ mAgent = bindToAgent(info);
mAgentPackage = pkg;
} catch (IOException | NameNotFoundException e) {
// fall through to error handling
@@ -805,15 +801,12 @@ public class FullRestoreEngine extends RestoreEngine {
return packages.contains(packageName);
}
- void sendOnRestorePackage(String name) {
- if (mObserver != null) {
- try {
- // TODO: use a more user-friendly name string
- mObserver.onRestorePackage(name);
- } catch (RemoteException e) {
- Slog.w(TAG, "full restore observer went away: restorePackage");
- mObserver = null;
- }
- }
+ private IBackupAgent bindToAgent(FileMetadata info) {
+ return mBackupManagerService.getBackupAgentConnectionManager().bindToAgentSynchronous(
+ mTargetApp,
+ FullBackup.KEY_VALUE_DATA_TOKEN.equals(info.domain)
+ ? ApplicationThreadConstants.BACKUP_MODE_RESTORE
+ : ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL,
+ mBackupEligibilityRules.getBackupDestination());
}
}
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 5ee51a5aa189..e5c7e5cce757 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -814,7 +814,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// Good to go! Set up and bind the agent...
mAgent =
- backupManagerService.bindToAgentSynchronous(
+ backupManagerService.getBackupAgentConnectionManager().bindToAgentSynchronous(
mCurrentPackage.applicationInfo,
ApplicationThreadConstants.BACKUP_MODE_RESTORE,
mBackupEligibilityRules.getBackupDestination());
@@ -1364,7 +1364,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
backupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
// Clear this to avoid using the memory until reboot.
- backupManagerService.clearNoRestrictedModePackages();
+ backupManagerService.getBackupAgentConnectionManager().clearNoRestrictedModePackages();
// If we have a PM token, we must under all circumstances be sure to
// handshake when we've finished.
@@ -1838,7 +1838,8 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
}
packageNames = transport.getPackagesThatShouldNotUseRestrictedMode(packageNames,
RESTORE);
- backupManagerService.setNoRestrictedModePackages(packageNames, RESTORE);
+ backupManagerService.getBackupAgentConnectionManager().setNoRestrictedModePackages(
+ packageNames, RESTORE);
} catch (RemoteException e) {
Slog.i(TAG, "Failed to retrieve restricted mode packages from transport");
}