Bmgr.java revision 9171749700853305f3e6abbcdbd9e02f3a71d459
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.commands.bmgr;
18
19import android.backup.IBackupManager;
20import android.backup.IRestoreObserver;
21import android.backup.IRestoreSession;
22import android.backup.RestoreSet;
23import android.os.RemoteException;
24import android.os.ServiceManager;
25
26public final class Bmgr {
27    IBackupManager mBmgr;
28    IRestoreSession mRestore;
29
30    static final String BMGR_NOT_RUNNING_ERR =
31            "Error: Could not access the Backup Manager.  Is the system running?";
32    static final String TRANSPORT_NOT_RUNNING_ERR =
33        "Error: Could not access the backup transport.  Is the system running?";
34
35    private String[] mArgs;
36    private int mNextArg;
37    private String mCurArgData;
38
39    public static void main(String[] args) {
40        try {
41            new Bmgr().run(args);
42        } catch (Exception e) {
43            System.err.println("Exception caught:");
44            e.printStackTrace();
45        }
46    }
47
48    public void run(String[] args) {
49        boolean validCommand = false;
50        if (args.length < 1) {
51            showUsage();
52            return;
53        }
54
55        mBmgr = IBackupManager.Stub.asInterface(ServiceManager.getService("backup"));
56        if (mBmgr == null) {
57            System.err.println(BMGR_NOT_RUNNING_ERR);
58            return;
59        }
60
61        mArgs = args;
62        String op = args[0];
63        mNextArg = 1;
64
65        if ("run".equals(op)) {
66            doRun();
67            return;
68        }
69
70        if ("backup".equals(op)) {
71            doBackup();
72            return;
73        }
74
75        if ("list".equals(op)) {
76            doList();
77            return;
78        }
79
80        if ("restore".equals(op)) {
81            doRestore();
82            return;
83        }
84
85        if ("transport".equals(op)) {
86            doTransport();
87            return;
88        }
89
90        System.err.println("Unknown command");
91        showUsage();
92    }
93
94    private void doRun() {
95        try {
96            mBmgr.backupNow();
97        } catch (RemoteException e) {
98            System.err.println(e.toString());
99            System.err.println(BMGR_NOT_RUNNING_ERR);
100        }
101    }
102
103    private void doBackup() {
104        boolean isFull = false;
105        String pkg = nextArg();
106        if ("-f".equals(pkg)) {
107            isFull = true;
108            pkg = nextArg();
109        }
110
111        if (pkg == null || pkg.startsWith("-")) {
112            showUsage();
113            return;
114        }
115
116        try {
117            // !!! TODO: handle full backup
118            mBmgr.dataChanged(pkg);
119        } catch (RemoteException e) {
120            System.err.println(e.toString());
121            System.err.println(BMGR_NOT_RUNNING_ERR);
122        }
123    }
124
125    private void doTransport() {
126        try {
127            String which = nextArg();
128            String old = mBmgr.selectBackupTransport(which);
129            if (old == null) {
130                System.out.println("Unknown transport '" + which
131                        + "' specified; no changes made.");
132            } else {
133                System.out.println("Selected transport " + which + " (formerly " + old + ")");
134            }
135        } catch (RemoteException e) {
136            System.err.println(e.toString());
137            System.err.println(BMGR_NOT_RUNNING_ERR);
138        }
139    }
140
141    private void doList() {
142        String arg = nextArg();     // sets, transports, packages set#
143        if ("transports".equals(arg)) {
144            doListTransports();
145            return;
146        }
147
148        // The rest of the 'list' options work with a restore session on the current transport
149        try {
150            String curTransport = mBmgr.getCurrentTransport();
151            mRestore = mBmgr.beginRestoreSession(curTransport);
152            if (mRestore == null) {
153                System.err.println(BMGR_NOT_RUNNING_ERR);
154                return;
155            }
156
157            if ("sets".equals(arg)) {
158                doListRestoreSets();
159            } else if ("transports".equals(arg)) {
160                doListTransports();
161            }
162
163            mRestore.endRestoreSession();
164        } catch (RemoteException e) {
165            System.err.println(e.toString());
166            System.err.println(BMGR_NOT_RUNNING_ERR);
167        }
168    }
169
170    private void doListTransports() {
171        try {
172            String current = mBmgr.getCurrentTransport();
173            String[] transports = mBmgr.listAllTransports();
174            if (transports == null || transports.length == 0) {
175                System.out.println("No transports available.");
176                return;
177            }
178
179            for (String t : transports) {
180                String pad = (t.equals(current)) ? "  * " : "    ";
181                System.out.println(pad + t);
182            }
183        } catch (RemoteException e) {
184            System.err.println(e.toString());
185            System.err.println(BMGR_NOT_RUNNING_ERR);
186        }
187    }
188
189    private void doListRestoreSets() {
190        try {
191            RestoreSet[] sets = mRestore.getAvailableRestoreSets();
192            if (sets == null || sets.length == 0) {
193                System.out.println("No restore sets available");
194            } else {
195                printRestoreSets(sets);
196            }
197        } catch (RemoteException e) {
198            System.err.println(e.toString());
199            System.err.println(TRANSPORT_NOT_RUNNING_ERR);
200        }
201    }
202
203    private void printRestoreSets(RestoreSet[] sets) {
204        for (RestoreSet s : sets) {
205            System.out.println("  " + s.token + " : " + s.name);
206        }
207    }
208
209    class RestoreObserver extends IRestoreObserver.Stub {
210        boolean done;
211        public void restoreStarting(int numPackages) {
212            System.out.println("restoreStarting: " + numPackages + " packages");
213        }
214
215        public void onUpdate(int nowBeingRestored) {
216            System.out.println("onUpdate: " + nowBeingRestored);
217        }
218
219        public void restoreFinished(int error) {
220            System.out.println("restoreFinished: " + error);
221            synchronized (this) {
222                done = true;
223                this.notify();
224            }
225        }
226    }
227
228    private void doRestore() {
229        long token;
230        try {
231            token = Long.parseLong(nextArg());
232        } catch (NumberFormatException e) {
233            showUsage();
234            return;
235        }
236
237        RestoreObserver observer = new RestoreObserver();
238
239        try {
240            boolean didRestore = false;
241            String curTransport = mBmgr.getCurrentTransport();
242            mRestore = mBmgr.beginRestoreSession(curTransport);
243            if (mRestore == null) {
244                System.err.println(BMGR_NOT_RUNNING_ERR);
245                return;
246            }
247            RestoreSet[] sets = mRestore.getAvailableRestoreSets();
248            for (RestoreSet s : sets) {
249                if (s.token == token) {
250                    System.out.println("Scheduling restore: " + s.name);
251                    mRestore.performRestore(token, observer);
252                    didRestore = true;
253                    break;
254                }
255            }
256            if (!didRestore) {
257                if (sets == null || sets.length == 0) {
258                    System.out.println("No available restore sets; no restore performed");
259                } else {
260                    System.out.println("No matching restore set token.  Available sets:");
261                    printRestoreSets(sets);
262                }
263            }
264            mRestore.endRestoreSession();
265        } catch (RemoteException e) {
266            System.err.println(e.toString());
267            System.err.println(BMGR_NOT_RUNNING_ERR);
268        }
269
270        // now wait for it to be done
271        synchronized (observer) {
272            while (!observer.done) {
273                try {
274                    observer.wait();
275                } catch (InterruptedException ex) {
276                }
277            }
278        }
279        System.out.println("done");
280    }
281
282    private String nextArg() {
283        if (mNextArg >= mArgs.length) {
284            return null;
285        }
286        String arg = mArgs[mNextArg];
287        mNextArg++;
288        return arg;
289    }
290
291    private static void showUsage() {
292        System.err.println("usage: bmgr [backup|restore|list|transport|run]");
293        System.err.println("       bmgr backup PACKAGE");
294        System.err.println("       bmgr list transports");
295        System.err.println("       bmgr list sets");
296        System.err.println("       bmgr transport WHICH");
297        System.err.println("       bmgr restore TOKEN");
298        System.err.println("       bmgr run");
299        System.err.println("");
300        System.err.println("The 'backup' command schedules a backup pass for the named package.");
301        System.err.println("Note that the backup pass will effectively be a no-op if the package");
302        System.err.println("does not actually have changed data to store.");
303        System.err.println("");
304        System.err.println("The 'list transports' command reports the names of the backup transports");
305        System.err.println("currently available on the device.  These names can be passed as arguments");
306        System.err.println("to the 'transport' command.  The currently selected transport is indicated");
307        System.err.println("with a '*' character.");
308        System.err.println("");
309        System.err.println("The 'list sets' command reports the token and name of each restore set");
310        System.err.println("available to the device via the current transport.");
311        System.err.println("");
312        System.err.println("The 'transport' command designates the named transport as the currently");
313        System.err.println("active one.  This setting is persistent across reboots.");
314        System.err.println("");
315        System.err.println("The 'restore' command initiates a restore operation, using the restore set");
316        System.err.println("from the current transport whose token matches the argument.");
317        System.err.println("");
318        System.err.println("The 'run' command causes any scheduled backup operation to be initiated");
319        System.err.println("immediately, without the usual waiting period for batching together");
320        System.err.println("data changes.");
321    }
322}
323