summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2009-05-06 11:22:00 -0700
committerChristopher Tate <ctate@google.com>2009-05-06 11:24:27 -0700
commit46758123868d91e7b186aebb27c4c4988dede43e (patch)
treedacb54c6da67d1ed7f355a956fc0b335d77af4b8 /services
parentc770ed8a6bb7614ed4a85a672e4e6830bed19a95 (diff)
downloadframeworks_base-46758123868d91e7b186aebb27c4c4988dede43e.zip
frameworks_base-46758123868d91e7b186aebb27c4c4988dede43e.tar.gz
frameworks_base-46758123868d91e7b186aebb27c4c4988dede43e.tar.bz2
Add a Backup Manager interface to request a full backup
Given a package name, the Backup Manager schedules a *full* (i.e. non- incremental) backup pass for that package. Also added the state-file handling for distinguishing to the target between the full and incremental backup requests.
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/BackupManagerService.java67
1 files changed, 52 insertions, 15 deletions
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 04cd53f..64b7f91 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -58,7 +58,16 @@ class BackupManagerService extends IBackupManager.Stub {
private SparseArray<HashSet<ServiceInfo>> mBackupParticipants
= new SparseArray<HashSet<ServiceInfo>>();
// set of backup services that have pending changes
- private HashSet<ServiceInfo> mPendingBackups = new HashSet<ServiceInfo>();
+ private class BackupRequest {
+ public ServiceInfo service;
+ public boolean fullBackup;
+
+ BackupRequest(ServiceInfo svc, boolean isFull) {
+ service = svc;
+ fullBackup = isFull;
+ }
+ }
+ private HashSet<BackupRequest> mPendingBackups = new HashSet<BackupRequest>();
private final Object mQueueLock = new Object();
private File mStateDir;
@@ -77,21 +86,21 @@ class BackupManagerService extends IBackupManager.Stub {
case MSG_RUN_BACKUP:
{
// snapshot the pending-backup set and work on that
- HashSet<ServiceInfo> queue;
+ HashSet<BackupRequest> queue;
synchronized (mQueueLock) {
queue = mPendingBackups;
- mPendingBackups = new HashSet<ServiceInfo>();
+ mPendingBackups = new HashSet<BackupRequest>();
// !!! TODO: start a new backup-queue journal file too
}
// Walk the set of pending backups, setting up the relevant files and
// invoking the backup service in each participant
Intent backupIntent = new Intent(BackupService.SERVICE_ACTION);
- for (ServiceInfo service : queue) {
+ for (BackupRequest request : queue) {
mBinding = true;
mTargetService = null;
- backupIntent.setClassName(service.packageName, service.name);
+ backupIntent.setClassName(request.service.packageName, request.service.name);
Log.d(TAG, "binding to " + backupIntent);
if (mContext.bindService(backupIntent, this, 0)) {
synchronized (mBindSignaller) {
@@ -106,15 +115,25 @@ class BackupManagerService extends IBackupManager.Stub {
try {
Log.d(TAG, "invoking doBackup() on " + backupIntent);
- File savedStateName = new File(mStateDir, service.packageName);
- File backupDataName = new File(mDataDir, service.packageName + ".data");
- File newStateName = new File(mStateDir, service.packageName + ".new");
-
- ParcelFileDescriptor savedState =
- ParcelFileDescriptor.open(savedStateName,
- ParcelFileDescriptor.MODE_READ_ONLY |
- ParcelFileDescriptor.MODE_CREATE);
+ // !!! TODO right now these naming schemes limit applications to
+ // one backup service per package
+ File savedStateName = new File(mStateDir,
+ request.service.packageName);
+ File dummyName = new File(mStateDir, "#####");
+ File backupDataName = new File(mDataDir,
+ request.service.packageName + ".data");
+ File newStateName = new File(mStateDir,
+ request.service.packageName + ".new");
+ // In a full backup, we pass a file that is never writeable, hence
+ // is always zero-sized, as a sentinel to the callee that they must
+ // write all of their data.
+ ParcelFileDescriptor savedState =
+ ParcelFileDescriptor.open(
+ (request.fullBackup) ? savedStateName : dummyName,
+ ParcelFileDescriptor.MODE_READ_ONLY |
+ ParcelFileDescriptor.MODE_CREATE);
+
backupDataName.delete();
ParcelFileDescriptor backupData =
ParcelFileDescriptor.open(backupDataName,
@@ -231,7 +250,7 @@ class BackupManagerService extends IBackupManager.Stub {
// packages associated with this uid
if (service.packageName.equals(packageName)) {
// add the caller to the set of pending backups
- if (mPendingBackups.add(service)) {
+ if (mPendingBackups.add(new BackupRequest(service, false))) {
// !!! TODO: write to the pending-backup journal file in case of crash
}
}
@@ -240,9 +259,27 @@ class BackupManagerService extends IBackupManager.Stub {
// Schedule a backup pass in a few minutes. As backup-eligible data
// keeps changing, continue to defer the backup pass until things
// settle down, to avoid extra overhead.
- mBackupHandler.removeMessages(MSG_RUN_BACKUP);
mBackupHandler.sendEmptyMessageDelayed(MSG_RUN_BACKUP, COLLECTION_INTERVAL);
}
}
}
+
+ // Schedule a backup pass for a given package, even if the caller is not part of
+ // that uid or package itself.
+ public void scheduleFullBackup(String packageName) throws RemoteException {
+ // !!! TODO: protect with a signature-or-system permission?
+ HashSet<ServiceInfo> targets = new HashSet<ServiceInfo>();
+ synchronized (mQueueLock) {
+ int numKeys = mBackupParticipants.size();
+ for (int index = 0; index < numKeys; index++) {
+ int uid = mBackupParticipants.keyAt(index);
+ HashSet<ServiceInfo> servicesAtUid = mBackupParticipants.get(uid);
+ for (ServiceInfo service: servicesAtUid) {
+ if (service.packageName.equals(packageName)) {
+ mPendingBackups.add(new BackupRequest(service, true));
+ }
+ }
+ }
+ }
+ }
}