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