Bmgr.java revision 6ef58a1509b9d3348a33ca5686917796c2759aa5
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 ("enabled".equals(op)) {
66            doEnabled();
67            return;
68        }
69
70        if ("enable".equals(op)) {
71            doEnable();
72            return;
73        }
74
75        if ("run".equals(op)) {
76            doRun();
77            return;
78        }
79
80        if ("backup".equals(op)) {
81            doBackup();
82            return;
83        }
84
85        if ("list".equals(op)) {
86            doList();
87            return;
88        }
89
90        if ("restore".equals(op)) {
91            doRestore();
92            return;
93        }
94
95        if ("transport".equals(op)) {
96            doTransport();
97            return;
98        }
99
100        System.err.println("Unknown command");
101        showUsage();
102    }
103
104    private String enableToString(boolean enabled) {
105        return enabled ? "enabled" : "disabled";
106    }
107
108    private void doEnabled() {
109        try {
110            boolean isEnabled = mBmgr.isBackupEnabled();
111            System.out.println("Backup Manager currently "
112                    + enableToString(isEnabled));
113        } catch (RemoteException e) {
114            System.err.println(e.toString());
115            System.err.println(BMGR_NOT_RUNNING_ERR);
116        }
117    }
118
119    private void doEnable() {
120        String arg = nextArg();
121        if (arg == null) {
122            showUsage();
123            return;
124        }
125
126        try {
127            boolean enable = Boolean.parseBoolean(arg);
128            mBmgr.setBackupEnabled(enable);
129            System.out.println("Backup Manager now " + enableToString(enable));
130        } catch (NumberFormatException e) {
131            showUsage();
132            return;
133        } catch (RemoteException e) {
134            System.err.println(e.toString());
135            System.err.println(BMGR_NOT_RUNNING_ERR);
136        }
137    }
138
139    private void doRun() {
140        try {
141            mBmgr.backupNow();
142        } catch (RemoteException e) {
143            System.err.println(e.toString());
144            System.err.println(BMGR_NOT_RUNNING_ERR);
145        }
146    }
147
148    private void doBackup() {
149        boolean isFull = false;
150        String pkg = nextArg();
151        if ("-f".equals(pkg)) {
152            isFull = true;
153            pkg = nextArg();
154        }
155
156        if (pkg == null || pkg.startsWith("-")) {
157            showUsage();
158            return;
159        }
160
161        try {
162            // !!! TODO: handle full backup
163            mBmgr.dataChanged(pkg);
164        } catch (RemoteException e) {
165            System.err.println(e.toString());
166            System.err.println(BMGR_NOT_RUNNING_ERR);
167        }
168    }
169
170    private void doTransport() {
171        try {
172            String which = nextArg();
173            String old = mBmgr.selectBackupTransport(which);
174            if (old == null) {
175                System.out.println("Unknown transport '" + which
176                        + "' specified; no changes made.");
177            } else {
178                System.out.println("Selected transport " + which + " (formerly " + old + ")");
179            }
180        } catch (RemoteException e) {
181            System.err.println(e.toString());
182            System.err.println(BMGR_NOT_RUNNING_ERR);
183        }
184    }
185
186    private void doList() {
187        String arg = nextArg();     // sets, transports, packages set#
188        if ("transports".equals(arg)) {
189            doListTransports();
190            return;
191        }
192
193        // The rest of the 'list' options work with a restore session on the current transport
194        try {
195            String curTransport = mBmgr.getCurrentTransport();
196            mRestore = mBmgr.beginRestoreSession(curTransport);
197            if (mRestore == null) {
198                System.err.println(BMGR_NOT_RUNNING_ERR);
199                return;
200            }
201
202            if ("sets".equals(arg)) {
203                doListRestoreSets();
204            } else if ("transports".equals(arg)) {
205                doListTransports();
206            }
207
208            mRestore.endRestoreSession();
209        } catch (RemoteException e) {
210            System.err.println(e.toString());
211            System.err.println(BMGR_NOT_RUNNING_ERR);
212        }
213    }
214
215    private void doListTransports() {
216        try {
217            String current = mBmgr.getCurrentTransport();
218            String[] transports = mBmgr.listAllTransports();
219            if (transports == null || transports.length == 0) {
220                System.out.println("No transports available.");
221                return;
222            }
223
224            for (String t : transports) {
225                String pad = (t.equals(current)) ? "  * " : "    ";
226                System.out.println(pad + t);
227            }
228        } catch (RemoteException e) {
229            System.err.println(e.toString());
230            System.err.println(BMGR_NOT_RUNNING_ERR);
231        }
232    }
233
234    private void doListRestoreSets() {
235        try {
236            RestoreSet[] sets = mRestore.getAvailableRestoreSets();
237            if (sets == null || sets.length == 0) {
238                System.out.println("No restore sets available");
239            } else {
240                printRestoreSets(sets);
241            }
242        } catch (RemoteException e) {
243            System.err.println(e.toString());
244            System.err.println(TRANSPORT_NOT_RUNNING_ERR);
245        }
246    }
247
248    private void printRestoreSets(RestoreSet[] sets) {
249        for (RestoreSet s : sets) {
250            System.out.println("  " + s.token + " : " + s.name);
251        }
252    }
253
254    class RestoreObserver extends IRestoreObserver.Stub {
255        boolean done;
256        public void restoreStarting(int numPackages) {
257            System.out.println("restoreStarting: " + numPackages + " packages");
258        }
259
260        public void onUpdate(int nowBeingRestored) {
261            System.out.println("onUpdate: " + nowBeingRestored);
262        }
263
264        public void restoreFinished(int error) {
265            System.out.println("restoreFinished: " + error);
266            synchronized (this) {
267                done = true;
268                this.notify();
269            }
270        }
271    }
272
273    private void doRestore() {
274        long token;
275        try {
276            token = Long.parseLong(nextArg());
277        } catch (NumberFormatException e) {
278            showUsage();
279            return;
280        }
281
282        RestoreObserver observer = new RestoreObserver();
283
284        try {
285            boolean didRestore = false;
286            String curTransport = mBmgr.getCurrentTransport();
287            mRestore = mBmgr.beginRestoreSession(curTransport);
288            if (mRestore == null) {
289                System.err.println(BMGR_NOT_RUNNING_ERR);
290                return;
291            }
292            RestoreSet[] sets = mRestore.getAvailableRestoreSets();
293            for (RestoreSet s : sets) {
294                if (s.token == token) {
295                    System.out.println("Scheduling restore: " + s.name);
296                    mRestore.performRestore(token, observer);
297                    didRestore = true;
298                    break;
299                }
300            }
301            if (!didRestore) {
302                if (sets == null || sets.length == 0) {
303                    System.out.println("No available restore sets; no restore performed");
304                } else {
305                    System.out.println("No matching restore set token.  Available sets:");
306                    printRestoreSets(sets);
307                }
308            }
309            mRestore.endRestoreSession();
310        } catch (RemoteException e) {
311            System.err.println(e.toString());
312            System.err.println(BMGR_NOT_RUNNING_ERR);
313        }
314
315        // now wait for it to be done
316        synchronized (observer) {
317            while (!observer.done) {
318                try {
319                    observer.wait();
320                } catch (InterruptedException ex) {
321                }
322            }
323        }
324        System.out.println("done");
325    }
326
327    private String nextArg() {
328        if (mNextArg >= mArgs.length) {
329            return null;
330        }
331        String arg = mArgs[mNextArg];
332        mNextArg++;
333        return arg;
334    }
335
336    private static void showUsage() {
337        System.err.println("usage: bmgr [backup|restore|list|transport|run]");
338        System.err.println("       bmgr backup PACKAGE");
339        System.err.println("       bmgr enable BOOL");
340        System.err.println("       bmgr enabled");
341        System.err.println("       bmgr list transports");
342        System.err.println("       bmgr list sets");
343        System.err.println("       bmgr transport WHICH");
344        System.err.println("       bmgr restore TOKEN");
345        System.err.println("       bmgr run");
346        System.err.println("");
347        System.err.println("The 'backup' command schedules a backup pass for the named package.");
348        System.err.println("Note that the backup pass will effectively be a no-op if the package");
349        System.err.println("does not actually have changed data to store.");
350        System.err.println("");
351        System.err.println("The 'enable' command enables or disables the entire backup mechanism.");
352        System.err.println("If the argument is 'true' it will be enabled, otherwise it will be");
353        System.err.println("disabled.  When disabled, neither backup or restore operations will");
354        System.err.println("be performed.");
355        System.err.println("");
356        System.err.println("The 'enabled' command reports the current enabled/disabled state of");
357        System.err.println("the backup mechanism.");
358        System.err.println("");
359        System.err.println("The 'list transports' command reports the names of the backup transports");
360        System.err.println("currently available on the device.  These names can be passed as arguments");
361        System.err.println("to the 'transport' command.  The currently selected transport is indicated");
362        System.err.println("with a '*' character.");
363        System.err.println("");
364        System.err.println("The 'list sets' command reports the token and name of each restore set");
365        System.err.println("available to the device via the current transport.");
366        System.err.println("");
367        System.err.println("The 'transport' command designates the named transport as the currently");
368        System.err.println("active one.  This setting is persistent across reboots.");
369        System.err.println("");
370        System.err.println("The 'restore' command initiates a restore operation, using the restore set");
371        System.err.println("from the current transport whose token matches the argument.");
372        System.err.println("");
373        System.err.println("The 'run' command causes any scheduled backup operation to be initiated");
374        System.err.println("immediately, without the usual waiting period for batching together");
375        System.err.println("data changes.");
376    }
377}
378