1ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate/*
2ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * Copyright (C) 2009 The Android Open Source Project
3ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate *
4ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * Licensed under the Apache License, Version 2.0 (the "License");
5ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * you may not use this file except in compliance with the License.
6ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * You may obtain a copy of the License at
7ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate *
8ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate *      http://www.apache.org/licenses/LICENSE-2.0
9ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate *
10ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * Unless required by applicable law or agreed to in writing, software
11ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * distributed under the License is distributed on an "AS IS" BASIS,
12ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * See the License for the specific language governing permissions and
14ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate * limitations under the License.
15ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate */
16ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
17ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tatepackage com.android.commands.bmgr;
18ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
19b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromovimport android.app.backup.BackupManager;
20b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromovimport android.app.backup.BackupProgress;
214528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tateimport android.app.backup.RestoreSet;
224528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tateimport android.app.backup.IBackupManager;
23b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromovimport android.app.backup.IBackupObserver;
244528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tateimport android.app.backup.IRestoreObserver;
254528186e0d65fc68ef0dd1941aa2ac8aefcd55a3Christopher Tateimport android.app.backup.IRestoreSession;
2610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromovimport android.content.pm.IPackageManager;
2710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromovimport android.content.pm.PackageInfo;
28ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tateimport android.os.RemoteException;
29ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tateimport android.os.ServiceManager;
3010f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromovimport android.os.UserHandle;
31ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
329ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tateimport java.util.ArrayList;
33284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tateimport java.util.HashSet;
3410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromovimport java.util.List;
35284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate
36ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tatepublic final class Bmgr {
37ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    IBackupManager mBmgr;
38ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    IRestoreSession mRestore;
39ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
40ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    static final String BMGR_NOT_RUNNING_ERR =
41ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            "Error: Could not access the Backup Manager.  Is the system running?";
42ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    static final String TRANSPORT_NOT_RUNNING_ERR =
4310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            "Error: Could not access the backup transport.  Is the system running?";
4410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov    static final String PM_NOT_RUNNING_ERR =
4510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            "Error: Could not access the Package Manager.  Is the system running?";
46ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
47ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private String[] mArgs;
48ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private int mNextArg;
49ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
50ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    public static void main(String[] args) {
51f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        try {
52f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            new Bmgr().run(args);
53f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        } catch (Exception e) {
54f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            System.err.println("Exception caught:");
55f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            e.printStackTrace();
56f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        }
57ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
58f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate
59ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    public void run(String[] args) {
60ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        if (args.length < 1) {
61ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            showUsage();
62ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return;
63ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
64ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
65ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        mBmgr = IBackupManager.Stub.asInterface(ServiceManager.getService("backup"));
66ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        if (mBmgr == null) {
67ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
68ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return;
69ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
70ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
71ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        mArgs = args;
72ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        String op = args[0];
73ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        mNextArg = 1;
74ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
756ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        if ("enabled".equals(op)) {
766ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            doEnabled();
776ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            return;
786ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        }
796ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate
806ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        if ("enable".equals(op)) {
816ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            doEnable();
826ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            return;
836ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        }
846ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate
85ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        if ("run".equals(op)) {
86ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            doRun();
87ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return;
88ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
89ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
90ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        if ("backup".equals(op)) {
91ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            doBackup();
92ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return;
93ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
94ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
95ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        if ("list".equals(op)) {
96ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            doList();
97ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return;
98ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
99f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate
100f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        if ("restore".equals(op)) {
101f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            doRestore();
102f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            return;
103f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        }
104abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate
105abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate        if ("transport".equals(op)) {
106abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate            doTransport();
107abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate            return;
108abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate        }
109abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate
110d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        if ("wipe".equals(op)) {
111d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate            doWipe();
112d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate            return;
113d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        }
114d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate
1159ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate        if ("fullbackup".equals(op)) {
1169ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate            doFullTransportBackup();
1179ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate            return;
1189ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate        }
1199ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate
120b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        if ("backupnow".equals(op)) {
121b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            doBackupNow();
122b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            return;
123b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
124b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
125e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate        if ("whitelist".equals(op)) {
126e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate            doPrintWhitelist();
127e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate            return;
128e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate        }
129e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate
130abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate        System.err.println("Unknown command");
131abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate        showUsage();
132ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
133ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
1346ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate    private String enableToString(boolean enabled) {
1356ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        return enabled ? "enabled" : "disabled";
1366ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate    }
1376ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate
1386ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate    private void doEnabled() {
1396ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        try {
1406ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            boolean isEnabled = mBmgr.isBackupEnabled();
1416ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            System.out.println("Backup Manager currently "
1426ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate                    + enableToString(isEnabled));
1436ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        } catch (RemoteException e) {
1446ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            System.err.println(e.toString());
1456ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
1466ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        }
1476ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate    }
1486ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate
1496ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate    private void doEnable() {
1506ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        String arg = nextArg();
1516ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        if (arg == null) {
1526ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            showUsage();
1536ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            return;
1546ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        }
1556ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate
1566ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        try {
1576ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            boolean enable = Boolean.parseBoolean(arg);
1586ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            mBmgr.setBackupEnabled(enable);
1596ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            System.out.println("Backup Manager now " + enableToString(enable));
1606ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        } catch (NumberFormatException e) {
1616ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            showUsage();
1626ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            return;
1636ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        } catch (RemoteException e) {
1646ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            System.err.println(e.toString());
1656ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
1666ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        }
1676ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate    }
1686ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate
169ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private void doRun() {
170ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        try {
171ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            mBmgr.backupNow();
172ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        } catch (RemoteException e) {
173ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(e.toString());
174ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
175ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
176ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
177ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
178ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private void doBackup() {
179ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        String pkg = nextArg();
1804a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        if (pkg == null) {
181ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            showUsage();
182ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return;
183ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
184ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
185ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        try {
186ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            mBmgr.dataChanged(pkg);
187ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        } catch (RemoteException e) {
188ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(e.toString());
189ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
190ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
191ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
192ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
1939ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate    private void doFullTransportBackup() {
1949ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate        System.out.println("Performing full transport backup");
1959ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate
1969ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate        String pkg;
197ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        ArrayList<String> allPkgs = new ArrayList<String>();
1989ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate        while ((pkg = nextArg()) != null) {
199ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate            allPkgs.add(pkg);
200ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        }
201ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        if (allPkgs.size() > 0) {
2029ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate            try {
203ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate                mBmgr.fullTransportBackup(allPkgs.toArray(new String[allPkgs.size()]));
2049ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate            } catch (RemoteException e) {
2059ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate                System.err.println(e.toString());
2069ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate                System.err.println(BMGR_NOT_RUNNING_ERR);
2079ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate            }
2089ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate        }
2099ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate    }
2109ff53a7100b1a40f5d2df3eb19a2f3f2fff39a46Christopher Tate
211b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov    class BackupObserver extends IBackupObserver.Stub {
212b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        boolean done = false;
213b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
214b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        @Override
215b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        public void onUpdate(String currentPackage, BackupProgress backupProgress) {
216b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            System.out.println(
21710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred
218b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                    + "/" + backupProgress.bytesExpected);
219b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
220b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
221b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        @Override
222b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        public void onResult(String currentPackage, int status) {
22310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.out.println("Package " + currentPackage + " with result: "
224b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                    + convertBackupStatusToString(status));
225b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
226b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
227b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        @Override
228b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        public void backupFinished(int status) {
22910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.out.println("Backup finished with result: "
23010f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                    + convertBackupStatusToString(status));
231b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            synchronized (this) {
232b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                done = true;
233b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                this.notify();
234b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            }
235b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
236b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
237b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        public void waitForCompletion() {
238b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            // The backupFinished() callback will throw the 'done' flag; we
239b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            // just sit and wait on that notification.
240b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            synchronized (this) {
241b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                while (!this.done) {
242b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                    try {
243b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                        this.wait();
244b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                    } catch (InterruptedException ex) {
245b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                    }
246b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                }
247b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            }
248b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
249b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
250b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov    }
251b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
252b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov    private static String convertBackupStatusToString(int errorCode) {
253b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        switch (errorCode) {
254b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            case BackupManager.SUCCESS:
255b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                return "Success";
256b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            case BackupManager.ERROR_BACKUP_NOT_ALLOWED:
257b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                return "Backup is not allowed";
258b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            case BackupManager.ERROR_PACKAGE_NOT_FOUND:
259b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                return "Package not found";
260b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            case BackupManager.ERROR_TRANSPORT_ABORTED:
261b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                return "Transport error";
262b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            case BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED:
263b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                return "Transport rejected package";
264b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            case BackupManager.ERROR_AGENT_FAILURE:
265b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                return "Agent error";
26610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            case BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED:
26710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                return "Size quota exceeded";
268b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            default:
269b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov                return "Unknown error";
270b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
271b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov    }
272b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
27310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov    private void backupNowAllPackages() {
27410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        int userId = UserHandle.USER_SYSTEM;
27510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        IPackageManager mPm =
27610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
27710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        if (mPm == null) {
27810f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.err.println(PM_NOT_RUNNING_ERR);
27910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            return;
28010f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        }
28110f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        List<PackageInfo> installedPackages = null;
28210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        try {
28310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            installedPackages =  mPm.getInstalledPackages(0, userId).getList();
28410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        } catch (RemoteException e) {
28510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.err.println(e.toString());
28610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.err.println(PM_NOT_RUNNING_ERR);
28710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        }
28810f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        if (installedPackages != null) {
28910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            List<String> packages = new ArrayList<>();
29010f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            for (PackageInfo pi : installedPackages) {
29110f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                try {
29210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                    if (mBmgr.isAppEligibleForBackup(pi.packageName)) {
29310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                        packages.add(pi.packageName);
29410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                    }
29510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                } catch (RemoteException e) {
29610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                    System.err.println(e.toString());
29710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                    System.err.println(BMGR_NOT_RUNNING_ERR);
29810f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                }
29910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            }
30010f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            backupNowPackages(packages);
30110f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        }
30210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov    }
30310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov
30410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov    private void backupNowPackages(List<String> packages) {
30510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        try {
30610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            BackupObserver observer = new BackupObserver();
30710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer);
30810f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            if (err == 0) {
30910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                // Off and running -- wait for the backup to complete
31010f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                observer.waitForCompletion();
31110f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            } else {
31210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                System.err.println("Unable to run backup");
31310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            }
31410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        } catch (RemoteException e) {
31510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.err.println(e.toString());
31610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.err.println(BMGR_NOT_RUNNING_ERR);
31710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        }
31810f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov    }
31910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov
320b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov    private void doBackupNow() {
321b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        String pkg;
32210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        boolean backupAll = false;
323b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        ArrayList<String> allPkgs = new ArrayList<String>();
324b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        while ((pkg = nextArg()) != null) {
32510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            if (pkg.equals("--all")) {
32610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                backupAll = true;
32710f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            } else {
32810f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                allPkgs.add(pkg);
32910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            }
330b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
33110f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        if (backupAll) {
33210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            if (allPkgs.size() == 0) {
33310f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                System.out.println("Running backup for all packages.");
33410f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                backupNowAllPackages();
33510f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            } else {
33610f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov                System.err.println("Provide only '--all' flag or list of packages.");
337b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov            }
33810f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        } else if (allPkgs.size() > 0) {
33910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.out.println("Running backup for " + allPkgs.size() +" requested packages.");
34010f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            backupNowPackages(allPkgs);
34110f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        } else {
34210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov            System.err.println("Provide '--all' flag or list of packages.");
343b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        }
344b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov    }
345b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov
346abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate    private void doTransport() {
347abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate        try {
3489171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            String which = nextArg();
3497e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate            if (which == null) {
3507e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate                showUsage();
3517e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate                return;
3527e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate            }
3537e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate
3549171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            String old = mBmgr.selectBackupTransport(which);
3559171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            if (old == null) {
3569171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                System.out.println("Unknown transport '" + which
3579171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                        + "' specified; no changes made.");
3589171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            } else {
3599171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                System.out.println("Selected transport " + which + " (formerly " + old + ")");
3609171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            }
361abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate        } catch (RemoteException e) {
362abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate            System.err.println(e.toString());
363abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
364abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate        }
365abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate    }
366abce4e8714bed26a2b37b20ad3f02cf619d71c9aChristopher Tate
367d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate    private void doWipe() {
368b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate        String transport = nextArg();
369b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate        if (transport == null) {
370b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate            showUsage();
371b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate            return;
372b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate        }
373b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate
374d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        String pkg = nextArg();
375d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        if (pkg == null) {
376d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate            showUsage();
377d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate            return;
378d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        }
379d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate
380d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        try {
381b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate            mBmgr.clearBackupData(transport, pkg);
382b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate            System.out.println("Wiped backup data for " + pkg + " on " + transport);
383d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        } catch (RemoteException e) {
384d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate            System.err.println(e.toString());
385d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
386d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        }
387d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate    }
388d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate
389ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private void doList() {
390ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        String arg = nextArg();     // sets, transports, packages set#
391ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        if ("transports".equals(arg)) {
392ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            doListTransports();
393ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return;
394ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
395ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
396ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        // The rest of the 'list' options work with a restore session on the current transport
397ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        try {
39844ab8453e1c4c46790f792a46d026fa1017d8cfeChris Tate            mRestore = mBmgr.beginRestoreSession(null, null);
399f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            if (mRestore == null) {
400f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate                System.err.println(BMGR_NOT_RUNNING_ERR);
401f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate                return;
402f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            }
403ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
404ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            if ("sets".equals(arg)) {
405ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate                doListRestoreSets();
4069171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            } else if ("transports".equals(arg)) {
4079171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                doListTransports();
408ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            }
409ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
410ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            mRestore.endRestoreSession();
411ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        } catch (RemoteException e) {
412ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(e.toString());
413ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
414ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
415ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
416ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
417ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private void doListTransports() {
4189171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        try {
4199171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            String current = mBmgr.getCurrentTransport();
4209171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            String[] transports = mBmgr.listAllTransports();
4219171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            if (transports == null || transports.length == 0) {
4229171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                System.out.println("No transports available.");
4239171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                return;
4249171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            }
4259171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate
4269171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            for (String t : transports) {
4279171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                String pad = (t.equals(current)) ? "  * " : "    ";
4289171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate                System.out.println(pad + t);
4299171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            }
4309171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        } catch (RemoteException e) {
4319171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            System.err.println(e.toString());
4329171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
4339171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        }
434ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
435ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
436ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private void doListRestoreSets() {
437ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        try {
4382d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate            RestoreObserver observer = new RestoreObserver();
4392d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate            int err = mRestore.getAvailableRestoreSets(observer);
4402d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate            if (err != 0) {
4412d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                System.out.println("Unable to request restore sets");
442ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            } else {
4432d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                observer.waitForCompletion();
4442d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                printRestoreSets(observer.sets);
445ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            }
446ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        } catch (RemoteException e) {
447ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(e.toString());
448ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            System.err.println(TRANSPORT_NOT_RUNNING_ERR);
449ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
450ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
451ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
452c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate    private void printRestoreSets(RestoreSet[] sets) {
45304686f428995fde3f6f5f5f12ccdd135f885ac84Fabrice Di Meglio        if (sets == null || sets.length == 0) {
45404686f428995fde3f6f5f5f12ccdd135f885ac84Fabrice Di Meglio            System.out.println("No restore sets");
45504686f428995fde3f6f5f5f12ccdd135f885ac84Fabrice Di Meglio            return;
45604686f428995fde3f6f5f5f12ccdd135f885ac84Fabrice Di Meglio        }
457c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate        for (RestoreSet s : sets) {
45877095d49f203eed6a6742f2605ca319e7360af32Christian Sonntag            System.out.println("  " + Long.toHexString(s.token) + " : " + s.name);
459c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate        }
460c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate    }
461c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate
4624a64bded06a0299785c295a975e2818308eb53e2Joe Onorato    class RestoreObserver extends IRestoreObserver.Stub {
4634a64bded06a0299785c295a975e2818308eb53e2Joe Onorato        boolean done;
4642d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate        RestoreSet[] sets = null;
4652d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate
4662d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate        public void restoreSetsAvailable(RestoreSet[] result) {
4672d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate            synchronized (this) {
4682d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                sets = result;
4692d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                done = true;
4702d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                this.notify();
4712d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate            }
4722d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate        }
4732d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate
4744a64bded06a0299785c295a975e2818308eb53e2Joe Onorato        public void restoreStarting(int numPackages) {
4754a64bded06a0299785c295a975e2818308eb53e2Joe Onorato            System.out.println("restoreStarting: " + numPackages + " packages");
4764a64bded06a0299785c295a975e2818308eb53e2Joe Onorato        }
4774a64bded06a0299785c295a975e2818308eb53e2Joe Onorato
4789c3cee9824026764275e4d84ba9b5d9fdc5da690Christopher Tate        public void onUpdate(int nowBeingRestored, String currentPackage) {
4799c3cee9824026764275e4d84ba9b5d9fdc5da690Christopher Tate            System.out.println("onUpdate: " + nowBeingRestored + " = " + currentPackage);
4804a64bded06a0299785c295a975e2818308eb53e2Joe Onorato        }
4814a64bded06a0299785c295a975e2818308eb53e2Joe Onorato
4824a64bded06a0299785c295a975e2818308eb53e2Joe Onorato        public void restoreFinished(int error) {
4834a64bded06a0299785c295a975e2818308eb53e2Joe Onorato            System.out.println("restoreFinished: " + error);
4844a64bded06a0299785c295a975e2818308eb53e2Joe Onorato            synchronized (this) {
4854a64bded06a0299785c295a975e2818308eb53e2Joe Onorato                done = true;
4864a64bded06a0299785c295a975e2818308eb53e2Joe Onorato                this.notify();
4874a64bded06a0299785c295a975e2818308eb53e2Joe Onorato            }
4884a64bded06a0299785c295a975e2818308eb53e2Joe Onorato        }
4897d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate
4907d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        public void waitForCompletion() {
4917d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            // The restoreFinished() callback will throw the 'done' flag; we
4927d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            // just sit and wait on that notification.
4937d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            synchronized (this) {
4947d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                while (!this.done) {
4957d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                    try {
4967d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                        this.wait();
4977d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                    } catch (InterruptedException ex) {
4987d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                    }
4997d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                }
5007d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            }
5017d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        }
5024a64bded06a0299785c295a975e2818308eb53e2Joe Onorato    }
5034a64bded06a0299785c295a975e2818308eb53e2Joe Onorato
504f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate    private void doRestore() {
5057d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        String arg = nextArg();
5067e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate        if (arg == null) {
5077e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate            showUsage();
5087e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate            return;
5097e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate        }
5107e76ff1c409bc22e89ed09ef90161164dae40838Christopher Tate
511fbec21ff43c8a35e95fca9ce40351350608974e9Christopher Tate        if (arg.indexOf('.') >= 0 || arg.equals("android")) {
5127d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            // it's a package name
5137d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            doRestorePackage(arg);
5147d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        } else {
5157d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            try {
516485c3a16cef38136a821e79a5fe37df4e1779d28Christian Sonntag                long token = Long.parseLong(arg, 16);
517284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                HashSet<String> filter = null;
518284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                while ((arg = nextArg()) != null) {
519284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                    if (filter == null) filter = new HashSet<String>();
520284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                    filter.add(arg);
521284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                }
522284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate
523284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                doRestoreAll(token, filter);
5247d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            } catch (NumberFormatException e) {
5257d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                showUsage();
5267d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                return;
5277d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            }
5287d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        }
5297d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate
5307d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.out.println("done");
5317d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate    }
5327d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate
5337d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate    private void doRestorePackage(String pkg) {
534f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        try {
53544ab8453e1c4c46790f792a46d026fa1017d8cfeChris Tate            mRestore = mBmgr.beginRestoreSession(pkg, null);
5367d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            if (mRestore == null) {
5377d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                System.err.println(BMGR_NOT_RUNNING_ERR);
5387d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                return;
5397d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            }
5407d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate
5417d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            RestoreObserver observer = new RestoreObserver();
5427d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            int err = mRestore.restorePackage(pkg, observer);
5437d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            if (err == 0) {
5447d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                // Off and running -- wait for the restore to complete
5457d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                observer.waitForCompletion();
5467d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            } else {
5477d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                System.err.println("Unable to restore package " + pkg);
5487d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            }
5497d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate
5507d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            // And finally shut down the session
5517d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            mRestore.endRestoreSession();
5527d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        } catch (RemoteException e) {
5537d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            System.err.println(e.toString());
5547d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
555f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        }
5567d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate    }
557f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate
558284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate    private void doRestoreAll(long token, HashSet<String> filter) {
5594a64bded06a0299785c295a975e2818308eb53e2Joe Onorato        RestoreObserver observer = new RestoreObserver();
5604a64bded06a0299785c295a975e2818308eb53e2Joe Onorato
561f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        try {
562c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate            boolean didRestore = false;
56344ab8453e1c4c46790f792a46d026fa1017d8cfeChris Tate            mRestore = mBmgr.beginRestoreSession(null, null);
564f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            if (mRestore == null) {
565f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate                System.err.println(BMGR_NOT_RUNNING_ERR);
566f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate                return;
567f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            }
5682d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate            RestoreSet[] sets = null;
5692d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate            int err = mRestore.getAvailableRestoreSets(observer);
5701398e27bb0f5768cbbd5b9d9fd7c8675da63ccb0Christopher Tate            if (err == 0) {
5712d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                observer.waitForCompletion();
5722d449afe3d075020bdd1115bcc15c9383cbce122Christopher Tate                sets = observer.sets;
5737a0fc8776782a18374ec6e3b4418027c3c685b1aChris Tate                if (sets != null) {
5747a0fc8776782a18374ec6e3b4418027c3c685b1aChris Tate                    for (RestoreSet s : sets) {
5757a0fc8776782a18374ec6e3b4418027c3c685b1aChris Tate                        if (s.token == token) {
5767a0fc8776782a18374ec6e3b4418027c3c685b1aChris Tate                            System.out.println("Scheduling restore: " + s.name);
577284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                            if (filter == null) {
578284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                                didRestore = (mRestore.restoreAll(token, observer) == 0);
579284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                            } else {
580284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                                String[] names = new String[filter.size()];
581284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                                filter.toArray(names);
582284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                                didRestore = (mRestore.restoreSome(token, observer, names) == 0);
583284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate                            }
5847a0fc8776782a18374ec6e3b4418027c3c685b1aChris Tate                            break;
5857a0fc8776782a18374ec6e3b4418027c3c685b1aChris Tate                        }
58684780f56f441deb4ff736987986daeaf64db17a4Christopher Tate                    }
587f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate                }
588f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            }
589c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate            if (!didRestore) {
590c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate                if (sets == null || sets.length == 0) {
591c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate                    System.out.println("No available restore sets; no restore performed");
592c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate                } else {
593c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate                    System.out.println("No matching restore set token.  Available sets:");
594c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate                    printRestoreSets(sets);
595c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate                }
596c73a218c2663e6ae3ec8a9ab8b9524f95702ade9Christopher Tate            }
59708e40b858e8a3266c5519a83fda6f7505f1c14dbChristopher Tate
5980e0b4ae5bc5c652c8339d71ed9667e1e37baaa03Christopher Tate            // if we kicked off a restore successfully, we have to wait for it
5990e0b4ae5bc5c652c8339d71ed9667e1e37baaa03Christopher Tate            // to complete before we can shut down the restore session safely
6000e0b4ae5bc5c652c8339d71ed9667e1e37baaa03Christopher Tate            if (didRestore) {
6017d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate                observer.waitForCompletion();
60208e40b858e8a3266c5519a83fda6f7505f1c14dbChristopher Tate            }
60308e40b858e8a3266c5519a83fda6f7505f1c14dbChristopher Tate
60408e40b858e8a3266c5519a83fda6f7505f1c14dbChristopher Tate            // once the restore has finished, close down the session and we're done
605f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            mRestore.endRestoreSession();
606f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        } catch (RemoteException e) {
607f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            System.err.println(e.toString());
608f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
609f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate        }
610f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate    }
611f68eb500f99361541049e09eb7f9ddd6f4ef4efaChristopher Tate
612e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate    private void doPrintWhitelist() {
613e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate        try {
614e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate            final String[] whitelist = mBmgr.getTransportWhitelist();
615e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate            if (whitelist != null) {
616e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate                for (String transport : whitelist) {
617e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate                    System.out.println(transport);
618e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate                }
619e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate            }
620e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate        } catch (RemoteException e) {
621e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate            System.err.println(e.toString());
622e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate            System.err.println(BMGR_NOT_RUNNING_ERR);
623e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate        }
624e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate    }
625e227ec61c24c3c33d42de4996d38fc4e44fa5e4dChristopher Tate
626ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private String nextArg() {
627ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        if (mNextArg >= mArgs.length) {
628ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate            return null;
629ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        }
630ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        String arg = mArgs[mNextArg];
631ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        mNextArg++;
632ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        return arg;
633ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
634ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate
635ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    private static void showUsage() {
636ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        System.err.println("usage: bmgr [backup|restore|list|transport|run]");
6379171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("       bmgr backup PACKAGE");
6386ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("       bmgr enable BOOL");
6396ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("       bmgr enabled");
6409171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("       bmgr list transports");
641ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        System.err.println("       bmgr list sets");
6429171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("       bmgr transport WHICH");
6439171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("       bmgr restore TOKEN");
644284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("       bmgr restore TOKEN PACKAGE...");
6457d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.err.println("       bmgr restore PACKAGE");
646ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate        System.err.println("       bmgr run");
647b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate        System.err.println("       bmgr wipe TRANSPORT PACKAGE");
648ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        System.err.println("       bmgr fullbackup PACKAGE...");
64910f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        System.err.println("       bmgr backupnow --all|PACKAGE...");
6509171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("");
6519171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("The 'backup' command schedules a backup pass for the named package.");
6529171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("Note that the backup pass will effectively be a no-op if the package");
6539171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("does not actually have changed data to store.");
6549171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("");
6556ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("The 'enable' command enables or disables the entire backup mechanism.");
6566ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("If the argument is 'true' it will be enabled, otherwise it will be");
6576ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("disabled.  When disabled, neither backup or restore operations will");
6586ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("be performed.");
6596ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("");
6606ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("The 'enabled' command reports the current enabled/disabled state of");
6616ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("the backup mechanism.");
6626ef58a1509b9d3348a33ca5686917796c2759aa5Christopher Tate        System.err.println("");
6639171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("The 'list transports' command reports the names of the backup transports");
6649171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("currently available on the device.  These names can be passed as arguments");
665ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        System.err.println("to the 'transport' and 'wipe' commands.  The currently active transport");
666b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate        System.err.println("is indicated with a '*' character.");
6679171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("");
6689171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("The 'list sets' command reports the token and name of each restore set");
669ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        System.err.println("available to the device via the currently active transport.");
6709171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("");
6719171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("The 'transport' command designates the named transport as the currently");
6729171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("active one.  This setting is persistent across reboots.");
6739171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("");
674284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("The 'restore' command when given just a restore token initiates a full-system");
6757d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.err.println("restore operation from the currently active transport.  It will deliver");
6767d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.err.println("the restore set designated by the TOKEN argument to each application");
6777d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.err.println("that had contributed data to that restore set.");
6787d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.err.println("");
679284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("The 'restore' command when given a token and one or more package names");
680284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("initiates a restore operation of just those given packages from the restore");
681284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("set designated by the TOKEN argument.  It is effectively the same as the");
682284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("'restore' operation supplying only a token, but applies a filter to the");
683284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("set of applications to be restored.");
684284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("");
685284f1bb4daf77f7e6b688c0936dd4a31ec2e7c74Christopher Tate        System.err.println("The 'restore' command when given just a package name intiates a restore of");
6867d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.err.println("just that one package according to the restore set selection algorithm");
6877d411a3b947ba82d1d57f73c0fa698c3b9c95892Christopher Tate        System.err.println("used by the RestoreSession.restorePackage() method.");
6889171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("");
6899171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("The 'run' command causes any scheduled backup operation to be initiated");
6909171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("immediately, without the usual waiting period for batching together");
6919171749700853305f3e6abbcdbd9e02f3a71d459Christopher Tate        System.err.println("data changes.");
692d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        System.err.println("");
693d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        System.err.println("The 'wipe' command causes all backed-up data for the given package to be");
694b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate        System.err.println("erased from the given transport's storage.  The next backup operation");
695d23d7f2d12c20314e1e8ff206fafc8f21745ca2dChristopher Tate        System.err.println("that the given application performs will rewrite its entire data set.");
696b0183f0ae311966cff0e10e8139c56f97288d1f2Christopher Tate        System.err.println("Transport names to use here are those reported by 'list transports'.");
697ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        System.err.println("");
698ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        System.err.println("The 'fullbackup' command induces a full-data stream backup for one or more");
699ab225b301b8b13a141053a33d5dd5eeccfc69887Christopher Tate        System.err.println("packages.  The data is sent via the currently active transport.");
700b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        System.err.println("");
701b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        System.err.println("The 'backupnow' command runs an immediate backup for one or more packages.");
70210f0f712498b8c4b6308788d20027b35a8ce43a0Sergey Poromov        System.err.println("    --all flag runs backup for all eligible packages.");
703b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        System.err.println("For each package it will run key/value or full data backup ");
704b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        System.err.println("depending on the package's manifest declarations.");
705b998532be8451993fe6d4e22f6ac290ffab57c76Sergey Poromov        System.err.println("The data is sent via the currently active transport.");
706ace7f094bf07bbd90cb998b9462e4f2d101a498cChristopher Tate    }
7075e8a4b842c20dd47b82e9915f1bd730ee1b0d46dJoe Onorato}
708