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.annotation.IntDef; 20 import android.annotation.UserIdInt; 21 import android.app.backup.BackupManager; 22 import android.app.backup.BackupManagerMonitor; 23 import android.app.backup.BackupProgress; 24 import android.app.backup.BackupTransport; 25 import android.app.backup.IBackupManager; 26 import android.app.backup.IBackupManagerMonitor; 27 import android.app.backup.IBackupObserver; 28 import android.app.backup.IRestoreObserver; 29 import android.app.backup.IRestoreSession; 30 import android.app.backup.ISelectBackupTransportCallback; 31 import android.app.backup.RestoreSet; 32 import android.content.ComponentName; 33 import android.content.Context; 34 import android.content.pm.IPackageManager; 35 import android.content.pm.PackageInfo; 36 import android.os.Bundle; 37 import android.os.RemoteException; 38 import android.os.ServiceManager; 39 import android.os.SystemClock; 40 import android.os.UserHandle; 41 import android.util.ArraySet; 42 import android.util.Slog; 43 44 import com.android.internal.annotations.GuardedBy; 45 import com.android.internal.annotations.VisibleForTesting; 46 47 import java.lang.annotation.Retention; 48 import java.lang.annotation.RetentionPolicy; 49 import java.util.ArrayList; 50 import java.util.Arrays; 51 import java.util.HashSet; 52 import java.util.List; 53 import java.util.Set; 54 import java.util.concurrent.CountDownLatch; 55 56 /** 57 * Adb shell command for {@link android.app.backup.IBackupManager}. 58 */ 59 public class Bmgr { 60 public static final String TAG = "Bmgr"; 61 62 private final IBackupManager mBmgr; 63 private IRestoreSession mRestore; 64 65 private static final String BMGR_NOT_RUNNING_ERR = 66 "Error: Could not access the Backup Manager. Is the system running?"; 67 private static final String TRANSPORT_NOT_RUNNING_ERR = 68 "Error: Could not access the backup transport. Is the system running?"; 69 private static final String PM_NOT_RUNNING_ERR = 70 "Error: Could not access the Package Manager. Is the system running?"; 71 72 private String[] mArgs; 73 private int mNextArg; 74 75 @VisibleForTesting 76 Bmgr(IBackupManager bmgr) { 77 mBmgr = bmgr; 78 } 79 80 Bmgr() { 81 mBmgr = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE)); 82 } 83 84 public static void main(String[] args) { 85 try { 86 new Bmgr().run(args); 87 } catch (Exception e) { 88 System.err.println("Exception caught:"); 89 e.printStackTrace(); 90 } 91 } 92 93 public void run(String[] args) { 94 if (args.length < 1) { 95 showUsage(); 96 return; 97 } 98 99 mArgs = args; 100 mNextArg = 0; 101 int userId = parseUserId(); 102 String op = nextArg(); 103 Slog.v(TAG, "Running " + op + " for user:" + userId); 104 105 if (mBmgr == null) { 106 System.err.println(BMGR_NOT_RUNNING_ERR); 107 return; 108 } 109 110 if ("activate".equals(op)) { 111 doActivateService(userId); 112 return; 113 } 114 115 if ("activated".equals(op)) { 116 doActivated(userId); 117 return; 118 } 119 120 if (!isBackupActive(userId)) { 121 return; 122 } 123 124 if ("enabled".equals(op)) { 125 doEnabled(userId); 126 return; 127 } 128 129 if ("enable".equals(op)) { 130 doEnable(userId); 131 return; 132 } 133 134 if ("run".equals(op)) { 135 doRun(userId); 136 return; 137 } 138 139 if ("backup".equals(op)) { 140 doBackup(userId); 141 return; 142 } 143 144 if ("init".equals(op)) { 145 doInit(userId); 146 return; 147 } 148 149 if ("list".equals(op)) { 150 doList(userId); 151 return; 152 } 153 154 if ("restore".equals(op)) { 155 doRestore(userId); 156 return; 157 } 158 159 if ("transport".equals(op)) { 160 doTransport(userId); 161 return; 162 } 163 164 if ("wipe".equals(op)) { 165 doWipe(userId); 166 return; 167 } 168 169 if ("fullbackup".equals(op)) { 170 doFullTransportBackup(userId); 171 return; 172 } 173 174 if ("backupnow".equals(op)) { 175 doBackupNow(userId); 176 return; 177 } 178 179 if ("cancel".equals(op)) { 180 doCancel(userId); 181 return; 182 } 183 184 if ("whitelist".equals(op)) { 185 doPrintWhitelist(); 186 return; 187 } 188 189 System.err.println("Unknown command"); 190 showUsage(); 191 } 192 193 boolean isBackupActive(@UserIdInt int userId) { 194 try { 195 if (!mBmgr.isBackupServiceActive(userId)) { 196 System.err.println(BMGR_NOT_RUNNING_ERR); 197 return false; 198 } 199 } catch (RemoteException e) { 200 System.err.println(e.toString()); 201 System.err.println(BMGR_NOT_RUNNING_ERR); 202 return false; 203 } 204 205 return true; 206 } 207 208 private String activatedToString(boolean activated) { 209 return activated ? "activated" : "deactivated"; 210 } 211 212 private void doActivated(@UserIdInt int userId) { 213 try { 214 System.out.println("Backup Manager currently " 215 + activatedToString(mBmgr.isBackupServiceActive(userId))); 216 } catch (RemoteException e) { 217 System.err.println(e.toString()); 218 System.err.println(BMGR_NOT_RUNNING_ERR); 219 } 220 221 } 222 223 private String enableToString(boolean enabled) { 224 return enabled ? "enabled" : "disabled"; 225 } 226 227 private void doEnabled(@UserIdInt int userId) { 228 try { 229 boolean isEnabled = mBmgr.isBackupEnabledForUser(userId); 230 System.out.println("Backup Manager currently " 231 + enableToString(isEnabled)); 232 } catch (RemoteException e) { 233 System.err.println(e.toString()); 234 System.err.println(BMGR_NOT_RUNNING_ERR); 235 } 236 } 237 238 private void doEnable(@UserIdInt int userId) { 239 String arg = nextArg(); 240 if (arg == null) { 241 showUsage(); 242 return; 243 } 244 245 try { 246 boolean enable = Boolean.parseBoolean(arg); 247 mBmgr.setBackupEnabledForUser(userId, enable); 248 System.out.println("Backup Manager now " + enableToString(enable)); 249 } catch (NumberFormatException e) { 250 showUsage(); 251 return; 252 } catch (RemoteException e) { 253 System.err.println(e.toString()); 254 System.err.println(BMGR_NOT_RUNNING_ERR); 255 } 256 } 257 258 void doRun(@UserIdInt int userId) { 259 try { 260 mBmgr.backupNowForUser(userId); 261 } catch (RemoteException e) { 262 System.err.println(e.toString()); 263 System.err.println(BMGR_NOT_RUNNING_ERR); 264 } 265 } 266 267 private void doBackup(@UserIdInt int userId) { 268 String pkg = nextArg(); 269 if (pkg == null) { 270 showUsage(); 271 return; 272 } 273 274 try { 275 mBmgr.dataChangedForUser(userId, pkg); 276 } catch (RemoteException e) { 277 System.err.println(e.toString()); 278 System.err.println(BMGR_NOT_RUNNING_ERR); 279 } 280 } 281 282 private void doFullTransportBackup(@UserIdInt int userId) { 283 System.out.println("Performing full transport backup"); 284 285 String pkg; 286 ArraySet<String> allPkgs = new ArraySet<String>(); 287 while ((pkg = nextArg()) != null) { 288 allPkgs.add(pkg); 289 } 290 if (allPkgs.size() > 0) { 291 try { 292 mBmgr.fullTransportBackupForUser( 293 userId, allPkgs.toArray(new String[allPkgs.size()])); 294 } catch (RemoteException e) { 295 System.err.println(e.toString()); 296 System.err.println(BMGR_NOT_RUNNING_ERR); 297 } 298 } 299 } 300 301 // IBackupObserver generically usable for any backup/init operation 302 private static abstract class Observer extends IBackupObserver.Stub { 303 private final Object trigger = new Object(); 304 305 @GuardedBy("trigger") 306 private volatile boolean done = false; 307 308 @Override 309 public void onUpdate(String currentPackage, BackupProgress backupProgress) { 310 } 311 312 @Override 313 public void onResult(String currentPackage, int status) { 314 } 315 316 @Override 317 public void backupFinished(int status) { 318 synchronized (trigger) { 319 done = true; 320 trigger.notify(); 321 } 322 } 323 324 public boolean done() { 325 return this.done; 326 } 327 328 // Wait forever 329 public void waitForCompletion() { 330 waitForCompletion(0); 331 } 332 333 // Wait for a given time and then give up 334 public void waitForCompletion(long timeout) { 335 // The backupFinished() callback will throw the 'done' flag; we 336 // just sit and wait on that notification. 337 final long targetTime = SystemClock.elapsedRealtime() + timeout; 338 synchronized (trigger) { 339 // Wait until either we're done, or we've reached a stated positive timeout 340 while (!done && (timeout <= 0 || SystemClock.elapsedRealtime() < targetTime)) { 341 try { 342 trigger.wait(1000L); 343 } catch (InterruptedException ex) { 344 } 345 } 346 } 347 } 348 } 349 350 private static class BackupObserver extends Observer { 351 @Override 352 public void onUpdate(String currentPackage, BackupProgress backupProgress) { 353 super.onUpdate(currentPackage, backupProgress); 354 System.out.println( 355 "Package " + currentPackage + " with progress: " + backupProgress.bytesTransferred 356 + "/" + backupProgress.bytesExpected); 357 } 358 359 @Override 360 public void onResult(String currentPackage, int status) { 361 super.onResult(currentPackage, status); 362 System.out.println("Package " + currentPackage + " with result: " 363 + convertBackupStatusToString(status)); 364 } 365 366 @Override 367 public void backupFinished(int status) { 368 super.backupFinished(status); 369 System.out.println("Backup finished with result: " 370 + convertBackupStatusToString(status)); 371 if (status == BackupManager.ERROR_BACKUP_CANCELLED) { 372 System.out.println("Backups can be cancelled if a backup is already running, check " 373 + "backup dumpsys"); 374 } 375 } 376 } 377 378 private static String convertBackupStatusToString(int errorCode) { 379 switch (errorCode) { 380 case BackupManager.SUCCESS: 381 return "Success"; 382 case BackupManager.ERROR_BACKUP_NOT_ALLOWED: 383 return "Backup is not allowed"; 384 case BackupManager.ERROR_PACKAGE_NOT_FOUND: 385 return "Package not found"; 386 case BackupManager.ERROR_TRANSPORT_ABORTED: 387 return "Transport error"; 388 case BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED: 389 return "Transport rejected package because it wasn't able to process it" 390 + " at the time"; 391 case BackupManager.ERROR_AGENT_FAILURE: 392 return "Agent error"; 393 case BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED: 394 return "Size quota exceeded"; 395 case BackupManager.ERROR_BACKUP_CANCELLED: 396 return "Backup cancelled"; 397 default: 398 return "Unknown error"; 399 } 400 } 401 402 private void backupNowAllPackages(@UserIdInt int userId, boolean nonIncrementalBackup, 403 @Monitor int monitorState) { 404 IPackageManager mPm = 405 IPackageManager.Stub.asInterface(ServiceManager.getService("package")); 406 if (mPm == null) { 407 System.err.println(PM_NOT_RUNNING_ERR); 408 return; 409 } 410 List<PackageInfo> installedPackages = null; 411 try { 412 installedPackages = mPm.getInstalledPackages(0, userId).getList(); 413 } catch (RemoteException e) { 414 System.err.println(e.toString()); 415 System.err.println(PM_NOT_RUNNING_ERR); 416 } 417 if (installedPackages != null) { 418 String[] packages = 419 installedPackages.stream().map(p -> p.packageName).toArray(String[]::new); 420 String[] filteredPackages = {}; 421 try { 422 filteredPackages = mBmgr.filterAppsEligibleForBackupForUser(userId, packages); 423 } catch (RemoteException e) { 424 System.err.println(e.toString()); 425 System.err.println(BMGR_NOT_RUNNING_ERR); 426 } 427 backupNowPackages(userId, Arrays.asList(filteredPackages), nonIncrementalBackup, 428 monitorState); 429 } 430 } 431 432 private void backupNowPackages( 433 @UserIdInt int userId, 434 List<String> packages, boolean nonIncrementalBackup, @Monitor int monitorState) { 435 int flags = 0; 436 if (nonIncrementalBackup) { 437 flags |= BackupManager.FLAG_NON_INCREMENTAL_BACKUP; 438 } 439 try { 440 BackupObserver observer = new BackupObserver(); 441 BackupMonitor monitor = 442 (monitorState != Monitor.OFF) 443 ? new BackupMonitor(monitorState == Monitor.VERBOSE) 444 : null; 445 int err = mBmgr.requestBackupForUser( 446 userId, 447 packages.toArray(new String[packages.size()]), 448 observer, 449 monitor, 450 flags); 451 if (err == 0) { 452 // Off and running -- wait for the backup to complete 453 observer.waitForCompletion(); 454 } else { 455 System.err.println("Unable to run backup"); 456 } 457 } catch (RemoteException e) { 458 System.err.println(e.toString()); 459 System.err.println(BMGR_NOT_RUNNING_ERR); 460 } 461 } 462 463 private void doBackupNow(@UserIdInt int userId) { 464 String pkg; 465 boolean backupAll = false; 466 boolean nonIncrementalBackup = false; 467 @Monitor int monitor = Monitor.OFF; 468 ArrayList<String> allPkgs = new ArrayList<String>(); 469 while ((pkg = nextArg()) != null) { 470 if (pkg.equals("--all")) { 471 backupAll = true; 472 } else if (pkg.equals("--non-incremental")) { 473 nonIncrementalBackup = true; 474 } else if (pkg.equals("--incremental")) { 475 nonIncrementalBackup = false; 476 } else if (pkg.equals("--monitor")) { 477 monitor = Monitor.NORMAL; 478 } else if (pkg.equals("--monitor-verbose")) { 479 monitor = Monitor.VERBOSE; 480 } else { 481 if (!allPkgs.contains(pkg)) { 482 allPkgs.add(pkg); 483 } 484 } 485 } 486 if (backupAll) { 487 if (allPkgs.size() == 0) { 488 System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") + 489 "incremental backup for all packages."); 490 backupNowAllPackages(userId, nonIncrementalBackup, monitor); 491 } else { 492 System.err.println("Provide only '--all' flag or list of packages."); 493 } 494 } else if (allPkgs.size() > 0) { 495 System.out.println("Running " + (nonIncrementalBackup ? "non-" : "") + 496 "incremental backup for " + allPkgs.size() +" requested packages."); 497 backupNowPackages(userId, allPkgs, nonIncrementalBackup, monitor); 498 } else { 499 System.err.println("Provide '--all' flag or list of packages."); 500 } 501 } 502 503 private void doCancel(@UserIdInt int userId) { 504 String arg = nextArg(); 505 if ("backups".equals(arg)) { 506 try { 507 mBmgr.cancelBackupsForUser(userId); 508 } catch (RemoteException e) { 509 System.err.println(e.toString()); 510 System.err.println(BMGR_NOT_RUNNING_ERR); 511 } 512 return; 513 } 514 515 System.err.println("Unknown command."); 516 } 517 518 private void doTransport(@UserIdInt int userId) { 519 try { 520 String which = nextArg(); 521 if (which == null) { 522 showUsage(); 523 return; 524 } 525 526 if ("-c".equals(which)) { 527 doTransportByComponent(userId); 528 return; 529 } 530 531 String old = mBmgr.selectBackupTransportForUser(userId, which); 532 if (old == null) { 533 System.out.println("Unknown transport '" + which 534 + "' specified; no changes made."); 535 } else { 536 System.out.println("Selected transport " + which + " (formerly " + old + ")"); 537 } 538 539 } catch (RemoteException e) { 540 System.err.println(e.toString()); 541 System.err.println(BMGR_NOT_RUNNING_ERR); 542 } 543 } 544 545 private void doTransportByComponent(@UserIdInt int userId) { 546 String which = nextArg(); 547 if (which == null) { 548 showUsage(); 549 return; 550 } 551 552 final CountDownLatch latch = new CountDownLatch(1); 553 554 try { 555 mBmgr.selectBackupTransportAsyncForUser( 556 userId, 557 ComponentName.unflattenFromString(which), 558 new ISelectBackupTransportCallback.Stub() { 559 @Override 560 public void onSuccess(String transportName) { 561 System.out.println("Success. Selected transport: " + transportName); 562 latch.countDown(); 563 } 564 565 @Override 566 public void onFailure(int reason) { 567 System.err.println("Failure. error=" + reason); 568 latch.countDown(); 569 } 570 }); 571 } catch (RemoteException e) { 572 System.err.println(e.toString()); 573 System.err.println(BMGR_NOT_RUNNING_ERR); 574 return; 575 } 576 577 try { 578 latch.await(); 579 } catch (InterruptedException e) { 580 System.err.println("Operation interrupted."); 581 } 582 } 583 584 private void doWipe(@UserIdInt int userId) { 585 String transport = nextArg(); 586 if (transport == null) { 587 showUsage(); 588 return; 589 } 590 591 String pkg = nextArg(); 592 if (pkg == null) { 593 showUsage(); 594 return; 595 } 596 597 try { 598 mBmgr.clearBackupDataForUser(userId, transport, pkg); 599 System.out.println("Wiped backup data for " + pkg + " on " + transport); 600 } catch (RemoteException e) { 601 System.err.println(e.toString()); 602 System.err.println(BMGR_NOT_RUNNING_ERR); 603 } 604 } 605 606 class InitObserver extends Observer { 607 public int result = BackupTransport.TRANSPORT_ERROR; 608 609 @Override 610 public void backupFinished(int status) { 611 super.backupFinished(status); 612 result = status; 613 } 614 } 615 616 private void doInit(@UserIdInt int userId) { 617 ArraySet<String> transports = new ArraySet<>(); 618 String transport; 619 while ((transport = nextArg()) != null) { 620 transports.add(transport); 621 } 622 if (transports.size() == 0) { 623 showUsage(); 624 return; 625 } 626 627 InitObserver observer = new InitObserver(); 628 try { 629 System.out.println("Initializing transports: " + transports); 630 mBmgr.initializeTransportsForUser( 631 userId, transports.toArray(new String[transports.size()]), observer); 632 observer.waitForCompletion(30*1000L); 633 System.out.println("Initialization result: " + observer.result); 634 } catch (RemoteException e) { 635 System.err.println(e.toString()); 636 System.err.println(BMGR_NOT_RUNNING_ERR); 637 } 638 } 639 640 private void doList(@UserIdInt int userId) { 641 String arg = nextArg(); // sets, transports, packages set# 642 if ("transports".equals(arg)) { 643 doListTransports(userId); 644 return; 645 } 646 647 // The rest of the 'list' options work with a restore session on the current transport 648 try { 649 mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null); 650 if (mRestore == null) { 651 System.err.println(BMGR_NOT_RUNNING_ERR); 652 return; 653 } 654 655 if ("sets".equals(arg)) { 656 doListRestoreSets(); 657 } 658 659 mRestore.endRestoreSession(); 660 } catch (RemoteException e) { 661 System.err.println(e.toString()); 662 System.err.println(BMGR_NOT_RUNNING_ERR); 663 } 664 } 665 666 private void doListTransports(@UserIdInt int userId) { 667 String arg = nextArg(); 668 669 try { 670 if ("-c".equals(arg)) { 671 for (ComponentName transport : mBmgr.listAllTransportComponentsForUser(userId)) { 672 System.out.println(transport.flattenToShortString()); 673 } 674 return; 675 } 676 677 String current = mBmgr.getCurrentTransportForUser(userId); 678 String[] transports = mBmgr.listAllTransportsForUser(userId); 679 if (transports == null || transports.length == 0) { 680 System.out.println("No transports available."); 681 return; 682 } 683 684 for (String t : transports) { 685 String pad = (t.equals(current)) ? " * " : " "; 686 System.out.println(pad + t); 687 } 688 } catch (RemoteException e) { 689 System.err.println(e.toString()); 690 System.err.println(BMGR_NOT_RUNNING_ERR); 691 } 692 } 693 694 private void doListRestoreSets() { 695 try { 696 RestoreObserver observer = new RestoreObserver(); 697 // TODO implement monitor here 698 int err = mRestore.getAvailableRestoreSets(observer, null); 699 if (err != 0) { 700 System.out.println("Unable to request restore sets"); 701 } else { 702 observer.waitForCompletion(); 703 printRestoreSets(observer.sets); 704 } 705 } catch (RemoteException e) { 706 System.err.println(e.toString()); 707 System.err.println(TRANSPORT_NOT_RUNNING_ERR); 708 } 709 } 710 711 private void printRestoreSets(RestoreSet[] sets) { 712 if (sets == null || sets.length == 0) { 713 System.out.println("No restore sets"); 714 return; 715 } 716 for (RestoreSet s : sets) { 717 System.out.println(" " + Long.toHexString(s.token) + " : " + s.name); 718 } 719 } 720 721 class RestoreObserver extends IRestoreObserver.Stub { 722 boolean done; 723 RestoreSet[] sets = null; 724 725 public void restoreSetsAvailable(RestoreSet[] result) { 726 synchronized (this) { 727 sets = result; 728 done = true; 729 this.notify(); 730 } 731 } 732 733 public void restoreStarting(int numPackages) { 734 System.out.println("restoreStarting: " + numPackages + " packages"); 735 } 736 737 public void onUpdate(int nowBeingRestored, String currentPackage) { 738 System.out.println("onUpdate: " + nowBeingRestored + " = " + currentPackage); 739 } 740 741 public void restoreFinished(int error) { 742 System.out.println("restoreFinished: " + error); 743 synchronized (this) { 744 done = true; 745 this.notify(); 746 } 747 } 748 749 /** 750 * Wait until either {@link #restoreFinished} or {@link #restoreStarting} is called. 751 * Once one is called, it clears the internal flag again, so that the same observer intance 752 * can be reused for a next operation. 753 */ 754 public void waitForCompletion() { 755 // The restoreFinished() callback will throw the 'done' flag; we 756 // just sit and wait on that notification. 757 synchronized (this) { 758 while (!this.done) { 759 try { 760 this.wait(); 761 } catch (InterruptedException ex) { 762 } 763 } 764 done = false; 765 } 766 } 767 } 768 769 private void doRestore(@UserIdInt int userId) { 770 String arg = nextArg(); 771 if (arg == null) { 772 showUsage(); 773 return; 774 } 775 776 if (arg.indexOf('.') >= 0 || arg.equals("android")) { 777 // it's a package name 778 doRestorePackage(arg); 779 } else { 780 try { 781 long token = Long.parseLong(arg, 16); 782 HashSet<String> filter = null; 783 while ((arg = nextArg()) != null) { 784 if (filter == null) filter = new HashSet<String>(); 785 filter.add(arg); 786 } 787 788 doRestoreAll(userId, token, filter); 789 } catch (NumberFormatException e) { 790 showUsage(); 791 return; 792 } 793 } 794 } 795 796 private void doRestorePackage(String pkg) { 797 System.err.println("The syntax 'restore <package>' is no longer supported, please use "); 798 System.err.println("'restore <token> <package>'."); 799 } 800 801 private void doRestoreAll(@UserIdInt int userId, long token, HashSet<String> filter) { 802 RestoreObserver observer = new RestoreObserver(); 803 804 try { 805 boolean didRestore = false; 806 mRestore = mBmgr.beginRestoreSessionForUser(userId, null, null); 807 if (mRestore == null) { 808 System.err.println(BMGR_NOT_RUNNING_ERR); 809 return; 810 } 811 RestoreSet[] sets = null; 812 // TODO implement monitor here 813 int err = mRestore.getAvailableRestoreSets(observer, null); 814 if (err == 0) { 815 observer.waitForCompletion(); 816 sets = observer.sets; 817 if (sets != null) { 818 for (RestoreSet s : sets) { 819 if (s.token == token) { 820 System.out.println("Scheduling restore: " + s.name); 821 if (filter == null) { 822 didRestore = (mRestore.restoreAll(token, observer, null) == 0); 823 } else { 824 String[] names = new String[filter.size()]; 825 filter.toArray(names); 826 didRestore = (mRestore.restorePackages(token, observer, names, 827 null) == 0); 828 } 829 break; 830 } 831 } 832 } 833 } 834 if (!didRestore) { 835 if (sets == null || sets.length == 0) { 836 System.out.println("No available restore sets; no restore performed"); 837 } else { 838 System.out.println("No matching restore set token. Available sets:"); 839 printRestoreSets(sets); 840 } 841 } 842 843 // if we kicked off a restore successfully, we have to wait for it 844 // to complete before we can shut down the restore session safely 845 if (didRestore) { 846 observer.waitForCompletion(); 847 } 848 849 // once the restore has finished, close down the session and we're done 850 mRestore.endRestoreSession(); 851 852 System.out.println("done"); 853 } catch (RemoteException e) { 854 System.err.println(e.toString()); 855 System.err.println(BMGR_NOT_RUNNING_ERR); 856 } 857 } 858 859 private void doPrintWhitelist() { 860 try { 861 final String[] whitelist = mBmgr.getTransportWhitelist(); 862 if (whitelist != null) { 863 for (String transport : whitelist) { 864 System.out.println(transport); 865 } 866 } 867 } catch (RemoteException e) { 868 System.err.println(e.toString()); 869 System.err.println(BMGR_NOT_RUNNING_ERR); 870 } 871 } 872 873 private void doActivateService(int userId) { 874 String arg = nextArg(); 875 if (arg == null) { 876 showUsage(); 877 return; 878 } 879 880 try { 881 boolean activate = Boolean.parseBoolean(arg); 882 mBmgr.setBackupServiceActive(userId, activate); 883 System.out.println( 884 "Backup service now " 885 + (activate ? "activated" : "deactivated") 886 + " for user " 887 + userId); 888 } catch (RemoteException e) { 889 System.err.println(e.toString()); 890 System.err.println(BMGR_NOT_RUNNING_ERR); 891 } 892 } 893 894 private String nextArg() { 895 if (mNextArg >= mArgs.length) { 896 return null; 897 } 898 String arg = mArgs[mNextArg]; 899 mNextArg++; 900 return arg; 901 } 902 903 private int parseUserId() { 904 String arg = nextArg(); 905 if ("--user".equals(arg)) { 906 return UserHandle.parseUserArg(nextArg()); 907 } else { 908 mNextArg--; 909 return UserHandle.USER_SYSTEM; 910 } 911 } 912 913 private static void showUsage() { 914 System.err.println("usage: bmgr [--user <userId>] [backup|restore|list|transport|run]"); 915 System.err.println(" bmgr backup PACKAGE"); 916 System.err.println(" bmgr enable BOOL"); 917 System.err.println(" bmgr enabled"); 918 System.err.println(" bmgr list transports [-c]"); 919 System.err.println(" bmgr list sets"); 920 System.err.println(" bmgr transport WHICH|-c WHICH_COMPONENT"); 921 System.err.println(" bmgr restore TOKEN"); 922 System.err.println(" bmgr restore TOKEN PACKAGE..."); 923 System.err.println(" bmgr run"); 924 System.err.println(" bmgr wipe TRANSPORT PACKAGE"); 925 System.err.println(" bmgr fullbackup PACKAGE..."); 926 System.err.println(" bmgr backupnow [--monitor|--monitor-verbose] --all|PACKAGE..."); 927 System.err.println(" bmgr cancel backups"); 928 System.err.println(" bmgr init TRANSPORT..."); 929 System.err.println(" bmgr activate BOOL"); 930 System.err.println(" bmgr activated"); 931 System.err.println(""); 932 System.err.println("The '--user' option specifies the user on which the operation is run."); 933 System.err.println("It must be the first argument before the operation."); 934 System.err.println("The default value is 0 which is the system user."); 935 System.err.println(""); 936 System.err.println("The 'backup' command schedules a backup pass for the named package."); 937 System.err.println("Note that the backup pass will effectively be a no-op if the package"); 938 System.err.println("does not actually have changed data to store."); 939 System.err.println(""); 940 System.err.println("The 'enable' command enables or disables the entire backup mechanism."); 941 System.err.println("If the argument is 'true' it will be enabled, otherwise it will be"); 942 System.err.println("disabled. When disabled, neither backup or restore operations will"); 943 System.err.println("be performed."); 944 System.err.println(""); 945 System.err.println("The 'enabled' command reports the current enabled/disabled state of"); 946 System.err.println("the backup mechanism."); 947 System.err.println(""); 948 System.err.println("The 'list transports' command reports the names of the backup transports"); 949 System.err.println("BackupManager is currently bound to. These names can be passed as arguments"); 950 System.err.println("to the 'transport' and 'wipe' commands. The currently active transport"); 951 System.err.println("is indicated with a '*' character. If -c flag is used, all available"); 952 System.err.println("transport components on the device are listed. These can be used with"); 953 System.err.println("the component variant of 'transport' command."); 954 System.err.println(""); 955 System.err.println("The 'list sets' command reports the token and name of each restore set"); 956 System.err.println("available to the device via the currently active transport."); 957 System.err.println(""); 958 System.err.println("The 'transport' command designates the named transport as the currently"); 959 System.err.println("active one. This setting is persistent across reboots. If -c flag is"); 960 System.err.println("specified, the following string is treated as a component name."); 961 System.err.println(""); 962 System.err.println("The 'restore' command when given just a restore token initiates a full-system"); 963 System.err.println("restore operation from the currently active transport. It will deliver"); 964 System.err.println("the restore set designated by the TOKEN argument to each application"); 965 System.err.println("that had contributed data to that restore set."); 966 System.err.println(""); 967 System.err.println("The 'restore' command when given a token and one or more package names"); 968 System.err.println("initiates a restore operation of just those given packages from the restore"); 969 System.err.println("set designated by the TOKEN argument. It is effectively the same as the"); 970 System.err.println("'restore' operation supplying only a token, but applies a filter to the"); 971 System.err.println("set of applications to be restored."); 972 System.err.println(""); 973 System.err.println("The 'run' command causes any scheduled backup operation to be initiated"); 974 System.err.println("immediately, without the usual waiting period for batching together"); 975 System.err.println("data changes."); 976 System.err.println(""); 977 System.err.println("The 'wipe' command causes all backed-up data for the given package to be"); 978 System.err.println("erased from the given transport's storage. The next backup operation"); 979 System.err.println("that the given application performs will rewrite its entire data set."); 980 System.err.println("Transport names to use here are those reported by 'list transports'."); 981 System.err.println(""); 982 System.err.println("The 'fullbackup' command induces a full-data stream backup for one or more"); 983 System.err.println("packages. The data is sent via the currently active transport."); 984 System.err.println(""); 985 System.err.println("The 'backupnow' command runs an immediate backup for one or more packages."); 986 System.err.println(" --all flag runs backup for all eligible packages."); 987 System.err.println(" --monitor flag prints monitor events."); 988 System.err.println(" --monitor-verbose flag prints monitor events with all keys."); 989 System.err.println("For each package it will run key/value or full data backup "); 990 System.err.println("depending on the package's manifest declarations."); 991 System.err.println("The data is sent via the currently active transport."); 992 System.err.println(""); 993 System.err.println("The 'cancel backups' command cancels all running backups."); 994 System.err.println(""); 995 System.err.println("The 'init' command initializes the given transports, wiping all data"); 996 System.err.println("from their backing data stores."); 997 System.err.println(""); 998 System.err.println("The 'activate' command activates or deactivates the backup service."); 999 System.err.println("If the argument is 'true' it will be activated, otherwise it will be"); 1000 System.err.println("deactivated. When deactivated, the service will not be running and no"); 1001 System.err.println("operations can be performed until activation."); 1002 System.err.println(""); 1003 System.err.println("The 'activated' command reports the current activated/deactivated"); 1004 System.err.println("state of the backup mechanism."); 1005 } 1006 1007 private static class BackupMonitor extends IBackupManagerMonitor.Stub { 1008 private final boolean mVerbose; 1009 1010 private BackupMonitor(boolean verbose) { 1011 mVerbose = verbose; 1012 } 1013 1014 @Override 1015 public void onEvent(Bundle event) throws RemoteException { 1016 StringBuilder out = new StringBuilder(); 1017 int id = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID); 1018 int category = event.getInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY); 1019 out.append("=> Event{").append(eventCategoryToString(category)); 1020 out.append(" / ").append(eventIdToString(id)); 1021 String packageName = event.getString(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME); 1022 if (packageName != null) { 1023 out.append(" : package = ").append(packageName); 1024 if (event.containsKey(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION)) { 1025 long version = 1026 event.getLong( 1027 BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION); 1028 out.append("(v").append(version).append(")"); 1029 } 1030 } 1031 if (mVerbose) { 1032 Set<String> remainingKeys = new ArraySet<>(event.keySet()); 1033 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_ID); 1034 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY); 1035 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME); 1036 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION); 1037 remainingKeys.remove(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION); 1038 if (!remainingKeys.isEmpty()) { 1039 out.append(", other keys ="); 1040 for (String key : remainingKeys) { 1041 out.append(" ").append(key); 1042 } 1043 } 1044 } 1045 out.append("}"); 1046 System.out.println(out.toString()); 1047 } 1048 } 1049 1050 private static String eventCategoryToString(int eventCategory) { 1051 switch (eventCategory) { 1052 case BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT: 1053 return "TRANSPORT"; 1054 case BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT: 1055 return "AGENT"; 1056 case BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY: 1057 return "BACKUP_MANAGER_POLICY"; 1058 default: 1059 return "UNKNOWN_CATEGORY"; 1060 } 1061 } 1062 1063 private static String eventIdToString(int eventId) { 1064 switch (eventId) { 1065 case BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_CANCEL: 1066 return "FULL_BACKUP_CANCEL"; 1067 case BackupManagerMonitor.LOG_EVENT_ID_ILLEGAL_KEY: 1068 return "ILLEGAL_KEY"; 1069 case BackupManagerMonitor.LOG_EVENT_ID_NO_DATA_TO_SEND: 1070 return "NO_DATA_TO_SEND"; 1071 case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_INELIGIBLE: 1072 return "PACKAGE_INELIGIBLE"; 1073 case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_KEY_VALUE_PARTICIPANT: 1074 return "PACKAGE_KEY_VALUE_PARTICIPANT"; 1075 case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_STOPPED: 1076 return "PACKAGE_STOPPED"; 1077 case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_FOUND: 1078 return "PACKAGE_NOT_FOUND"; 1079 case BackupManagerMonitor.LOG_EVENT_ID_BACKUP_DISABLED: 1080 return "BACKUP_DISABLED"; 1081 case BackupManagerMonitor.LOG_EVENT_ID_DEVICE_NOT_PROVISIONED: 1082 return "DEVICE_NOT_PROVISIONED"; 1083 case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_TRANSPORT_NOT_PRESENT: 1084 return "PACKAGE_TRANSPORT_NOT_PRESENT"; 1085 case BackupManagerMonitor.LOG_EVENT_ID_ERROR_PREFLIGHT: 1086 return "ERROR_PREFLIGHT"; 1087 case BackupManagerMonitor.LOG_EVENT_ID_QUOTA_HIT_PREFLIGHT: 1088 return "QUOTA_HIT_PREFLIGHT"; 1089 case BackupManagerMonitor.LOG_EVENT_ID_EXCEPTION_FULL_BACKUP: 1090 return "EXCEPTION_FULL_BACKUP"; 1091 case BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_CANCEL: 1092 return "KEY_VALUE_BACKUP_CANCEL"; 1093 case BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE: 1094 return "NO_RESTORE_METADATA_AVAILABLE"; 1095 case BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED: 1096 return "NO_PM_METADATA_RECEIVED"; 1097 case BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA: 1098 return "PM_AGENT_HAS_NO_METADATA"; 1099 case BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT: 1100 return "LOST_TRANSPORT"; 1101 case BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT: 1102 return "PACKAGE_NOT_PRESENT"; 1103 case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER: 1104 return "RESTORE_VERSION_HIGHER"; 1105 case BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT: 1106 return "APP_HAS_NO_AGENT"; 1107 case BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH: 1108 return "SIGNATURE_MISMATCH"; 1109 case BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT: 1110 return "CANT_FIND_AGENT"; 1111 case BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT: 1112 return "KEY_VALUE_RESTORE_TIMEOUT"; 1113 case BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION: 1114 return "RESTORE_ANY_VERSION"; 1115 case BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH: 1116 return "VERSIONS_MATCH"; 1117 case BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER: 1118 return "VERSION_OF_BACKUP_OLDER"; 1119 case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_SIGNATURE_MISMATCH: 1120 return "FULL_RESTORE_SIGNATURE_MISMATCH"; 1121 case BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT: 1122 return "SYSTEM_APP_NO_AGENT"; 1123 case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_ALLOW_BACKUP_FALSE: 1124 return "FULL_RESTORE_ALLOW_BACKUP_FALSE"; 1125 case BackupManagerMonitor.LOG_EVENT_ID_APK_NOT_INSTALLED: 1126 return "APK_NOT_INSTALLED"; 1127 case BackupManagerMonitor.LOG_EVENT_ID_CANNOT_RESTORE_WITHOUT_APK: 1128 return "CANNOT_RESTORE_WITHOUT_APK"; 1129 case BackupManagerMonitor.LOG_EVENT_ID_MISSING_SIGNATURE: 1130 return "MISSING_SIGNATURE"; 1131 case BackupManagerMonitor.LOG_EVENT_ID_EXPECTED_DIFFERENT_PACKAGE: 1132 return "EXPECTED_DIFFERENT_PACKAGE"; 1133 case BackupManagerMonitor.LOG_EVENT_ID_UNKNOWN_VERSION: 1134 return "UNKNOWN_VERSION"; 1135 case BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT: 1136 return "FULL_RESTORE_TIMEOUT"; 1137 case BackupManagerMonitor.LOG_EVENT_ID_CORRUPT_MANIFEST: 1138 return "CORRUPT_MANIFEST"; 1139 case BackupManagerMonitor.LOG_EVENT_ID_WIDGET_METADATA_MISMATCH: 1140 return "WIDGET_METADATA_MISMATCH"; 1141 case BackupManagerMonitor.LOG_EVENT_ID_WIDGET_UNKNOWN_VERSION: 1142 return "WIDGET_UNKNOWN_VERSION"; 1143 case BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES: 1144 return "NO_PACKAGES"; 1145 case BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL: 1146 return "TRANSPORT_IS_NULL"; 1147 default: 1148 return "UNKNOWN_ID"; 1149 } 1150 } 1151 1152 @IntDef({Monitor.OFF, Monitor.NORMAL, Monitor.VERBOSE}) 1153 @Retention(RetentionPolicy.SOURCE) 1154 private @interface Monitor { 1155 int OFF = 0; 1156 int NORMAL = 1; 1157 int VERBOSE = 2; 1158 } 1159 } 1160