summaryrefslogtreecommitdiffstats
path: root/packages/SharedStorageBackup
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2013-02-19 14:08:59 -0800
committerChristopher Tate <ctate@google.com>2013-03-07 13:47:20 -0800
commit46cc43c6fa7623820d4ae9149496cf96bb15f8a3 (patch)
treefe3a33bcdf0dc82414eb274aedefaef53aace059 /packages/SharedStorageBackup
parent32884c376fd06799f46ea3b1ded89ba9d21f8f14 (diff)
downloadframeworks_base-46cc43c6fa7623820d4ae9149496cf96bb15f8a3.zip
frameworks_base-46cc43c6fa7623820d4ae9149496cf96bb15f8a3.tar.gz
frameworks_base-46cc43c6fa7623820d4ae9149496cf96bb15f8a3.tar.bz2
Full backup/restore now handles OBBs sensibly
OBB backup/ restore is no longer handled within the target app process. This is done to avoid having to require that OBB-using apps have full read/write permission for external storage. The new OBB backup service is a new component running in the same app as the already-existing shared storage backup agent. The backup infrastructure delegates backup/restore of apps' OBB contents to this component (because the system process may not itself read/write external storage). From the command line, OBB backup is enabled by using new -obb / -noobb flags with adb backup. The default is noobb. Finally, a couple of nit fixes: - buffer-size mismatch between the writer and reader of chunked file data has been corrected; now the reading side won't be issuing an extra pipe read per chunk. - bu now explicitly closes the transport socket fd after adopting it. This was benign but triggered a logged warning about leaked fds. Bug: 6718844 Change-Id: Ie252494e2327e9ab97cf9ed87c298410a8618492
Diffstat (limited to 'packages/SharedStorageBackup')
-rw-r--r--packages/SharedStorageBackup/AndroidManifest.xml7
-rw-r--r--packages/SharedStorageBackup/proguard.flags1
-rw-r--r--packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java151
3 files changed, 159 insertions, 0 deletions
diff --git a/packages/SharedStorageBackup/AndroidManifest.xml b/packages/SharedStorageBackup/AndroidManifest.xml
index fc21df3..b8df88e 100644
--- a/packages/SharedStorageBackup/AndroidManifest.xml
+++ b/packages/SharedStorageBackup/AndroidManifest.xml
@@ -24,5 +24,12 @@
<application android:allowClearUserData="false"
android:permission="android.permission.CONFIRM_FULL_BACKUP"
android:backupAgent="SharedStorageAgent" >
+
+ <service android:name=".ObbBackupService"
+ android:enabled="true"
+ android:exported="true">
+ </service>
+
</application>
+
</manifest>
diff --git a/packages/SharedStorageBackup/proguard.flags b/packages/SharedStorageBackup/proguard.flags
index f43cb81..6a66a47 100644
--- a/packages/SharedStorageBackup/proguard.flags
+++ b/packages/SharedStorageBackup/proguard.flags
@@ -1 +1,2 @@
-keep class com.android.sharedstoragebackup.SharedStorageAgent
+-keep class com.android.sharedstoragebackup.ObbBackupService
diff --git a/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java
new file mode 100644
index 0000000..7ebe096
--- /dev/null
+++ b/packages/SharedStorageBackup/src/com/android/sharedstoragebackup/ObbBackupService.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2013 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 com.android.sharedstoragebackup;
+
+import android.app.Service;
+import android.app.backup.BackupDataOutput;
+import android.app.backup.FullBackup;
+import android.app.backup.IBackupManager;
+import android.content.Intent;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.android.internal.backup.IObbBackupService;
+
+/**
+ * Service that the Backup Manager Services delegates OBB backup/restore operations to,
+ * because those require accessing external storage.
+ *
+ * {@hide}
+ */
+public class ObbBackupService extends Service {
+ static final String TAG = "ObbBackupService";
+ static final boolean DEBUG = true;
+
+ /**
+ * IObbBackupService interface implementation
+ */
+ IObbBackupService mService = new IObbBackupService.Stub() {
+ /*
+ * Back up a package's OBB directory tree
+ */
+ @Override
+ public void backupObbs(String packageName, ParcelFileDescriptor data,
+ int token, IBackupManager callbackBinder) {
+ final FileDescriptor outFd = data.getFileDescriptor();
+ try {
+ File obbDir = Environment.getExternalStorageAppObbDirectory(packageName);
+ if (obbDir != null) {
+ if (obbDir.exists()) {
+ ArrayList<File> obbList = allFileContents(obbDir);
+ if (obbList != null) {
+ // okay, there's at least something there
+ if (DEBUG) {
+ Log.i(TAG, obbList.size() + " files to back up");
+ }
+ final String rootPath = obbDir.getCanonicalPath();
+ final BackupDataOutput out = new BackupDataOutput(outFd);
+ for (File f : obbList) {
+ final String filePath = f.getCanonicalPath();
+ if (DEBUG) {
+ Log.i(TAG, "storing: " + filePath);
+ }
+ FullBackup.backupToTar(packageName, FullBackup.OBB_TREE_TOKEN, null,
+ rootPath, filePath, out);
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Exception backing up OBBs for " + packageName, e);
+ } finally {
+ // Send the EOD marker indicating that there is no more data
+ try {
+ FileOutputStream out = new FileOutputStream(outFd);
+ byte[] buf = new byte[4];
+ out.write(buf);
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to finalize obb backup stream!");
+ }
+
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ /*
+ * Restore an OBB file for the given package from the incoming stream
+ */
+ @Override
+ public void restoreObbFile(String packageName, ParcelFileDescriptor data,
+ long fileSize, int type, String path, long mode, long mtime,
+ int token, IBackupManager callbackBinder) {
+ try {
+ File outFile = Environment.getExternalStorageAppObbDirectory(packageName);
+ if (outFile != null) {
+ outFile = new File(outFile, path);
+ }
+ // outFile is null here if we couldn't get access to external storage,
+ // in which case restoreFile() will discard the data cleanly and let
+ // us proceed with the next file segment in the stream. We pass -1
+ // for the file mode to suppress attempts to chmod() on shared storage.
+ FullBackup.restoreFile(data, fileSize, type, -1, mtime, outFile);
+ } catch (IOException e) {
+ Log.i(TAG, "Exception restoring OBB " + path, e);
+ } finally {
+ try {
+ callbackBinder.opComplete(token);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+
+ ArrayList<File> allFileContents(File rootDir) {
+ final ArrayList<File> files = new ArrayList<File>();
+ final ArrayList<File> dirs = new ArrayList<File>();
+
+ dirs.add(rootDir);
+ while (!dirs.isEmpty()) {
+ File dir = dirs.remove(0);
+ File[] contents = dir.listFiles();
+ if (contents != null) {
+ for (File f : contents) {
+ if (f.isDirectory()) dirs.add(f);
+ else if (f.isFile()) files.add(f);
+ }
+ }
+ }
+ return files;
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mService.asBinder();
+ }
+}