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