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 android.app.backup; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemApi; 23 import android.annotation.TestApi; 24 import android.compat.annotation.UnsupportedAppUsage; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.os.Bundle; 29 import android.os.Handler; 30 import android.os.Message; 31 import android.os.RemoteException; 32 import android.os.ServiceManager; 33 import android.os.UserHandle; 34 import android.util.Log; 35 import android.util.Pair; 36 37 /** 38 * The interface through which an application interacts with the Android backup service to 39 * request backup and restore operations. 40 * Applications instantiate it using the constructor and issue calls through that instance. 41 * <p> 42 * When an application has made changes to data which should be backed up, a 43 * call to {@link #dataChanged()} will notify the backup service. The system 44 * will then schedule a backup operation to occur in the near future. Repeated 45 * calls to {@link #dataChanged()} have no further effect until the backup 46 * operation actually occurs. 47 * <p> 48 * A backup or restore operation for your application begins when the system launches the 49 * {@link android.app.backup.BackupAgent} subclass you've declared in your manifest. See the 50 * documentation for {@link android.app.backup.BackupAgent} for a detailed description 51 * of how the operation then proceeds. 52 * <p> 53 * Several attributes affecting the operation of the backup and restore mechanism 54 * can be set on the <code> 55 * <a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a></code> 56 * tag in your application's AndroidManifest.xml file. 57 * 58 * <div class="special reference"> 59 * <h3>Developer Guides</h3> 60 * <p>For more information about using BackupManager, read the 61 * <a href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p></div> 62 * 63 * @attr ref android.R.styleable#AndroidManifestApplication_allowBackup 64 * @attr ref android.R.styleable#AndroidManifestApplication_backupAgent 65 * @attr ref android.R.styleable#AndroidManifestApplication_killAfterRestore 66 * @attr ref android.R.styleable#AndroidManifestApplication_restoreAnyVersion 67 */ 68 public class BackupManager { 69 private static final String TAG = "BackupManager"; 70 71 // BackupObserver status codes 72 /** 73 * Indicates that backup succeeded. 74 * 75 * @hide 76 */ 77 @SystemApi 78 public static final int SUCCESS = 0; 79 80 /** 81 * Indicates that backup is either not enabled at all or 82 * backup for the package was rejected by backup service 83 * or backup transport, 84 * 85 * @hide 86 */ 87 @SystemApi 88 public static final int ERROR_BACKUP_NOT_ALLOWED = -2001; 89 90 /** 91 * The requested app is not installed on the device. 92 * 93 * @hide 94 */ 95 @SystemApi 96 public static final int ERROR_PACKAGE_NOT_FOUND = -2002; 97 98 /** 99 * The backup operation was cancelled. 100 * 101 * @hide 102 */ 103 @SystemApi 104 public static final int ERROR_BACKUP_CANCELLED = -2003; 105 106 /** 107 * The transport for some reason was not in a good state and 108 * aborted the entire backup request. This is a transient 109 * failure and should not be retried immediately. 110 * 111 * @hide 112 */ 113 @SystemApi 114 public static final int ERROR_TRANSPORT_ABORTED = BackupTransport.TRANSPORT_ERROR; 115 116 /** 117 * Returned when the transport was unable to process the 118 * backup request for a given package, for example if the 119 * transport hit a transient network failure. The remaining 120 * packages provided to {@link #requestBackup(String[], BackupObserver)} 121 * will still be attempted. 122 * 123 * @hide 124 */ 125 @SystemApi 126 public static final int ERROR_TRANSPORT_PACKAGE_REJECTED = 127 BackupTransport.TRANSPORT_PACKAGE_REJECTED; 128 129 /** 130 * Returned when the transport reject the attempt to backup because 131 * backup data size exceeded current quota limit for this package. 132 * 133 * @hide 134 */ 135 @SystemApi 136 public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED = 137 BackupTransport.TRANSPORT_QUOTA_EXCEEDED; 138 139 /** 140 * The {@link BackupAgent} for the requested package failed for some reason 141 * and didn't provide appropriate backup data. 142 * 143 * @hide 144 */ 145 @SystemApi 146 public static final int ERROR_AGENT_FAILURE = BackupTransport.AGENT_ERROR; 147 148 /** 149 * Intent extra when any subsidiary backup-related UI is launched from Settings: does 150 * device policy or configuration permit backup operations to run at all? 151 * 152 * @hide 153 */ 154 public static final String EXTRA_BACKUP_SERVICES_AVAILABLE = "backup_services_available"; 155 156 /** 157 * If this flag is passed to {@link #requestBackup(String[], BackupObserver, int)}, 158 * BackupManager will pass a blank old state to BackupAgents of requested packages. 159 * 160 * @hide 161 */ 162 @SystemApi 163 public static final int FLAG_NON_INCREMENTAL_BACKUP = 1; 164 165 /** 166 * Use with {@link #requestBackup} to force backup of 167 * package meta data. Typically you do not need to explicitly request this be backed up as it is 168 * handled internally by the BackupManager. If you are requesting backups with 169 * FLAG_NON_INCREMENTAL, this package won't automatically be backed up and you have to 170 * explicitly request for its backup. 171 * 172 * @hide 173 */ 174 @SystemApi 175 public static final String PACKAGE_MANAGER_SENTINEL = "@pm@"; 176 177 178 /** 179 * This error code is passed to {@link SelectBackupTransportCallback#onFailure(int)} 180 * if the requested transport is unavailable. 181 * 182 * @hide 183 */ 184 @SystemApi 185 public static final int ERROR_TRANSPORT_UNAVAILABLE = -1; 186 187 /** 188 * This error code is passed to {@link SelectBackupTransportCallback#onFailure(int)} if the 189 * requested transport is not a valid BackupTransport. 190 * 191 * @hide 192 */ 193 @SystemApi 194 public static final int ERROR_TRANSPORT_INVALID = -2; 195 196 private Context mContext; 197 @UnsupportedAppUsage 198 private static IBackupManager sService; 199 200 @UnsupportedAppUsage checkServiceBinder()201 private static void checkServiceBinder() { 202 if (sService == null) { 203 sService = IBackupManager.Stub.asInterface( 204 ServiceManager.getService(Context.BACKUP_SERVICE)); 205 } 206 } 207 208 /** 209 * Constructs a BackupManager object through which the application can 210 * communicate with the Android backup system. 211 * 212 * @param context The {@link android.content.Context} that was provided when 213 * one of your application's {@link android.app.Activity Activities} 214 * was created. 215 */ BackupManager(Context context)216 public BackupManager(Context context) { 217 mContext = context; 218 } 219 220 /** 221 * Notifies the Android backup system that your application wishes to back up 222 * new changes to its data. A backup operation using your application's 223 * {@link android.app.backup.BackupAgent} subclass will be scheduled when you 224 * call this method. 225 */ dataChanged()226 public void dataChanged() { 227 checkServiceBinder(); 228 if (sService != null) { 229 try { 230 sService.dataChanged(mContext.getPackageName()); 231 } catch (RemoteException e) { 232 Log.d(TAG, "dataChanged() couldn't connect"); 233 } 234 } 235 } 236 237 /** 238 * Convenience method for callers who need to indicate that some other package 239 * needs a backup pass. This can be useful in the case of groups of packages 240 * that share a uid. 241 * <p> 242 * This method requires that the application hold the "android.permission.BACKUP" 243 * permission if the package named in the argument does not run under the same uid 244 * as the caller. 245 * 246 * @param packageName The package name identifying the application to back up. 247 */ dataChanged(String packageName)248 public static void dataChanged(String packageName) { 249 checkServiceBinder(); 250 if (sService != null) { 251 try { 252 sService.dataChanged(packageName); 253 } catch (RemoteException e) { 254 Log.e(TAG, "dataChanged(pkg) couldn't connect"); 255 } 256 } 257 } 258 259 /** 260 * @deprecated Applications shouldn't request a restore operation using this method. In Android 261 * P and later, this method is a no-op. 262 * 263 * <p>Restore the calling application from backup. The data will be restored from the 264 * current backup dataset if the application has stored data there, or from 265 * the dataset used during the last full device setup operation if the current 266 * backup dataset has no matching data. If no backup data exists for this application 267 * in either source, a non-zero value is returned. 268 * 269 * <p>If this method returns zero (meaning success), the OS attempts to retrieve a backed-up 270 * dataset from the remote transport, instantiate the application's backup agent, and pass the 271 * dataset to the agent's 272 * {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) onRestore()} 273 * method. 274 * 275 * <p class="caution">Unlike other restore operations, this method doesn't terminate the 276 * application after the restore. The application continues running to receive the 277 * {@link RestoreObserver} callbacks on the {@code observer} argument. Full backups use an 278 * {@link android.app.Application Application} base class while key-value backups use the 279 * application subclass declared in the AndroidManifest.xml {@code <application>} tag. 280 * 281 * @param observer The {@link RestoreObserver} to receive callbacks during the restore 282 * operation. This must not be null. 283 * 284 * @return Zero on success; nonzero on error. 285 */ 286 @Deprecated requestRestore(RestoreObserver observer)287 public int requestRestore(RestoreObserver observer) { 288 return requestRestore(observer, null); 289 } 290 291 // system APIs start here 292 293 /** 294 * @deprecated Since Android P app can no longer request restoring of its backup. 295 * 296 * <p>Restore the calling application from backup. The data will be restored from the 297 * current backup dataset if the application has stored data there, or from 298 * the dataset used during the last full device setup operation if the current 299 * backup dataset has no matching data. If no backup data exists for this application 300 * in either source, a nonzero value will be returned. 301 * 302 * <p>If this method returns zero (meaning success), the OS will attempt to retrieve 303 * a backed-up dataset from the remote transport, instantiate the application's 304 * backup agent, and pass the dataset to the agent's 305 * {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) onRestore()} 306 * method. 307 * 308 * @param observer The {@link RestoreObserver} to receive callbacks during the restore 309 * operation. This must not be null. 310 * 311 * @param monitor the {@link BackupManagerMonitor} to receive callbacks during the restore 312 * operation. 313 * 314 * @return Zero on success; nonzero on error. 315 * 316 * @hide 317 */ 318 @Deprecated 319 @SystemApi requestRestore(RestoreObserver observer, BackupManagerMonitor monitor)320 public int requestRestore(RestoreObserver observer, BackupManagerMonitor monitor) { 321 Log.w(TAG, "requestRestore(): Since Android P app can no longer request restoring" 322 + " of its backup."); 323 return -1; 324 } 325 326 /** 327 * Begin the process of restoring data from backup. See the 328 * {@link android.app.backup.RestoreSession} class for documentation on that process. 329 * @hide 330 */ 331 @SystemApi 332 @RequiresPermission(android.Manifest.permission.BACKUP) beginRestoreSession()333 public RestoreSession beginRestoreSession() { 334 RestoreSession session = null; 335 checkServiceBinder(); 336 if (sService != null) { 337 try { 338 // All packages, current transport 339 IRestoreSession binder = 340 sService.beginRestoreSessionForUser(mContext.getUserId(), null, null); 341 if (binder != null) { 342 session = new RestoreSession(mContext, binder); 343 } 344 } catch (RemoteException e) { 345 Log.e(TAG, "beginRestoreSession() couldn't connect"); 346 } 347 } 348 return session; 349 } 350 351 /** 352 * Enable/disable the backup service entirely. When disabled, no backup 353 * or restore operations will take place. Data-changed notifications will 354 * still be observed and collected, however, so that changes made while the 355 * mechanism was disabled will still be backed up properly if it is enabled 356 * at some point in the future. 357 * 358 * @hide 359 */ 360 @SystemApi 361 @RequiresPermission(android.Manifest.permission.BACKUP) setBackupEnabled(boolean isEnabled)362 public void setBackupEnabled(boolean isEnabled) { 363 checkServiceBinder(); 364 if (sService != null) { 365 try { 366 sService.setBackupEnabled(isEnabled); 367 } catch (RemoteException e) { 368 Log.e(TAG, "setBackupEnabled() couldn't connect"); 369 } 370 } 371 } 372 373 /** 374 * Report whether the backup mechanism is currently enabled. 375 * 376 * @hide 377 */ 378 @SystemApi 379 @RequiresPermission(android.Manifest.permission.BACKUP) isBackupEnabled()380 public boolean isBackupEnabled() { 381 checkServiceBinder(); 382 if (sService != null) { 383 try { 384 return sService.isBackupEnabled(); 385 } catch (RemoteException e) { 386 Log.e(TAG, "isBackupEnabled() couldn't connect"); 387 } 388 } 389 return false; 390 } 391 392 /** 393 * Report whether the backup mechanism is currently active. 394 * When it is inactive, the device will not perform any backup operations, nor will it 395 * deliver data for restore, although clients can still safely call BackupManager methods. 396 * 397 * @hide 398 */ 399 @SystemApi 400 @RequiresPermission(android.Manifest.permission.BACKUP) isBackupServiceActive(UserHandle user)401 public boolean isBackupServiceActive(UserHandle user) { 402 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, 403 "isBackupServiceActive"); 404 checkServiceBinder(); 405 if (sService != null) { 406 try { 407 return sService.isBackupServiceActive(user.getIdentifier()); 408 } catch (RemoteException e) { 409 Log.e(TAG, "isBackupEnabled() couldn't connect"); 410 } 411 } 412 return false; 413 } 414 415 /** 416 * Enable/disable data restore at application install time. When enabled, app 417 * installation will include an attempt to fetch the app's historical data from 418 * the archival restore dataset (if any). When disabled, no such attempt will 419 * be made. 420 * 421 * @hide 422 */ 423 @SystemApi 424 @RequiresPermission(android.Manifest.permission.BACKUP) setAutoRestore(boolean isEnabled)425 public void setAutoRestore(boolean isEnabled) { 426 checkServiceBinder(); 427 if (sService != null) { 428 try { 429 sService.setAutoRestore(isEnabled); 430 } catch (RemoteException e) { 431 Log.e(TAG, "setAutoRestore() couldn't connect"); 432 } 433 } 434 } 435 436 /** 437 * Identify the currently selected transport. 438 * @return The name of the currently active backup transport. In case of 439 * failure or if no transport is currently active, this method returns {@code null}. 440 * 441 * @hide 442 */ 443 @SystemApi 444 @RequiresPermission(android.Manifest.permission.BACKUP) getCurrentTransport()445 public String getCurrentTransport() { 446 checkServiceBinder(); 447 if (sService != null) { 448 try { 449 return sService.getCurrentTransport(); 450 } catch (RemoteException e) { 451 Log.e(TAG, "getCurrentTransport() couldn't connect"); 452 } 453 } 454 return null; 455 } 456 457 /** 458 * Returns the {@link ComponentName} of the host service of the selected transport or {@code 459 * null} if no transport selected or if the transport selected is not registered. 460 * 461 * @hide 462 */ 463 @SystemApi 464 @RequiresPermission(android.Manifest.permission.BACKUP) 465 @Nullable getCurrentTransportComponent()466 public ComponentName getCurrentTransportComponent() { 467 checkServiceBinder(); 468 if (sService != null) { 469 try { 470 return sService.getCurrentTransportComponentForUser(mContext.getUserId()); 471 } catch (RemoteException e) { 472 Log.e(TAG, "getCurrentTransportComponent() couldn't connect"); 473 } 474 } 475 return null; 476 } 477 478 /** 479 * Request a list of all available backup transports' names. 480 * 481 * @hide 482 */ 483 @SystemApi 484 @RequiresPermission(android.Manifest.permission.BACKUP) listAllTransports()485 public String[] listAllTransports() { 486 checkServiceBinder(); 487 if (sService != null) { 488 try { 489 return sService.listAllTransports(); 490 } catch (RemoteException e) { 491 Log.e(TAG, "listAllTransports() couldn't connect"); 492 } 493 } 494 return null; 495 } 496 497 /** 498 * Update the attributes of the transport identified by {@code transportComponent}. If the 499 * specified transport has not been bound at least once (for registration), this call will be 500 * ignored. Only the host process of the transport can change its description, otherwise a 501 * {@link SecurityException} will be thrown. 502 * 503 * @param transportComponent The identity of the transport being described. 504 * @param name A {@link String} with the new name for the transport. This is NOT for 505 * identification. MUST NOT be {@code null}. 506 * @param configurationIntent An {@link Intent} that can be passed to {@link 507 * Context#startActivity} in order to launch the transport's configuration UI. It may be 508 * {@code null} if the transport does not offer any user-facing configuration UI. 509 * @param currentDestinationString A {@link String} describing the destination to which the 510 * transport is currently sending data. MUST NOT be {@code null}. 511 * @param dataManagementIntent An {@link Intent} that can be passed to {@link 512 * Context#startActivity} in order to launch the transport's data-management UI. It may be 513 * {@code null} if the transport does not offer any user-facing data management UI. 514 * @param dataManagementLabel A {@link String} to be used as the label for the transport's data 515 * management affordance. This MUST be {@code null} when dataManagementIntent is {@code 516 * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. 517 * @throws SecurityException If the UID of the calling process differs from the package UID of 518 * {@code transportComponent} or if the caller does NOT have BACKUP permission. 519 * @deprecated Since Android Q, please use the variant {@link 520 * #updateTransportAttributes(ComponentName, String, Intent, String, Intent, CharSequence)} 521 * instead. 522 * @hide 523 */ 524 @Deprecated 525 @SystemApi 526 @RequiresPermission(android.Manifest.permission.BACKUP) updateTransportAttributes( @onNull ComponentName transportComponent, @NonNull String name, @Nullable Intent configurationIntent, @NonNull String currentDestinationString, @Nullable Intent dataManagementIntent, @Nullable String dataManagementLabel)527 public void updateTransportAttributes( 528 @NonNull ComponentName transportComponent, 529 @NonNull String name, 530 @Nullable Intent configurationIntent, 531 @NonNull String currentDestinationString, 532 @Nullable Intent dataManagementIntent, 533 @Nullable String dataManagementLabel) { 534 updateTransportAttributes( 535 transportComponent, 536 name, 537 configurationIntent, 538 currentDestinationString, 539 dataManagementIntent, 540 (CharSequence) dataManagementLabel); 541 } 542 543 /** 544 * Update the attributes of the transport identified by {@code transportComponent}. If the 545 * specified transport has not been bound at least once (for registration), this call will be 546 * ignored. Only the host process of the transport can change its description, otherwise a 547 * {@link SecurityException} will be thrown. 548 * 549 * @param transportComponent The identity of the transport being described. 550 * @param name A {@link String} with the new name for the transport. This is NOT for 551 * identification. MUST NOT be {@code null}. 552 * @param configurationIntent An {@link Intent} that can be passed to {@link 553 * Context#startActivity} in order to launch the transport's configuration UI. It may be 554 * {@code null} if the transport does not offer any user-facing configuration UI. 555 * @param currentDestinationString A {@link String} describing the destination to which the 556 * transport is currently sending data. MUST NOT be {@code null}. 557 * @param dataManagementIntent An {@link Intent} that can be passed to {@link 558 * Context#startActivity} in order to launch the transport's data-management UI. It may be 559 * {@code null} if the transport does not offer any user-facing data management UI. 560 * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's 561 * data management affordance. This MUST be {@code null} when dataManagementIntent is {@code 562 * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. 563 * @throws SecurityException If the UID of the calling process differs from the package UID of 564 * {@code transportComponent} or if the caller does NOT have BACKUP permission. 565 * @hide 566 */ 567 @SystemApi 568 @RequiresPermission(android.Manifest.permission.BACKUP) updateTransportAttributes( @onNull ComponentName transportComponent, @NonNull String name, @Nullable Intent configurationIntent, @NonNull String currentDestinationString, @Nullable Intent dataManagementIntent, @Nullable CharSequence dataManagementLabel)569 public void updateTransportAttributes( 570 @NonNull ComponentName transportComponent, 571 @NonNull String name, 572 @Nullable Intent configurationIntent, 573 @NonNull String currentDestinationString, 574 @Nullable Intent dataManagementIntent, 575 @Nullable CharSequence dataManagementLabel) { 576 checkServiceBinder(); 577 if (sService != null) { 578 try { 579 sService.updateTransportAttributesForUser( 580 mContext.getUserId(), 581 transportComponent, 582 name, 583 configurationIntent, 584 currentDestinationString, 585 dataManagementIntent, 586 dataManagementLabel); 587 } catch (RemoteException e) { 588 Log.e(TAG, "describeTransport() couldn't connect"); 589 } 590 } 591 } 592 593 /** 594 * Specify the current backup transport. 595 * 596 * @param transport The name of the transport to select. This should be one 597 * of the names returned by {@link #listAllTransports()}. This is the String returned by 598 * {@link BackupTransport#name()} for the particular transport. 599 * @return The name of the previously selected transport. If the given transport 600 * name is not one of the currently available transports, no change is made to 601 * the current transport setting and the method returns null. 602 * 603 * @hide 604 */ 605 @Deprecated 606 @SystemApi 607 @RequiresPermission(android.Manifest.permission.BACKUP) selectBackupTransport(String transport)608 public String selectBackupTransport(String transport) { 609 checkServiceBinder(); 610 if (sService != null) { 611 try { 612 return sService.selectBackupTransport(transport); 613 } catch (RemoteException e) { 614 Log.e(TAG, "selectBackupTransport() couldn't connect"); 615 } 616 } 617 return null; 618 } 619 620 /** 621 * Specify the current backup transport and get notified when the transport is ready to be used. 622 * This method is async because BackupManager might need to bind to the specified transport 623 * which is in a separate process. 624 * 625 * @param transport ComponentName of the service hosting the transport. This is different from 626 * the transport's name that is returned by {@link BackupTransport#name()}. 627 * @param listener A listener object to get a callback on the transport being selected. 628 * 629 * @hide 630 */ 631 @SystemApi 632 @RequiresPermission(android.Manifest.permission.BACKUP) selectBackupTransport(ComponentName transport, SelectBackupTransportCallback listener)633 public void selectBackupTransport(ComponentName transport, 634 SelectBackupTransportCallback listener) { 635 checkServiceBinder(); 636 if (sService != null) { 637 try { 638 SelectTransportListenerWrapper wrapper = listener == null ? 639 null : new SelectTransportListenerWrapper(mContext, listener); 640 sService.selectBackupTransportAsyncForUser( 641 mContext.getUserId(), transport, wrapper); 642 } catch (RemoteException e) { 643 Log.e(TAG, "selectBackupTransportAsync() couldn't connect"); 644 } 645 } 646 } 647 648 /** 649 * Schedule an immediate backup attempt for all pending key/value updates. This 650 * is primarily intended for transports to use when they detect a suitable 651 * opportunity for doing a backup pass. If there are no pending updates to 652 * be sent, no action will be taken. Even if some updates are pending, the 653 * transport will still be asked to confirm via the usual requestBackupTime() 654 * method. 655 * 656 * @hide 657 */ 658 @SystemApi 659 @RequiresPermission(android.Manifest.permission.BACKUP) backupNow()660 public void backupNow() { 661 checkServiceBinder(); 662 if (sService != null) { 663 try { 664 sService.backupNow(); 665 } catch (RemoteException e) { 666 Log.e(TAG, "backupNow() couldn't connect"); 667 } 668 } 669 } 670 671 /** 672 * Ask the framework which dataset, if any, the given package's data would be 673 * restored from if we were to install it right now. 674 * 675 * @param packageName The name of the package whose most-suitable dataset we 676 * wish to look up 677 * @return The dataset token from which a restore should be attempted, or zero if 678 * no suitable data is available. 679 * 680 * @hide 681 */ 682 @SystemApi 683 @RequiresPermission(android.Manifest.permission.BACKUP) getAvailableRestoreToken(String packageName)684 public long getAvailableRestoreToken(String packageName) { 685 checkServiceBinder(); 686 if (sService != null) { 687 try { 688 return sService.getAvailableRestoreTokenForUser(mContext.getUserId(), packageName); 689 } catch (RemoteException e) { 690 Log.e(TAG, "getAvailableRestoreToken() couldn't connect"); 691 } 692 } 693 return 0; 694 } 695 696 /** 697 * Ask the framework whether this app is eligible for backup. 698 * 699 * @param packageName The name of the package. 700 * @return Whether this app is eligible for backup. 701 * 702 * @hide 703 */ 704 @SystemApi 705 @RequiresPermission(android.Manifest.permission.BACKUP) isAppEligibleForBackup(String packageName)706 public boolean isAppEligibleForBackup(String packageName) { 707 checkServiceBinder(); 708 if (sService != null) { 709 try { 710 return sService.isAppEligibleForBackupForUser(mContext.getUserId(), packageName); 711 } catch (RemoteException e) { 712 Log.e(TAG, "isAppEligibleForBackup(pkg) couldn't connect"); 713 } 714 } 715 return false; 716 } 717 718 /** 719 * Request an immediate backup, providing an observer to which results of the backup operation 720 * will be published. The Android backup system will decide for each package whether it will 721 * be full app data backup or key/value-pair-based backup. 722 * 723 * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all 724 * provided packages using the remote transport. 725 * 726 * @param packages List of package names to backup. 727 * @param observer The {@link BackupObserver} to receive callbacks during the backup 728 * operation. Could be {@code null}. 729 * @return {@link BackupManager#SUCCESS} on success; nonzero on error. 730 * @exception IllegalArgumentException on null or empty {@code packages} param. 731 * 732 * @hide 733 */ 734 @SystemApi 735 @RequiresPermission(android.Manifest.permission.BACKUP) requestBackup(String[] packages, BackupObserver observer)736 public int requestBackup(String[] packages, BackupObserver observer) { 737 return requestBackup(packages, observer, null, 0); 738 } 739 740 /** 741 * Request an immediate backup, providing an observer to which results of the backup operation 742 * will be published. The Android backup system will decide for each package whether it will 743 * be full app data backup or key/value-pair-based backup. 744 * 745 * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all 746 * provided packages using the remote transport. 747 * 748 * @param packages List of package names to backup. 749 * @param observer The {@link BackupObserver} to receive callbacks during the backup 750 * operation. Could be {@code null}. 751 * @param monitor The {@link BackupManagerMonitorWrapper} to receive callbacks of important 752 * events during the backup operation. Could be {@code null}. 753 * @param flags {@link #FLAG_NON_INCREMENTAL_BACKUP}. 754 * @return {@link BackupManager#SUCCESS} on success; nonzero on error. 755 * @throws IllegalArgumentException on null or empty {@code packages} param. 756 * @hide 757 */ 758 @SystemApi 759 @RequiresPermission(android.Manifest.permission.BACKUP) requestBackup(String[] packages, BackupObserver observer, BackupManagerMonitor monitor, int flags)760 public int requestBackup(String[] packages, BackupObserver observer, 761 BackupManagerMonitor monitor, int flags) { 762 checkServiceBinder(); 763 if (sService != null) { 764 try { 765 BackupObserverWrapper observerWrapper = observer == null 766 ? null 767 : new BackupObserverWrapper(mContext, observer); 768 BackupManagerMonitorWrapper monitorWrapper = monitor == null 769 ? null 770 : new BackupManagerMonitorWrapper(monitor); 771 return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags); 772 } catch (RemoteException e) { 773 Log.e(TAG, "requestBackup() couldn't connect"); 774 } 775 } 776 return -1; 777 } 778 779 /** 780 * Cancel all running backups. After this call returns, no currently running backups will 781 * interact with the selected transport. 782 * 783 * @hide 784 */ 785 @SystemApi 786 @RequiresPermission(android.Manifest.permission.BACKUP) cancelBackups()787 public void cancelBackups() { 788 checkServiceBinder(); 789 if (sService != null) { 790 try { 791 sService.cancelBackups(); 792 } catch (RemoteException e) { 793 Log.e(TAG, "cancelBackups() couldn't connect."); 794 } 795 } 796 } 797 798 /** 799 * Returns a {@link UserHandle} for the user that has {@code ancestralSerialNumber} as the 800 * serial number of the its ancestral work profile or {@code null} if there is none. 801 * 802 * <p> The ancestral serial number will have a corresponding {@link UserHandle} if the device 803 * has a work profile that was restored from another work profile with serial number 804 * {@code ancestralSerialNumber}. 805 * 806 * @see android.os.UserManager#getSerialNumberForUser(UserHandle) 807 */ 808 @Nullable getUserForAncestralSerialNumber(long ancestralSerialNumber)809 public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) { 810 checkServiceBinder(); 811 if (sService != null) { 812 try { 813 return sService.getUserForAncestralSerialNumber(ancestralSerialNumber); 814 } catch (RemoteException e) { 815 Log.e(TAG, "getUserForAncestralSerialNumber() couldn't connect"); 816 } 817 } 818 return null; 819 } 820 821 /** 822 * Sets the ancestral work profile for the calling user. 823 * 824 * <p> The ancestral work profile corresponds to the profile that was used to restore to the 825 * callers profile. 826 * @hide 827 */ 828 @SystemApi 829 @RequiresPermission(android.Manifest.permission.BACKUP) setAncestralSerialNumber(long ancestralSerialNumber)830 public void setAncestralSerialNumber(long ancestralSerialNumber) { 831 checkServiceBinder(); 832 if (sService != null) { 833 try { 834 sService.setAncestralSerialNumber(ancestralSerialNumber); 835 } catch (RemoteException e) { 836 Log.e(TAG, "setAncestralSerialNumber() couldn't connect"); 837 } 838 } 839 } 840 841 /** 842 * Returns an {@link Intent} for the specified transport's configuration UI. 843 * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, 844 * Intent, CharSequence)}. 845 * @param transportName The name of the registered transport. 846 * @hide 847 */ 848 @SystemApi 849 @TestApi 850 @RequiresPermission(android.Manifest.permission.BACKUP) getConfigurationIntent(String transportName)851 public Intent getConfigurationIntent(String transportName) { 852 checkServiceBinder(); 853 if (sService != null) { 854 try { 855 return sService.getConfigurationIntentForUser(mContext.getUserId(), transportName); 856 } catch (RemoteException e) { 857 Log.e(TAG, "getConfigurationIntent() couldn't connect"); 858 } 859 } 860 return null; 861 } 862 863 /** 864 * Returns a {@link String} describing where the specified transport is sending data. 865 * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, 866 * Intent, CharSequence)}. 867 * @param transportName The name of the registered transport. 868 * @hide 869 */ 870 @SystemApi 871 @TestApi 872 @RequiresPermission(android.Manifest.permission.BACKUP) getDestinationString(String transportName)873 public String getDestinationString(String transportName) { 874 checkServiceBinder(); 875 if (sService != null) { 876 try { 877 return sService.getDestinationStringForUser(mContext.getUserId(), transportName); 878 } catch (RemoteException e) { 879 Log.e(TAG, "getDestinationString() couldn't connect"); 880 } 881 } 882 return null; 883 } 884 885 /** 886 * Returns an {@link Intent} for the specified transport's data management UI. 887 * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String, 888 * Intent, CharSequence)}. 889 * @param transportName The name of the registered transport. 890 * @hide 891 */ 892 @SystemApi 893 @TestApi 894 @RequiresPermission(android.Manifest.permission.BACKUP) getDataManagementIntent(String transportName)895 public Intent getDataManagementIntent(String transportName) { 896 checkServiceBinder(); 897 if (sService != null) { 898 try { 899 return sService.getDataManagementIntentForUser(mContext.getUserId(), transportName); 900 } catch (RemoteException e) { 901 Log.e(TAG, "getDataManagementIntent() couldn't connect"); 902 } 903 } 904 return null; 905 } 906 907 /** 908 * Returns a {@link String} describing what the specified transport's data management intent is 909 * used for. This value is set by {@link #updateTransportAttributes(ComponentName, String, 910 * Intent, String, Intent, CharSequence)}. 911 * 912 * @param transportName The name of the registered transport. 913 * @deprecated Since Android Q, please use the variant {@link 914 * #getDataManagementIntentLabel(String)} instead. 915 * @hide 916 */ 917 @Deprecated 918 @SystemApi 919 @TestApi 920 @RequiresPermission(android.Manifest.permission.BACKUP) 921 @Nullable getDataManagementLabel(@onNull String transportName)922 public String getDataManagementLabel(@NonNull String transportName) { 923 CharSequence label = getDataManagementIntentLabel(transportName); 924 return label == null ? null : label.toString(); 925 } 926 927 /** 928 * Returns a {@link CharSequence} describing what the specified transport's data management 929 * intent is used for. This value is set by {@link #updateTransportAttributes(ComponentName, 930 * String, Intent, String, Intent, CharSequence)}. 931 * 932 * @param transportName The name of the registered transport. 933 * @hide 934 */ 935 @SystemApi 936 @TestApi 937 @RequiresPermission(android.Manifest.permission.BACKUP) 938 @Nullable getDataManagementIntentLabel(@onNull String transportName)939 public CharSequence getDataManagementIntentLabel(@NonNull String transportName) { 940 checkServiceBinder(); 941 if (sService != null) { 942 try { 943 return sService.getDataManagementLabelForUser(mContext.getUserId(), transportName); 944 } catch (RemoteException e) { 945 Log.e(TAG, "getDataManagementIntentLabel() couldn't connect"); 946 } 947 } 948 return null; 949 } 950 951 /* 952 * We wrap incoming binder calls with a private class implementation that 953 * redirects them into main-thread actions. This serializes the backup 954 * progress callbacks nicely within the usual main-thread lifecycle pattern. 955 */ 956 private class BackupObserverWrapper extends IBackupObserver.Stub { 957 final Handler mHandler; 958 final BackupObserver mObserver; 959 960 static final int MSG_UPDATE = 1; 961 static final int MSG_RESULT = 2; 962 static final int MSG_FINISHED = 3; 963 BackupObserverWrapper(Context context, BackupObserver observer)964 BackupObserverWrapper(Context context, BackupObserver observer) { 965 mHandler = new Handler(context.getMainLooper()) { 966 @Override 967 public void handleMessage(Message msg) { 968 switch (msg.what) { 969 case MSG_UPDATE: 970 Pair<String, BackupProgress> obj = 971 (Pair<String, BackupProgress>) msg.obj; 972 mObserver.onUpdate(obj.first, obj.second); 973 break; 974 case MSG_RESULT: 975 mObserver.onResult((String)msg.obj, msg.arg1); 976 break; 977 case MSG_FINISHED: 978 mObserver.backupFinished(msg.arg1); 979 break; 980 default: 981 Log.w(TAG, "Unknown message: " + msg); 982 break; 983 } 984 } 985 }; 986 mObserver = observer; 987 } 988 989 // Binder calls into this object just enqueue on the main-thread handler 990 @Override onUpdate(String currentPackage, BackupProgress backupProgress)991 public void onUpdate(String currentPackage, BackupProgress backupProgress) { 992 mHandler.sendMessage( 993 mHandler.obtainMessage(MSG_UPDATE, Pair.create(currentPackage, backupProgress))); 994 } 995 996 @Override onResult(String currentPackage, int status)997 public void onResult(String currentPackage, int status) { 998 mHandler.sendMessage( 999 mHandler.obtainMessage(MSG_RESULT, status, 0, currentPackage)); 1000 } 1001 1002 @Override backupFinished(int status)1003 public void backupFinished(int status) { 1004 mHandler.sendMessage( 1005 mHandler.obtainMessage(MSG_FINISHED, status, 0)); 1006 } 1007 } 1008 1009 private class SelectTransportListenerWrapper extends ISelectBackupTransportCallback.Stub { 1010 1011 private final Handler mHandler; 1012 private final SelectBackupTransportCallback mListener; 1013 SelectTransportListenerWrapper(Context context, SelectBackupTransportCallback listener)1014 SelectTransportListenerWrapper(Context context, SelectBackupTransportCallback listener) { 1015 mHandler = new Handler(context.getMainLooper()); 1016 mListener = listener; 1017 } 1018 1019 @Override onSuccess(final String transportName)1020 public void onSuccess(final String transportName) { 1021 mHandler.post(new Runnable() { 1022 @Override 1023 public void run() { 1024 mListener.onSuccess(transportName); 1025 } 1026 }); 1027 } 1028 1029 @Override onFailure(final int reason)1030 public void onFailure(final int reason) { 1031 mHandler.post(new Runnable() { 1032 @Override 1033 public void run() { 1034 mListener.onFailure(reason); 1035 } 1036 }); 1037 } 1038 } 1039 1040 private class BackupManagerMonitorWrapper extends IBackupManagerMonitor.Stub { 1041 final BackupManagerMonitor mMonitor; 1042 BackupManagerMonitorWrapper(BackupManagerMonitor monitor)1043 BackupManagerMonitorWrapper(BackupManagerMonitor monitor) { 1044 mMonitor = monitor; 1045 } 1046 1047 @Override onEvent(final Bundle event)1048 public void onEvent(final Bundle event) throws RemoteException { 1049 mMonitor.onEvent(event); 1050 } 1051 } 1052 1053 } 1054