diff options
author | Christopher Tate <ctate@google.com> | 2009-05-06 11:22:00 -0700 |
---|---|---|
committer | Christopher Tate <ctate@google.com> | 2009-05-06 11:24:27 -0700 |
commit | 46758123868d91e7b186aebb27c4c4988dede43e (patch) | |
tree | dacb54c6da67d1ed7f355a956fc0b335d77af4b8 /services | |
parent | c770ed8a6bb7614ed4a85a672e4e6830bed19a95 (diff) | |
download | frameworks_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.java | 67 |
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)); + } + } + } + } + } } |