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