Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d582787a authored by Annie Meng's avatar Annie Meng
Browse files

Create "android" backup agent in the system process for all users

1) Return the system user's appInfo for "android" so we launch into the
system process.
2) In the system process, each user has its own instance of the "android"
backup agent to allow for parallel backups across users.
3) Update agent bookkeeping to key by user id.

Bug: 111500434
Test: 1) "adb shell bmgr backupnow android" for system and non-system
user; verify through debugger and logging that each user has its own
agent instance and both run in the system process; verify backup
succeeds
2) Repeat with "adb shell bmgr restore [token] android"

Change-Id: Ie9c8934daac02fb1c09f37753ef02ef957d18a75
parent 063180fa
Loading
Loading
Loading
Loading
+27 −8
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ import android.util.MergedConfiguration;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.SuperNotCalledException;
import android.util.proto.ProtoOutputStream;
@@ -306,8 +307,14 @@ public final class ActivityThread extends ClientTransactionHandler {
    @UnsupportedAppUsage
    final ArrayList<Application> mAllApplications
            = new ArrayList<Application>();
    // set of instantiated backup agents, keyed by package name
    final ArrayMap<String, BackupAgent> mBackupAgents = new ArrayMap<String, BackupAgent>();
    /**
     * Bookkeeping of instantiated backup agents indexed first by user id, then by package name.
     * Indexing by user id supports parallel backups across users on system packages as they run in
     * the same process with the same package name. Indexing by package name supports multiple
     * distinct applications running in the same process.
     */
    private final SparseArray<ArrayMap<String, BackupAgent>> mBackupAgentsByUser =
            new SparseArray<>();
    /** Reference to singleton {@link ActivityThread} */
    @UnsupportedAppUsage
    private static volatile ActivityThread sCurrentActivityThread;
@@ -882,10 +889,11 @@ public final class ActivityThread extends ClientTransactionHandler {
        }

        public final void scheduleDestroyBackupAgent(ApplicationInfo app,
                CompatibilityInfo compatInfo) {
                CompatibilityInfo compatInfo, int userId) {
            CreateBackupAgentData d = new CreateBackupAgentData();
            d.appInfo = app;
            d.compatInfo = compatInfo;
            d.userId = userId;

            sendMessage(H.DESTROY_BACKUP_AGENT, d);
        }
@@ -3613,7 +3621,8 @@ public final class ActivityThread extends ClientTransactionHandler {

        try {
            IBinder binder = null;
            BackupAgent agent = mBackupAgents.get(packageName);
            ArrayMap<String, BackupAgent> backupAgents = getBackupAgentsForUser(data.userId);
            BackupAgent agent = backupAgents.get(packageName);
            if (agent != null) {
                // reusing the existing instance
                if (DEBUG_BACKUP) {
@@ -3634,7 +3643,7 @@ public final class ActivityThread extends ClientTransactionHandler {

                    agent.onCreate(UserHandle.of(data.userId));
                    binder = agent.onBind();
                    mBackupAgents.put(packageName, agent);
                    backupAgents.put(packageName, agent);
                } catch (Exception e) {
                    // If this is during restore, fail silently; otherwise go
                    // ahead and let the user see the crash.
@@ -3650,7 +3659,7 @@ public final class ActivityThread extends ClientTransactionHandler {

            // tell the OS that we're live now
            try {
                ActivityManager.getService().backupAgentCreated(packageName, binder);
                ActivityManager.getService().backupAgentCreated(packageName, binder, data.userId);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
@@ -3666,7 +3675,8 @@ public final class ActivityThread extends ClientTransactionHandler {

        LoadedApk packageInfo = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
        String packageName = packageInfo.mPackageName;
        BackupAgent agent = mBackupAgents.get(packageName);
        ArrayMap<String, BackupAgent> backupAgents = getBackupAgentsForUser(data.userId);
        BackupAgent agent = backupAgents.get(packageName);
        if (agent != null) {
            try {
                agent.onDestroy();
@@ -3674,12 +3684,21 @@ public final class ActivityThread extends ClientTransactionHandler {
                Slog.w(TAG, "Exception thrown in onDestroy by backup agent of " + data.appInfo);
                e.printStackTrace();
            }
            mBackupAgents.remove(packageName);
            backupAgents.remove(packageName);
        } else {
            Slog.w(TAG, "Attempt to destroy unknown backup agent " + data);
        }
    }

    private ArrayMap<String, BackupAgent> getBackupAgentsForUser(int userId) {
        ArrayMap<String, BackupAgent> backupAgents = mBackupAgentsByUser.get(userId);
        if (backupAgents == null) {
            backupAgents = new ArrayMap<>();
            mBackupAgentsByUser.put(userId, backupAgents);
        }
        return backupAgents;
    }

    @UnsupportedAppUsage
    private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
+2 −2
Original line number Diff line number Diff line
@@ -221,8 +221,8 @@ interface IActivityManager {
    boolean shutdown(int timeout);
    void stopAppSwitches();
    void resumeAppSwitches();
    boolean bindBackupAgent(in String packageName, int backupRestoreMode, int userId);
    void backupAgentCreated(in String packageName, in IBinder agent);
    boolean bindBackupAgent(in String packageName, int backupRestoreMode, int targetUserId);
    void backupAgentCreated(in String packageName, in IBinder agent, int userId);
    void unbindBackupAgent(in ApplicationInfo appInfo);
    int getUidForIntentSender(in IIntentSender sender);
    int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ oneway interface IApplicationThread {
    void scheduleCreateBackupAgent(in ApplicationInfo app, in CompatibilityInfo compatInfo,
            int backupMode, int userId);
    void scheduleDestroyBackupAgent(in ApplicationInfo app,
            in CompatibilityInfo compatInfo);
            in CompatibilityInfo compatInfo, int userId);
    void scheduleOnNewActivityOptions(IBinder token, in Bundle options);
    void scheduleSuicide();
    void dispatchPackageBroadcast(int cmd, in String[] packages);
+1 −1
Original line number Diff line number Diff line
@@ -470,7 +470,7 @@ public class TransactionParcelTests {

        @Override
        public void scheduleDestroyBackupAgent(ApplicationInfo applicationInfo,
                CompatibilityInfo compatibilityInfo) throws RemoteException {
                CompatibilityInfo compatibilityInfo, int userId) throws RemoteException {
        }

        @Override
+26 −15
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NA
import static com.android.server.am.MemoryStatUtil.hasMemcg;
import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
import static com.android.server.am.MemoryStatUtil.readRssHighWaterMarkFromProcfs;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
@@ -13638,18 +13639,26 @@ public class ActivityManagerService extends IActivityManager.Stub
    // 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 userId) {
    public boolean bindBackupAgent(String packageName, int backupMode, int targetUserId) {
        if (DEBUG_BACKUP) {
            Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode="
                    + backupMode + " userId=" + userId + " callingUid = " + Binder.getCallingUid()
            Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode
                    + " targetUserId=" + targetUserId + " callingUid = " + Binder.getCallingUid()
                    + " uid = " + Process.myUid());
        }
        enforceCallingPermission("android.permission.CONFIRM_FULL_BACKUP", "bindBackupAgent");
        // The instantiatedUserId is the user of the process the backup agent is started in. This is
        // different from the targetUserId which is the user whose data is to be backed up or
        // restored. This distinction is important for system-process packages that live in the
        // system user's process but backup/restore data for non-system users.
        // TODO (b/123688746): Handle all system-process packages with singleton check.
        final int instantiatedUserId =
                PLATFORM_PACKAGE_NAME.equals(packageName) ? UserHandle.USER_SYSTEM : targetUserId;
        IPackageManager pm = AppGlobals.getPackageManager();
        ApplicationInfo app = null;
        try {
            app = pm.getApplicationInfo(packageName, STOCK_PM_FLAGS, userId);
            app = pm.getApplicationInfo(packageName, STOCK_PM_FLAGS, instantiatedUserId);
        } catch (RemoteException e) {
            // can't happen; package manager is process-local
        }
@@ -13673,7 +13682,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                        + app.packageName + ": " + e);
            }
            BackupRecord r = new BackupRecord(app, backupMode, userId);
            BackupRecord r = new BackupRecord(app, backupMode, targetUserId);
            ComponentName hostingName =
                    (backupMode == ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL)
                            ? new ComponentName(app.packageName, app.backupAgentName)
@@ -13695,10 +13704,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                proc.inFullBackup = true;
            }
            r.app = proc;
            final BackupRecord backupTarget = mBackupTargets.get(userId);
            final BackupRecord backupTarget = mBackupTargets.get(targetUserId);
            oldBackupUid = backupTarget != null ? backupTarget.appInfo.uid : -1;
            newBackupUid = proc.inFullBackup ? r.appInfo.uid : -1;
            mBackupTargets.put(userId, r);
            mBackupTargets.put(targetUserId, r);
            // Try not to kill the process during backup
            updateOomAdjLocked(proc, true);
@@ -13709,7 +13718,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "Agent proc already running: " + proc);
                try {
                    proc.thread.scheduleCreateBackupAgent(app,
                            compatibilityInfoForPackage(app), backupMode, userId);
                            compatibilityInfoForPackage(app), backupMode, targetUserId);
                } catch (RemoteException e) {
                    // Will time out on the backup manager side
                }
@@ -13749,16 +13758,18 @@ public class ActivityManagerService extends IActivityManager.Stub
    // A backup agent has just come up
    @Override
    public void backupAgentCreated(String agentPackageName, IBinder agent) {
        final int callingUserId = UserHandle.getCallingUserId();
    public void backupAgentCreated(String agentPackageName, IBinder agent, int userId) {
        // Resolve the target user id and enforce permissions.
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, /* allowAll */ false, ALLOW_FULL_ONLY, "backupAgentCreated", null);
        if (DEBUG_BACKUP) {
            Slog.v(TAG_BACKUP, "backupAgentCreated: " + agentPackageName + " = " + agent
                    + " callingUserId = " + callingUserId + " callingUid = "
                    + Binder.getCallingUid() + " uid = " + Process.myUid());
                    + " callingUserId = " + UserHandle.getCallingUserId() + " userId = " + userId
                    + " callingUid = " + Binder.getCallingUid() + " uid = " + Process.myUid());
        }
        synchronized(this) {
            final BackupRecord backupTarget = mBackupTargets.get(callingUserId);
            final BackupRecord backupTarget = mBackupTargets.get(userId);
            String backupAppName = backupTarget == null ? null : backupTarget.appInfo.packageName;
            if (!agentPackageName.equals(backupAppName)) {
                Slog.e(TAG, "Backup agent created for " + agentPackageName + " but not requested!");
@@ -13770,7 +13781,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        try {
            IBackupManager bm = IBackupManager.Stub.asInterface(
                    ServiceManager.getService(Context.BACKUP_SERVICE));
            bm.agentConnectedForUser(callingUserId, agentPackageName, agent);
            bm.agentConnectedForUser(userId, agentPackageName, agent);
        } catch (RemoteException e) {
            // can't happen; the backup manager service is local
        } catch (Exception e) {
@@ -13823,7 +13834,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                if (proc.thread != null) {
                    try {
                        proc.thread.scheduleDestroyBackupAgent(appInfo,
                                compatibilityInfoForPackage(appInfo));
                                compatibilityInfoForPackage(appInfo), userId);
                    } catch (Exception e) {
                        Slog.e(TAG, "Exception when unbinding backup agent:");
                        e.printStackTrace();