am 856dd8a6: Merge change 4952 into donut
Merge commit '856dd8a60a70a5b7dca2bf2114872ce063e2ad60' * commit '856dd8a60a70a5b7dca2bf2114872ce063e2ad60': Helper API cleanup. Allows multiple helpers to function,
This commit is contained in:
committed by
The Android Open Source Project
commit
4527acb0c3
@@ -48,8 +48,8 @@ public class FullBackupAgent extends BackupAgent {
|
||||
}
|
||||
|
||||
// That's the file set; now back it all up
|
||||
FileBackupHelper helper = new FileBackupHelper(this);
|
||||
helper.performBackup(oldState, data, newState, (String[])allFiles.toArray());
|
||||
FileBackupHelper helper = new FileBackupHelper(this, (String[])allFiles.toArray());
|
||||
helper.performBackup(oldState, data, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -55,6 +55,10 @@ public class BackupDataOutput {
|
||||
}
|
||||
}
|
||||
|
||||
public void setKeyPrefix(String keyPrefix) {
|
||||
setKeyPrefix_native(mBackupWriter, keyPrefix);
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
dtor(mBackupWriter);
|
||||
@@ -62,11 +66,12 @@ public class BackupDataOutput {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private native static int ctor(FileDescriptor fd);
|
||||
private native static void dtor(int mBackupWriter);
|
||||
|
||||
private native static int writeEntityHeader_native(int mBackupWriter, String key, int dataSize);
|
||||
private native static int writeEntityData_native(int mBackupWriter, byte[] data, int size);
|
||||
private native static void setKeyPrefix_native(int mBackupWriter, String keyPrefix);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,26 @@ import android.os.ParcelFileDescriptor;
|
||||
import java.io.InputStream;
|
||||
|
||||
/** @hide */
|
||||
public interface RestoreHelper {
|
||||
public interface BackupHelper {
|
||||
/**
|
||||
* Called by RestoreHelperDispatcher to dispatch one entity of data.
|
||||
* Based on oldState, determine which of the files from the application's data directory
|
||||
* need to be backed up, write them to the data stream, and fill in newState with the
|
||||
* state as it exists now.
|
||||
*/
|
||||
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState);
|
||||
|
||||
/**
|
||||
* Called by BackupHelperDispatcher to dispatch one entity of data.
|
||||
* <p class=note>
|
||||
* Do not close the <code>data</code> stream. Do not read more than
|
||||
* <code>dataSize</code> bytes from <code>data</code>.
|
||||
*/
|
||||
public void restoreEntity(BackupDataInputStream data);
|
||||
public void writeSnapshot(ParcelFileDescriptor fd);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void writeRestoreSnapshot(ParcelFileDescriptor fd);
|
||||
}
|
||||
|
||||
56
core/java/android/backup/BackupHelperAgent.java
Normal file
56
core/java/android/backup/BackupHelperAgent.java
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.backup;
|
||||
|
||||
import android.app.BackupAgent;
|
||||
import android.backup.BackupHelper;
|
||||
import android.backup.BackupHelperDispatcher;
|
||||
import android.backup.BackupDataInput;
|
||||
import android.backup.BackupDataOutput;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/** @hide */
|
||||
public class BackupHelperAgent extends BackupAgent {
|
||||
static final String TAG = "BackupHelperAgent";
|
||||
|
||||
BackupHelperDispatcher mDispatcher = new BackupHelperDispatcher();
|
||||
|
||||
@Override
|
||||
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState) {
|
||||
mDispatcher.performBackup(oldState, data, newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
|
||||
throws IOException {
|
||||
mDispatcher.performRestore(data, newState);
|
||||
}
|
||||
|
||||
public BackupHelperDispatcher getDispatcher() {
|
||||
return mDispatcher;
|
||||
}
|
||||
|
||||
public void addHelper(String keyPrefix, BackupHelper helper) {
|
||||
mDispatcher.addHelper(keyPrefix, helper);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,20 +20,34 @@ import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** @hide */
|
||||
public class RestoreHelperDispatcher {
|
||||
private static final String TAG = "RestoreHelperDispatcher";
|
||||
public class BackupHelperDispatcher {
|
||||
private static final String TAG = "BackupHelperDispatcher";
|
||||
|
||||
HashMap<String,RestoreHelper> mHelpers = new HashMap<String,RestoreHelper>();
|
||||
TreeMap<String,BackupHelper> mHelpers = new TreeMap<String,BackupHelper>();
|
||||
|
||||
public BackupHelperDispatcher() {
|
||||
}
|
||||
|
||||
public void addHelper(String keyPrefix, RestoreHelper helper) {
|
||||
public void addHelper(String keyPrefix, BackupHelper helper) {
|
||||
mHelpers.put(keyPrefix, helper);
|
||||
}
|
||||
|
||||
public void dispatch(BackupDataInput input, ParcelFileDescriptor newState) throws IOException {
|
||||
/** TODO: Make this save and restore the key prefix. */
|
||||
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState) {
|
||||
// Write out the state files -- mHelpers is a TreeMap, so the order is well defined.
|
||||
for (Map.Entry<String,BackupHelper> entry: mHelpers.entrySet()) {
|
||||
data.setKeyPrefix(entry.getKey());
|
||||
entry.getValue().performBackup(oldState, data, newState);
|
||||
}
|
||||
}
|
||||
|
||||
public void performRestore(BackupDataInput input, ParcelFileDescriptor newState)
|
||||
throws IOException {
|
||||
boolean alreadyComplained = false;
|
||||
|
||||
BackupDataInputStream stream = new BackupDataInputStream(input);
|
||||
@@ -43,7 +57,7 @@ public class RestoreHelperDispatcher {
|
||||
int pos = rawKey.indexOf(':');
|
||||
if (pos > 0) {
|
||||
String prefix = rawKey.substring(0, pos);
|
||||
RestoreHelper helper = mHelpers.get(prefix);
|
||||
BackupHelper helper = mHelpers.get(prefix);
|
||||
if (helper != null) {
|
||||
stream.dataSize = input.getDataSize();
|
||||
stream.key = rawKey.substring(pos+1);
|
||||
@@ -63,15 +77,9 @@ public class RestoreHelperDispatcher {
|
||||
input.skipEntityData(); // In case they didn't consume the data.
|
||||
}
|
||||
|
||||
if (mHelpers.size() > 1) {
|
||||
throw new RuntimeException("RestoreHelperDispatcher won't get your your"
|
||||
+ " data in the right order yet.");
|
||||
}
|
||||
|
||||
// Write out the state files
|
||||
for (RestoreHelper helper: mHelpers.values()) {
|
||||
// TODO: Write a header for the state
|
||||
helper.writeSnapshot(newState);
|
||||
// Write out the state files -- mHelpers is a TreeMap, so the order is well defined.
|
||||
for (BackupHelper helper: mHelpers.values()) {
|
||||
helper.writeRestoreSnapshot(newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,19 +24,19 @@ import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
/** @hide */
|
||||
public class FileBackupHelper {
|
||||
public class FileBackupHelper extends FileBackupHelperBase implements BackupHelper {
|
||||
private static final String TAG = "FileBackupHelper";
|
||||
|
||||
Context mContext;
|
||||
String mKeyPrefix;
|
||||
File mFilesDir;
|
||||
String[] mFiles;
|
||||
|
||||
public FileBackupHelper(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
public FileBackupHelper(Context context, String... files) {
|
||||
super(context);
|
||||
|
||||
public FileBackupHelper(Context context, String keyPrefix) {
|
||||
mContext = context;
|
||||
mKeyPrefix = keyPrefix;
|
||||
mFilesDir = context.getFilesDir();
|
||||
mFiles = files;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,8 +45,9 @@ public class FileBackupHelper {
|
||||
* state as it exists now.
|
||||
*/
|
||||
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState, String[] files) {
|
||||
ParcelFileDescriptor newState) {
|
||||
// file names
|
||||
String[] files = mFiles;
|
||||
File base = mContext.getFilesDir();
|
||||
final int N = files.length;
|
||||
String[] fullPaths = new String[N];
|
||||
@@ -54,66 +55,18 @@ public class FileBackupHelper {
|
||||
fullPaths[i] = (new File(base, files[i])).getAbsolutePath();
|
||||
}
|
||||
|
||||
// keys
|
||||
String[] keys = makeKeys(mKeyPrefix, files);
|
||||
|
||||
// go
|
||||
performBackup_checked(oldState, data, newState, fullPaths, keys);
|
||||
performBackup_checked(oldState, data, newState, fullPaths, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* If keyPrefix is not null, prepend it to each of the strings in <code>original</code>;
|
||||
* otherwise, return original.
|
||||
*/
|
||||
static String[] makeKeys(String keyPrefix, String[] original) {
|
||||
if (keyPrefix != null) {
|
||||
String[] keys;
|
||||
final int N = original.length;
|
||||
keys = new String[N];
|
||||
for (int i=0; i<N; i++) {
|
||||
keys[i] = keyPrefix + ':' + original[i];
|
||||
}
|
||||
return keys;
|
||||
} else {
|
||||
return original;
|
||||
public void restoreEntity(BackupDataInputStream data) {
|
||||
// TODO: turn this off before ship
|
||||
Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
|
||||
String key = data.getKey();
|
||||
if (isKeyInList(key, mFiles)) {
|
||||
File f = new File(mFilesDir, key);
|
||||
writeFile(f, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the parameters so the native code doens't have to throw all the exceptions
|
||||
* since it's easier to do that from java.
|
||||
*/
|
||||
static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState, String[] files, String[] keys) {
|
||||
if (files.length == 0) {
|
||||
return;
|
||||
}
|
||||
// files must be all absolute paths
|
||||
for (String f: files) {
|
||||
if (f.charAt(0) != '/') {
|
||||
throw new RuntimeException("files must have all absolute paths: " + f);
|
||||
}
|
||||
}
|
||||
// the length of files and keys must be the same
|
||||
if (files.length != keys.length) {
|
||||
throw new RuntimeException("files.length=" + files.length
|
||||
+ " keys.length=" + keys.length);
|
||||
}
|
||||
// oldStateFd can be null
|
||||
FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
|
||||
FileDescriptor newStateFd = newState.getFileDescriptor();
|
||||
if (newStateFd == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
|
||||
|
||||
if (err != 0) {
|
||||
// TODO: more here
|
||||
throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
|
||||
}
|
||||
}
|
||||
|
||||
native private static int performBackup_native(FileDescriptor oldState,
|
||||
int data, FileDescriptor newState, String[] files, String[] keys);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,14 +25,14 @@ import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
class RestoreHelperBase {
|
||||
class FileBackupHelperBase {
|
||||
private static final String TAG = "RestoreHelperBase";
|
||||
|
||||
int mPtr;
|
||||
Context mContext;
|
||||
boolean mExceptionLogged;
|
||||
|
||||
RestoreHelperBase(Context context) {
|
||||
FileBackupHelperBase(Context context) {
|
||||
mPtr = ctor();
|
||||
mContext = context;
|
||||
}
|
||||
@@ -45,6 +45,41 @@ class RestoreHelperBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the parameters so the native code doens't have to throw all the exceptions
|
||||
* since it's easier to do that from java.
|
||||
*/
|
||||
static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState, String[] files, String[] keys) {
|
||||
if (files.length == 0) {
|
||||
return;
|
||||
}
|
||||
// files must be all absolute paths
|
||||
for (String f: files) {
|
||||
if (f.charAt(0) != '/') {
|
||||
throw new RuntimeException("files must have all absolute paths: " + f);
|
||||
}
|
||||
}
|
||||
// the length of files and keys must be the same
|
||||
if (files.length != keys.length) {
|
||||
throw new RuntimeException("files.length=" + files.length
|
||||
+ " keys.length=" + keys.length);
|
||||
}
|
||||
// oldStateFd can be null
|
||||
FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
|
||||
FileDescriptor newStateFd = newState.getFileDescriptor();
|
||||
if (newStateFd == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
|
||||
|
||||
if (err != 0) {
|
||||
// TODO: more here
|
||||
throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
|
||||
}
|
||||
}
|
||||
|
||||
void writeFile(File f, InputStream in) {
|
||||
if (!(in instanceof BackupDataInputStream)) {
|
||||
throw new IllegalStateException("input stream must be a BackupDataInputStream");
|
||||
@@ -68,13 +103,26 @@ class RestoreHelperBase {
|
||||
}
|
||||
}
|
||||
|
||||
public void writeSnapshot(ParcelFileDescriptor fd) {
|
||||
public void writeRestoreSnapshot(ParcelFileDescriptor fd) {
|
||||
int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
|
||||
// TODO: Do something with the error.
|
||||
}
|
||||
|
||||
boolean isKeyInList(String key, String[] list) {
|
||||
for (String s: list) {
|
||||
if (s.equals(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static native int ctor();
|
||||
private static native void dtor(int ptr);
|
||||
|
||||
native private static int performBackup_native(FileDescriptor oldState,
|
||||
int data, FileDescriptor newState, String[] files, String[] keys);
|
||||
|
||||
private static native int writeFile_native(int ptr, String filename, int backupReader);
|
||||
private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.backup;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/** @hide */
|
||||
public class FileRestoreHelper extends RestoreHelperBase implements RestoreHelper {
|
||||
private static final String TAG = "FileRestoreHelper";
|
||||
|
||||
File mFilesDir;
|
||||
|
||||
public FileRestoreHelper(Context context) {
|
||||
super(context);
|
||||
mFilesDir = context.getFilesDir();
|
||||
}
|
||||
|
||||
public void restoreEntity(BackupDataInputStream data) {
|
||||
Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size()); // TODO: turn this off before ship
|
||||
File f = new File(mFilesDir, data.getKey());
|
||||
writeFile(f, data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,39 +18,51 @@ package android.backup;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
/** @hide */
|
||||
public class SharedPreferencesBackupHelper {
|
||||
public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper {
|
||||
private static final String TAG = "SharedPreferencesBackupHelper";
|
||||
|
||||
private Context mContext;
|
||||
private String mKeyPrefix;
|
||||
private String[] mPrefGroups;
|
||||
|
||||
public SharedPreferencesBackupHelper(Context context, String[] prefGroups) {
|
||||
super(context);
|
||||
|
||||
public SharedPreferencesBackupHelper(Context context) {
|
||||
mContext = context;
|
||||
mPrefGroups = prefGroups;
|
||||
}
|
||||
|
||||
public SharedPreferencesBackupHelper(Context context, String keyPrefix) {
|
||||
mContext = context;
|
||||
mKeyPrefix = keyPrefix;
|
||||
}
|
||||
|
||||
public void performBackup(ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot,
|
||||
BackupDataOutput data, String[] prefGroups) {
|
||||
public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState) {
|
||||
Context context = mContext;
|
||||
|
||||
// make filenames for the prefGroups
|
||||
String[] prefGroups = mPrefGroups;
|
||||
final int N = prefGroups.length;
|
||||
String[] files = new String[N];
|
||||
for (int i=0; i<N; i++) {
|
||||
files[i] = context.getSharedPrefsFile(prefGroups[i]).getAbsolutePath();
|
||||
}
|
||||
|
||||
// make keys if necessary
|
||||
String[] keys = FileBackupHelper.makeKeys(mKeyPrefix, prefGroups);
|
||||
|
||||
// go
|
||||
FileBackupHelper.performBackup_checked(oldSnapshot, data, newSnapshot, files, prefGroups);
|
||||
performBackup_checked(oldState, data, newState, files, prefGroups);
|
||||
}
|
||||
|
||||
public void restoreEntity(BackupDataInputStream data) {
|
||||
Context context = mContext;
|
||||
|
||||
// TODO: turn this off before ship
|
||||
Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
|
||||
String key = data.getKey();
|
||||
if (isKeyInList(key, mPrefGroups)) {
|
||||
File f = context.getSharedPrefsFile(key).getAbsoluteFile();
|
||||
writeFile(f, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,8 +121,7 @@ LOCAL_SRC_FILES:= \
|
||||
com_android_internal_graphics_NativeUtils.cpp \
|
||||
android_backup_BackupDataInput.cpp \
|
||||
android_backup_BackupDataOutput.cpp \
|
||||
android_backup_FileBackupHelper.cpp \
|
||||
android_backup_RestoreHelperBase.cpp
|
||||
android_backup_FileBackupHelperBase.cpp
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(JNI_H_INCLUDE) \
|
||||
|
||||
@@ -155,8 +155,7 @@ extern int register_android_util_Base64(JNIEnv* env);
|
||||
extern int register_android_location_GpsLocationProvider(JNIEnv* env);
|
||||
extern int register_android_backup_BackupDataInput(JNIEnv *env);
|
||||
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
|
||||
extern int register_android_backup_FileBackupHelper(JNIEnv *env);
|
||||
extern int register_android_backup_RestoreHelperBase(JNIEnv *env);
|
||||
extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
|
||||
|
||||
static AndroidRuntime* gCurRuntime = NULL;
|
||||
|
||||
@@ -1241,8 +1240,7 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_location_GpsLocationProvider),
|
||||
REG_JNI(register_android_backup_BackupDataInput),
|
||||
REG_JNI(register_android_backup_BackupDataOutput),
|
||||
REG_JNI(register_android_backup_FileBackupHelper),
|
||||
REG_JNI(register_android_backup_RestoreHelperBase),
|
||||
REG_JNI(register_android_backup_FileBackupHelperBase),
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -87,11 +87,26 @@ writeEntityData_native(JNIEnv* env, jobject clazz, int w, jbyteArray data, int s
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
setKeyPrefix_native(JNIEnv* env, jobject clazz, int w, jstring keyPrefixObj)
|
||||
{
|
||||
int err;
|
||||
BackupDataWriter* writer = (BackupDataWriter*)w;
|
||||
|
||||
const char* keyPrefixUTF = env->GetStringUTFChars(keyPrefixObj, NULL);
|
||||
String8 keyPrefix(keyPrefixUTF ? keyPrefixUTF : "");
|
||||
|
||||
writer->SetKeyPrefix(keyPrefix);
|
||||
|
||||
env->ReleaseStringUTFChars(keyPrefixObj, keyPrefixUTF);
|
||||
}
|
||||
|
||||
static const JNINativeMethod g_methods[] = {
|
||||
{ "ctor", "(Ljava/io/FileDescriptor;)I", (void*)ctor_native },
|
||||
{ "dtor", "(I)V", (void*)dtor_native },
|
||||
{ "writeEntityHeader_native", "(ILjava/lang/String;I)I", (void*)writeEntityHeader_native },
|
||||
{ "writeEntityData_native", "(I[BI)I", (void*)writeEntityData_native },
|
||||
{ "setKeyPrefix_native", "(ILjava/lang/String;)V", (void*)setKeyPrefix_native },
|
||||
};
|
||||
|
||||
int register_android_backup_BackupDataOutput(JNIEnv* env)
|
||||
|
||||
@@ -28,6 +28,18 @@ namespace android
|
||||
// java.io.FileDescriptor
|
||||
static jfieldID s_descriptorField = 0;
|
||||
|
||||
static int
|
||||
ctor(JNIEnv* env, jobject clazz)
|
||||
{
|
||||
return (int)new RestoreHelperBase();
|
||||
}
|
||||
|
||||
static void
|
||||
dtor(JNIEnv* env, jobject clazz, jint ptr)
|
||||
{
|
||||
delete (RestoreHelperBase*)ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data,
|
||||
jobject newState, jobjectArray files, jobjectArray keys)
|
||||
@@ -66,13 +78,48 @@ performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data,
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
|
||||
{
|
||||
int err;
|
||||
RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
|
||||
BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
|
||||
char const* filename;
|
||||
|
||||
filename = env->GetStringUTFChars(filenameObj, NULL);
|
||||
|
||||
err = restore->WriteFile(String8(filename), reader);
|
||||
|
||||
env->ReleaseStringUTFChars(filenameObj, filename);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
|
||||
{
|
||||
int err;
|
||||
|
||||
RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
|
||||
int fd = env->GetIntField(fileDescriptor, s_descriptorField);
|
||||
|
||||
err = restore->WriteSnapshot(fd);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const JNINativeMethod g_methods[] = {
|
||||
{ "ctor", "()I", (void*)ctor },
|
||||
{ "dtor", "(I)V", (void*)dtor },
|
||||
{ "performBackup_native",
|
||||
"(Ljava/io/FileDescriptor;ILjava/io/FileDescriptor;[Ljava/lang/String;[Ljava/lang/String;)I",
|
||||
(void*)performBackup_native },
|
||||
{ "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
|
||||
{ "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
|
||||
};
|
||||
|
||||
int register_android_backup_FileBackupHelper(JNIEnv* env)
|
||||
int register_android_backup_FileBackupHelperBase(JNIEnv* env)
|
||||
{
|
||||
jclass clazz;
|
||||
|
||||
@@ -82,7 +129,7 @@ int register_android_backup_FileBackupHelper(JNIEnv* env)
|
||||
LOG_FATAL_IF(s_descriptorField == NULL,
|
||||
"Unable to find descriptor field in java.io.FileDescriptor");
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelper",
|
||||
return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelperBase",
|
||||
g_methods, NELEM(g_methods));
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2009 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "FileBackupHelper_native"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
|
||||
#include <utils/BackupHelpers.h>
|
||||
|
||||
namespace android
|
||||
{
|
||||
|
||||
// java.io.FileDescriptor
|
||||
static jfieldID s_descriptorField = 0;
|
||||
|
||||
static int
|
||||
ctor(JNIEnv* env, jobject clazz)
|
||||
{
|
||||
return (int)new RestoreHelperBase();
|
||||
}
|
||||
|
||||
static void
|
||||
dtor(JNIEnv* env, jobject clazz, jint ptr)
|
||||
{
|
||||
delete (RestoreHelperBase*)ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
|
||||
{
|
||||
int err;
|
||||
RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
|
||||
BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
|
||||
char const* filename;
|
||||
|
||||
filename = env->GetStringUTFChars(filenameObj, NULL);
|
||||
|
||||
err = restore->WriteFile(String8(filename), reader);
|
||||
|
||||
env->ReleaseStringUTFChars(filenameObj, filename);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int
|
||||
writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
|
||||
{
|
||||
int err;
|
||||
|
||||
RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
|
||||
int fd = env->GetIntField(fileDescriptor, s_descriptorField);
|
||||
|
||||
err = restore->WriteSnapshot(fd);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const JNINativeMethod g_methods[] = {
|
||||
{ "ctor", "()I", (void*)ctor },
|
||||
{ "dtor", "(I)V", (void*)dtor },
|
||||
{ "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
|
||||
{ "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
|
||||
};
|
||||
|
||||
int register_android_backup_RestoreHelperBase(JNIEnv* env)
|
||||
{
|
||||
jclass clazz;
|
||||
|
||||
clazz = env->FindClass("java/io/FileDescriptor");
|
||||
LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
|
||||
s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
|
||||
LOG_FATAL_IF(s_descriptorField == NULL,
|
||||
"Unable to find descriptor field in java.io.FileDescriptor");
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(env, "android/backup/RestoreHelperBase",
|
||||
g_methods, NELEM(g_methods));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,6 +71,8 @@ public:
|
||||
status_t WriteEntityHeader(const String8& key, size_t dataSize);
|
||||
status_t WriteEntityData(const void* data, size_t size);
|
||||
|
||||
void SetKeyPrefix(const String8& keyPrefix);
|
||||
|
||||
private:
|
||||
explicit BackupDataWriter();
|
||||
status_t write_padding_for(int n);
|
||||
@@ -79,6 +81,7 @@ private:
|
||||
status_t m_status;
|
||||
ssize_t m_pos;
|
||||
int m_entityCount;
|
||||
String8 m_keyPrefix;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -99,10 +99,20 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
|
||||
return amt;
|
||||
}
|
||||
|
||||
String8 k;
|
||||
if (m_keyPrefix.length() > 0) {
|
||||
k = m_keyPrefix;
|
||||
k += ":";
|
||||
k += key;
|
||||
} else {
|
||||
k = key;
|
||||
}
|
||||
LOGD("m_keyPrefix=%s key=%s k=%s", m_keyPrefix.string(), key.string(), k.string());
|
||||
|
||||
entity_header_v1 header;
|
||||
ssize_t keyLen;
|
||||
|
||||
keyLen = key.length();
|
||||
keyLen = k.length();
|
||||
|
||||
header.type = tolel(BACKUP_HEADER_ENTITY_V1);
|
||||
header.keyLen = tolel(keyLen);
|
||||
@@ -115,7 +125,7 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize)
|
||||
}
|
||||
m_pos += amt;
|
||||
|
||||
amt = write(m_fd, key.string(), keyLen+1);
|
||||
amt = write(m_fd, k.string(), keyLen+1);
|
||||
if (amt != keyLen+1) {
|
||||
m_status = errno;
|
||||
return m_status;
|
||||
@@ -148,6 +158,11 @@ BackupDataWriter::WriteEntityData(const void* data, size_t size)
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
|
||||
{
|
||||
m_keyPrefix = keyPrefix;
|
||||
}
|
||||
|
||||
|
||||
BackupDataReader::BackupDataReader(int fd)
|
||||
@@ -298,7 +313,7 @@ BackupDataReader::ReadEntityData(void* data, size_t size)
|
||||
if (remaining <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (size > remaining) {
|
||||
if (((int)size) > remaining) {
|
||||
size = remaining;
|
||||
}
|
||||
//LOGD(" reading %d bytes", size);
|
||||
|
||||
@@ -164,8 +164,8 @@ class BackupManagerService extends IBackupManager.Stub {
|
||||
// Set up our transport options and initialize the default transport
|
||||
// TODO: Have transports register themselves somehow?
|
||||
// TODO: Don't create transports that we don't need to?
|
||||
//mTransportId = BackupManager.TRANSPORT_LOCAL;
|
||||
mTransportId = BackupManager.TRANSPORT_GOOGLE;
|
||||
mTransportId = BackupManager.TRANSPORT_LOCAL;
|
||||
//mTransportId = BackupManager.TRANSPORT_GOOGLE;
|
||||
mLocalTransport = new LocalTransport(context); // This is actually pretty cheap
|
||||
mGoogleTransport = null;
|
||||
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
package com.android.backuptest;
|
||||
|
||||
import android.app.ListActivity;
|
||||
import android.backup.BackupHelperDispatcher;
|
||||
import android.backup.BackupDataInput;
|
||||
import android.backup.BackupDataOutput;
|
||||
import android.backup.BackupManager;
|
||||
import android.backup.FileBackupHelper;
|
||||
import android.backup.FileRestoreHelper;
|
||||
import android.backup.RestoreHelperDispatcher;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
@@ -142,10 +141,10 @@ public class BackupTestActivity extends ListActivity
|
||||
ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
|
||||
ParcelFileDescriptor.MODE_TRUNCATE);
|
||||
FileBackupHelper h = new FileBackupHelper(BackupTestActivity.this,
|
||||
"FileBackupHelper");
|
||||
new String[] { "a", "empty" });
|
||||
FileOutputStream dataFile = openFileOutput("backup_test", MODE_WORLD_READABLE);
|
||||
BackupDataOutput data = new BackupDataOutput(dataFile.getFD());
|
||||
h.performBackup(null, data, state, new String[] { "a", "empty" });
|
||||
h.performBackup(null, data, state);
|
||||
dataFile.close();
|
||||
state.close();
|
||||
} catch (IOException ex) {
|
||||
@@ -156,16 +155,16 @@ public class BackupTestActivity extends ListActivity
|
||||
new Test("Restore Helpers") {
|
||||
void run() {
|
||||
try {
|
||||
RestoreHelperDispatcher dispatch = new RestoreHelperDispatcher();
|
||||
dispatch.addHelper("FileBackupHelper",
|
||||
new FileRestoreHelper(BackupTestActivity.this));
|
||||
BackupHelperDispatcher dispatch = new BackupHelperDispatcher();
|
||||
dispatch.addHelper("", new FileBackupHelper(BackupTestActivity.this,
|
||||
new String[] { "a", "empty" }));
|
||||
FileInputStream dataFile = openFileInput("backup_test");
|
||||
BackupDataInput data = new BackupDataInput(dataFile.getFD());
|
||||
ParcelFileDescriptor state = ParcelFileDescriptor.open(
|
||||
new File(getFilesDir(), "restore_state"),
|
||||
ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
|
||||
ParcelFileDescriptor.MODE_TRUNCATE);
|
||||
dispatch.dispatch(data, state);
|
||||
dispatch.performRestore(data, state);
|
||||
dataFile.close();
|
||||
state.close();
|
||||
} catch (IOException ex) {
|
||||
|
||||
@@ -16,46 +16,13 @@
|
||||
|
||||
package com.android.backuptest;
|
||||
|
||||
import android.app.BackupAgent;
|
||||
import android.backup.BackupDataInput;
|
||||
import android.backup.BackupDataOutput;
|
||||
import android.backup.BackupHelperAgent;
|
||||
import android.backup.FileBackupHelper;
|
||||
import android.backup.FileRestoreHelper;
|
||||
import android.backup.RestoreHelperDispatcher;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BackupTestAgent extends BackupAgent
|
||||
public class BackupTestAgent extends BackupHelperAgent
|
||||
{
|
||||
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
|
||||
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
|
||||
ParcelFileDescriptor newState) {
|
||||
Log.d(TAG, "onBackup");
|
||||
|
||||
(new FileBackupHelper(this, DATA_FILES)).performBackup(oldState, data, newState, FILES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
|
||||
throws IOException {
|
||||
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, newState);
|
||||
public void onCreate() {
|
||||
addHelper("data_files", new FileBackupHelper(this, BackupTestActivity.FILE_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user