diff options
-rw-r--r-- | core/java/android/app/backup/BackupAgent.java | 1 | ||||
-rw-r--r-- | core/java/android/app/backup/FullBackup.java | 7 | ||||
-rw-r--r-- | core/java/android/app/backup/FullBackupAgent.java | 26 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 3 | ||||
-rw-r--r-- | core/jni/android_app_backup_FullBackup.cpp | 2 | ||||
-rw-r--r-- | libs/utils/BackupHelpers.cpp | 4 | ||||
-rw-r--r-- | packages/SharedStorageBackup/Android.mk | 33 | ||||
-rw-r--r-- | packages/SharedStorageBackup/AndroidManifest.xml | 29 | ||||
-rw-r--r-- | packages/SharedStorageBackup/proguard.flags | 1 | ||||
-rw-r--r-- | packages/SharedStorageBackup/src/com/android/sharedstoragebackup/SharedStorageAgent.java | 93 | ||||
-rw-r--r-- | services/java/com/android/server/BackupManagerService.java | 172 | ||||
-rw-r--r-- | services/java/com/android/server/SystemBackupAgent.java | 2 |
12 files changed, 288 insertions, 85 deletions
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java index 17f8adb..63f3258 100644 --- a/core/java/android/app/backup/BackupAgent.java +++ b/core/java/android/app/backup/BackupAgent.java @@ -278,7 +278,6 @@ public abstract class BackupAgent extends ContextWrapper { int token, IBackupManager callbackBinder) throws RemoteException { long ident = Binder.clearCallingIdentity(); try { -Log.d(TAG, "doRestoreFile() => onRestoreFile()"); BackupAgent.this.onRestoreFile(data, size, type, domain, path, mode, mtime); } catch (IOException e) { throw new RuntimeException(e); diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java index dfb0dd7..3b70e19 100644 --- a/core/java/android/app/backup/FullBackup.java +++ b/core/java/android/app/backup/FullBackup.java @@ -46,7 +46,7 @@ public class FullBackup { public static final String SHARED_STORAGE_TOKEN = "shared"; public static final String APPS_PREFIX = "apps/"; - public static final String SHARED_PREFIX = "shared/"; + public static final String SHARED_PREFIX = SHARED_STORAGE_TOKEN + "/"; public static final String FULL_BACKUP_INTENT_ACTION = "fullback"; public static final String FULL_RESTORE_INTENT_ACTION = "fullrest"; @@ -61,7 +61,8 @@ public class FullBackup { String linkdomain, String rootpath, String path, BackupDataOutput output); static public void restoreToFile(ParcelFileDescriptor data, - long size, int type, long mode, long mtime, File outFile) throws IOException { + long size, int type, long mode, long mtime, File outFile, + boolean doChmod) throws IOException { if (type == FullBackup.TYPE_DIRECTORY) { // Canonically a directory has no associated content, so we don't need to read // anything from the pipe in this case. Just create the directory here and @@ -116,7 +117,7 @@ public class FullBackup { } // Now twiddle the state to match the backup, assuming all went well - if (outFile != null) { + if (doChmod && outFile != null) { try { Libcore.os.chmod(outFile.getPath(), (int)mode); } catch (ErrnoException e) { diff --git a/core/java/android/app/backup/FullBackupAgent.java b/core/java/android/app/backup/FullBackupAgent.java index 4dca593..df1c363 100644 --- a/core/java/android/app/backup/FullBackupAgent.java +++ b/core/java/android/app/backup/FullBackupAgent.java @@ -28,8 +28,6 @@ import libcore.io.OsConstants; import libcore.io.StructStat; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.util.HashSet; import java.util.LinkedList; @@ -84,9 +82,10 @@ public class FullBackupAgent extends BackupAgent { @Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, - ParcelFileDescriptor newState) { + ParcelFileDescriptor newState) throws IOException { // Filters, the scan queue, and the set of resulting entities HashSet<String> filterSet = new HashSet<String>(); + String packageName = getPackageName(); // Okay, start with the app's root tree, but exclude all of the canonical subdirs if (mLibDir != null) { @@ -96,25 +95,28 @@ public class FullBackupAgent extends BackupAgent { filterSet.add(mDatabaseDir); filterSet.add(mSharedPrefsDir); filterSet.add(mFilesDir); - processTree(FullBackup.ROOT_TREE_TOKEN, mMainDir, filterSet, data); + processTree(packageName, FullBackup.ROOT_TREE_TOKEN, mMainDir, filterSet, data); // Now do the same for the files dir, db dir, and shared prefs dir filterSet.add(mMainDir); filterSet.remove(mFilesDir); - processTree(FullBackup.DATA_TREE_TOKEN, mFilesDir, filterSet, data); + processTree(packageName, FullBackup.DATA_TREE_TOKEN, mFilesDir, filterSet, data); filterSet.add(mFilesDir); filterSet.remove(mDatabaseDir); - processTree(FullBackup.DATABASE_TREE_TOKEN, mDatabaseDir, filterSet, data); + processTree(packageName, FullBackup.DATABASE_TREE_TOKEN, mDatabaseDir, filterSet, data); filterSet.add(mDatabaseDir); filterSet.remove(mSharedPrefsDir); - processTree(FullBackup.SHAREDPREFS_TREE_TOKEN, mSharedPrefsDir, filterSet, data); + processTree(packageName, FullBackup.SHAREDPREFS_TREE_TOKEN, mSharedPrefsDir, filterSet, data); } - private void processTree(String domain, String rootPath, + // Scan the dir tree (if it actually exists) and process each entry we find. If the + // 'excludes' parameter is non-null, it is consulted each time a new file system entity + // is visited to see whether that entity (and its subtree, if appropriate) should be + // omitted from the backup process. + protected void processTree(String packageName, String domain, String rootPath, HashSet<String> excludes, BackupDataOutput data) { - // Scan the dir tree (if it actually exists) and process each entry we find File rootFile = new File(rootPath); if (rootFile.exists()) { LinkedList<File> scanQueue = new LinkedList<File>(); @@ -125,7 +127,7 @@ public class FullBackupAgent extends BackupAgent { String filePath = file.getAbsolutePath(); // prune this subtree? - if (excludes.contains(filePath)) { + if (excludes != null && excludes.contains(filePath)) { continue; } @@ -149,7 +151,7 @@ public class FullBackupAgent extends BackupAgent { } // Finally, back this file up before proceeding - FullBackup.backupToTar(getPackageName(), domain, null, rootPath, filePath, data); + FullBackup.backupToTar(packageName, domain, null, rootPath, filePath, data); } } } @@ -218,6 +220,6 @@ public class FullBackupAgent extends BackupAgent { if (DEBUG) Log.i(TAG, "[" + domain + " : " + relpath + "] mapped to " + outFile.getPath()); // Now that we've figured out where the data goes, send it on its way - FullBackup.restoreToFile(data, size, type, mode, mtime, outFile); + FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true); } } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 09fede0..31ad6e9 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1517,11 +1517,12 @@ public class PackageParser { } } + // fullBackupAgent is explicitly handled even if allowBackup is false name = sa.getNonConfigurationString( com.android.internal.R.styleable.AndroidManifestApplication_fullBackupAgent, 0); if (name != null) { ai.fullBackupAgentName = buildClassName(pkgName, name, outError); - if (true) { + if (false) { Log.v(TAG, "android:fullBackupAgent=" + ai.fullBackupAgentName + " from " + pkgName + "+" + name); } diff --git a/core/jni/android_app_backup_FullBackup.cpp b/core/jni/android_app_backup_FullBackup.cpp index ecfe5ff..b36fa3e 100644 --- a/core/jni/android_app_backup_FullBackup.cpp +++ b/core/jni/android_app_backup_FullBackup.cpp @@ -73,6 +73,8 @@ static struct { static int backupToTar(JNIEnv* env, jobject clazz, jstring packageNameObj, jstring domainObj, jstring linkdomain, jstring rootpathObj, jstring pathObj, jobject dataOutputObj) { + int ret; + // Extract the various strings, allowing for null object pointers const char* packagenamechars = env->GetStringUTFChars(packageNameObj, NULL); const char* rootchars = env->GetStringUTFChars(rootpathObj, NULL); diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp index f933199..b433fd3 100644 --- a/libs/utils/BackupHelpers.cpp +++ b/libs/utils/BackupHelpers.cpp @@ -503,10 +503,10 @@ int write_tarfile(const String8& packageName, const String8& domain, needExtended = true; } - // Non-7bit-clean path also means needing pax extended format + // Non-7bit-clean path or embedded spaces also mean needing pax extended format if (!needExtended) { for (size_t i = 0; i < filepath.length(); i++) { - if ((filepath[i] & 0x80) != 0) { + if ((filepath[i] & 0x80) != 0 || filepath[i] == ' ') { needExtended = true; break; } diff --git a/packages/SharedStorageBackup/Android.mk b/packages/SharedStorageBackup/Android.mk new file mode 100644 index 0000000..1d4f4da --- /dev/null +++ b/packages/SharedStorageBackup/Android.mk @@ -0,0 +1,33 @@ +# +# Copyright (C) 2011 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. +# + +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +LOCAL_PACKAGE_NAME := SharedStorageBackup +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) + +######################## +include $(call all-makefiles-under,$(LOCAL_PATH)) + diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml new file mode 100644 index 0000000..258059c --- /dev/null +++ b/packages/SharedStorageBackup/AndroidManifest.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +** Copyright 2011, 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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.sharedstoragebackup" > + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" /> + + <application android:allowClearUserData="false" + android:permission="android.permission.CONFIRM_FULL_BACKUP" + android:fullBackupAgent=".SharedStorageAgent" + android:allowBackup="false" > + </application> +</manifest> diff --git a/packages/SharedStorageBackup/proguard.flags b/packages/SharedStorageBackup/proguard.flags new file mode 100644 index 0000000..f43cb81 --- /dev/null +++ b/packages/SharedStorageBackup/proguard.flags @@ -0,0 +1 @@ +-keep class com.android.sharedstoragebackup.SharedStorageAgent 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); + } +} diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 7c6d3c1..b568af1 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -134,6 +134,7 @@ class BackupManagerService extends IBackupManager.Stub { // Timeout intervals for agent backup & restore operations static final long TIMEOUT_BACKUP_INTERVAL = 30 * 1000; static final long TIMEOUT_FULL_BACKUP_INTERVAL = 5 * 60 * 1000; + static final long TIMEOUT_SHARED_BACKUP_INTERVAL = 30 * 60 * 1000; static final long TIMEOUT_RESTORE_INTERVAL = 60 * 1000; // User confirmation timeout for a full backup/restore operation @@ -1691,7 +1692,7 @@ class BackupManagerService extends IBackupManager.Stub { public void run() { final List<PackageInfo> packagesToBackup; - Slog.i(TAG, "--- Performing full-dataset restore ---"); + Slog.i(TAG, "--- Performing full-dataset backup ---"); sendStartBackup(); // doAllApps supersedes the package set if any @@ -1720,64 +1721,23 @@ class BackupManagerService extends IBackupManager.Stub { } } - // Now back up the app data via the agent mechanism PackageInfo pkg = null; try { + // Now back up the app data via the agent mechanism int N = packagesToBackup.size(); for (int i = 0; i < N; i++) { pkg = packagesToBackup.get(i); + backupOnePackage(pkg); + } - Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName); - - IBackupAgent agent = bindToAgentSynchronous(pkg.applicationInfo, - IApplicationThread.BACKUP_MODE_FULL); - if (agent != null) { - try { - ApplicationInfo app = pkg.applicationInfo; - boolean sendApk = mIncludeApks - && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0) - && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 || - (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); - - sendOnBackupPackage(pkg.packageName); - - { - BackupDataOutput output = new BackupDataOutput( - mOutputFile.getFileDescriptor()); - - if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName); - writeAppManifest(pkg, mManifestFile, sendApk); - FullBackup.backupToTar(pkg.packageName, null, null, - mFilesDir.getAbsolutePath(), - mManifestFile.getAbsolutePath(), - output); - } - - if (DEBUG) Slog.d(TAG, "Calling doBackup()"); - final int token = generateToken(); - prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL); - agent.doBackup(null, mOutputFile, null, sendApk, - token, mBackupManagerBinder); - boolean success = waitUntilOperationComplete(token); - if (!success) { - Slog.d(TAG, "Full backup failed on package " + pkg.packageName); - } else { - if (DEBUG) Slog.d(TAG, "Full backup success: " + pkg.packageName); - } - } catch (IOException e) { - Slog.e(TAG, "Error backing up " + pkg.packageName, e); - } - } else { - Slog.w(TAG, "Unable to bind to full agent for " + pkg.packageName); - } - tearDown(pkg); + // Finally, shared storage if requested + if (mIncludeShared) { + backupSharedStorage(); } } catch (RemoteException e) { Slog.e(TAG, "App died during full backup"); } finally { - if (pkg != null) { - tearDown(pkg); - } + tearDown(pkg); try { mOutputFile.close(); } catch (IOException e) { @@ -1796,6 +1756,79 @@ class BackupManagerService extends IBackupManager.Stub { } } + private void backupOnePackage(PackageInfo pkg) throws RemoteException { + Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName); + + IBackupAgent agent = bindToAgentSynchronous(pkg.applicationInfo, + IApplicationThread.BACKUP_MODE_FULL); + if (agent != null) { + try { + ApplicationInfo app = pkg.applicationInfo; + boolean sendApk = mIncludeApks + && ((app.flags & ApplicationInfo.FLAG_FORWARD_LOCK) == 0) + && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 || + (app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0); + + sendOnBackupPackage(pkg.packageName); + + { + BackupDataOutput output = new BackupDataOutput( + mOutputFile.getFileDescriptor()); + + if (DEBUG) Slog.d(TAG, "Writing manifest for " + pkg.packageName); + writeAppManifest(pkg, mManifestFile, sendApk); + FullBackup.backupToTar(pkg.packageName, null, null, + mFilesDir.getAbsolutePath(), + mManifestFile.getAbsolutePath(), + output); + } + + if (DEBUG) Slog.d(TAG, "Calling doBackup()"); + final int token = generateToken(); + prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL); + agent.doBackup(null, mOutputFile, null, sendApk, + token, mBackupManagerBinder); + if (!waitUntilOperationComplete(token)) { + Slog.e(TAG, "Full backup failed on package " + pkg.packageName); + } else { + if (DEBUG) Slog.d(TAG, "Full backup success: " + pkg.packageName); + } + } catch (IOException e) { + Slog.e(TAG, "Error backing up " + pkg.packageName, e); + } + } else { + Slog.w(TAG, "Unable to bind to full agent for " + pkg.packageName); + } + tearDown(pkg); + } + + private void backupSharedStorage() throws RemoteException { + PackageInfo pkg = null; + try { + pkg = mPackageManager.getPackageInfo("com.android.sharedstoragebackup", 0); + IBackupAgent agent = bindToAgentSynchronous(pkg.applicationInfo, + IApplicationThread.BACKUP_MODE_FULL); + if (agent != null) { + sendOnBackupPackage("Shared storage"); + + final int token = generateToken(); + prepareOperationTimeout(token, TIMEOUT_SHARED_BACKUP_INTERVAL); + agent.doBackup(null, mOutputFile, null, false, token, mBackupManagerBinder); + if (!waitUntilOperationComplete(token)) { + Slog.e(TAG, "Full backup failed on shared storage"); + } else { + if (DEBUG) Slog.d(TAG, "Full shared storage backup success"); + } + } else { + Slog.e(TAG, "Could not bind to shared storage backup agent"); + } + } catch (NameNotFoundException e) { + Slog.e(TAG, "Shared storage backup package not found"); + } finally { + tearDown(pkg); + } + } + private void writeAppManifest(PackageInfo pkg, File manifestFile, boolean withApk) throws IOException { // Manifest format. All data are strings ending in LF: @@ -1836,23 +1869,24 @@ class BackupManagerService extends IBackupManager.Stub { } private void tearDown(PackageInfo pkg) { - final ApplicationInfo app = pkg.applicationInfo; - try { - // unbind and tidy up even on timeout or failure, just in case - mActivityManager.unbindBackupAgent(app); - - // The agent was running with a stub Application object, so shut it down. - // !!! We hardcode the confirmation UI's package name here rather than use a - // manifest flag! TODO something less direct. - if (app.uid != Process.SYSTEM_UID - && !pkg.packageName.equals("com.android.backupconfirm")) { - if (DEBUG) Slog.d(TAG, "Backup complete, killing host process"); - mActivityManager.killApplicationProcess(app.processName, app.uid); - } else { - if (DEBUG) Slog.d(TAG, "Not killing after restore: " + app.processName); + if (pkg != null) { + final ApplicationInfo app = pkg.applicationInfo; + if (app != null) { + try { + // unbind and tidy up even on timeout or failure, just in case + mActivityManager.unbindBackupAgent(app); + + // The agent was running with a stub Application object, so shut it down. + if (app.uid != Process.SYSTEM_UID) { + if (DEBUG) Slog.d(TAG, "Backup complete, killing host process"); + mActivityManager.killApplicationProcess(app.processName, app.uid); + } else { + if (DEBUG) Slog.d(TAG, "Not killing after restore: " + app.processName); + } + } catch (RemoteException e) { + Slog.d(TAG, "Lost app trying to shut down"); + } } - } catch (RemoteException e) { - Slog.d(TAG, "Lost app trying to shut down"); } } @@ -1949,6 +1983,7 @@ class BackupManagerService extends IBackupManager.Stub { // with a whitelist of packages known to be unclearable. mClearedPackages.add("android"); mClearedPackages.add("com.android.providers.settings"); + } class RestoreFileRunnable implements Runnable { @@ -1988,6 +2023,11 @@ class BackupManagerService extends IBackupManager.Stub { Slog.i(TAG, "--- Performing full-dataset restore ---"); sendStartRestore(); + // Are we able to restore shared-storage data? + if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { + mPackagePolicies.put("com.android.sharedstoragebackup", RestorePolicy.ACCEPT); + } + try { byte[] buffer = new byte[32 * 1024]; FileInputStream instream = new FileInputStream(mInputFile.getFileDescriptor()); @@ -2707,7 +2747,9 @@ class BackupManagerService extends IBackupManager.Stub { info.path, 0, FullBackup.SHARED_PREFIX.length())) { // File in shared storage. !!! TODO: implement this. info.path = info.path.substring(FullBackup.SHARED_PREFIX.length()); + info.packageName = "com.android.sharedstoragebackup"; info.domain = FullBackup.SHARED_STORAGE_TOKEN; + if (DEBUG) Slog.i(TAG, "File in shared storage: " + info.path); } else if (FullBackup.APPS_PREFIX.regionMatches(0, info.path, 0, FullBackup.APPS_PREFIX.length())) { // App content! Parse out the package name and domain diff --git a/services/java/com/android/server/SystemBackupAgent.java b/services/java/com/android/server/SystemBackupAgent.java index 99c8af6..08c6699 100644 --- a/services/java/com/android/server/SystemBackupAgent.java +++ b/services/java/com/android/server/SystemBackupAgent.java @@ -138,7 +138,7 @@ public class SystemBackupAgent extends BackupAgentHelper { if (outFile == null) { Slog.w(TAG, "Skipping unrecognized system file: [ " + domain + " : " + path + " ]"); } - FullBackup.restoreToFile(data, size, type, mode, mtime, outFile); + FullBackup.restoreToFile(data, size, type, mode, mtime, outFile, true); if (restoredWallpaper) { WallpaperManagerService wallpaper = |