summaryrefslogtreecommitdiff
path: root/services/backup
diff options
context:
space:
mode:
author Sarp Misoglu <sarpm@google.com> 2024-11-27 18:57:15 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-27 18:57:15 +0000
commitc943c24144d0560ee2bc712898af3106c966f81b (patch)
treef74d520080686758f45846286fdd5ee56daebf02 /services/backup
parente45a169b67269db221433b5ab6f8578b698a3bac (diff)
parentb87b97921307a0476f017aec2ae42bbcb58995bd (diff)
Merge "Don't kill apps if they are not in restricted mode" into main
Diffstat (limited to 'services/backup')
-rw-r--r--services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java95
-rw-r--r--services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java3
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java33
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java3
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java3
-rw-r--r--services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java19
-rw-r--r--services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java2
-rw-r--r--services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java3
-rw-r--r--services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java48
9 files changed, 99 insertions, 110 deletions
diff --git a/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
index 02f186557ca4..6ced096e8778 100644
--- a/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
+++ b/services/backup/java/com/android/server/backup/BackupAgentConnectionManager.java
@@ -101,11 +101,16 @@ public class BackupAgentConnectionManager {
private static final class BackupAgentConnection {
public final ApplicationInfo appInfo;
+ public final int backupMode;
+ public final boolean inRestrictedMode;
public IBackupAgent backupAgent;
public boolean connecting = true; // Assume we are trying to connect on creation.
- private BackupAgentConnection(ApplicationInfo appInfo) {
+ private BackupAgentConnection(ApplicationInfo appInfo, int backupMode,
+ boolean inRestrictedMode) {
this.appInfo = appInfo;
+ this.backupMode = backupMode;
+ this.inRestrictedMode = inRestrictedMode;
}
}
@@ -113,26 +118,31 @@ public class BackupAgentConnectionManager {
* Fires off a backup agent, blocking until it attaches (i.e. ActivityManager calls
* {@link #agentConnected(String, IBinder)}) or until this operation times out.
*
- * @param mode a {@code BACKUP_MODE} from {@link android.app.ApplicationThreadConstants}.
+ * @param backupMode a {@code BACKUP_MODE} from {@link android.app.ApplicationThreadConstants}.
*/
@Nullable
- public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int mode,
+ public IBackupAgent bindToAgentSynchronous(ApplicationInfo app, int backupMode,
@BackupAnnotations.BackupDestination int backupDestination) {
+ if (app == null) {
+ Slog.w(TAG, mUserIdMsg + "bindToAgentSynchronous for null app");
+ return null;
+ }
+
synchronized (mAgentConnectLock) {
- boolean useRestrictedMode = shouldUseRestrictedBackupModeForPackage(mode,
+ boolean useRestrictedMode = shouldUseRestrictedBackupModeForPackage(backupMode,
app.packageName);
if (mCurrentConnection != null) {
Slog.e(TAG, mUserIdMsg + "binding to new agent before unbinding from old one: "
+ mCurrentConnection.appInfo.packageName);
}
- mCurrentConnection = new BackupAgentConnection(app);
+ mCurrentConnection = new BackupAgentConnection(app, backupMode, useRestrictedMode);
// bindBackupAgent() is an async API. It will kick off the app's process and call
// agentConnected() when it receives the agent from the app.
boolean startedBindSuccessfully = false;
try {
- startedBindSuccessfully = mActivityManager.bindBackupAgent(app.packageName, mode,
- mUserId, backupDestination, useRestrictedMode);
+ startedBindSuccessfully = mActivityManager.bindBackupAgent(app.packageName,
+ backupMode, mUserId, backupDestination, useRestrictedMode);
} catch (RemoteException e) {
// can't happen - ActivityManager is local
}
@@ -173,28 +183,66 @@ public class BackupAgentConnectionManager {
/**
* Tell the ActivityManager that we are done with the {@link IBackupAgent} of this {@code app}.
* It will tell the app to destroy the agent.
+ *
+ * <p>If {@code allowKill} is set, this will kill the app's process if the app is in restricted
+ * mode or if it was started for restore and specified {@code android:killAfterRestore} in its
+ * manifest.
+ *
+ * @see #shouldUseRestrictedBackupModeForPackage(int, String)
*/
- public void unbindAgent(ApplicationInfo app) {
- synchronized (mAgentConnectLock) {
- if (mCurrentConnection == null) {
- Slog.w(TAG, mUserIdMsg + "unbindAgent but no current connection");
- } else if (!mCurrentConnection.appInfo.packageName.equals(app.packageName)) {
- Slog.w(TAG, mUserIdMsg + "unbindAgent for unexpected package: " + app.packageName
- + " expected: " + mCurrentConnection.appInfo.packageName);
- } else {
- mCurrentConnection = null;
- }
+ public void unbindAgent(ApplicationInfo app, boolean allowKill) {
+ if (app == null) {
+ Slog.w(TAG, mUserIdMsg + "unbindAgent for null app");
+ return;
+ }
+ synchronized (mAgentConnectLock) {
// Even if we weren't expecting to be bound to this agent, we should still call
// ActivityManager just in case. It will ignore the call if it also wasn't expecting it.
try {
mActivityManager.unbindBackupAgent(app);
+
+ // Evaluate this before potentially setting mCurrentConnection = null.
+ boolean willKill = allowKill && shouldKillAppOnUnbind(app);
+
+ if (mCurrentConnection == null) {
+ Slog.w(TAG, mUserIdMsg + "unbindAgent but no current connection");
+ } else if (!mCurrentConnection.appInfo.packageName.equals(app.packageName)) {
+ Slog.w(TAG,
+ mUserIdMsg + "unbindAgent for unexpected package: " + app.packageName
+ + " expected: " + mCurrentConnection.appInfo.packageName);
+ } else {
+ mCurrentConnection = null;
+ }
+
+ if (willKill) {
+ Slog.i(TAG, mUserIdMsg + "Killing agent host process");
+ mActivityManager.killApplicationProcess(app.processName, app.uid);
+ }
} catch (RemoteException e) {
// Can't happen - activity manager is local
}
}
}
+ @GuardedBy("mAgentConnectLock")
+ private boolean shouldKillAppOnUnbind(ApplicationInfo app) {
+ // We don't ask system UID processes to be killed.
+ if (UserHandle.isCore(app.uid)) {
+ return false;
+ }
+
+ // If the app is in restricted mode or if we're not sure if it is because our internal
+ // state is messed up, we need to avoid it being stuck in it.
+ if (mCurrentConnection == null || mCurrentConnection.inRestrictedMode) {
+ return true;
+ }
+
+ // App was doing restore and asked to be killed afterwards.
+ return isBackupModeRestore(mCurrentConnection.backupMode)
+ && (app.flags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0;
+ }
+
/**
* 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
@@ -307,16 +355,16 @@ public class BackupAgentConnectionManager {
*/
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;
}
+ if (!Flags.enableRestrictedModeChanges()) {
+ return true;
+ }
+
try {
PackageManager.Property property = mPackageManager.getPropertyAsUser(
PackageManager.PROPERTY_USE_RESTRICTED_BACKUP_MODE,
@@ -352,6 +400,11 @@ public class BackupAgentConnectionManager {
return true;
}
+ private static boolean isBackupModeRestore(int backupMode) {
+ return backupMode == ApplicationThreadConstants.BACKUP_MODE_RESTORE
+ || backupMode == ApplicationThreadConstants.BACKUP_MODE_RESTORE_FULL;
+ }
+
@VisibleForTesting
Thread getThreadForCancellation(Runnable operation) {
return new Thread(operation, /* operationName */ "agent-disconnected");
diff --git a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
index 136bacdd6399..b343ec8e709b 100644
--- a/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/KeyValueAdbBackupEngine.java
@@ -300,7 +300,8 @@ public class KeyValueAdbBackupEngine {
}
private void cleanup() {
- mBackupManagerService.tearDownAgentAndKill(mCurrentPackage.applicationInfo);
+ mBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ mCurrentPackage.applicationInfo, /* allowKill= */ true);
mBlankStateName.delete();
mNewStateName.delete();
mBackupDataName.delete();
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index e085f6e63067..a90b693c5a1d 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -1998,39 +1998,6 @@ public class UserBackupManagerService {
return mOperationStorage.isBackupOperationInProgress();
}
- /** Unbind the backup agent and kill the app if it's a non-system app. */
- public void tearDownAgentAndKill(ApplicationInfo app) {
- if (app == null) {
- // Null means the system package, so just quietly move on. :)
- return;
- }
-
- try {
- // unbind and tidy up even on timeout or failure, just in case
- mActivityManager.unbindBackupAgent(app);
-
- // The agent was running with a stub Application object, so shut it down.
- // !!! We hardcode the confirmation UI's package name here rather than use a
- // manifest flag! TODO something less direct.
- if (!UserHandle.isCore(app.uid)
- && !app.packageName.equals("com.android.backupconfirm")) {
- if (MORE_DEBUG) {
- Slog.d(TAG, addUserIdToLogMessage(mUserId, "Killing agent host process"));
- }
- mActivityManager.killApplicationProcess(app.processName, app.uid);
- } else {
- if (MORE_DEBUG) {
- Slog.d(
- TAG,
- addUserIdToLogMessage(
- mUserId, "Not killing after operation: " + app.processName));
- }
- }
- } catch (RemoteException e) {
- Slog.d(TAG, addUserIdToLogMessage(mUserId, "Lost app trying to shut down"));
- }
- }
-
// ----- Full-data backup scheduling -----
/**
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 b98cb1086680..cf617a523bec 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/FullBackupEngine.java
@@ -323,7 +323,8 @@ public class FullBackupEngine {
private void tearDown() {
if (mPkg != null) {
- backupManagerService.tearDownAgentAndKill(mPkg.applicationInfo);
+ backupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ mPkg.applicationInfo, /* allowKill= */ true);
}
}
}
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 dc6709141b25..0ba0d710af38 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformAdbBackupTask.java
@@ -503,7 +503,8 @@ public class PerformAdbBackupTask extends FullBackupTask implements BackupRestor
Slog.w(TAG, "adb backup cancel of " + target);
}
if (target != null) {
- mUserBackupManagerService.tearDownAgentAndKill(mCurrentTarget.applicationInfo);
+ mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ target.applicationInfo, /* allowKill= */ true);
}
mOperationStorage.removeOperation(mCurrentOpToken);
}
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 65730c9591a8..799494831f19 100644
--- a/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
+++ b/services/backup/java/com/android/server/backup/fullbackup/PerformFullTransportBackupTask.java
@@ -596,8 +596,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
// from the preflight pass. If we got as far as preflight, we now need
// to tear down the target process.
if (mBackupRunner != null) {
- mUserBackupManagerService.tearDownAgentAndKill(
- currentPackage.applicationInfo);
+ mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ currentPackage.applicationInfo, /* allowKill= */ true);
}
// ... and continue looping.
} else if (backupPackageStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
@@ -609,7 +609,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
EventLog.writeEvent(EventLogTags.FULL_BACKUP_QUOTA_EXCEEDED,
packageName);
}
- mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+ mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ currentPackage.applicationInfo, /* allowKill= */ true);
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus == BackupTransport.AGENT_ERROR) {
BackupObserverUtils
@@ -617,7 +618,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
BackupManager.ERROR_AGENT_FAILURE);
Slog.w(TAG, "Application failure for package: " + packageName);
EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName);
- mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+ mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ currentPackage.applicationInfo, /* allowKill= */ true);
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus == BackupManager.ERROR_BACKUP_CANCELLED) {
BackupObserverUtils
@@ -626,7 +628,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
Slog.w(TAG, "Backup cancelled. package=" + packageName +
", cancelAll=" + mCancelAll);
EventLog.writeEvent(EventLogTags.FULL_BACKUP_CANCELLED, packageName);
- mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+ mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ currentPackage.applicationInfo, /* allowKill= */ true);
// Do nothing, clean up, and continue looping.
} else if (backupPackageStatus != BackupTransport.TRANSPORT_OK) {
BackupObserverUtils
@@ -636,7 +639,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE);
// Abort entire backup pass.
backupRunStatus = BackupManager.ERROR_TRANSPORT_ABORTED;
- mUserBackupManagerService.tearDownAgentAndKill(currentPackage.applicationInfo);
+ mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ currentPackage.applicationInfo, /* allowKill= */ true);
return;
} else {
// Success!
@@ -1005,7 +1009,8 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
mIsCancelled = true;
// Cancel tasks spun off by this task.
mUserBackupManagerService.handleCancel(mEphemeralToken, cancelAll);
- mUserBackupManagerService.tearDownAgentAndKill(mTarget.applicationInfo);
+ mUserBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ mTarget.applicationInfo, /* allowKill= */ true);
// Free up everyone waiting on this task and its children.
mPreflightLatch.countDown();
mBackupLatch.countDown();
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 82232a653858..689c43a1cc96 100644
--- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
+++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java
@@ -1303,7 +1303,7 @@ 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.getBackupAgentConnectionManager().unbindAgent(
- mCurrentPackage.applicationInfo);
+ mCurrentPackage.applicationInfo, /* allowKill= */ false);
}
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 b59e860f81fe..237ffa3bdb21 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -727,7 +727,8 @@ public class FullRestoreEngine extends RestoreEngine {
latch.await();
}
- mBackupManagerService.tearDownAgentAndKill(app);
+ mBackupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ app, /* allowKill= */ true);
} catch (RemoteException e) {
Slog.d(TAG, "Lost app trying to shut down");
}
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 e5c7e5cce757..dad84c86deef 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -51,7 +51,6 @@ import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.EventLog;
@@ -1487,49 +1486,10 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask {
// If this wasn't the PM pseudopackage, tear down the agent side
if (mCurrentPackage.applicationInfo != null) {
- // unbind and tidy up even on timeout or failure
- try {
- backupManagerService
- .getActivityManager()
- .unbindBackupAgent(mCurrentPackage.applicationInfo);
-
- // The agent was probably running with a stub Application object,
- // which isn't a valid run mode for the main app logic. Shut
- // down the app so that next time it's launched, it gets the
- // usual full initialization. Note that this is only done for
- // full-system restores: when a single app has requested a restore,
- // it is explicitly not killed following that operation.
- //
- // We execute this kill when these conditions hold:
- // 1. it's not a system-uid process,
- // 2. the app did not request its own restore (mTargetPackage == null), and
- // either
- // 3a. the app is a full-data target (TYPE_FULL_STREAM) or
- // b. the app does not state android:killAfterRestore="false" in its manifest
- final int appFlags = mCurrentPackage.applicationInfo.flags;
- final boolean killAfterRestore =
- !UserHandle.isCore(mCurrentPackage.applicationInfo.uid)
- && ((mRestoreDescription.getDataType()
- == RestoreDescription.TYPE_FULL_STREAM)
- || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE)
- != 0));
-
- if (mTargetPackage == null && killAfterRestore) {
- if (DEBUG) {
- Slog.d(
- TAG,
- "Restore complete, killing host process of "
- + mCurrentPackage.applicationInfo.processName);
- }
- backupManagerService
- .getActivityManager()
- .killApplicationProcess(
- mCurrentPackage.applicationInfo.processName,
- mCurrentPackage.applicationInfo.uid);
- }
- } catch (RemoteException e) {
- // can't happen; we run in the same process as the activity manager
- }
+ // If mTargetPackage is not null it means the app requested its own restore, in which
+ // case we won't allow the app to be killed.
+ backupManagerService.getBackupAgentConnectionManager().unbindAgent(
+ mCurrentPackage.applicationInfo, /* allowKill= */ mTargetPackage == null);
}
// The caller is responsible for reestablishing the state machine; our