Merge "[Multi-user] Make backup and initialize receivers per user"
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index b01117c..d7a2365 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -503,26 +503,46 @@
 
         mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng);
 
-        // Alarm receivers for scheduled backups & initialization operations
-        BroadcastReceiver mRunBackupReceiver = new RunBackupReceiver(this);
+        // Receivers for scheduled backups and transport initialization operations.
+        BroadcastReceiver runBackupReceiver = new RunBackupReceiver(this);
         IntentFilter filter = new IntentFilter();
         filter.addAction(RUN_BACKUP_ACTION);
-        context.registerReceiver(mRunBackupReceiver, filter,
-                android.Manifest.permission.BACKUP, null);
+        context.registerReceiverAsUser(
+                runBackupReceiver,
+                UserHandle.of(userId),
+                filter,
+                android.Manifest.permission.BACKUP,
+                /* scheduler */ null);
 
-        BroadcastReceiver mRunInitReceiver = new RunInitializeReceiver(this);
+        BroadcastReceiver runInitReceiver = new RunInitializeReceiver(this);
         filter = new IntentFilter();
         filter.addAction(RUN_INITIALIZE_ACTION);
-        context.registerReceiver(mRunInitReceiver, filter,
-                android.Manifest.permission.BACKUP, null);
+        context.registerReceiverAsUser(
+                runInitReceiver,
+                UserHandle.of(userId),
+                filter,
+                android.Manifest.permission.BACKUP,
+                /* scheduler */ null);
 
         Intent backupIntent = new Intent(RUN_BACKUP_ACTION);
         backupIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mRunBackupIntent = PendingIntent.getBroadcast(context, 0, backupIntent, 0);
+        mRunBackupIntent =
+                PendingIntent.getBroadcastAsUser(
+                        context,
+                        /* requestCode */ 0,
+                        backupIntent,
+                        /* flags */ 0,
+                        UserHandle.of(userId));
 
         Intent initIntent = new Intent(RUN_INITIALIZE_ACTION);
         initIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mRunInitIntent = PendingIntent.getBroadcast(context, 0, initIntent, 0);
+        mRunInitIntent =
+                PendingIntent.getBroadcastAsUser(
+                        context,
+                        /* requestCode */ 0,
+                        initIntent,
+                        /* flags */ 0,
+                        UserHandle.of(userId));
 
         // Set up the backup-request journaling
         mJournalDir = new File(mBaseStateDir, "pending");
diff --git a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
index 3b87724..d37b106 100644
--- a/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunBackupReceiver.java
@@ -26,62 +26,84 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Handler;
 import android.os.Message;
 import android.util.Slog;
 
 import com.android.server.backup.UserBackupManagerService;
 
+/**
+ * A {@link BroadcastReceiver} for the action {@link UserBackupManagerService#RUN_BACKUP_ACTION}
+ * that runs an immediate backup operation if eligible.
+ */
 public class RunBackupReceiver extends BroadcastReceiver {
+    private final UserBackupManagerService mUserBackupManagerService;
 
-    private UserBackupManagerService backupManagerService;
-
-    public RunBackupReceiver(UserBackupManagerService backupManagerService) {
-        this.backupManagerService = backupManagerService;
+    public RunBackupReceiver(UserBackupManagerService userBackupManagerService) {
+        mUserBackupManagerService = userBackupManagerService;
     }
 
+    /**
+     * Run a backup pass if we're eligible. We're eligible if the following conditions are met:
+     *
+     * <ul>
+     *   <li>No transports are pending initialization (otherwise we kick off an initialization
+     *       operation instead).
+     *   <li>Backup is enabled for the user.
+     *   <li>The user has completed setup.
+     *   <li>No backup operation is currently running for the user.
+     * </ul>
+     */
     public void onReceive(Context context, Intent intent) {
-        if (RUN_BACKUP_ACTION.equals(intent.getAction())) {
-            synchronized (backupManagerService.getQueueLock()) {
-                if (backupManagerService.getPendingInits().size() > 0) {
-                    // If there are pending init operations, we process those
-                    // and then settle into the usual periodic backup schedule.
-                    if (MORE_DEBUG) {
-                        Slog.v(TAG, "Init pending at scheduled backup");
-                    }
-                    try {
-                        backupManagerService.getAlarmManager().cancel(
-                                backupManagerService.getRunInitIntent());
-                        backupManagerService.getRunInitIntent().send();
-                    } catch (PendingIntent.CanceledException ce) {
-                        Slog.e(TAG, "Run init intent cancelled");
-                        // can't really do more than bail here
-                    }
-                } else {
-                    // Don't run backups now if we're disabled or not yet
-                    // fully set up.
-                    if (backupManagerService.isEnabled()
-                            && backupManagerService.isSetupComplete()) {
-                        if (!backupManagerService.isBackupRunning()) {
-                            if (DEBUG) {
-                                Slog.v(TAG, "Running a backup pass");
-                            }
+        if (!RUN_BACKUP_ACTION.equals(intent.getAction())) {
+            return;
+        }
 
-                            // Acquire the wakelock and pass it to the backup thread.  it will
-                            // be released once backup concludes.
-                            backupManagerService.setBackupRunning(true);
-                            backupManagerService.getWakelock().acquire();
-
-                            Message msg = backupManagerService.getBackupHandler().obtainMessage(
-                                    MSG_RUN_BACKUP);
-                            backupManagerService.getBackupHandler().sendMessage(msg);
-                        } else {
-                            Slog.i(TAG, "Backup time but one already running");
-                        }
-                    } else {
-                        Slog.w(TAG, "Backup pass but enabled=" + backupManagerService.isEnabled()
-                                + " setupComplete=" + backupManagerService.isSetupComplete());
-                    }
+        synchronized (mUserBackupManagerService.getQueueLock()) {
+            if (mUserBackupManagerService.getPendingInits().size() > 0) {
+                // If there are pending init operations, we process those and then settle into the
+                // usual periodic backup schedule.
+                if (MORE_DEBUG) {
+                    Slog.v(TAG, "Init pending at scheduled backup");
                 }
+                try {
+                    PendingIntent runInitIntent = mUserBackupManagerService.getRunInitIntent();
+                    mUserBackupManagerService.getAlarmManager().cancel(runInitIntent);
+                    runInitIntent.send();
+                } catch (PendingIntent.CanceledException ce) {
+                    Slog.w(TAG, "Run init intent cancelled");
+                }
+            } else {
+                // Don't run backups if we're disabled or not yet set up.
+                if (!mUserBackupManagerService.isEnabled()
+                        || !mUserBackupManagerService.isSetupComplete()) {
+                    Slog.w(
+                            TAG,
+                            "Backup pass but enabled="
+                                    + mUserBackupManagerService.isEnabled()
+                                    + " setupComplete="
+                                    + mUserBackupManagerService.isSetupComplete());
+                    return;
+                }
+
+                // Don't run backups if one is already running.
+                if (mUserBackupManagerService.isBackupRunning()) {
+                    Slog.i(TAG, "Backup time but one already running");
+                    return;
+                }
+
+                if (DEBUG) {
+                    Slog.v(TAG, "Running a backup pass");
+                }
+
+                // Acquire the wakelock and pass it to the backup thread. It will be released once
+                // backup concludes.
+                mUserBackupManagerService.setBackupRunning(true);
+                mUserBackupManagerService.getWakelock().acquire();
+
+                Handler backupHandler = mUserBackupManagerService.getBackupHandler();
+                Message message = backupHandler.obtainMessage(MSG_RUN_BACKUP);
+                backupHandler.sendMessage(message);
             }
         }
     }
diff --git a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
index 38870cb..97711e3 100644
--- a/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
+++ b/services/backup/java/com/android/server/backup/internal/RunInitializeReceiver.java
@@ -24,41 +24,50 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.PowerManager;
-import android.util.ArraySet;
 import android.util.Slog;
 
 import com.android.server.backup.UserBackupManagerService;
 
-public class RunInitializeReceiver extends BroadcastReceiver {
-    private final UserBackupManagerService mBackupManagerService;
+import java.util.Set;
 
-    public RunInitializeReceiver(UserBackupManagerService backupManagerService) {
-        mBackupManagerService = backupManagerService;
+/**
+ * A {@link BroadcastReceiver} for the action {@link UserBackupManagerService#RUN_INITIALIZE_ACTION}
+ * that runs an initialization operation on all pending transports.
+ */
+public class RunInitializeReceiver extends BroadcastReceiver {
+    private final UserBackupManagerService mUserBackupManagerService;
+
+    public RunInitializeReceiver(UserBackupManagerService userBackupManagerService) {
+        mUserBackupManagerService = userBackupManagerService;
     }
 
     public void onReceive(Context context, Intent intent) {
-        if (RUN_INITIALIZE_ACTION.equals(intent.getAction())) {
-            synchronized (mBackupManagerService.getQueueLock()) {
-                final ArraySet<String> pendingInits = mBackupManagerService.getPendingInits();
-                if (DEBUG) {
-                    Slog.v(TAG, "Running a device init; " + pendingInits.size() + " pending");
-                }
+        if (!RUN_INITIALIZE_ACTION.equals(intent.getAction())) {
+            return;
+        }
 
-                if (pendingInits.size() > 0) {
-                    final String[] transports =
-                            pendingInits.toArray(new String[pendingInits.size()]);
+        synchronized (mUserBackupManagerService.getQueueLock()) {
+            Set<String> pendingInits = mUserBackupManagerService.getPendingInits();
+            if (DEBUG) {
+                Slog.v(TAG, "Running a device init; " + pendingInits.size() + " pending");
+            }
 
-                    mBackupManagerService.clearPendingInits();
+            if (pendingInits.size() > 0) {
+                String[] transports = pendingInits.toArray(new String[pendingInits.size()]);
 
-                    PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock();
-                    wakelock.acquire();
-                    OnTaskFinishedListener listener = caller -> wakelock.release();
+                mUserBackupManagerService.clearPendingInits();
 
-                    Runnable task =
-                            new PerformInitializeTask(
-                                    mBackupManagerService, transports, null, listener);
-                    mBackupManagerService.getBackupHandler().post(task);
-                }
+                PowerManager.WakeLock wakelock = mUserBackupManagerService.getWakelock();
+                wakelock.acquire();
+                OnTaskFinishedListener listener = caller -> wakelock.release();
+
+                Runnable task =
+                        new PerformInitializeTask(
+                                mUserBackupManagerService,
+                                transports,
+                                /* observer */ null,
+                                listener);
+                mUserBackupManagerService.getBackupHandler().post(task);
             }
         }
     }