backup fixes:
- BackupTestAgent calls the DispatchHelper - Make BackupAgent.onRestore take a BackupDataInput, not just a generic ParcelFileDescriptor.
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
package android.app;
|
package android.app;
|
||||||
|
|
||||||
import android.app.IBackupAgent;
|
import android.app.IBackupAgent;
|
||||||
|
import android.backup.BackupDataInput;
|
||||||
import android.backup.BackupDataOutput;
|
import android.backup.BackupDataOutput;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
@@ -25,6 +26,8 @@ import android.os.ParcelFileDescriptor;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the central interface between an application and Android's
|
* This is the central interface between an application and Android's
|
||||||
* settings backup mechanism.
|
* settings backup mechanism.
|
||||||
@@ -32,6 +35,8 @@ import android.util.Log;
|
|||||||
* @hide pending API solidification
|
* @hide pending API solidification
|
||||||
*/
|
*/
|
||||||
public abstract class BackupAgent extends ContextWrapper {
|
public abstract class BackupAgent extends ContextWrapper {
|
||||||
|
private static final String TAG = "BackupAgent";
|
||||||
|
|
||||||
public BackupAgent() {
|
public BackupAgent() {
|
||||||
super(null);
|
super(null);
|
||||||
}
|
}
|
||||||
@@ -77,8 +82,8 @@ public abstract class BackupAgent extends ContextWrapper {
|
|||||||
* file. The application should record the final backup state
|
* file. The application should record the final backup state
|
||||||
* here after restoring its data from dataFd.
|
* here after restoring its data from dataFd.
|
||||||
*/
|
*/
|
||||||
public abstract void onRestore(ParcelFileDescriptor /* TODO: BackupDataInput */ data,
|
public abstract void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
|
||||||
ParcelFileDescriptor newState);
|
throws IOException;
|
||||||
|
|
||||||
|
|
||||||
// ----- Core implementation -----
|
// ----- Core implementation -----
|
||||||
@@ -107,13 +112,11 @@ public abstract class BackupAgent extends ContextWrapper {
|
|||||||
ParcelFileDescriptor newState) throws RemoteException {
|
ParcelFileDescriptor newState) throws RemoteException {
|
||||||
// !!! TODO - real implementation; for now just invoke the callbacks directly
|
// !!! TODO - real implementation; for now just invoke the callbacks directly
|
||||||
Log.v(TAG, "doBackup() invoked");
|
Log.v(TAG, "doBackup() invoked");
|
||||||
BackupDataOutput output = new BackupDataOutput(BackupAgent.this,
|
BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
|
||||||
data.getFileDescriptor());
|
|
||||||
try {
|
try {
|
||||||
BackupAgent.this.onBackup(oldState, output, newState);
|
BackupAgent.this.onBackup(oldState, output, newState);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
Log.d("BackupAgent", "onBackup ("
|
Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
|
||||||
+ BackupAgent.this.getClass().getName() + ") threw", ex);
|
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +125,16 @@ public abstract class BackupAgent extends ContextWrapper {
|
|||||||
ParcelFileDescriptor newState) throws RemoteException {
|
ParcelFileDescriptor newState) throws RemoteException {
|
||||||
// !!! TODO - real implementation; for now just invoke the callbacks directly
|
// !!! TODO - real implementation; for now just invoke the callbacks directly
|
||||||
Log.v(TAG, "doRestore() invoked");
|
Log.v(TAG, "doRestore() invoked");
|
||||||
BackupAgent.this.onRestore(data, newState);
|
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
|
||||||
|
try {
|
||||||
|
BackupAgent.this.onRestore(input, newState);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package android.app;
|
package android.app;
|
||||||
|
|
||||||
|
import android.backup.BackupDataInput;
|
||||||
import android.backup.BackupDataOutput;
|
import android.backup.BackupDataOutput;
|
||||||
import android.backup.FileBackupHelper;
|
import android.backup.FileBackupHelper;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
@@ -52,6 +53,6 @@ public class FullBackupAgent extends BackupAgent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestore(ParcelFileDescriptor data, ParcelFileDescriptor newState) {
|
public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,11 @@ import java.io.IOException;
|
|||||||
/** @hide */
|
/** @hide */
|
||||||
public class BackupDataOutput {
|
public class BackupDataOutput {
|
||||||
int mBackupWriter;
|
int mBackupWriter;
|
||||||
private Context mContext;
|
|
||||||
|
|
||||||
public static final int OP_UPDATE = 1;
|
public static final int OP_UPDATE = 1;
|
||||||
public static final int OP_DELETE = 2;
|
public static final int OP_DELETE = 2;
|
||||||
|
|
||||||
public BackupDataOutput(Context context, FileDescriptor fd) {
|
public BackupDataOutput(FileDescriptor fd) {
|
||||||
mContext = context;
|
|
||||||
if (fd == null) throw new NullPointerException();
|
if (fd == null) throw new NullPointerException();
|
||||||
mBackupWriter = ctor(fd);
|
mBackupWriter = ctor(fd);
|
||||||
if (mBackupWriter == 0) {
|
if (mBackupWriter == 0) {
|
||||||
|
|||||||
@@ -16,11 +16,15 @@
|
|||||||
|
|
||||||
package android.backup;
|
package android.backup;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public class RestoreHelperDispatcher {
|
public class RestoreHelperDispatcher {
|
||||||
|
private static final String TAG = "RestoreHelperDispatcher";
|
||||||
|
|
||||||
HashMap<String,RestoreHelper> mHelpers = new HashMap<String,RestoreHelper>();
|
HashMap<String,RestoreHelper> mHelpers = new HashMap<String,RestoreHelper>();
|
||||||
|
|
||||||
public void addHelper(String keyPrefix, RestoreHelper helper) {
|
public void addHelper(String keyPrefix, RestoreHelper helper) {
|
||||||
@@ -28,8 +32,11 @@ public class RestoreHelperDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void dispatch(BackupDataInput input) throws IOException {
|
public void dispatch(BackupDataInput input) throws IOException {
|
||||||
|
boolean alreadyComplained = false;
|
||||||
|
|
||||||
BackupDataInputStream stream = new BackupDataInputStream(input);
|
BackupDataInputStream stream = new BackupDataInputStream(input);
|
||||||
while (input.readNextHeader()) {
|
while (input.readNextHeader()) {
|
||||||
|
|
||||||
String rawKey = input.getKey();
|
String rawKey = input.getKey();
|
||||||
int pos = rawKey.indexOf(':');
|
int pos = rawKey.indexOf(':');
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
@@ -39,6 +46,16 @@ public class RestoreHelperDispatcher {
|
|||||||
stream.dataSize = input.getDataSize();
|
stream.dataSize = input.getDataSize();
|
||||||
stream.key = rawKey.substring(pos+1);
|
stream.key = rawKey.substring(pos+1);
|
||||||
helper.restoreEntity(stream);
|
helper.restoreEntity(stream);
|
||||||
|
} else {
|
||||||
|
if (!alreadyComplained) {
|
||||||
|
Log.w(TAG, "Couldn't find helper for: '" + rawKey + "'");
|
||||||
|
alreadyComplained = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!alreadyComplained) {
|
||||||
|
Log.w(TAG, "Entity with no prefix: '" + rawKey + "'");
|
||||||
|
alreadyComplained = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input.skipEntityData(); // In case they didn't consume the data.
|
input.skipEntityData(); // In case they didn't consume the data.
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ public class LocalTransport extends IBackupTransport.Stub {
|
|||||||
File[] blobs = packageDir.listFiles();
|
File[] blobs = packageDir.listFiles();
|
||||||
int err = 0;
|
int err = 0;
|
||||||
if (blobs != null && blobs.length > 0) {
|
if (blobs != null && blobs.length > 0) {
|
||||||
BackupDataOutput out = new BackupDataOutput(mContext, outFd.getFileDescriptor());
|
BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
|
||||||
try {
|
try {
|
||||||
for (File f : blobs) {
|
for (File f : blobs) {
|
||||||
FileInputStream in = new FileInputStream(f);
|
FileInputStream in = new FileInputStream(f);
|
||||||
|
|||||||
@@ -144,8 +144,7 @@ public class BackupTestActivity extends ListActivity
|
|||||||
FileBackupHelper h = new FileBackupHelper(BackupTestActivity.this,
|
FileBackupHelper h = new FileBackupHelper(BackupTestActivity.this,
|
||||||
"FileBackupHelper");
|
"FileBackupHelper");
|
||||||
FileOutputStream dataFile = openFileOutput("backup_test", MODE_WORLD_READABLE);
|
FileOutputStream dataFile = openFileOutput("backup_test", MODE_WORLD_READABLE);
|
||||||
BackupDataOutput data = new BackupDataOutput(BackupTestActivity.this,
|
BackupDataOutput data = new BackupDataOutput(dataFile.getFD());
|
||||||
dataFile.getFD());
|
|
||||||
h.performBackup(null, data, state, new String[] { "a", "empty" });
|
h.performBackup(null, data, state, new String[] { "a", "empty" });
|
||||||
dataFile.close();
|
dataFile.close();
|
||||||
state.close();
|
state.close();
|
||||||
|
|||||||
@@ -17,28 +17,45 @@
|
|||||||
package com.android.backuptest;
|
package com.android.backuptest;
|
||||||
|
|
||||||
import android.app.BackupAgent;
|
import android.app.BackupAgent;
|
||||||
|
import android.backup.BackupDataInput;
|
||||||
import android.backup.BackupDataOutput;
|
import android.backup.BackupDataOutput;
|
||||||
import android.backup.FileBackupHelper;
|
import android.backup.FileBackupHelper;
|
||||||
|
import android.backup.FileRestoreHelper;
|
||||||
|
import android.backup.RestoreHelperDispatcher;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class BackupTestAgent extends BackupAgent
|
public class BackupTestAgent extends BackupAgent
|
||||||
{
|
{
|
||||||
static final String TAG = "BackupTestAgent";
|
static final String TAG = "BackupTestAgent";
|
||||||
|
|
||||||
|
static final String SHARED_PREFS = "shared_prefs";
|
||||||
|
static final String DATA_FILES = "data_files";
|
||||||
|
static final String[] FILES = new String[] {
|
||||||
|
BackupTestActivity.FILE_NAME
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||||
ParcelFileDescriptor newState) {
|
ParcelFileDescriptor newState) {
|
||||||
Log.d(TAG, "onBackup");
|
Log.d(TAG, "onBackup");
|
||||||
FileBackupHelper helper = new FileBackupHelper(this);
|
|
||||||
helper.performBackup(oldState, data, newState, new String[] {
|
(new FileBackupHelper(this, DATA_FILES)).performBackup(oldState, data, newState, FILES);
|
||||||
BackupTestActivity.FILE_NAME
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRestore(ParcelFileDescriptor data, ParcelFileDescriptor newState) {
|
public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
|
||||||
|
throws IOException {
|
||||||
Log.d(TAG, "onRestore");
|
Log.d(TAG, "onRestore");
|
||||||
|
|
||||||
|
RestoreHelperDispatcher dispatch = new RestoreHelperDispatcher();
|
||||||
|
|
||||||
|
// dispatch.addHelper(SHARED_PREFS, new SharedPrefsRestoreHelper(this));
|
||||||
|
dispatch.addHelper(DATA_FILES, new FileRestoreHelper(this));
|
||||||
|
|
||||||
|
dispatch.dispatch(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user