Merge change 6104 into donut

* changes:
  Add a "clear backed-up data" method to the backup mechanism
This commit is contained in:
Android (Google) Code Review
2009-07-02 12:10:42 -07:00
4 changed files with 135 additions and 3 deletions

View File

@@ -32,9 +32,23 @@ interface IBackupManager {
/**
* Tell the system service that the caller has made changes to its
* data, and therefore needs to undergo an incremental backup pass.
*
* Any application can invoke this method for its own package, but
* only callers who hold the android.permission.BACKUP permission
* may invoke it for arbitrary packages.
*/
void dataChanged(String packageName);
/**
* Erase all backed-up data for the given package from the storage
* destination.
*
* Any application can invoke this method for its own package, but
* only callers who hold the android.permission.BACKUP permission
* may invoke it for arbitrary packages.
*/
void clearBackupData(String packageName);
/**
* Notifies the Backup Manager Service that an agent has become available. This
* method is only invoked by the Activity Manager.

View File

@@ -83,13 +83,25 @@ interface IBackupTransport {
boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd);
/**
* Finish sending application data to the backup destination. This must be
* called after {@link #performBackup} to ensure that all data is sent. Only
* when this method returns true can the backup be assumed to have succeeded.
* Erase the give application's data from the backup destination. This clears
* out the given package's data from the current backup set, making it as though
* the app had never yet been backed up. After this is called, {@link finishBackup}
* must be called to ensure that the operation is recorded successfully.
*
* @return false if errors occurred (the backup should be aborted and rescheduled),
* true if everything is OK so far (but {@link #finishBackup} must be called).
*/
boolean clearBackupData(in PackageInfo packageInfo);
/**
* Finish sending application data to the backup destination. This must be
* called after {@link #performBackup} or {@link clearBackupData} to ensure that
* all data is sent. Only when this method returns true can a backup be assumed
* to have succeeded.
*
* @return false if errors occurred (the backup should be aborted and rescheduled),
* true if everything is OK.
*/
boolean finishBackup();
/**

View File

@@ -111,6 +111,17 @@ public class LocalTransport extends IBackupTransport.Stub {
}
}
public boolean clearBackupData(PackageInfo packageInfo) {
if (DEBUG) Log.v(TAG, "clearBackupData() pkg=" + packageInfo.packageName);
File packageDir = new File(mDataDir, packageInfo.packageName);
for (File f : packageDir.listFiles()) {
f.delete();
}
packageDir.delete();
return true;
}
public boolean finishBackup() throws RemoteException {
if (DEBUG) Log.v(TAG, "finishBackup()");
return true;

View File

@@ -81,6 +81,7 @@ class BackupManagerService extends IBackupManager.Stub {
private static final int MSG_RUN_BACKUP = 1;
private static final int MSG_RUN_FULL_BACKUP = 2;
private static final int MSG_RUN_RESTORE = 3;
private static final int MSG_RUN_CLEAR = 4;
// Timeout interval for deciding that a bind or clear-data has taken too long
static final long TIMEOUT_INTERVAL = 10 * 1000;
@@ -148,6 +149,16 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
private class ClearParams {
public IBackupTransport transport;
public PackageInfo packageInfo;
ClearParams(IBackupTransport _transport, PackageInfo _info) {
transport = _transport;
packageInfo = _info;
}
}
// Where we keep our journal files and other bookkeeping
private File mBaseStateDir;
private File mDataDir;
@@ -386,6 +397,13 @@ class BackupManagerService extends IBackupManager.Stub {
(new PerformRestoreThread(params.transport, params.observer, params.token)).start();
break;
}
case MSG_RUN_CLEAR:
{
ClearParams params = (ClearParams)msg.obj;
(new PerformClearThread(params.transport, params.packageInfo)).start();
break;
}
}
}
}
@@ -1071,6 +1089,37 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
class PerformClearThread extends Thread {
IBackupTransport mTransport;
PackageInfo mPackage;
PerformClearThread(IBackupTransport transport, PackageInfo packageInfo) {
mTransport = transport;
mPackage = packageInfo;
}
@Override
public void run() {
try {
// Clear the on-device backup state to ensure a full backup next time
File stateDir = new File(mBaseStateDir, mTransport.transportDirName());
File stateFile = new File(stateDir, mPackage.packageName);
stateFile.delete();
// Tell the transport to remove all the persistent storage for the app
mTransport.clearBackupData(mPackage);
} catch (RemoteException e) {
// can't happen; the transport is local
} finally {
try {
mTransport.finishBackup();
} catch (RemoteException e) {
// can't happen; the transport is local
}
}
}
}
// ----- IBackupManager binder interface -----
@@ -1142,6 +1191,52 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
// Clear the given package's backup data from the current transport
public void clearBackupData(String packageName) {
if (DEBUG) Log.v(TAG, "clearBackupData() of " + packageName);
PackageInfo info;
try {
info = mPackageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
} catch (NameNotFoundException e) {
Log.d(TAG, "No such package '" + packageName + "' - not clearing backup data");
return;
}
// If the caller does not hold the BACKUP permission, it can only request a
// wipe of its own backed-up data.
HashSet<ApplicationInfo> apps;
if ((mContext.checkPermission("android.permission.BACKUP", Binder.getCallingPid(),
Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
apps = mBackupParticipants.get(Binder.getCallingUid());
} else {
// a caller with full permission can ask to back up any participating app
// !!! TODO: allow data-clear of ANY app?
if (DEBUG) Log.v(TAG, "Privileged caller, allowing clear of other apps");
apps = new HashSet<ApplicationInfo>();
int N = mBackupParticipants.size();
for (int i = 0; i < N; i++) {
HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
if (s != null) {
apps.addAll(s);
}
}
}
// now find the given package in the set of candidate apps
for (ApplicationInfo app : apps) {
if (app.packageName.equals(packageName)) {
if (DEBUG) Log.v(TAG, "Found the app - running clear process");
// found it; fire off the clear request
synchronized (mQueueLock) {
Message msg = mBackupHandler.obtainMessage(MSG_RUN_CLEAR,
new ClearParams(getTransport(mCurrentTransport), info));
mBackupHandler.sendMessage(msg);
}
break;
}
}
}
// Run a backup pass immediately for any applications that have declared
// that they have pending updates.
public void backupNow() throws RemoteException {