diff options
Diffstat (limited to 'packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java')
-rw-r--r-- | packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java new file mode 100644 index 0000000..b02ca2e --- /dev/null +++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java @@ -0,0 +1,93 @@ +package com.android.sharedstoragebackup; + +import android.app.backup.FullBackup; +import android.app.backup.FullBackupAgent; +import android.app.backup.BackupDataInput; +import android.app.backup.BackupDataOutput; +import android.content.Context; +import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.os.storage.StorageManager; +import android.os.storage.StorageVolume; +import android.util.Slog; + +import java.io.File; +import java.io.IOException; + +public class SharedStorageAgent extends FullBackupAgent { + static final String TAG = "SharedStorageAgent"; + static final boolean DEBUG = true; + + StorageVolume[] mVolumes; + + @Override + public void onCreate() { + StorageManager mgr = (StorageManager) getSystemService(Context.STORAGE_SERVICE); + if (mgr != null) { + mVolumes = mgr.getVolumeList(); + } else { + Slog.e(TAG, "Unable to access Storage Manager"); + } + } + + @Override + public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, + ParcelFileDescriptor newState) throws IOException { + // If there are shared-storage volumes available, run the inherited directory- + // hierarchy backup process on them. By convention in the Storage Manager, the + // "primary" shared storage volume is first in the list. + if (mVolumes != null) { + for (int i = 0; i < mVolumes.length; i++) { + StorageVolume v = mVolumes[i]; + // Express the contents of volume N this way in the tar stream: + // shared/N/path/to/file + // The restore will then extract to the given volume + String domain = FullBackup.SHARED_PREFIX + i; + processTree(null, domain, v.getPath(), null, data); + } + } + } + + /** + * Incremental onRestore() implementation is not used. + */ + @Override + public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) + throws IOException { + } + + /** + * Full restore of one file to shared storage + */ + @Override + public void onRestoreFile(ParcelFileDescriptor data, long size, + int type, String domain, String relpath, long mode, long mtime) + throws IOException { + Slog.d(TAG, "Shared restore: [ " + domain + " : " + relpath + "]"); + + File outFile = null; + + // The file path must be in the semantic form [number]/path/to/file... + int slash = relpath.indexOf('/'); + if (slash > 0) { + try { + int i = Integer.parseInt(relpath.substring(0, slash)); + if (i <= mVolumes.length) { + outFile = new File(mVolumes[i].getPath(), relpath.substring(slash + 1)); + if (DEBUG) Slog.i(TAG, " => " + outFile.getAbsolutePath()); + } else { + Slog.w(TAG, "Cannot restore data for unavailable volume " + i); + } + } catch (NumberFormatException e) { + if (DEBUG) Slog.w(TAG, "Bad volume number token: " + relpath.substring(0, slash)); + } + } else { + if (DEBUG) Slog.i(TAG, "Can't find volume-number token"); + } + if (outFile == null) { + Slog.e(TAG, "Skipping data with malformed path " + relpath); + } + + FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, false); + } +} |