diff options
Diffstat (limited to 'packages/SharedStorageBackup')
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(); + } +} |