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 17 package com.android.commands.bmgr; 18 19 import android.app.backup.BackupManager; 20 import android.app.backup.BackupProgress; 21 import android.app.backup.BackupTransport; 22 import android.app.backup.IBackupManager; 23 import android.app.backup.IBackupObserver; 24 import android.app.backup.IRestoreObserver; 25 import android.app.backup.IRestoreSession; 26 import android.app.backup.ISelectBackupTransportCallback; 27 import android.app.backup.RestoreSet; 28 import android.content.ComponentName; 29 import android.content.pm.IPackageManager; 30 import android.content.pm.PackageInfo; 31 import android.os.RemoteException; 32 import android.os.ServiceManager; 33 import android.os.SystemClock; 34 import android.os.UserHandle; 35 import android.util.ArraySet; 36 37 import com.android.internal.annotations.GuardedBy; 38 39 import java.util.ArrayList; 40 import java.util.Arrays; 41 import java.util.HashSet; 42 import java.util.List; 43 import java.util.concurrent.CountDownLatch; 44 45 public final class Bmgr { 46 IBackupManager mBmgr; 47 IRestoreSession mRestore; 48 49 static final String BMGR_NOT_RUNNING_ERR = 50 "Error: Could not access the Backup Manager. Is the system running?"; 51 static final String TRANSPORT_NOT_RUNNING_ERR = 52 "Error: Could not access the backup transport. Is the system running?"; 53 static final String PM_NOT_RUNNING_ERR = 54 "Error: Could not access the Package Manager. Is the system running?"; 55 56 private String[] mArgs; 57 private int mNextArg; 58 59 public static void main(String[] args) { 60 try { 61 new Bmgr().run(args); 62 } catch (Exception e) { 63 System.err.println("Exception caught:"); 64 e.printStackTrace(); 65 } 66 } 67 68 public void run(String[] args) { 69 if (args.length < 1) { 70 showUsage(); 71 return; 72 } 73 74 mBmgr = IBackupManager.Stub.asInterface(ServiceManager.getService("backup")); 75 if (mBmgr == null) { 76 System.err.println(BMGR_NOT_RUNNING_ERR); 77 return; 78 } 79 80 mArgs = args; 81 String op = args[0]; 82 mNextArg = 1; 83 84 if ("enabled".equals(op)) { 85 doEnabled(); 86 return; 87 } 88 89 if ("enable".equals(op)) { 90 doEnable(); 91 return; 92 } 93 94 if ("run".equals(op)) { 95 doRun(); 96 return; 97 } 98 99 if ("backup".equals(op)) { 100 doBackup(); 101 return; 102 } 103 104 if ("init".equals(op)) { 105 doInit(); 106 return; 107 } 108 109 if ("list".equals(op)) { 110 doList(); 111 return; 112 } 113 114 if ("restore".equals(op)) { 115 doRestore(); 116 return; 117 } 118 119 if ("transport".equals(op)) { 120 doTransport(); 121 return; 122 } 123 124 if ("wipe".equals(op)) { 125 doWipe(); 126 return; 127 } 128 129 if ("fullbackup".equals(op)) { 130 doFullTransportBackup(); 131 return; 132 } 133 134 if ("backupnow".equals(op)) { 135 doBackupNow(); 136 return; 137 } 138 139 if ("cancel".equals(op)) { 140 doCancel(); 141 return; 142 } 143 144 if ("whitelist".equals(op)) { 145 doPrintWhitelist(); 146 return; 147 } 148 149 System.err.println("Unknown command"); 150 showUsage(); 151 } 152 153 private String enableToString(boolean enabled) { 154 return enabled ? "enabled" : "disabled"; 155 } 156 157 private void doEnabled() { 158 try { 159 boolean isEnabled = mBmgr.isBackupEnabled(); 160 System.out.println("Backup Manager currently " 161 + enableToString(isEnabled)); 162 } catch (RemoteException e) { 163 System.err.println(e.toString()); 164 System.err.println(BMGR_NOT_RUNNING_ERR); 165 } 166 } 167 168 private void doEnable() { 169 String arg = nextArg(); 170 if (arg == null) { 171 showUsage(); 172 return; 173 } 174 175 try { 176 boolean enable = Boolean.parseBoolean(arg); 177 mBmgr.setBackupEnabled(enable); 178 System.out.println("Backup Manager now " + enableToString(enable)); 179 } catch (NumberFormatException e) { 180 showUsage(); 181 return; 182 } catch (RemoteException e) { 183 System.err.println(e.toString()); 184 System.err.println(BMGR_NOT_RUNNING_ERR); 185 } 186 } 187 188 private void doRun() { 189 try { 190 mBmgr.backupNow(); 191 } catch (RemoteException e) { 192 System.err.println(e.toString()); 193 System.err.println(BMGR_NOT_RUNNING_ERR); 194 } 195 } 196 197 private void doBackup() { 198 String pkg = nextArg(); 199 if (pkg == null) { 200 showUsage(); 201 return; 202 } 203 204 try { 205 mBmgr.dataChanged(pkg); 206 } catch (RemoteException e) { 207 System.err.println(e.toString()); 208 System.err.println(BMGR_NOT_RUNNING_ERR); 209 } 210 } 211 212 private void doFullTransportBackup() { 213 System.out.println("Performing full transport backup"); 214 215 String pkg; 216 ArraySet<String> allPkgs = new ArraySet<String>(); 217 while ((pkg = nextArg()) != null) { 218 allPkgs.add(pkg); 219 } 220 if (allPkgs.size() > 0) { 221 try { 222 mBmgr.fullTransportBackup(allPkgs.toArray(new String[allPkgs.size()])); 223 } catch (RemoteException e) { 224 System.err.println(e.toString()); 225 System.err.println(BMGR_NOT_RUNNING_ERR); 226 } 227 } 228 } 229 230 // IBackupObserver generically usable for any backup/init operation 231 abstract class Observer extends IBackupObserver.Stub { 232 private final Object trigger = new Object(); 233 234 @GuardedBy("trigger") 235 private volatile boolean done = false; 236 237 @Override 238 public void onUpdate(String currentPackage, BackupProgress backupProgress) { 239 } 240 241 @Override 242 public void onResult(String currentPackage, int status) { 243 } 244 245 @Override 246 public void backupFinished(int status) { 247 synchronized (trigger) { 248 done = true; 249 trigger.notify(); 250 } 251 } 252 253 public boolean done() { 254 return this.done; 255 } 256 257 // Wait forever 258 public void waitForCompletion() { 259 waitForCompletion(0); 260 } 261 262 // Wait for a given time and then give up 263 public void waitForCompletion(long timeout) { 264 // The backupFinished() callback will throw the 'done' flag; we 265 // just sit and wait on that notification. 266 final long targetTime = SystemClock.elapsedRealtime() + timeout; 267 synchronized (trigger) { 268 // Wait until either we're done, or we've reached a stated positive timeout 269 while (!done && (timeout <= 0 || SystemClock.elapsedRealtime() < targetTime)) { 270 try { 271 trigger.wait(1000L); 272 } catch (InterruptedException ex) { 273 } 274 } 275 } 276 } 277 } 278 279 class BackupObserver extends Observer { 280 @Override 281 public void onUpdate(String currentPackage, BackupProgress backupProgress) { 282 super.onUpdate(currentPackage, backupProgress); 283 System.out.println( 284 "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred 285 + "/" + backupProgress.bytesExpected); 286 } 287 288 @Override 289 public void onResult(String currentPackage, int status) { 290 super.onResult(currentPackage, status); 291 System.out.println("Package " + currentPackage + " with result: " 292 + convertBackupStatusToString(status)); 293 } 294 295 @Override 296 public void backupFinished(int status) { 297 super.backupFinished(status); 298 System.out.println("Backup finished with result: " 299 + convertBackupStatusToString(status)); 300 if (status == BackupManager.ERROR_BACKUP_CANCELLED) { 301 System.out.println("Backups can be cancelled if a backup is already running, check " 302 + "backup dumpsys"); 303 } 304 } 305 } 306 307 private static String convertBackupStatusToString(int errorCode) { 308 switch (errorCode) { 309 case BackupManager.SUCCESS: 310 return "Success"; 311 case BackupManager.ERROR_BACKUP_NOT_ALLOWED: 312 return "Backup is not allowed"; 313 case BackupManager.ERROR_PACKAGE_NOT_FOUND: 314 return "Package not found"; 315 case BackupManager.ERROR_TRANSPORT_ABORTED: 316 return "Transport error"; 317 case BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED: 318 return "Transport rejected package because it wasn't able to process it" 319 + " at the time"; 320 case BackupManager.ERROR_AGENT_FAILURE: 321 return "Agent error"; 322 case BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED: 323 return "Size quota exceeded"; 324 case BackupManager.ERROR_BACKUP_CANCELLED: 325 return "Backup cancelled"; 326 default: 327 return "Unknown error"; 328 } 329 } 330 331 private void backupNowAllPackages(boolean nonIncrementalBackup) { 332 int userId = UserHandle.USER_SYSTEM; 333 IPackageManager mPm = 334 IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 335 if (mPm == null) { 336 System.err.println(PM_NOT_RUNNING_ERR); 337 return; 338 } 339 List<PackageInfo> installedPackages = null; 340 try { 341 installedPackages = mPm.getInstalledPackages(0, userId).getList(); 342 } catch (RemoteException e) { 343 System.err.println(e.toString()); 344 System.err.println(PM_NOT_RUNNING_ERR); 345 } 346 if (installedPackages != null) { 347 String[] packages = 348 installedPackages.stream().map(p -> p.packageName).toArray(String[]::new); 349 String[] filteredPackages = {}; 350 try { 351 filteredPackages = mBmgr.filterAppsEligibleForBackup(packages); 352 } catch (RemoteException e) { 353 System.err.println(e.toString()); 354 System.err.println(BMGR_NOT_RUNNING_ERR); 355 } 356 backupNowPackages(Arrays.asList(filteredPackages), nonIncrementalBackup); 357 } 358 } 359 360 private void backupNowPackages(List<String> packages, boolean nonIncrementalBackup) { 361 int flags = 0; 362 if (nonIncrementalBackup) { 363 flags |= BackupManager.FLAG_NON_INCREMENTAL_BACKUP; 364 } 365 try { 366 BackupObserver observer = new BackupObserver(); 367 // TODO: implement monitor here? 368 int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer, 369 null, flags); 370 if (err == 0) { 371 // Off and running -- wait for the backup to complete 372 observer.waitForCompletion(); 373 } else { 374 System.err.println("Unable to run backup"); 375 } 376 } catch (RemoteException e) { 377 System.err.println(e.toString()); 378 System.err.println(BMGR_NOT_RUNNING_ERR); 379 } 380 } 381 382 private void doBackupNow() { 383 String pkg; 384 boolean backupAll = false; 385 boolean nonIncrementalBackup = false; 386 ArrayList<String> allPkgs = new ArrayList<String>(); 387 while ((pkg = nextArg()) != null) { 388 if (pkg.equals("--all")) { 389 backupAll = true; 390 } else if (pkg.equals("--non-incremental")) { 391 nonIncrementalBackup = true; 392 } else if (pkg.equals("--incremental")) { 393 nonIncrementalBackup = false; 394 } else { 395 if (!allPkgs.contains(pkg)) { 396 allPkgs.add(pkg); 397 } 398 } 399 } 400 if (backupAll) { 401 if (allPkgs.size() == 0) { 402 System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") + 403 "incremental backup for all packages."); 404 backupNowAllPackages(nonIncrementalBackup); 405 } else { 406 System.err.println("Provide only '--all' flag or list of packages."); 407 } 408 } else if (allPkgs.size() > 0) { 409 System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") + 410 "incremental backup for " + allPkgs.size() +" requested packages."); 411 backupNowPackages(allPkgs, nonIncrementalBackup); 412 } else { 413 System.err.println("Provide '--all' flag or list of packages."); 414 } 415 } 416 417 private void doCancel() { 418 String arg = nextArg(); 419 if ("backups".equals(arg)) { 420 try { 421 mBmgr.cancelBackups(); 422 } catch (RemoteException e) { 423 System.err.println(e.toString()); 424 System.err.println(BMGR_NOT_RUNNING_ERR); 425 } 426 return; 427 } 428 429 System.err.println("Unknown command."); 430 } 431 432 private void doTransport() { 433 try { 434 String which = nextArg(); 435 if (which == null) { 436 showUsage(); 437 return; 438 } 439 440 if ("-c".equals(which)) { 441 doTransportByComponent(); 442 return; 443 } 444 445 String old = mBmgr.selectBackupTransport(which); 446 if (old == null) { 447 System.out.println("Unknown transport '" + which 448 + "' specified; no changes made."); 449 } else { 450 System.out.println("Selected transport " + which + " (formerly " + old + ")"); 451 } 452 453 } catch (RemoteException e) { 454 System.err.println(e.toString()); 455 System.err.println(BMGR_NOT_RUNNING_ERR); 456 } 457 } 458 459 private void doTransportByComponent() { 460 String which = nextArg(); 461 if (which == null) { 462 showUsage(); 463 return; 464 } 465 466 final CountDownLatch latch = new CountDownLatch(1); 467 468 try { 469 mBmgr.selectBackupTransportAsync(ComponentName.unflattenFromString(which), 470 new ISelectBackupTransportCallback.Stub() { 471 @Override 472 public void onSuccess(String transportName) { 473 System.out.println("Success. Selected transport: " + transportName); 474 latch.countDown(); 475 } 476 477 @Override 478 public void onFailure(int reason) { 479 System.err.println("Failure. error=" + reason); 480 latch.countDown(); 481 } 482 }); 483 } catch (RemoteException e) { 484 System.err.println(e.toString()); 485 System.err.println(BMGR_NOT_RUNNING_ERR); 486 return; 487 } 488 489 try { 490 latch.await(); 491 } catch (InterruptedException e) { 492 System.err.println("Operation interrupted."); 493 } 494 } 495 496 private void doWipe() { 497 String transport = nextArg(); 498 if (transport == null) { 499 showUsage(); 500 return; 501 } 502 503 String pkg = nextArg(); 504 if (pkg == null) { 505 showUsage(); 506 return; 507 } 508 509 try { 510 mBmgr.clearBackupData(transport, pkg); 511 System.out.println("Wiped backup data for " + pkg + " on " + transport); 512 } catch (RemoteException e) { 513 System.err.println(e.toString()); 514 System.err.println(BMGR_NOT_RUNNING_ERR); 515 } 516 } 517 518 class InitObserver extends Observer { 519 public int result = BackupTransport.TRANSPORT_ERROR; 520 521 @Override 522 public void backupFinished(int status) { 523 super.backupFinished(status); 524 result = status; 525 } 526 } 527 528 private void doInit() { 529 ArraySet<String> transports = new ArraySet<>(); 530 String transport; 531 while ((transport = nextArg()) != null) { 532 transports.add(transport); 533 } 534 if (transports.size() == 0) { 535 showUsage(); 536 return; 537 } 538 539 InitObserver observer = new InitObserver(); 540 try { 541 System.out.println("Initializing transports: " + transports); 542 mBmgr.initializeTransports(transports.toArray(new String[transports.size()]), observer); 543 observer.waitForCompletion(30*1000L); 544 System.out.println("Initialization result: " + observer.result); 545 } catch (RemoteException e) { 546 System.err.println(e.toString()); 547 System.err.println(BMGR_NOT_RUNNING_ERR); 548 } 549 } 550 551 private void doList() { 552 String arg = nextArg(); // sets, transports, packages set# 553 if ("transports".equals(arg)) { 554 doListTransports(); 555 return; 556 } 557 558 // The rest of the 'list' options work with a restore session on the current transport 559 try { 560 mRestore = mBmgr.beginRestoreSession(null, null); 561 if (mRestore == null) { 562 System.err.println(BMGR_NOT_RUNNING_ERR); 563 return; 564 } 565 566 if ("sets".equals(arg)) { 567 doListRestoreSets(); 568 } else if ("transports".equals(arg)) { 569 doListTransports(); 570 } 571 572 mRestore.endRestoreSession(); 573 } catch (RemoteException e) { 574 System.err.println(e.toString()); 575 System.err.println(BMGR_NOT_RUNNING_ERR); 576 } 577 } 578 579 private void doListTransports() { 580 String arg = nextArg(); 581 582 try { 583 if ("-c".equals(arg)) { 584 for (ComponentName transport : mBmgr.listAllTransportComponents()) { 585 System.out.println(transport.flattenToShortString()); 586 } 587 return; 588 } 589 590 String current = mBmgr.getCurrentTransport(); 591 String[] transports = mBmgr.listAllTransports(); 592 if (transports == null || transports.length == 0) { 593 System.out.println("No transports available."); 594 return; 595 } 596 597 for (String t : transports) { 598 String pad = (t.equals(current)) ? " * " : " "; 599 System.out.println(pad + t); 600 } 601 } catch (RemoteException e) { 602 System.err.println(e.toString()); 603 System.err.println(BMGR_NOT_RUNNING_ERR); 604 } 605 } 606 607 private void doListRestoreSets() { 608 try { 609 RestoreObserver observer = new RestoreObserver(); 610 // TODO implement monitor here 611 int err = mRestore.getAvailableRestoreSets(observer, null); 612 if (err != 0) { 613 System.out.println("Unable to request restore sets"); 614 } else { 615 observer.waitForCompletion(); 616 printRestoreSets(observer.sets); 617 } 618 } catch (RemoteException e) { 619 System.err.println(e.toString()); 620 System.err.println(TRANSPORT_NOT_RUNNING_ERR); 621 } 622 } 623 624 private void printRestoreSets(RestoreSet[] sets) { 625 if (sets == null || sets.length == 0) { 626 System.out.println("No restore sets"); 627 return; 628 } 629 for (RestoreSet s : sets) { 630 System.out.println(" " + Long.toHexString(s.token) + " : " + s.name); 631 } 632 } 633 634 class RestoreObserver extends IRestoreObserver.Stub { 635 boolean done; 636 RestoreSet[] sets = null; 637 638 public void restoreSetsAvailable(RestoreSet[] result) { 639 synchronized (this) { 640 sets = result; 641 done = true; 642 this.notify(); 643 } 644 } 645 646 public void restoreStarting(int numPackages) { 647 System.out.println("restoreStarting: " + numPackages + " packages"); 648 } 649 650 public void onUpdate(int nowBeingRestored, String currentPackage) { 651 System.out.println("onUpdate: " + nowBeingRestored + " = " + currentPackage); 652 } 653 654 public void restoreFinished(int error) { 655 System.out.println("restoreFinished: " + error); 656 synchronized (this) { 657 done = true; 658 this.notify(); 659 } 660 } 661 662 /** 663 * Wait until either {@link #restoreFinished} or {@link #restoreStarting} is called. 664 * Once one is called, it clears the internal flag again, so that the same observer intance 665 * can be reused for a next operation. 666 */ 667 public void waitForCompletion() { 668 // The restoreFinished() callback will throw the 'done' flag; we 669 // just sit and wait on that notification. 670 synchronized (this) { 671 while (!this.done) { 672 try { 673 this.wait(); 674 } catch (InterruptedException ex) { 675 } 676 } 677 done = false; 678 } 679 } 680 } 681 682 private void doRestore() { 683 String arg = nextArg(); 684 if (arg == null) { 685 showUsage(); 686 return; 687 } 688 689 if (arg.indexOf('.') >= 0 || arg.equals("android")) { 690 // it's a package name 691 doRestorePackage(arg); 692 } else { 693 try { 694 long token = Long.parseLong(arg, 16); 695 HashSet<String> filter = null; 696 while ((arg = nextArg()) != null) { 697 if (filter == null) filter = new HashSet<String>(); 698 filter.add(arg); 699 } 700 701 doRestoreAll(token, filter); 702 } catch (NumberFormatException e) { 703 showUsage(); 704 return; 705 } 706 } 707 708 System.out.println("done"); 709 } 710 711 private void doRestorePackage(String pkg) { 712 try { 713 mRestore = mBmgr.beginRestoreSession(pkg, null); 714 if (mRestore == null) { 715 System.err.println(BMGR_NOT_RUNNING_ERR); 716 return; 717 } 718 719 RestoreObserver observer = new RestoreObserver(); 720 // TODO implement monitor here 721 int err = mRestore.restorePackage(pkg, observer, null ); 722 if (err == 0) { 723 // Off and running -- wait for the restore to complete 724 observer.waitForCompletion(); 725 } else { 726 System.err.println("Unable to restore package " + pkg); 727 } 728 729 // And finally shut down the session 730 mRestore.endRestoreSession(); 731 } catch (RemoteException e) { 732 System.err.println(e.toString()); 733 System.err.println(BMGR_NOT_RUNNING_ERR); 734 } 735 } 736 737 private void doRestoreAll(long token, HashSet<String> filter) { 738 RestoreObserver observer = new RestoreObserver(); 739 740 try { 741 boolean didRestore = false; 742 mRestore = mBmgr.beginRestoreSession(null, null); 743 if (mRestore == null) { 744 System.err.println(BMGR_NOT_RUNNING_ERR); 745 return; 746 } 747 RestoreSet[] sets = null; 748 // TODO implement monitor here 749 int err = mRestore.getAvailableRestoreSets(observer, null); 750 if (err == 0) { 751 observer.waitForCompletion(); 752 sets = observer.sets; 753 if (sets != null) { 754 for (RestoreSet s : sets) { 755 if (s.token == token) { 756 System.out.println("Scheduling restore: " + s.name); 757 if (filter == null) { 758 didRestore = (mRestore.restoreAll(token, observer, null) == 0); 759 } else { 760 String[] names = new String[filter.size()]; 761 filter.toArray(names); 762 didRestore = (mRestore.restoreSome(token, observer, 763 null, names) == 0); 764 } 765 break; 766 } 767 } 768 } 769 } 770 if (!didRestore) { 771 if (sets == null || sets.length == 0) { 772 System.out.println("No available restore sets; no restore performed"); 773 } else { 774 System.out.println("No matching restore set token. Available sets:"); 775 printRestoreSets(sets); 776 } 777 } 778 779 // if we kicked off a restore successfully, we have to wait for it 780 // to complete before we can shut down the restore session safely 781 if (didRestore) { 782 observer.waitForCompletion(); 783 } 784 785 // once the restore has finished, close down the session and we're done 786 mRestore.endRestoreSession(); 787 } catch (RemoteException e) { 788 System.err.println(e.toString()); 789 System.err.println(BMGR_NOT_RUNNING_ERR); 790 } 791 } 792 793 private void doPrintWhitelist() { 794 try { 795 final String[] whitelist = mBmgr.getTransportWhitelist(); 796 if (whitelist != null) { 797 for (String transport : whitelist) { 798 System.out.println(transport); 799 } 800 } 801 } catch (RemoteException e) { 802 System.err.println(e.toString()); 803 System.err.println(BMGR_NOT_RUNNING_ERR); 804 } 805 } 806 807 private String nextArg() { 808 if (mNextArg >= mArgs.length) { 809 return null; 810 } 811 String arg = mArgs[mNextArg]; 812 mNextArg++; 813 return arg; 814 } 815 816 private static void showUsage() { 817 System.err.println("usage: bmgr [backup|restore|list|transport|run]"); 818 System.err.println(" bmgr backup PACKAGE"); 819 System.err.println(" bmgr enable BOOL"); 820 System.err.println(" bmgr enabled"); 821 System.err.println(" bmgr list transports [-c]"); 822 System.err.println(" bmgr list sets"); 823 System.err.println(" bmgr transport WHICH|-c WHICH_COMPONENT"); 824 System.err.println(" bmgr restore TOKEN"); 825 System.err.println(" bmgr restore TOKEN PACKAGE..."); 826 System.err.println(" bmgr restore PACKAGE"); 827 System.err.println(" bmgr run"); 828 System.err.println(" bmgr wipe TRANSPORT PACKAGE"); 829 System.err.println(" bmgr fullbackup PACKAGE..."); 830 System.err.println(" bmgr backupnow --all|PACKAGE..."); 831 System.err.println(" bmgr cancel backups"); 832 System.err.println(""); 833 System.err.println("The 'backup' command schedules a backup pass for the named package."); 834 System.err.println("Note that the backup pass will effectively be a no-op if the package"); 835 System.err.println("does not actually have changed data to store."); 836 System.err.println(""); 837 System.err.println("The 'enable' command enables or disables the entire backup mechanism."); 838 System.err.println("If the argument is 'true' it will be enabled, otherwise it will be"); 839 System.err.println("disabled. When disabled, neither backup or restore operations will"); 840 System.err.println("be performed."); 841 System.err.println(""); 842 System.err.println("The 'enabled' command reports the current enabled/disabled state of"); 843 System.err.println("the backup mechanism."); 844 System.err.println(""); 845 System.err.println("The 'list transports' command reports the names of the backup transports"); 846 System.err.println("BackupManager is currently bound to. These names can be passed as arguments"); 847 System.err.println("to the 'transport' and 'wipe' commands. The currently active transport"); 848 System.err.println("is indicated with a '*' character. If -c flag is used, all available"); 849 System.err.println("transport components on the device are listed. These can be used with"); 850 System.err.println("the component variant of 'transport' command."); 851 System.err.println(""); 852 System.err.println("The 'list sets' command reports the token and name of each restore set"); 853 System.err.println("available to the device via the currently active transport."); 854 System.err.println(""); 855 System.err.println("The 'transport' command designates the named transport as the currently"); 856 System.err.println("active one. This setting is persistent across reboots. If -c flag is"); 857 System.err.println("specified, the following string is treated as a component name."); 858 System.err.println(""); 859 System.err.println("The 'restore' command when given just a restore token initiates a full-system"); 860 System.err.println("restore operation from the currently active transport. It will deliver"); 861 System.err.println("the restore set designated by the TOKEN argument to each application"); 862 System.err.println("that had contributed data to that restore set."); 863 System.err.println(""); 864 System.err.println("The 'restore' command when given a token and one or more package names"); 865 System.err.println("initiates a restore operation of just those given packages from the restore"); 866 System.err.println("set designated by the TOKEN argument. It is effectively the same as the"); 867 System.err.println("'restore' operation supplying only a token, but applies a filter to the"); 868 System.err.println("set of applications to be restored."); 869 System.err.println(""); 870 System.err.println("The 'restore' command when given just a package name intiates a restore of"); 871 System.err.println("just that one package according to the restore set selection algorithm"); 872 System.err.println("used by the RestoreSession.restorePackage() method."); 873 System.err.println(""); 874 System.err.println("The 'run' command causes any scheduled backup operation to be initiated"); 875 System.err.println("immediately, without the usual waiting period for batching together"); 876 System.err.println("data changes."); 877 System.err.println(""); 878 System.err.println("The 'wipe' command causes all backed-up data for the given package to be"); 879 System.err.println("erased from the given transport's storage. The next backup operation"); 880 System.err.println("that the given application performs will rewrite its entire data set."); 881 System.err.println("Transport names to use here are those reported by 'list transports'."); 882 System.err.println(""); 883 System.err.println("The 'fullbackup' command induces a full-data stream backup for one or more"); 884 System.err.println("packages. The data is sent via the currently active transport."); 885 System.err.println(""); 886 System.err.println("The 'backupnow' command runs an immediate backup for one or more packages."); 887 System.err.println(" --all flag runs backup for all eligible packages."); 888 System.err.println("For each package it will run key/value or full data backup "); 889 System.err.println("depending on the package's manifest declarations."); 890 System.err.println("The data is sent via the currently active transport."); 891 System.err.println("The 'cancel backups' command cancels all running backups."); 892 } 893 } 894