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