PerformAdbBackupTask.java revision d6c00c711000aa70db51f46b48a86c2884e91b15
1f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov/*
2f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * Copyright (C) 2017 The Android Open Source Project
3f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov *
4f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * Licensed under the Apache License, Version 2.0 (the "License");
5f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * you may not use this file except in compliance with the License.
6f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * You may obtain a copy of the License at
7f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov *
8f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov *      http://www.apache.org/licenses/LICENSE-2.0
9f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov *
10f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * Unless required by applicable law or agreed to in writing, software
11f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * distributed under the License is distributed on an "AS IS" BASIS,
12f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * See the License for the specific language governing permissions and
14f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * limitations under the License
15f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov */
16f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
17f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovpackage com.android.server.backup.fullbackup;
18f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
19f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.app.backup.IFullBackupRestoreObserver;
20f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.content.pm.ApplicationInfo;
21f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.content.pm.PackageInfo;
22f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.content.pm.PackageManager;
23f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.content.pm.PackageManager.NameNotFoundException;
24f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.os.ParcelFileDescriptor;
25f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.os.RemoteException;
26f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.os.UserHandle;
27f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport android.util.Slog;
2821510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov
29f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport com.android.server.AppWidgetBackupBridge;
30f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport com.android.server.backup.BackupRestoreTask;
31f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport com.android.server.backup.KeyValueAdbBackupEngine;
32f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport com.android.server.backup.RefactoredBackupManagerService;
3321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov
34f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.io.ByteArrayOutputStream;
35f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.io.DataOutputStream;
36f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.io.FileOutputStream;
37f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.io.IOException;
38f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.io.OutputStream;
39f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.ArrayList;
40f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.Arrays;
41f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.Iterator;
42f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.List;
43f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.Map.Entry;
44f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.TreeMap;
45f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.concurrent.atomic.AtomicBoolean;
46f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.zip.Deflater;
47f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport java.util.zip.DeflaterOutputStream;
4821510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov
49f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport javax.crypto.Cipher;
50f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport javax.crypto.CipherOutputStream;
51f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport javax.crypto.SecretKey;
52f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovimport javax.crypto.spec.SecretKeySpec;
53f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
54f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov/**
55f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov * Full backup task variant used for adb backup.
56f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov */
57f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikovpublic class PerformAdbBackupTask extends FullBackupTask implements BackupRestoreTask {
58f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
59f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    private RefactoredBackupManagerService backupManagerService;
60f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    FullBackupEngine mBackupEngine;
61f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    final AtomicBoolean mLatch;
62f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
63f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    ParcelFileDescriptor mOutputFile;
64f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    DeflaterOutputStream mDeflater;
65f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mIncludeApks;
66f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mIncludeObbs;
67f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mIncludeShared;
68f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mDoWidgets;
69f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mAllApps;
70f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mIncludeSystem;
71f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mCompress;
72f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    boolean mKeyValue;
73f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    ArrayList<String> mPackages;
74f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    PackageInfo mCurrentTarget;
75f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    String mCurrentPassword;
76f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    String mEncryptPassword;
77f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    private final int mCurrentOpToken;
78f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
79f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    public PerformAdbBackupTask(RefactoredBackupManagerService backupManagerService,
8021510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            ParcelFileDescriptor fd, IFullBackupRestoreObserver observer,
8121510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            boolean includeApks, boolean includeObbs, boolean includeShared, boolean doWidgets,
8221510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            String curPassword, String encryptPassword, boolean doAllApps, boolean doSystem,
8321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            boolean doCompress, boolean doKeyValue, String[] packages, AtomicBoolean latch) {
84f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        super(observer);
85f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        this.backupManagerService = backupManagerService;
86f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mCurrentOpToken = backupManagerService.generateRandomIntegerToken();
87f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mLatch = latch;
88f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
89f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mOutputFile = fd;
90f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mIncludeApks = includeApks;
91f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mIncludeObbs = includeObbs;
92f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mIncludeShared = includeShared;
93f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mDoWidgets = doWidgets;
94f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mAllApps = doAllApps;
95f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mIncludeSystem = doSystem;
96f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mPackages = (packages == null)
9721510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                ? new ArrayList<String>()
9821510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                : new ArrayList<>(Arrays.asList(packages));
99f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mCurrentPassword = curPassword;
100f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // when backing up, if there is a current backup password, we require that
101f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // the user use a nonempty encryption password as well.  if one is supplied
102f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // in the UI we use that, but if the UI was left empty we fall back to the
103f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // current backup password (which was supplied by the user as well).
104f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        if (encryptPassword == null || "".equals(encryptPassword)) {
105f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            mEncryptPassword = curPassword;
106f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        } else {
107f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            mEncryptPassword = encryptPassword;
108f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
109f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        if (RefactoredBackupManagerService.MORE_DEBUG) {
11021510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            Slog.w(RefactoredBackupManagerService.TAG,
11121510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    "Encrypting backup with passphrase=" + mEncryptPassword);
112f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
113f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mCompress = doCompress;
114f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mKeyValue = doKeyValue;
115f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
116f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
117f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    void addPackagesToSet(TreeMap<String, PackageInfo> set, List<String> pkgNames) {
118f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        for (String pkgName : pkgNames) {
119f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (!set.containsKey(pkgName)) {
120f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                try {
121d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov                    PackageInfo info = backupManagerService.getPackageManager().getPackageInfo(pkgName,
12221510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            PackageManager.GET_SIGNATURES);
123f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    set.put(pkgName, info);
124f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                } catch (NameNotFoundException e) {
12521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    Slog.w(RefactoredBackupManagerService.TAG,
12621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            "Unknown package " + pkgName + ", skipping");
127f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
128f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
129f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
130f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
131f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
132f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    private OutputStream emitAesBackupHeader(StringBuilder headerbuf,
13321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            OutputStream ofstream) throws Exception {
134f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // User key will be used to encrypt the master key.
135f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        byte[] newUserSalt = backupManagerService
13621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                .randomBytes(RefactoredBackupManagerService.PBKDF2_SALT_SIZE);
137f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        SecretKey userKey = backupManagerService
13821510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                .buildPasswordKey(RefactoredBackupManagerService.PBKDF_CURRENT, mEncryptPassword,
13921510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        newUserSalt,
14021510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        RefactoredBackupManagerService.PBKDF2_HASH_ROUNDS);
141f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
142f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // the master key is random for each backup
143f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        byte[] masterPw = new byte[256 / 8];
144d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov        backupManagerService.getRng().nextBytes(masterPw);
145f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        byte[] checksumSalt = backupManagerService
14621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                .randomBytes(RefactoredBackupManagerService.PBKDF2_SALT_SIZE);
147f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
148f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // primary encryption of the datastream with the random key
149f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
150f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        SecretKeySpec masterKeySpec = new SecretKeySpec(masterPw, "AES");
151f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        c.init(Cipher.ENCRYPT_MODE, masterKeySpec);
152f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        OutputStream finalOutput = new CipherOutputStream(ofstream, c);
153f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
154f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // line 4: name of encryption algorithm
155f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append(RefactoredBackupManagerService.ENCRYPTION_ALGORITHM_NAME);
156f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append('\n');
157f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // line 5: user password salt [hex]
158f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append(backupManagerService.byteArrayToHex(newUserSalt));
159f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append('\n');
160f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // line 6: master key checksum salt [hex]
161f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append(backupManagerService.byteArrayToHex(checksumSalt));
162f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append('\n');
163f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // line 7: number of PBKDF2 rounds used [decimal]
164f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append(RefactoredBackupManagerService.PBKDF2_HASH_ROUNDS);
165f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append('\n');
166f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
167f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // line 8: IV of the user key [hex]
168f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        Cipher mkC = Cipher.getInstance("AES/CBC/PKCS5Padding");
169f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkC.init(Cipher.ENCRYPT_MODE, userKey);
170f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
171f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        byte[] IV = mkC.getIV();
172f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append(backupManagerService.byteArrayToHex(IV));
173f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append('\n');
174f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
175f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // line 9: master IV + key blob, encrypted by the user key [hex].  Blob format:
176f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        //    [byte] IV length = Niv
177f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        //    [array of Niv bytes] IV itself
178f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        //    [byte] master key length = Nmk
179f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        //    [array of Nmk bytes] master key itself
180f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        //    [byte] MK checksum hash length = Nck
181f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        //    [array of Nck bytes] master key checksum hash
182f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        //
183f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // The checksum is the (master key + checksum salt), run through the
184f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // stated number of PBKDF2 rounds
185f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        IV = c.getIV();
186f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        byte[] mk = masterKeySpec.getEncoded();
187f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        byte[] checksum = backupManagerService
18821510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                .makeKeyChecksum(RefactoredBackupManagerService.PBKDF_CURRENT,
18921510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        masterKeySpec.getEncoded(),
19021510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        checksumSalt, RefactoredBackupManagerService.PBKDF2_HASH_ROUNDS);
191f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
192f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        ByteArrayOutputStream blob = new ByteArrayOutputStream(IV.length + mk.length
19321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                + checksum.length + 3);
194f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        DataOutputStream mkOut = new DataOutputStream(blob);
195f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkOut.writeByte(IV.length);
196f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkOut.write(IV);
197f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkOut.writeByte(mk.length);
198f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkOut.write(mk);
199f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkOut.writeByte(checksum.length);
200f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkOut.write(checksum);
201f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        mkOut.flush();
202f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        byte[] encryptedMk = mkC.doFinal(blob.toByteArray());
203f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append(backupManagerService.byteArrayToHex(encryptedMk));
204f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        headerbuf.append('\n');
205f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
206f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        return finalOutput;
207f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
208f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
209f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    private void finalizeBackup(OutputStream out) {
210f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        try {
211f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // A standard 'tar' EOF sequence: two 512-byte blocks of all zeroes.
212f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            byte[] eof = new byte[512 * 2]; // newly allocated == zero filled
213f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            out.write(eof);
214f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        } catch (IOException e) {
21521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            Slog.w(RefactoredBackupManagerService.TAG,
21621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    "Error attempting to finalize backup stream");
217f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
218f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
219f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
220f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    @Override
221f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    public void run() {
222f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        String includeKeyValue = mKeyValue ? ", including key-value backups" : "";
22321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov        Slog.i(RefactoredBackupManagerService.TAG,
22421510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                "--- Performing adb backup" + includeKeyValue + " ---");
225f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
226f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        TreeMap<String, PackageInfo> packagesToBackup = new TreeMap<>();
227f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        FullBackupObbConnection obbConnection = new FullBackupObbConnection(
22821510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                backupManagerService);
229f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        obbConnection.establish();  // we'll want this later
230f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
231f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        sendStartBackup();
232f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
233f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // doAllApps supersedes the package set if any
234f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        if (mAllApps) {
23521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            List<PackageInfo> allPackages =
236d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov                    backupManagerService.getPackageManager().getInstalledPackages(
23721510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            PackageManager.GET_SIGNATURES);
238f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            for (int i = 0; i < allPackages.size(); i++) {
239f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                PackageInfo pkg = allPackages.get(i);
240f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                // Exclude system apps if we've been asked to do so
241f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (mIncludeSystem == true
24221510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        || ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)) {
243f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    packagesToBackup.put(pkg.packageName, pkg);
244f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
245f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
246f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
247f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
248f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // If we're doing widget state as well, ensure that we have all the involved
249f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // host & provider packages in the set
250f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        if (mDoWidgets) {
251f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // TODO: http://b/22388012
252f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            List<String> pkgs =
25321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    AppWidgetBackupBridge.getWidgetParticipants(UserHandle.USER_SYSTEM);
254f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (pkgs != null) {
255f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (RefactoredBackupManagerService.MORE_DEBUG) {
25621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    Slog.i(RefactoredBackupManagerService.TAG,
25721510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            "Adding widget participants to backup set:");
258f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    StringBuilder sb = new StringBuilder(128);
259f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    sb.append("   ");
260f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    for (String s : pkgs) {
261f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                        sb.append(' ');
262f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                        sb.append(s);
263f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    }
264f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    Slog.i(RefactoredBackupManagerService.TAG, sb.toString());
265f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
266f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                addPackagesToSet(packagesToBackup, pkgs);
267f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
268f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
269f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
270f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // Now process the command line argument packages, if any. Note that explicitly-
271f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // named system-partition packages will be included even if includeSystem was
272f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // set to false.
273f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        if (mPackages != null) {
274f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            addPackagesToSet(packagesToBackup, mPackages);
275f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
276f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
277f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // Now we cull any inapplicable / inappropriate packages from the set.  This
278f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // includes the special shared-storage agent package; we handle that one
279f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // explicitly at the end of the backup pass. Packages supporting key-value backup are
280f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // added to their own queue, and handled after packages supporting fullbackup.
281f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        ArrayList<PackageInfo> keyValueBackupQueue = new ArrayList<>();
282f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        Iterator<Entry<String, PackageInfo>> iter = packagesToBackup.entrySet().iterator();
283f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        while (iter.hasNext()) {
284f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            PackageInfo pkg = iter.next().getValue();
285f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (!RefactoredBackupManagerService.appIsEligibleForBackup(pkg.applicationInfo)
28621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    || RefactoredBackupManagerService.appIsStopped(pkg.applicationInfo)) {
287f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                iter.remove();
288f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (RefactoredBackupManagerService.DEBUG) {
289f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    Slog.i(RefactoredBackupManagerService.TAG, "Package " + pkg.packageName
29021510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            + " is not eligible for backup, removing.");
291f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
292f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            } else if (RefactoredBackupManagerService.appIsKeyValueOnly(pkg)) {
293f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                iter.remove();
294f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (RefactoredBackupManagerService.DEBUG) {
295f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    Slog.i(RefactoredBackupManagerService.TAG, "Package " + pkg.packageName
29621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            + " is key-value.");
297f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
298f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                keyValueBackupQueue.add(pkg);
299f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
300f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
301f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
302f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // flatten the set of packages now so we can explicitly control the ordering
303f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        ArrayList<PackageInfo> backupQueue =
30421510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                new ArrayList<>(packagesToBackup.values());
305f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        FileOutputStream ofstream = new FileOutputStream(mOutputFile.getFileDescriptor());
306f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        OutputStream out = null;
307f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
308f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        PackageInfo pkg = null;
309f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        try {
310f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);
311f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
312f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // Only allow encrypted backups of encrypted devices
313f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (backupManagerService.deviceIsEncrypted() && !encrypting) {
31421510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                Slog.e(RefactoredBackupManagerService.TAG,
31521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        "Unencrypted backup of encrypted device; aborting");
316f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                return;
317f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
318f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
319f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            OutputStream finalOutput = ofstream;
320f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
321f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // Verify that the given password matches the currently-active
322f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // backup password, if any
323f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (!backupManagerService.backupPasswordMatches(mCurrentPassword)) {
324f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (RefactoredBackupManagerService.DEBUG) {
32521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    Slog.w(RefactoredBackupManagerService.TAG,
32621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            "Backup password mismatch; aborting");
327f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
328f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                return;
329f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
330f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
331f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // Write the global file header.  All strings are UTF-8 encoded; lines end
332f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // with a '\n' byte.  Actual backup data begins immediately following the
333f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // final '\n'.
334f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            //
335f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 1: "ANDROID BACKUP"
336f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 2: backup file format version, currently "5"
337f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 3: compressed?  "0" if not compressed, "1" if compressed.
338f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 4: name of encryption algorithm [currently only "none" or "AES-256"]
339f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            //
340f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // When line 4 is not "none", then additional header data follows:
341f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            //
342f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 5: user password salt [hex]
343f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 6: master key checksum salt [hex]
344f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 7: number of PBKDF2 rounds to use (same for user & master) [decimal]
345f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 8: IV of the user key [hex]
346f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // line 9: master key blob [hex]
347f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            //     IV of the master key, master key itself, master key checksum hash
348f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            //
349f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // The master key checksum is the master key plus its checksum salt, run through
350f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // 10k rounds of PBKDF2.  This is used to verify that the user has supplied the
351f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // correct password for decrypting the archive:  the master key decrypted from
352f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // the archive using the user-supplied password is also run through PBKDF2 in
353f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // this way, and if the result does not match the checksum as stored in the
354f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // archive, then we know that the user-supplied password does not match the
355f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // archive's.
356f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            StringBuilder headerbuf = new StringBuilder(1024);
357f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
358f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            headerbuf.append(RefactoredBackupManagerService.BACKUP_FILE_HEADER_MAGIC);
35921510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov            headerbuf.append(
36021510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    RefactoredBackupManagerService.BACKUP_FILE_VERSION); // integer, no trailing \n
361f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            headerbuf.append(mCompress ? "\n1\n" : "\n0\n");
362f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
363f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            try {
364f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                // Set up the encryption stage if appropriate, and emit the correct header
365f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (encrypting) {
366f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    finalOutput = emitAesBackupHeader(headerbuf, finalOutput);
367f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                } else {
368f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    headerbuf.append("none\n");
369f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
370f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
371f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                byte[] header = headerbuf.toString().getBytes("UTF-8");
372f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                ofstream.write(header);
373f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
374f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                // Set up the compression stage feeding into the encryption stage (if any)
375f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (mCompress) {
376f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
377f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    finalOutput = new DeflaterOutputStream(finalOutput, deflater, true);
378f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
379f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
380f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                out = finalOutput;
381f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            } catch (Exception e) {
382f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                // Should never happen!
383f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                Slog.e(RefactoredBackupManagerService.TAG, "Unable to emit archive header", e);
384f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                return;
385f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
386f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
387f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // Shared storage if requested
388f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (mIncludeShared) {
389f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                try {
390d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov                    pkg = backupManagerService.getPackageManager().getPackageInfo(
39121510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE, 0);
392f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    backupQueue.add(pkg);
393f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                } catch (NameNotFoundException e) {
39421510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                    Slog.e(RefactoredBackupManagerService.TAG,
39521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            "Unable to find shared-storage backup handler");
396f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
397f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
398f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
399f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // Now actually run the constructed backup sequence for full backup
400f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            int N = backupQueue.size();
401f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            for (int i = 0; i < N; i++) {
402f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                pkg = backupQueue.get(i);
403f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (RefactoredBackupManagerService.DEBUG) {
404f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    Slog.i(RefactoredBackupManagerService.TAG,
40521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            "--- Performing full backup for package " + pkg.packageName
40621510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                                    + " ---");
407f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
408f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                final boolean isSharedStorage =
40921510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        pkg.packageName.equals(
41021510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                                RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE);
411f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
412f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                mBackupEngine = new FullBackupEngine(backupManagerService, out,
41321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        null, pkg, mIncludeApks, this, Long.MAX_VALUE, mCurrentOpToken);
414f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
415f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
416f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                // Don't need to check preflight result as there is no preflight hook.
417f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                mCurrentTarget = pkg;
418f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                mBackupEngine.backupOnePackage();
419f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
420f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                // after the app's agent runs to handle its private filesystem
421f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                // contents, back up any OBB content it has on its behalf.
422f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (mIncludeObbs) {
423f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    boolean obbOkay = obbConnection.backupObbs(pkg, out);
424f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    if (!obbOkay) {
425f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                        throw new RuntimeException("Failure writing OBB stack for " + pkg);
426f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    }
427f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
428f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
429f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // And for key-value backup if enabled
430f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (mKeyValue) {
431f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                for (PackageInfo keyValuePackage : keyValueBackupQueue) {
432f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    if (RefactoredBackupManagerService.DEBUG) {
43321510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                        Slog.i(RefactoredBackupManagerService.TAG,
43421510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                                "--- Performing key-value backup for package "
43521510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                                        + keyValuePackage.packageName + " ---");
436f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    }
437f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    KeyValueAdbBackupEngine kvBackupEngine =
43821510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                            new KeyValueAdbBackupEngine(out, keyValuePackage,
43921510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                                    backupManagerService,
440d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov                                    backupManagerService.getPackageManager(),
441d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov                                    backupManagerService.getBaseStateDir(),
442d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov                                    backupManagerService.getDataDir());
443f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    sendOnBackupPackage(keyValuePackage.packageName);
444f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    kvBackupEngine.backupOnePackage();
445f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
446f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
447f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
448f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            // Done!
449f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            finalizeBackup(out);
450f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        } catch (RemoteException e) {
451f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            Slog.e(RefactoredBackupManagerService.TAG, "App died during full backup");
452f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        } catch (Exception e) {
453f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            Slog.e(RefactoredBackupManagerService.TAG, "Internal exception during full backup", e);
454f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        } finally {
455f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            try {
456f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                if (out != null) {
457f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    out.flush();
458f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                    out.close();
459f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                }
460f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                mOutputFile.close();
461f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            } catch (IOException e) {
462f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                /* nothing we can do about this */
463f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
464f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            synchronized (mLatch) {
465f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                mLatch.set(true);
466f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov                mLatch.notifyAll();
467f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
468f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            sendEndBackup();
469f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            obbConnection.tearDown();
470f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            if (RefactoredBackupManagerService.DEBUG) {
47121510f0b7571f0689dc48c4f8fdbafea883cbdd0Artem Iglikov                Slog.d(RefactoredBackupManagerService.TAG, "Full backup pass complete.");
472f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            }
473d6c00c711000aa70db51f46b48a86c2884e91b15Artem Iglikov            backupManagerService.getWakelock().release();
474f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
475f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
476f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
477f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    // BackupRestoreTask methods, used for timeout handling
478f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    @Override
479f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    public void execute() {
480f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // Unused
481f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
482f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
483f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    @Override
484f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    public void operationComplete(long result) {
485f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        // Unused
486f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
487f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov
488f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    @Override
489f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    public void handleCancel(boolean cancelAll) {
490f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        final PackageInfo target = mCurrentTarget;
491f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        if (RefactoredBackupManagerService.DEBUG) {
492f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            Slog.w(RefactoredBackupManagerService.TAG, "adb backup cancel of " + target);
493f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
494f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        if (target != null) {
495f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov            backupManagerService.tearDownAgentAndKill(mCurrentTarget.applicationInfo);
496f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        }
497f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov        backupManagerService.removeOperation(mCurrentOpToken);
498f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov    }
499f251e3509838e3fbc62ccdba9d4cfd0527f67acdArtem Iglikov}
500