1b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethpackage com.android.server.backup; 2b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 3b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport static android.os.ParcelFileDescriptor.MODE_CREATE; 4b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport static android.os.ParcelFileDescriptor.MODE_READ_ONLY; 5b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport static android.os.ParcelFileDescriptor.MODE_READ_WRITE; 6b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport static android.os.ParcelFileDescriptor.MODE_TRUNCATE; 7b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport static com.android.server.backup.BackupManagerService.OP_TYPE_BACKUP_WAIT; 8b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport static com.android.server.backup.BackupManagerService.TIMEOUT_BACKUP_INTERVAL; 9b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 10b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.app.ApplicationThreadConstants; 11b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.app.IBackupAgent; 12b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.app.backup.FullBackup; 13b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.app.backup.FullBackupDataOutput; 14b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.content.pm.ApplicationInfo; 15b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.content.pm.PackageInfo; 16b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.content.pm.PackageManager; 17b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.os.ParcelFileDescriptor; 18b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.os.RemoteException; 19b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.os.SELinux; 20b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport android.util.Slog; 21b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 22b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport libcore.io.IoUtils; 23b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 24b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport java.io.File; 25b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport java.io.FileNotFoundException; 26b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport java.io.FileOutputStream; 27b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport java.io.IOException; 28b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethimport java.io.OutputStream; 29b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 30b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth/** 31b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth * Used by BackupManagerService to perform adb backup for key-value packages. At the moment this 32b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth * class resembles what is done in the standard key-value code paths in BackupManagerService, and 33b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth * should be unified later. 34b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth * 35b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth * TODO: We should create unified backup/restore engines that can be used for both transport and 36b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth * adb backup/restore, and for fullbackup and key-value backup. 37b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth */ 38b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halsethclass KeyValueAdbBackupEngine { 39b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private static final String TAG = "KeyValueAdbBackupEngine"; 40b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private static final boolean DEBUG = false; 41b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 42b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private static final String BACKUP_KEY_VALUE_DIRECTORY_NAME = "key_value_dir"; 43b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private static final String BACKUP_KEY_VALUE_BLANK_STATE_FILENAME = "blank_state"; 44b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private static final String BACKUP_KEY_VALUE_BACKUP_DATA_FILENAME_SUFFIX = ".data"; 45b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private static final String BACKUP_KEY_VALUE_NEW_STATE_FILENAME_SUFFIX = ".new"; 46b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 47b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private BackupManagerService mBackupManagerService; 48b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final PackageManager mPackageManager; 49b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final OutputStream mOutput; 50b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final PackageInfo mCurrentPackage; 51b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final File mDataDir; 52b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final File mStateDir; 53b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final File mBlankStateName; 54b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final File mBackupDataName; 55b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final File mNewStateName; 56b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final File mManifestFile; 57b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private ParcelFileDescriptor mSavedState; 58b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private ParcelFileDescriptor mBackupData; 59b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private ParcelFileDescriptor mNewState; 60b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 61b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth KeyValueAdbBackupEngine(OutputStream output, PackageInfo packageInfo, 62b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth BackupManagerService backupManagerService, PackageManager packageManager, 63b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth File baseStateDir, File dataDir) { 64b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mOutput = output; 65b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mCurrentPackage = packageInfo; 66b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupManagerService = backupManagerService; 67b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mPackageManager = packageManager; 68b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 69b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mDataDir = dataDir; 70b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mStateDir = new File(baseStateDir, BACKUP_KEY_VALUE_DIRECTORY_NAME); 71b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mStateDir.mkdirs(); 72b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 73b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth String pkg = mCurrentPackage.packageName; 74b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 75b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBlankStateName = new File(mStateDir, BACKUP_KEY_VALUE_BLANK_STATE_FILENAME); 76b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupDataName = new File(mDataDir, 77b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth pkg + BACKUP_KEY_VALUE_BACKUP_DATA_FILENAME_SUFFIX); 78b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mNewStateName = new File(mStateDir, 79b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth pkg + BACKUP_KEY_VALUE_NEW_STATE_FILENAME_SUFFIX); 80b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 81b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mManifestFile = new File(mDataDir, BackupManagerService.BACKUP_MANIFEST_FILENAME); 82b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 83b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 84b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth void backupOnePackage() throws IOException { 85b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth ApplicationInfo targetApp = mCurrentPackage.applicationInfo; 86b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 87b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth try { 88b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth prepareBackupFiles(mCurrentPackage.packageName); 89b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 90b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth IBackupAgent agent = bindToAgent(targetApp); 91b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 92b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (agent == null) { 93b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // We failed binding to the agent, so ignore this package 94b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Failed binding to BackupAgent for package " 95b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth + mCurrentPackage.packageName); 96b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth return; 97b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 98b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 99b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // We are bound to agent, initiate backup. 100b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (!invokeAgentForAdbBackup(mCurrentPackage.packageName, agent)) { 101b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // Backup failed, skip package. 102b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Backup Failed for package " + mCurrentPackage.packageName); 103b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth return; 104b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 105b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 106b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // Backup finished successfully. Copy the backup data to the output stream. 107b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth writeBackupData(); 108b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } catch (FileNotFoundException e) { 109b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Failed creating files for package " + mCurrentPackage.packageName 110b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth + " will ignore package. " + e); 111b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } finally { 112b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // We are either done, failed or have timed out, so do cleanup and kill the agent. 113b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth cleanup(); 114b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 115b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 116b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 117b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private void prepareBackupFiles(String packageName) throws FileNotFoundException { 118b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 119b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // We pass a blank state to make sure we are getting the complete backup, not just an 120b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // increment 121b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mSavedState = ParcelFileDescriptor.open(mBlankStateName, 122b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth MODE_READ_ONLY | MODE_CREATE); // Make an empty file if necessary 123b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 124b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupData = ParcelFileDescriptor.open(mBackupDataName, 125b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE); 126b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 127b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (!SELinux.restorecon(mBackupDataName)) { 128b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "SELinux restorecon failed on " + mBackupDataName); 129b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 130b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 131b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mNewState = ParcelFileDescriptor.open(mNewStateName, 132b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE); 133b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 134b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 135b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private IBackupAgent bindToAgent(ApplicationInfo targetApp) { 136b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth try { 137b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth return mBackupManagerService.bindToAgentSynchronous(targetApp, 138b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL); 139b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } catch (SecurityException e) { 140b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "error in binding to agent for package " + targetApp.packageName 141b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth + ". " + e); 142b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth return null; 143b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 144b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 145b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 146b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // Return true on backup success, false otherwise 147b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private boolean invokeAgentForAdbBackup(String packageName, IBackupAgent agent) { 148b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth int token = mBackupManagerService.generateToken(); 149b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth try { 150b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupManagerService.prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL, null, 151b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth OP_TYPE_BACKUP_WAIT); 152b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 153b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // Start backup and wait for BackupManagerService to get callback for success or timeout 154b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth agent.doBackup(mSavedState, mBackupData, mNewState, Long.MAX_VALUE, token, 155b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupManagerService.mBackupManagerBinder); 156b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (!mBackupManagerService.waitUntilOperationComplete(token)) { 157b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Key-value backup failed on package " + packageName); 158b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth return false; 159b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 160b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (DEBUG) { 161b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.i(TAG, "Key-value backup success for package " + packageName); 162b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 163b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth return true; 164b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } catch (RemoteException e) { 165b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Error invoking agent for backup on " + packageName + ". " + e); 166b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth return false; 167b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 168b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 169b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 170b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth class KeyValueAdbBackupDataCopier implements Runnable { 171b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final PackageInfo mPackage; 172b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final ParcelFileDescriptor mPipe; 173b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private final int mToken; 174b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 175b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth KeyValueAdbBackupDataCopier(PackageInfo pack, ParcelFileDescriptor pipe, 176b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth int token) 177b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth throws IOException { 178b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mPackage = pack; 179b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mPipe = ParcelFileDescriptor.dup(pipe.getFileDescriptor()); 180b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mToken = token; 181b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 182b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 183b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth @Override 184b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth public void run() { 185b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth try { 186b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth FullBackupDataOutput output = new FullBackupDataOutput(mPipe); 187b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 188b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (DEBUG) { 189b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.d(TAG, "Writing manifest for " + mPackage.packageName); 190b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 191b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth BackupManagerService.writeAppManifest( 192b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mPackage, mPackageManager, mManifestFile, false, false); 193b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth FullBackup.backupToTar(mPackage.packageName, FullBackup.KEY_VALUE_DATA_TOKEN, null, 194b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mDataDir.getAbsolutePath(), 195b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mManifestFile.getAbsolutePath(), 196b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth output); 197b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mManifestFile.delete(); 198b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 199b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (DEBUG) { 200b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.d(TAG, "Writing key-value package payload" + mPackage.packageName); 201b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 202b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth FullBackup.backupToTar(mPackage.packageName, FullBackup.KEY_VALUE_DATA_TOKEN, null, 203b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mDataDir.getAbsolutePath(), 204b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupDataName.getAbsolutePath(), 205b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth output); 206b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 207b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // Write EOD marker 208b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth try { 209b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth FileOutputStream out = new FileOutputStream(mPipe.getFileDescriptor()); 210b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth byte[] buf = new byte[4]; 211b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth out.write(buf); 212b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } catch (IOException e) { 213b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Unable to finalize backup stream!"); 214b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 215b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 216b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth try { 217b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupManagerService.mBackupManagerBinder.opComplete(mToken, 0); 218b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } catch (RemoteException e) { 219b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // we'll time out anyway, so we're safe 220b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 221b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 222b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } catch (IOException e) { 223b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Error running full backup for " + mPackage.packageName + ". " + e); 224b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } finally { 225b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth IoUtils.closeQuietly(mPipe); 226b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 227b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 228b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 229b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 230b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private void writeBackupData() throws IOException { 231b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 232b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth int token = mBackupManagerService.generateToken(); 233b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 234b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth ParcelFileDescriptor[] pipes = null; 235b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth try { 236b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth pipes = ParcelFileDescriptor.createPipe(); 237b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 238b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupManagerService.prepareOperationTimeout(token, TIMEOUT_BACKUP_INTERVAL, null, 239b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth OP_TYPE_BACKUP_WAIT); 240b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 241b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // We will have to create a runnable that will read the manifest and backup data we 242b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // created, such that we can pipe the data into mOutput. The reason we do this is that 243b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // internally FullBackup.backupToTar is used, which will create the necessary file 244b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // header, but will also chunk the data. The method routeSocketDataToOutput in 245b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // BackupManagerService will dechunk the data, and append it to the TAR outputstream. 246b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth KeyValueAdbBackupDataCopier runner = new KeyValueAdbBackupDataCopier(mCurrentPackage, pipes[1], 247b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth token); 248b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth pipes[1].close(); // the runner has dup'd it 249b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth pipes[1] = null; 250b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Thread t = new Thread(runner, "key-value-app-data-runner"); 251b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth t.start(); 252b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 253b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // Now pull data from the app and stuff it into the output 254b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth BackupManagerService.routeSocketDataToOutput(pipes[0], mOutput); 255b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 256b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (!mBackupManagerService.waitUntilOperationComplete(token)) { 257b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Full backup failed on package " + mCurrentPackage.packageName); 258b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } else { 259b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (DEBUG) { 260b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.d(TAG, "Full package backup success: " + mCurrentPackage.packageName); 261b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 262b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 263b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } catch (IOException e) { 264b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth Slog.e(TAG, "Error backing up " + mCurrentPackage.packageName + ": " + e); 265b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } finally { 266b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth // flush after every package 267b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mOutput.flush(); 268b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth if (pipes != null) { 269b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth IoUtils.closeQuietly(pipes[0]); 270b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth IoUtils.closeQuietly(pipes[1]); 271b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 272b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 273b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 274b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth 275b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth private void cleanup() { 276b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupManagerService.tearDownAgentAndKill(mCurrentPackage.applicationInfo); 277b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBlankStateName.delete(); 278b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mNewStateName.delete(); 279b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth mBackupDataName.delete(); 280b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth } 281b59a4b85ade3f1f408def6a0dd3dbb146225bdd7Johan Toras Halseth} 282