summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/backup/LocalTransport.java86
-rw-r--r--core/jni/android_backup_BackupDataInput.cpp81
-rw-r--r--core/jni/android_backup_BackupDataOutput.cpp2
3 files changed, 114 insertions, 55 deletions
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 62fba4a..83182f2 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -1,5 +1,6 @@
package com.android.internal.backup;
+import android.backup.BackupDataInput;
import android.backup.RestoreSet;
import android.content.Context;
import android.content.pm.PackageInfo;
@@ -24,7 +25,7 @@ import java.util.ArrayList;
public class LocalTransport extends IBackupTransport.Stub {
private static final String TAG = "LocalTransport";
- private static final String DATA_FILE_NAME = "data";
+ private static final boolean DEBUG = true;
private Context mContext;
private PackageManager mPackageManager;
@@ -37,6 +38,7 @@ public class LocalTransport extends IBackupTransport.Stub {
public LocalTransport(Context context) {
+ if (DEBUG) Log.v(TAG, "Transport constructed");
mContext = context;
mPackageManager = context.getPackageManager();
}
@@ -47,29 +49,63 @@ public class LocalTransport extends IBackupTransport.Stub {
}
public int startSession() throws RemoteException {
+ if (DEBUG) Log.v(TAG, "session started");
+ mDataDir.mkdirs();
return 0;
}
public int endSession() throws RemoteException {
+ if (DEBUG) Log.v(TAG, "session ended");
return 0;
}
public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
throws RemoteException {
- File packageDir = new File(mDataDir, packageInfo.packageName);
- File imageFileName = new File(packageDir, DATA_FILE_NAME);
-
- //!!! TODO: process the (partial) update into the persistent restore set:
-
- // Parse out the existing image file into the key/value map
+ if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName);
+ int err = 0;
- // Parse out the backup data into the key/value updates
-
- // Apply the backup key/value updates to the image
+ File packageDir = new File(mDataDir, packageInfo.packageName);
+ packageDir.mkdirs();
- // Write out the image in the canonical format
+ // Each 'record' in the restore set is kept in its own file, named by
+ // the record key. Wind through the data file, extracting individual
+ // record operations and building a set of all the updates to apply
+ // in this update.
+ BackupDataInput changeSet = new BackupDataInput(data.getFileDescriptor());
+ try {
+ int bufSize = 512;
+ byte[] buf = new byte[bufSize];
+ while (changeSet.readNextHeader()) {
+ String key = changeSet.getKey();
+ int dataSize = changeSet.getDataSize();
+ if (DEBUG) Log.v(TAG, "Got change set key=" + key + " size=" + dataSize);
+ if (dataSize > bufSize) {
+ bufSize = dataSize;
+ buf = new byte[bufSize];
+ }
+ changeSet.readEntityData(buf, dataSize);
+ if (DEBUG) Log.v(TAG, " + data size " + dataSize);
+
+ File entityFile = new File(packageDir, key);
+ FileOutputStream entity = new FileOutputStream(entityFile);
+ try {
+ entity.write(buf, 0, dataSize);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to update key file "
+ + entityFile.getAbsolutePath());
+ err = -1;
+ } finally {
+ entity.close();
+ }
+ }
+ } catch (IOException e) {
+ // oops, something went wrong. abort the operation and return error.
+ Log.v(TAG, "Exception reading backup input:");
+ e.printStackTrace();
+ err = -1;
+ }
- return -1;
+ return err;
}
// Restore handling
@@ -83,6 +119,7 @@ public class LocalTransport extends IBackupTransport.Stub {
}
public PackageInfo[] getAppSet(int token) throws android.os.RemoteException {
+ if (DEBUG) Log.v(TAG, "getting app set " + token);
// the available packages are the extant subdirs of mDatadir
File[] packageDirs = mDataDir.listFiles(mDirFileFilter);
ArrayList<PackageInfo> packages = new ArrayList<PackageInfo>();
@@ -99,9 +136,11 @@ public class LocalTransport extends IBackupTransport.Stub {
}
}
- Log.v(TAG, "Built app set of " + packages.size() + " entries:");
- for (PackageInfo p : packages) {
- Log.v(TAG, " + " + p.packageName);
+ if (DEBUG) {
+ Log.v(TAG, "Built app set of " + packages.size() + " entries:");
+ for (PackageInfo p : packages) {
+ Log.v(TAG, " + " + p.packageName);
+ }
}
PackageInfo[] result = new PackageInfo[packages.size()];
@@ -110,16 +149,25 @@ public class LocalTransport extends IBackupTransport.Stub {
public int getRestoreData(int token, PackageInfo packageInfo, ParcelFileDescriptor output)
throws android.os.RemoteException {
+ if (DEBUG) Log.v(TAG, "getting restore data " + token + " : " + packageInfo.packageName);
// we only support one hardcoded restore set
if (token != 0) return -1;
// the data for a given package is at a known location
File packageDir = new File(mDataDir, packageInfo.packageName);
- File imageFile = new File(packageDir, DATA_FILE_NAME);
- // restore is relatively easy: we already maintain the full data set in
- // the canonical form understandable to the BackupAgent
- return copyFileToFD(imageFile, output);
+ // The restore set is the concatenation of the individual record blobs,
+ // each of which is a file in the package's directory
+ File[] blobs = packageDir.listFiles();
+ int err = 0;
+ if (blobs != null && blobs.length > 0) {
+ for (File f : blobs) {
+ err = copyFileToFD(f, output);
+ if (err != 0) break;
+ }
+ }
+
+ return err;
}
private int copyFileToFD(File source, ParcelFileDescriptor dest) {
diff --git a/core/jni/android_backup_BackupDataInput.cpp b/core/jni/android_backup_BackupDataInput.cpp
index d8c2535..5b2fb73 100644
--- a/core/jni/android_backup_BackupDataInput.cpp
+++ b/core/jni/android_backup_BackupDataInput.cpp
@@ -62,43 +62,54 @@ readNextHeader_native(JNIEnv* env, jobject clazz, int r, jobject entity)
return err < 0 ? err : -1;
}
- while (reader->HasEntities()) {
- int type;
+ int type = 0;
- err = reader->ReadNextHeader(&type);
+ err = reader->ReadNextHeader(&type);
+ if (err == EIO) {
+ // Clean EOF with no footer block; just claim we're done
+ return 1;
+ }
+
+ if (err != 0) {
+ return err < 0 ? err : -1;
+ }
+
+ switch (type) {
+ case BACKUP_HEADER_APP_V1:
+ {
+ String8 packageName;
+ int cookie;
+ err = reader->ReadAppHeader(&packageName, &cookie);
if (err != 0) {
+ LOGD("ReadAppHeader() returned %d; aborting", err);
return err < 0 ? err : -1;
}
-
- switch (type) {
- case BACKUP_HEADER_APP_V1:
- {
- String8 packageName;
- int cookie;
- err = reader->ReadAppHeader(&packageName, &cookie);
- if (err != 0) {
- return err < 0 ? err : -1;
- }
- break;
- }
- case BACKUP_HEADER_ENTITY_V1:
- {
- String8 key;
- size_t dataSize;
- err = reader->ReadEntityHeader(&key, &dataSize);
- if (err != 0) {
- return err < 0 ? err : -1;
- }
- // TODO: Set the fields in the entity object
- return 0;
- }
- case BACKUP_FOOTER_APP_V1:
- break;
- default:
- LOGD("Unknown header type: 0x%08x\n", type);
- return -1;
+ break;
+ }
+ case BACKUP_HEADER_ENTITY_V1:
+ {
+ String8 key;
+ size_t dataSize;
+ err = reader->ReadEntityHeader(&key, &dataSize);
+ if (err != 0) {
+ LOGD("ReadEntityHeader(); aborting", err);
+ return err < 0 ? err : -1;
}
+ // TODO: Set the fields in the entity object
+ jstring keyStr = env->NewStringUTF(key.string());
+ env->SetObjectField(entity, s_keyField, keyStr);
+ env->SetIntField(entity, s_dataSizeField, dataSize);
+ return 0;
+ }
+ case BACKUP_FOOTER_APP_V1:
+ {
+ break;
}
+ default:
+ LOGD("Unknown header type: 0x%08x\n", type);
+ return -1;
+ }
+
// done
return 1;
}
@@ -109,17 +120,17 @@ readEntityData_native(JNIEnv* env, jobject clazz, int r, jbyteArray data, int si
int err;
BackupDataReader* reader = (BackupDataReader*)r;
- if (env->GetArrayLength(data) > size) {
+ if (env->GetArrayLength(data) < size) {
// size mismatch
return -1;
}
jbyte* dataBytes = env->GetByteArrayElements(data, NULL);
if (dataBytes == NULL) {
- return -1;
+ return -2;
}
- err = reader->ReadEntityData(dataBytes, size);
+ err = reader->ReadEntityData(dataBytes, size);
env->ReleaseByteArrayElements(data, dataBytes, 0);
@@ -136,7 +147,7 @@ static const JNINativeMethod g_methods[] = {
int register_android_backup_BackupDataInput(JNIEnv* env)
{
- LOGD("register_android_backup_BackupDataInput");
+ //LOGD("register_android_backup_BackupDataInput");
jclass clazz;
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index 9660326..6362439 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -96,7 +96,7 @@ static const JNINativeMethod g_methods[] = {
int register_android_backup_BackupDataOutput(JNIEnv* env)
{
- LOGD("register_android_backup_BackupDataOutput");
+ //LOGD("register_android_backup_BackupDataOutput");
jclass clazz;