diff options
-rw-r--r-- | core/java/com/android/internal/backup/LocalTransport.java | 86 | ||||
-rw-r--r-- | core/jni/android_backup_BackupDataInput.cpp | 81 | ||||
-rw-r--r-- | core/jni/android_backup_BackupDataOutput.cpp | 2 |
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; |