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