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