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