Merge change 972 into donut
* changes:
Back-merge all changes done in master to DumpRenderTree to donut.
diff --git a/core/java/android/backup/BackupService.java b/core/java/android/backup/BackupService.java
index d912d8c..6197182 100644
--- a/core/java/android/backup/BackupService.java
+++ b/core/java/android/backup/BackupService.java
@@ -22,6 +22,7 @@
import android.backup.IBackupService;
import android.content.Intent;
import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
@@ -59,23 +60,25 @@
* The application is being asked to write any data changed since the
* last time it performed a backup operation. The state data recorded
* during the last backup pass is provided in the oldStateFd file descriptor.
- * If oldStateFd is negative, no old state is available and the application
- * should perform a full backup. In both cases, a representation of the
- * final backup state after this pass should be written to the file pointed
+ * If oldState.getStatSize() is zero or negative, no old state is available
+ * and the application should perform a full backup. In both cases, a representation
+ * of the final backup state after this pass should be written to the file pointed
* to by the newStateFd file descriptor.
*
- * @param oldStateFd An open, read-only file descriptor pointing to the last
- * backup state provided by the application. May be negative,
- * in which case no prior state is being provided and the
- * application should perform a full backup.
- * @param dataFd An open, read/write file descriptor pointing to the backup data
- * destination. Typically the application will use backup helper
- * classes to write to this file.
- * @param newStateFd An open, read/write file descriptor pointing to an empty
- * file. The application should record the final backup state
- * here after writing the requested data to dataFd.
+ * @param oldState An open, read-only ParcelFileDescriptor pointing to the last backup
+ * state provided by the application. May be empty or invalid, in which
+ * case no prior state is being provided and the application should
+ * perform a full backup.
+ * @param data An open, read/write ParcelFileDescriptor pointing to the backup data
+ * destination. Typically the application will use backup helper
+ * classes to write to this file.
+ * @param newState An open, read/write ParcelFileDescriptor pointing to an empty
+ * file. The application should record the final backup state
+ * here after writing the requested data to dataFd.
*/
- public abstract void onBackup(int oldStateFd, int dataFd, int newStateFd);
+ public abstract void onBackup(ParcelFileDescriptor oldState,
+ ParcelFileDescriptor data,
+ ParcelFileDescriptor newState);
/**
* The application is being restored from backup, and should replace any
@@ -84,13 +87,13 @@
* the restore is finished, the application should write a representation
* of the final state to the newStateFd file descriptor,
*
- * @param dataFd An open, read-only file descriptor pointing to a full snapshot
- * of the application's data.
- * @param newStateFd An open, read/write file descriptor pointing to an empty
- * file. The application should record the final backup state
- * here after restoring its data from dataFd.
+ * @param data An open, read-only ParcelFileDescriptor pointing to a full snapshot
+ * of the application's data.
+ * @param newState An open, read/write ParcelFileDescriptor pointing to an empty
+ * file. The application should record the final backup state
+ * here after restoring its data from dataFd.
*/
- public abstract void onRestore(int dataFd, int newStateFd);
+ public abstract void onRestore(ParcelFileDescriptor data, ParcelFileDescriptor newState);
// ----- Core implementation -----
@@ -110,17 +113,19 @@
// ----- IBackupService binder interface -----
private class BackupServiceBinder extends IBackupService.Stub {
- public void doBackup(int oldStateFd, int dataFd, int newStateFd)
- throws RemoteException {
+ public void doBackup(ParcelFileDescriptor oldState,
+ ParcelFileDescriptor data,
+ ParcelFileDescriptor newState) throws RemoteException {
// !!! TODO - real implementation; for now just invoke the callbacks directly
Log.v("BackupServiceBinder", "doBackup() invoked");
- BackupService.this.onBackup(oldStateFd, dataFd, newStateFd);
+ BackupService.this.onBackup(oldState, data, newState);
}
- public void doRestore(int dataFd, int newStateFd) throws RemoteException {
+ public void doRestore(ParcelFileDescriptor data,
+ ParcelFileDescriptor newState) throws RemoteException {
// !!! TODO - real implementation; for now just invoke the callbacks directly
Log.v("BackupServiceBinder", "doRestore() invoked");
- BackupService.this.onRestore(dataFd, newStateFd);
+ BackupService.this.onRestore(data, newState);
}
}
}
diff --git a/core/java/android/backup/IBackupService.aidl b/core/java/android/backup/IBackupService.aidl
index 24544bd..1bde8ea 100644
--- a/core/java/android/backup/IBackupService.aidl
+++ b/core/java/android/backup/IBackupService.aidl
@@ -16,38 +16,44 @@
package android.backup;
+import android.os.ParcelFileDescriptor;
+
/**
* Interface presented by applications being asked to participate in the
* backup & restore mechanism. End user code does not typically implement
* this interface; they subclass BackupService instead.
*
* {@hide}
- */
+ */
interface IBackupService {
/**
* Request that the app perform an incremental backup.
*
- * @param oldStateFd Read-only file containing the description blob of the
+ * @param oldState Read-only file containing the description blob of the
* app's data state as of the last backup operation's completion.
+ * This file is empty or invalid when a full backup is being
+ * requested.
*
- * @param dataFd Read-write file, empty when onBackup() is called, that
+ * @param data Read-write file, empty when onBackup() is called, that
* is the data destination for this backup pass's incrementals.
*
- * @param newStateFd Read-write file, empty when onBackup() is called,
+ * @param newState Read-write file, empty when onBackup() is called,
* where the new state blob is to be recorded.
*/
- void doBackup(int oldStateFd, int dataFd, int newStateFd);
+ void doBackup(in ParcelFileDescriptor oldState,
+ in ParcelFileDescriptor data,
+ in ParcelFileDescriptor newState);
/**
* Restore an entire data snapshot to the application.
*
- * @param dataFd Read-only file containing the full data snapshot of the
+ * @param data Read-only file containing the full data snapshot of the
* app's backup. This is to be a <i>replacement</i> of the app's
* current data, not to be merged into it.
*
- * @param newStateFd Read-write file, empty when onRestore() is called,
+ * @param newState Read-write file, empty when onRestore() is called,
* that is to be written with the state description that holds after
* the restore has been completed.
*/
- void doRestore(int dataFd, int newStateFd);
+ void doRestore(in ParcelFileDescriptor data, in ParcelFileDescriptor newState);
}
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 0f95318..f5f3561 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -26,15 +26,19 @@
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Binder;
+import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;
import android.util.SparseArray;
import android.backup.IBackupManager;
+import java.io.File;
+import java.io.FileNotFoundException;
import java.lang.String;
import java.util.HashSet;
import java.util.List;
@@ -57,6 +61,7 @@
private HashSet<ServiceInfo> mPendingBackups = new HashSet<ServiceInfo>();
private final Object mQueueLock = new Object();
+ private File mStateDir;
// ----- Handler that runs the actual backup process asynchronously -----
@@ -99,12 +104,41 @@
if (mTargetService != null) {
try {
Log.d(TAG, "invoking doBackup() on " + backupIntent);
- // !!! TODO: set up files
- mTargetService.doBackup(-1, -1, -1);
+
+ File savedStateName = new File(mStateDir, service.packageName);
+ File backupDataName = new File(mStateDir, service.packageName + ".data");
+ File newStateName = new File(mStateDir, service.packageName + ".new");
+
+ ParcelFileDescriptor savedState =
+ ParcelFileDescriptor.open(savedStateName,
+ ParcelFileDescriptor.MODE_READ_ONLY |
+ ParcelFileDescriptor.MODE_CREATE);
+ ParcelFileDescriptor backupData =
+ ParcelFileDescriptor.open(backupDataName,
+ ParcelFileDescriptor.MODE_READ_WRITE |
+ ParcelFileDescriptor.MODE_CREATE);
+ ParcelFileDescriptor newState =
+ ParcelFileDescriptor.open(newStateName,
+ ParcelFileDescriptor.MODE_READ_WRITE |
+ ParcelFileDescriptor.MODE_CREATE);
+
+ mTargetService.doBackup(savedState, backupData, newState);
+
+ // !!! TODO: Now propagate the newly-backed-up data to the transport
+
+ // !!! TODO: After successful transport, juggle the files so that
+ // next time the new state is used as the old state
+
+ } catch (FileNotFoundException fnf) {
+ Log.d(TAG, "File not found on backup: ");
+ fnf.printStackTrace();
} catch (RemoteException e) {
Log.d(TAG, "Remote target " + backupIntent
+ " threw during backup:");
e.printStackTrace();
+ } catch (Exception e) {
+ Log.w(TAG, "Final exception guard in backup: ");
+ e.printStackTrace();
}
mContext.unbindService(this);
}
@@ -138,6 +172,11 @@
mContext = context;
mPackageManager = context.getPackageManager();
+ // Set up our bookkeeping
+ File dataDir = Environment.getDataDirectory();
+ mStateDir = new File(dataDir, "backup");
+ mStateDir.mkdirs();
+
// Identify the backup participants
// !!! TODO: also watch package-install to keep this up to date
List<ResolveInfo> services = mPackageManager.queryIntentServices(