1 /* 2 * Copyright (C) 2014 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.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.content.Intent; 24 import android.content.pm.PackageInfo; 25 import android.os.IBinder; 26 import android.os.ParcelFileDescriptor; 27 import android.os.RemoteException; 28 29 import com.android.internal.backup.IBackupTransport; 30 import com.android.internal.backup.ITransportStatusCallback; 31 import com.android.internal.infra.AndroidFuture; 32 import com.android.server.backup.Flags; 33 34 import java.util.Arrays; 35 import java.util.List; 36 37 /** 38 * Concrete class that provides a stable-API bridge between IBackupTransport 39 * and its implementations. 40 * 41 * @hide 42 */ 43 @SystemApi 44 public class BackupTransport { 45 // Zero return always means things are okay. If returned from 46 // getNextFullRestoreDataChunk(), it means that no data could be delivered at 47 // this time, but the restore is still running and the caller should simply 48 // retry. 49 public static final int TRANSPORT_OK = 0; 50 51 // -1 is special; it is used in getNextFullRestoreDataChunk() to indicate that 52 // we've delivered the entire data stream for the current restore target. 53 public static final int NO_MORE_DATA = -1; 54 55 // Result codes that indicate real errors are negative and not -1 56 public static final int TRANSPORT_ERROR = -1000; 57 public static final int TRANSPORT_NOT_INITIALIZED = -1001; 58 public static final int TRANSPORT_PACKAGE_REJECTED = -1002; 59 public static final int AGENT_ERROR = -1003; 60 public static final int AGENT_UNKNOWN = -1004; 61 public static final int TRANSPORT_QUOTA_EXCEEDED = -1005; 62 63 /** 64 * Indicates that the transport cannot accept a diff backup for this package. 65 * 66 * <p>Backup manager should clear its state for this package and immediately retry a 67 * non-incremental backup. This might be used if the transport no longer has data for this 68 * package in its backing store. 69 * 70 * <p>This is only valid when backup manager called {@link 71 * #performBackup(PackageInfo, ParcelFileDescriptor, int)} with {@link #FLAG_INCREMENTAL}. 72 */ 73 public static final int TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED = -1006; 74 75 // Indicates that operation was initiated by user, not a scheduled one. 76 // Transport should ignore its own moratoriums for call with this flag set. 77 public static final int FLAG_USER_INITIATED = 1; 78 79 /** 80 * For key value backup, indicates that the backup data is a diff from a previous backup. The 81 * transport must apply this diff to an existing backup to build the new backup set. 82 * 83 * @see #performBackup(PackageInfo, ParcelFileDescriptor, int) 84 */ 85 public static final int FLAG_INCREMENTAL = 1 << 1; 86 87 /** 88 * For key value backup, indicates that the backup data is a complete set, not a diff from a 89 * previous backup. The transport should clear any previous backup when storing this backup. 90 * 91 * @see #performBackup(PackageInfo, ParcelFileDescriptor, int) 92 */ 93 public static final int FLAG_NON_INCREMENTAL = 1 << 2; 94 95 /** 96 * For key value backup, indicates that the backup contains no new data since the last backup 97 * attempt completed without any errors. The transport should use this to record that 98 * a successful backup attempt has been completed but no backup data has been changed. 99 * 100 * @see #performBackup(PackageInfo, ParcelFileDescriptor, int) 101 */ 102 public static final int FLAG_DATA_NOT_CHANGED = 1 << 3; 103 104 /** 105 * Used as a boolean extra in the binding intent of transports. We pass {@code true} to 106 * notify transports that the current connection is used for registering the transport. 107 */ 108 public static final String EXTRA_TRANSPORT_REGISTRATION = 109 "android.app.backup.extra.TRANSPORT_REGISTRATION"; 110 111 IBackupTransport mBinderImpl = new TransportImpl(); 112 getBinder()113 public IBinder getBinder() { 114 return mBinderImpl.asBinder(); 115 } 116 117 // ------------------------------------------------------------------------------------ 118 // Transport self-description and general configuration interfaces 119 // 120 121 /** 122 * Ask the transport for the name under which it should be registered. This will 123 * typically be its host service's component name, but need not be. 124 */ name()125 public String name() { 126 throw new UnsupportedOperationException("Transport name() not implemented"); 127 } 128 129 /** 130 * Ask the transport for an Intent that can be used to launch any internal 131 * configuration Activity that it wishes to present. For example, the transport 132 * may offer a UI for allowing the user to supply login credentials for the 133 * transport's off-device backend. 134 * 135 * <p>If the transport does not supply any user-facing configuration UI, it should 136 * return {@code null} from this method. 137 * 138 * @return An Intent that can be passed to Context.startActivity() in order to 139 * launch the transport's configuration UI. This method will return {@code null} 140 * if the transport does not offer any user-facing configuration UI. 141 */ configurationIntent()142 public Intent configurationIntent() { 143 return null; 144 } 145 146 /** 147 * On demand, supply a one-line string that can be shown to the user that 148 * describes the current backend destination. For example, a transport that 149 * can potentially associate backup data with arbitrary user accounts should 150 * include the name of the currently-active account here. 151 * 152 * @return A string describing the destination to which the transport is currently 153 * sending data. This method should not return null. 154 */ currentDestinationString()155 public String currentDestinationString() { 156 throw new UnsupportedOperationException( 157 "Transport currentDestinationString() not implemented"); 158 } 159 160 /** 161 * Ask the transport for an Intent that can be used to launch a more detailed 162 * secondary data management activity. For example, the configuration intent might 163 * be one for allowing the user to select which account they wish to associate 164 * their backups with, and the management intent might be one which presents a 165 * UI for managing the data on the backend. 166 * 167 * <p>In the Settings UI, the configuration intent will typically be invoked 168 * when the user taps on the preferences item labeled with the current 169 * destination string, and the management intent will be placed in an overflow 170 * menu labelled with the management label string. 171 * 172 * <p>If the transport does not supply any user-facing data management 173 * UI, then it should return {@code null} from this method. 174 * 175 * @return An intent that can be passed to Context.startActivity() in order to 176 * launch the transport's data-management UI. This method will return 177 * {@code null} if the transport does not offer any user-facing data 178 * management UI. 179 */ dataManagementIntent()180 public Intent dataManagementIntent() { 181 return null; 182 } 183 184 /** 185 * On demand, supply a short string that can be shown to the user as the label on an overflow 186 * menu item used to invoke the data management UI. 187 * 188 * @return A string to be used as the label for the transport's data management affordance. If 189 * the transport supplies a data management intent, this method must not return {@code 190 * null}. 191 * @deprecated Since Android Q, please use the variant {@link #dataManagementIntentLabel()} 192 * instead. 193 */ 194 @Deprecated 195 @Nullable dataManagementLabel()196 public String dataManagementLabel() { 197 throw new UnsupportedOperationException( 198 "Transport dataManagementLabel() not implemented"); 199 } 200 201 /** 202 * On demand, supply a short CharSequence that can be shown to the user as the label on an 203 * overflow menu item used to invoke the data management UI. 204 * 205 * @return A CharSequence to be used as the label for the transport's data management 206 * affordance. If the transport supplies a data management intent, this method must not 207 * return {@code null}. 208 */ 209 @Nullable dataManagementIntentLabel()210 public CharSequence dataManagementIntentLabel() { 211 return dataManagementLabel(); 212 } 213 214 /** 215 * Ask the transport where, on local device storage, to keep backup state blobs. 216 * This is per-transport so that mock transports used for testing can coexist with 217 * "live" backup services without interfering with the live bookkeeping. The 218 * returned string should be a name that is expected to be unambiguous among all 219 * available backup transports; the name of the class implementing the transport 220 * is a good choice. 221 * 222 * @return A unique name, suitable for use as a file or directory name, that the 223 * Backup Manager could use to disambiguate state files associated with 224 * different backup transports. 225 */ transportDirName()226 public String transportDirName() { 227 throw new UnsupportedOperationException( 228 "Transport transportDirName() not implemented"); 229 } 230 231 // ------------------------------------------------------------------------------------ 232 // Device-level operations common to both key/value and full-data storage 233 234 /** 235 * Initialize the server side storage for this device, erasing all stored data. 236 * The transport may send the request immediately, or may buffer it. After 237 * this is called, {@link #finishBackup} will be called to ensure the request 238 * is sent and received successfully. 239 * 240 * <p>If the transport returns anything other than TRANSPORT_OK from this method, 241 * the OS will halt the current initialize operation and schedule a retry in the 242 * near future. Even if the transport is in a state such that attempting to 243 * "initialize" the backend storage is meaningless -- for example, if there is 244 * no current live dataset at all, or there is no authenticated account under which 245 * to store the data remotely -- the transport should return TRANSPORT_OK here 246 * and treat the initializeDevice() / finishBackup() pair as a graceful no-op. 247 * 248 * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far) or 249 * {@link BackupTransport#TRANSPORT_ERROR} (to retry following network error 250 * or other failure). 251 */ initializeDevice()252 public int initializeDevice() { 253 return BackupTransport.TRANSPORT_ERROR; 254 } 255 256 /** 257 * Erase the given application's data from the backup destination. This clears 258 * out the given package's data from the current backup set, making it as though 259 * the app had never yet been backed up. After this is called, {@link finishBackup} 260 * must be called to ensure that the operation is recorded successfully. 261 * 262 * @return the same error codes as {@link #performBackup}. 263 */ clearBackupData(PackageInfo packageInfo)264 public int clearBackupData(PackageInfo packageInfo) { 265 return BackupTransport.TRANSPORT_ERROR; 266 } 267 268 /** 269 * Finish sending application data to the backup destination. This must be 270 * called after {@link #performBackup}, {@link #performFullBackup}, or {@link clearBackupData} 271 * to ensure that all data is sent and the operation properly finalized. Only when this 272 * method returns true can a backup be assumed to have succeeded. 273 * 274 * @return the same error codes as {@link #performBackup} or {@link #performFullBackup}. 275 */ finishBackup()276 public int finishBackup() { 277 return BackupTransport.TRANSPORT_ERROR; 278 } 279 280 // ------------------------------------------------------------------------------------ 281 // Key/value incremental backup support interfaces 282 283 /** 284 * Verify that this is a suitable time for a key/value backup pass. This should return zero 285 * if a backup is reasonable right now, some positive value otherwise. This method 286 * will be called outside of the {@link #performBackup}/{@link #finishBackup} pair. 287 * 288 * <p>If this is not a suitable time for a backup, the transport should return a 289 * backoff delay, in milliseconds, after which the Backup Manager should try again. 290 * 291 * @return Zero if this is a suitable time for a backup pass, or a positive time delay 292 * in milliseconds to suggest deferring the backup pass for a while. 293 */ requestBackupTime()294 public long requestBackupTime() { 295 return 0; 296 } 297 298 /** 299 * Send one application's key/value data update to the backup destination. The 300 * transport may send the data immediately, or may buffer it. If this method returns 301 * {@link #TRANSPORT_OK}, {@link #finishBackup} will then be called to ensure the data 302 * is sent and recorded successfully. 303 * 304 * If the backup data is a diff against the previous backup then the flag {@link 305 * BackupTransport#FLAG_INCREMENTAL} will be set. Otherwise, if the data is a complete backup 306 * set then {@link BackupTransport#FLAG_NON_INCREMENTAL} will be set. Before P neither flag will 307 * be set regardless of whether the backup is incremental or not. 308 * 309 * <p>If {@link BackupTransport#FLAG_INCREMENTAL} is set and the transport does not have data 310 * for this package in its storage backend then it cannot apply the incremental diff. Thus it 311 * should return {@link BackupTransport#TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED} to indicate 312 * that backup manager should delete its state and retry the package as a non-incremental 313 * backup. Before P, or if this is a non-incremental backup, then this return code is equivalent 314 * to {@link BackupTransport#TRANSPORT_ERROR}. 315 * 316 * @param packageInfo The identity of the application whose data is being backed up. 317 * This specifically includes the signature list for the package. 318 * @param inFd Descriptor of file with data that resulted from invoking the application's 319 * BackupService.doBackup() method. This may be a pipe rather than a file on 320 * persistent media, so it may not be seekable. 321 * @param flags a combination of {@link BackupTransport#FLAG_USER_INITIATED}, {@link 322 * BackupTransport#FLAG_NON_INCREMENTAL}, {@link BackupTransport#FLAG_INCREMENTAL}, 323 * {@link BackupTransport#FLAG_DATA_NOT_CHANGED},or 0. 324 * @return one of {@link BackupTransport#TRANSPORT_OK} (OK so far), 325 * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED} (to suppress backup of this 326 * specific package, but allow others to proceed), 327 * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure), {@link 328 * BackupTransport#TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED} (if the transport cannot accept 329 * an incremental backup for this package), or {@link 330 * BackupTransport#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has become lost due to 331 * inactivity purge or some other reason and needs re-initializing) 332 */ performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags)333 public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags) { 334 return performBackup(packageInfo, inFd); 335 } 336 337 /** 338 * Legacy version of {@link #performBackup(PackageInfo, ParcelFileDescriptor, int)} that 339 * doesn't use flags parameter. 340 */ performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd)341 public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) { 342 return BackupTransport.TRANSPORT_ERROR; 343 } 344 345 // ------------------------------------------------------------------------------------ 346 // Key/value dataset restore interfaces 347 348 /** 349 * Get the set of all backups currently available over this transport. 350 * 351 * @return Descriptions of the set of restore images available for this device, 352 * or null if an error occurred (the attempt should be rescheduled). 353 **/ getAvailableRestoreSets()354 public RestoreSet[] getAvailableRestoreSets() { 355 return null; 356 } 357 358 /** 359 * Get the identifying token of the backup set currently being stored from 360 * this device. This is used in the case of applications wishing to restore 361 * their last-known-good data. 362 * 363 * @return A token that can be passed to {@link #startRestore}, or 0 if there 364 * is no backup set available corresponding to the current device state. 365 */ getCurrentRestoreSet()366 public long getCurrentRestoreSet() { 367 return 0; 368 } 369 370 /** 371 * Start restoring application data from backup. After calling this function, 372 * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData} 373 * to walk through the actual application data. 374 * 375 * @param token A backup token as returned by {@link #getAvailableRestoreSets} 376 * or {@link #getCurrentRestoreSet}. 377 * @param packages List of applications to restore (if data is available). 378 * Application data will be restored in the order given. 379 * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far, call 380 * {@link #nextRestorePackage}) or {@link BackupTransport#TRANSPORT_ERROR} 381 * (an error occurred, the restore should be aborted and rescheduled). 382 */ startRestore(long token, PackageInfo[] packages)383 public int startRestore(long token, PackageInfo[] packages) { 384 return BackupTransport.TRANSPORT_ERROR; 385 } 386 387 /** 388 * Get the package name of the next application with data in the backup store, plus 389 * a description of the structure of the restored archive: either TYPE_KEY_VALUE for 390 * an original-API key/value dataset, or TYPE_FULL_STREAM for a tarball-type archive stream. 391 * 392 * <p>If the package name in the returned RestoreDescription object is the singleton 393 * {@link RestoreDescription#NO_MORE_PACKAGES}, it indicates that no further data is available 394 * in the current restore session: all packages described in startRestore() have been 395 * processed. 396 * 397 * <p>If this method returns {@code null}, it means that a transport-level error has 398 * occurred and the entire restore operation should be abandoned. 399 * 400 * <p class="note">The OS may call {@link #nextRestorePackage()} multiple times 401 * before calling either {@link #getRestoreData(ParcelFileDescriptor) getRestoreData()} 402 * or {@link #getNextFullRestoreDataChunk(ParcelFileDescriptor) getNextFullRestoreDataChunk()}. 403 * It does this when it has determined that it needs to skip restore of one or more 404 * packages. The transport should not actually transfer any restore data for 405 * the given package in response to {@link #nextRestorePackage()}, but rather wait 406 * for an explicit request before doing so. 407 * 408 * @return A RestoreDescription object containing the name of one of the packages 409 * supplied to {@link #startRestore} plus an indicator of the data type of that 410 * restore data; or {@link RestoreDescription#NO_MORE_PACKAGES} to indicate that 411 * no more packages can be restored in this session; or {@code null} to indicate 412 * a transport-level error. 413 */ nextRestorePackage()414 public RestoreDescription nextRestorePackage() { 415 return null; 416 } 417 418 /** 419 * Get the data for the application returned by {@link #nextRestorePackage}, if that 420 * method reported {@link RestoreDescription#TYPE_KEY_VALUE} as its delivery type. 421 * If the package has only TYPE_FULL_STREAM data, then this method will return an 422 * error. 423 * 424 * @param data An open, writable file into which the key/value backup data should be stored. 425 * @return the same error codes as {@link #startRestore}. 426 */ getRestoreData(ParcelFileDescriptor outFd)427 public int getRestoreData(ParcelFileDescriptor outFd) { 428 return BackupTransport.TRANSPORT_ERROR; 429 } 430 431 /** 432 * End a restore session (aborting any in-process data transfer as necessary), 433 * freeing any resources and connections used during the restore process. 434 */ finishRestore()435 public void finishRestore() { 436 throw new UnsupportedOperationException( 437 "Transport finishRestore() not implemented"); 438 } 439 440 // ------------------------------------------------------------------------------------ 441 // Full backup interfaces 442 443 /** 444 * Verify that this is a suitable time for a full-data backup pass. This should return zero 445 * if a backup is reasonable right now, some positive value otherwise. This method 446 * will be called outside of the {@link #performFullBackup}/{@link #finishBackup} pair. 447 * 448 * <p>If this is not a suitable time for a backup, the transport should return a 449 * backoff delay, in milliseconds, after which the Backup Manager should try again. 450 * 451 * @return Zero if this is a suitable time for a backup pass, or a positive time delay 452 * in milliseconds to suggest deferring the backup pass for a while. 453 * 454 * @see #requestBackupTime() 455 */ requestFullBackupTime()456 public long requestFullBackupTime() { 457 return 0; 458 } 459 460 /** 461 * Begin the process of sending an application's full-data archive to the backend. 462 * The description of the package whose data will be delivered is provided, as well as 463 * the socket file descriptor on which the transport will receive the data itself. 464 * 465 * <p>If the package is not eligible for backup, the transport should return 466 * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED}. In this case the system will 467 * simply proceed with the next candidate if any, or finish the full backup operation 468 * if all apps have been processed. 469 * 470 * <p>After the transport returns {@link BackupTransport#TRANSPORT_OK} from this 471 * method, the OS will proceed to call {@link #sendBackupData()} one or more times 472 * to deliver the application's data as a streamed tarball. The transport should not 473 * read() from the socket except as instructed to via the {@link #sendBackupData(int)} 474 * method. 475 * 476 * <p>After all data has been delivered to the transport, the system will call 477 * {@link #finishBackup()}. At this point the transport should commit the data to 478 * its datastore, if appropriate, and close the socket that had been provided in 479 * {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}. 480 * 481 * <p class="note">If the transport returns TRANSPORT_OK from this method, then the 482 * OS will always provide a matching call to {@link #finishBackup()} even if sending 483 * data via {@link #sendBackupData(int)} failed at some point. 484 * 485 * @param targetPackage The package whose data is to follow. 486 * @param socket The socket file descriptor through which the data will be provided. 487 * If the transport returns {@link #TRANSPORT_PACKAGE_REJECTED} here, it must still 488 * close this file descriptor now; otherwise it should be cached for use during 489 * succeeding calls to {@link #sendBackupData(int)}, and closed in response to 490 * {@link #finishBackup()}. 491 * @param flags {@link BackupTransport#FLAG_USER_INITIATED} or 0. 492 * @return TRANSPORT_PACKAGE_REJECTED to indicate that the stated application is not 493 * to be backed up; TRANSPORT_OK to indicate that the OS may proceed with delivering 494 * backup data; TRANSPORT_ERROR to indicate a fatal error condition that precludes 495 * performing a backup at this time. 496 */ performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket, int flags)497 public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket, 498 int flags) { 499 return performFullBackup(targetPackage, socket); 500 } 501 502 /** 503 * Legacy version of {@link #performFullBackup(PackageInfo, ParcelFileDescriptor, int)} that 504 * doesn't use flags parameter. 505 */ performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket)506 public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) { 507 return BackupTransport.TRANSPORT_PACKAGE_REJECTED; 508 } 509 510 /** 511 * Called after {@link #performFullBackup} to make sure that the transport is willing to 512 * handle a full-data backup operation of the specified size on the current package. 513 * If the transport returns anything other than TRANSPORT_OK, the package's backup 514 * operation will be skipped (and {@link #finishBackup() invoked} with no data for that 515 * package being passed to {@link #sendBackupData}. 516 * 517 * <p class="note">The platform does no size-based rejection of full backup attempts on 518 * its own: it is always the responsibility of the transport to implement its own policy. 519 * In particular, even if the preflighted payload size is zero, the platform will still call 520 * this method and will proceed to back up an archive metadata header with no file content 521 * if this method returns TRANSPORT_OK. To avoid storing such payloads the transport 522 * must recognize this case and return TRANSPORT_PACKAGE_REJECTED. 523 * 524 * Added in {@link android.os.Build.VERSION_CODES#M}. 525 * 526 * @param size The estimated size of the full-data payload for this app. This includes 527 * manifest and archive format overhead, but is not guaranteed to be precise. 528 * @return TRANSPORT_OK if the platform is to proceed with the full-data backup, 529 * TRANSPORT_PACKAGE_REJECTED if the proposed payload size is too large for 530 * the transport to handle, or TRANSPORT_ERROR to indicate a fatal error 531 * condition that means the platform cannot perform a backup at this time. 532 */ checkFullBackupSize(long size)533 public int checkFullBackupSize(long size) { 534 return BackupTransport.TRANSPORT_OK; 535 } 536 537 /** 538 * Tells the transport to read {@code numBytes} bytes of data from the socket file 539 * descriptor provided in the {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)} 540 * call, and deliver those bytes to the datastore. 541 * 542 * @param numBytes The number of bytes of tarball data available to be read from the 543 * socket. 544 * @return TRANSPORT_OK on successful processing of the data; TRANSPORT_ERROR to 545 * indicate a fatal error situation. If an error is returned, the system will 546 * call finishBackup() and stop attempting backups until after a backoff and retry 547 * interval. 548 */ sendBackupData(int numBytes)549 public int sendBackupData(int numBytes) { 550 return BackupTransport.TRANSPORT_ERROR; 551 } 552 553 /** 554 * Tells the transport to cancel the currently-ongoing full backup operation. This 555 * will happen between {@link #performFullBackup()} and {@link #finishBackup()} 556 * if the OS needs to abort the backup operation for any reason, such as a crash in 557 * the application undergoing backup. 558 * 559 * <p>When it receives this call, the transport should discard any partial archive 560 * that it has stored so far. If possible it should also roll back to the previous 561 * known-good archive in its datastore. 562 * 563 * <p>If the transport receives this callback, it will <em>not</em> receive a 564 * call to {@link #finishBackup()}. It needs to tear down any ongoing backup state 565 * here. 566 */ cancelFullBackup()567 public void cancelFullBackup() { 568 throw new UnsupportedOperationException( 569 "Transport cancelFullBackup() not implemented"); 570 } 571 572 /** 573 * Ask the transport whether this app is eligible for backup. 574 * 575 * @param targetPackage The identity of the application. 576 * @param isFullBackup If set, transport should check if app is eligible for full data backup, 577 * otherwise to check if eligible for key-value backup. 578 * @return Whether this app is eligible for backup. 579 */ isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup)580 public boolean isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup) { 581 return true; 582 } 583 584 /** 585 * Ask the transport about current quota for backup size of the package. 586 * 587 * @param packageName ID of package to provide the quota. 588 * @param isFullBackup If set, transport should return limit for full data backup, otherwise 589 * for key-value backup. 590 * @return Current limit on backup size in bytes. 591 */ getBackupQuota(String packageName, boolean isFullBackup)592 public long getBackupQuota(String packageName, boolean isFullBackup) { 593 return Long.MAX_VALUE; 594 } 595 596 // ------------------------------------------------------------------------------------ 597 // Full restore interfaces 598 599 /** 600 * Ask the transport to provide data for the "current" package being restored. This 601 * is the package that was just reported by {@link #nextRestorePackage()} as having 602 * {@link RestoreDescription#TYPE_FULL_STREAM} data. 603 * 604 * The transport writes some data to the socket supplied to this call, and returns 605 * the number of bytes written. The system will then read that many bytes and 606 * stream them to the application's agent for restore, then will call this method again 607 * to receive the next chunk of the archive. This sequence will be repeated until the 608 * transport returns zero indicating that all of the package's data has been delivered 609 * (or returns a negative value indicating some sort of hard error condition at the 610 * transport level). 611 * 612 * <p>After this method returns zero, the system will then call 613 * {@link #nextRestorePackage()} to begin the restore process for the next 614 * application, and the sequence begins again. 615 * 616 * <p>The transport should always close this socket when returning from this method. 617 * Do not cache this socket across multiple calls or you may leak file descriptors. 618 * 619 * @param socket The file descriptor that the transport will use for delivering the 620 * streamed archive. The transport must close this socket in all cases when returning 621 * from this method. 622 * @return {@link #NO_MORE_DATA} when no more data for the current package is available. 623 * A positive value indicates the presence of that many bytes to be delivered to the app. 624 * A value of zero indicates that no data was deliverable at this time, but the restore 625 * is still running and the caller should retry. {@link #TRANSPORT_PACKAGE_REJECTED} 626 * means that the current package's restore operation should be aborted, but that 627 * the transport itself is still in a good state and so a multiple-package restore 628 * sequence can still be continued. Any other negative return value is treated as a 629 * fatal error condition that aborts all further restore operations on the current dataset. 630 */ getNextFullRestoreDataChunk(ParcelFileDescriptor socket)631 public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) { 632 return 0; 633 } 634 635 /** 636 * If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM} 637 * data for restore, it will invoke this method to tell the transport that it should 638 * abandon the data download for the current package. The OS will then either call 639 * {@link #nextRestorePackage()} again to move on to restoring the next package in the 640 * set being iterated over, or will call {@link #finishRestore()} to shut down the restore 641 * operation. 642 * 643 * @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the 644 * current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious 645 * transport-level failure. If the transport reports an error here, the entire restore 646 * operation will immediately be finished with no further attempts to restore app data. 647 */ abortFullRestore()648 public int abortFullRestore() { 649 return BackupTransport.TRANSPORT_OK; 650 } 651 652 /** 653 * Returns flags with additional information about the transport, which is accessible to the 654 * {@link android.app.backup.BackupAgent}. This allows the agent to decide what to do based on 655 * properties of the transport. 656 */ getTransportFlags()657 public int getTransportFlags() { 658 return 0; 659 } 660 661 /** 662 * Ask the transport for a {@link BackupManagerMonitor} instance which will be used by the 663 * framework to report logging events back to the transport. 664 * 665 * <p>Backups requested from outside the framework may pass in a monitor with the request, 666 * however backups initiated by the framework will call this method to retrieve one. 667 * 668 * @return {@link BackupManagerMonitor} or {@code null} if the transport implementation does not 669 * wish to receive the logging events. 670 */ 671 @Nullable getBackupManagerMonitor()672 public BackupManagerMonitor getBackupManagerMonitor() { 673 return null; 674 } 675 676 /** 677 * Ask the transport whether packages that are about to be backed up or restored should not be 678 * put into a restricted mode by the framework and started normally instead. 679 * 680 * @param operationType 0 for backup, 1 for restore. 681 * @return a subset of the {@code packageNames} passed in, indicating 682 * which packages should NOT be put into restricted mode for the given operation type. 683 */ 684 @NonNull 685 @FlaggedApi(Flags.FLAG_ENABLE_RESTRICTED_MODE_CHANGES) getPackagesThatShouldNotUseRestrictedMode( @onNull List<String> packageNames, @BackupAnnotations.OperationType int operationType)686 public List<String> getPackagesThatShouldNotUseRestrictedMode( 687 @NonNull List<String> packageNames, 688 @BackupAnnotations.OperationType int operationType) { 689 return List.of(); 690 } 691 692 /** 693 * Bridge between the actual IBackupTransport implementation and the stable API. If the 694 * binder interface needs to change, we use this layer to translate so that we can 695 * (if appropriate) decouple those framework-side changes from the BackupTransport 696 * implementations. 697 */ 698 class TransportImpl extends IBackupTransport.Stub { 699 700 @Override name(AndroidFuture<String> resultFuture)701 public void name(AndroidFuture<String> resultFuture) throws RemoteException { 702 try { 703 String result = BackupTransport.this.name(); 704 resultFuture.complete(result); 705 } catch (RuntimeException e) { 706 resultFuture.cancel(/* mayInterruptIfRunning */ true); 707 } 708 } 709 710 @Override configurationIntent(AndroidFuture<Intent> resultFuture)711 public void configurationIntent(AndroidFuture<Intent> resultFuture) 712 throws RemoteException { 713 try { 714 Intent result = BackupTransport.this.configurationIntent(); 715 resultFuture.complete(result); 716 } catch (RuntimeException e) { 717 resultFuture.cancel(/* mayInterruptIfRunning */ true); 718 } 719 } 720 721 @Override currentDestinationString(AndroidFuture<String> resultFuture)722 public void currentDestinationString(AndroidFuture<String> resultFuture) 723 throws RemoteException { 724 try { 725 String result = BackupTransport.this.currentDestinationString(); 726 resultFuture.complete(result); 727 } catch (RuntimeException e) { 728 resultFuture.cancel(/* mayInterruptIfRunning */ true); 729 } 730 } 731 732 @Override dataManagementIntent(AndroidFuture<Intent> resultFuture)733 public void dataManagementIntent(AndroidFuture<Intent> resultFuture) 734 throws RemoteException { 735 try { 736 Intent result = BackupTransport.this.dataManagementIntent(); 737 resultFuture.complete(result); 738 } catch (RuntimeException e) { 739 resultFuture.cancel(/* mayInterruptIfRunning */ true); 740 } 741 } 742 743 @Override dataManagementIntentLabel(AndroidFuture<CharSequence> resultFuture)744 public void dataManagementIntentLabel(AndroidFuture<CharSequence> resultFuture) 745 throws RemoteException { 746 try { 747 CharSequence result = BackupTransport.this.dataManagementIntentLabel(); 748 resultFuture.complete(result); 749 } catch (RuntimeException e) { 750 resultFuture.cancel(/* mayInterruptIfRunning */ true); 751 } 752 } 753 754 @Override transportDirName(AndroidFuture<String> resultFuture)755 public void transportDirName(AndroidFuture<String> resultFuture) throws RemoteException { 756 try { 757 String result = BackupTransport.this.transportDirName(); 758 resultFuture.complete(result); 759 } catch (RuntimeException e) { 760 resultFuture.cancel(/* mayInterruptIfRunning */ true); 761 } 762 } 763 764 @Override requestBackupTime(AndroidFuture<Long> resultFuture)765 public void requestBackupTime(AndroidFuture<Long> resultFuture) throws RemoteException { 766 try { 767 long result = BackupTransport.this.requestBackupTime(); 768 resultFuture.complete(result); 769 } catch (RuntimeException e) { 770 resultFuture.cancel(/* mayInterruptIfRunning */ true); 771 } 772 } 773 774 @Override initializeDevice(ITransportStatusCallback callback)775 public void initializeDevice(ITransportStatusCallback callback) throws RemoteException { 776 try { 777 int result = BackupTransport.this.initializeDevice(); 778 callback.onOperationCompleteWithStatus(result); 779 } catch (RuntimeException e) { 780 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 781 } 782 } 783 784 @Override performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags, ITransportStatusCallback callback)785 public void performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags, 786 ITransportStatusCallback callback) throws RemoteException { 787 try { 788 int result = BackupTransport.this.performBackup(packageInfo, inFd, flags); 789 callback.onOperationCompleteWithStatus(result); 790 } catch (RuntimeException e) { 791 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 792 } 793 } 794 795 @Override clearBackupData(PackageInfo packageInfo, ITransportStatusCallback callback)796 public void clearBackupData(PackageInfo packageInfo, ITransportStatusCallback callback) 797 throws RemoteException { 798 try { 799 int result = BackupTransport.this.clearBackupData(packageInfo); 800 callback.onOperationCompleteWithStatus(result); 801 } catch (RuntimeException e) { 802 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 803 } 804 } 805 806 @Override finishBackup(ITransportStatusCallback callback)807 public void finishBackup(ITransportStatusCallback callback) throws RemoteException { 808 try { 809 int result = BackupTransport.this.finishBackup(); 810 callback.onOperationCompleteWithStatus(result); 811 } catch (RuntimeException e) { 812 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 813 } 814 } 815 816 @Override getAvailableRestoreSets(AndroidFuture<List<RestoreSet>> resultFuture)817 public void getAvailableRestoreSets(AndroidFuture<List<RestoreSet>> resultFuture) 818 throws RemoteException { 819 try { 820 RestoreSet[] result = BackupTransport.this.getAvailableRestoreSets(); 821 resultFuture.complete(Arrays.asList(result)); 822 } catch (RuntimeException e) { 823 resultFuture.cancel(/* mayInterruptIfRunning */ true); 824 } 825 } 826 827 @Override getCurrentRestoreSet(AndroidFuture<Long> resultFuture)828 public void getCurrentRestoreSet(AndroidFuture<Long> resultFuture) 829 throws RemoteException { 830 try { 831 long result = BackupTransport.this.getCurrentRestoreSet(); 832 resultFuture.complete(result); 833 } catch (RuntimeException e) { 834 resultFuture.cancel(/* mayInterruptIfRunning */ true); 835 } 836 } 837 838 @Override startRestore(long token, PackageInfo[] packages, ITransportStatusCallback callback)839 public void startRestore(long token, PackageInfo[] packages, 840 ITransportStatusCallback callback) throws RemoteException { 841 try { 842 int result = BackupTransport.this.startRestore(token, packages); 843 callback.onOperationCompleteWithStatus(result); 844 } catch (RuntimeException e) { 845 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 846 } 847 } 848 849 @Override nextRestorePackage(AndroidFuture<RestoreDescription> resultFuture)850 public void nextRestorePackage(AndroidFuture<RestoreDescription> resultFuture) 851 throws RemoteException { 852 try { 853 RestoreDescription result = BackupTransport.this.nextRestorePackage(); 854 resultFuture.complete(result); 855 } catch (RuntimeException e) { 856 resultFuture.cancel(/* mayInterruptIfRunning */ true); 857 } 858 } 859 860 @Override getRestoreData(ParcelFileDescriptor outFd, ITransportStatusCallback callback)861 public void getRestoreData(ParcelFileDescriptor outFd, 862 ITransportStatusCallback callback) throws RemoteException { 863 try { 864 int result = BackupTransport.this.getRestoreData(outFd); 865 callback.onOperationCompleteWithStatus(result); 866 } catch (RuntimeException e) { 867 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 868 } 869 } 870 871 @Override finishRestore(ITransportStatusCallback callback)872 public void finishRestore(ITransportStatusCallback callback) 873 throws RemoteException { 874 try { 875 BackupTransport.this.finishRestore(); 876 callback.onOperationComplete(); 877 } catch (RuntimeException e) { 878 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 879 } 880 } 881 882 @Override requestFullBackupTime(AndroidFuture<Long> resultFuture)883 public void requestFullBackupTime(AndroidFuture<Long> resultFuture) 884 throws RemoteException { 885 try { 886 long result = BackupTransport.this.requestFullBackupTime(); 887 resultFuture.complete(result); 888 } catch (RuntimeException e) { 889 resultFuture.cancel(/* mayInterruptIfRunning */ true); 890 } 891 } 892 893 @Override performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket, int flags, ITransportStatusCallback callback)894 public void performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket, 895 int flags, ITransportStatusCallback callback) throws RemoteException { 896 try { 897 int result = BackupTransport.this.performFullBackup(targetPackage, socket, flags); 898 callback.onOperationCompleteWithStatus(result); 899 } catch (RuntimeException e) { 900 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 901 } 902 } 903 904 @Override checkFullBackupSize(long size, ITransportStatusCallback callback)905 public void checkFullBackupSize(long size, ITransportStatusCallback callback) 906 throws RemoteException { 907 try { 908 int result = BackupTransport.this.checkFullBackupSize(size); 909 callback.onOperationCompleteWithStatus(result); 910 } catch (RuntimeException e) { 911 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 912 } 913 } 914 915 @Override sendBackupData(int numBytes, ITransportStatusCallback callback)916 public void sendBackupData(int numBytes, ITransportStatusCallback callback) 917 throws RemoteException { 918 try { 919 int result = BackupTransport.this.sendBackupData(numBytes); 920 callback.onOperationCompleteWithStatus(result); 921 } catch (RuntimeException e) { 922 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 923 } 924 } 925 926 @Override cancelFullBackup(ITransportStatusCallback callback)927 public void cancelFullBackup(ITransportStatusCallback callback) throws RemoteException { 928 try { 929 BackupTransport.this.cancelFullBackup(); 930 callback.onOperationComplete(); 931 } catch (RuntimeException e) { 932 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 933 } 934 } 935 936 @Override isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup, AndroidFuture<Boolean> resultFuture)937 public void isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup, 938 AndroidFuture<Boolean> resultFuture) throws RemoteException { 939 try { 940 boolean result = BackupTransport.this.isAppEligibleForBackup(targetPackage, 941 isFullBackup); 942 resultFuture.complete(result); 943 } catch (RuntimeException e) { 944 resultFuture.cancel(/* mayInterruptIfRunning */ true); 945 } 946 } 947 948 @Override getBackupQuota(String packageName, boolean isFullBackup, AndroidFuture<Long> resultFuture)949 public void getBackupQuota(String packageName, boolean isFullBackup, 950 AndroidFuture<Long> resultFuture) throws RemoteException { 951 try { 952 long result = BackupTransport.this.getBackupQuota(packageName, isFullBackup); 953 resultFuture.complete(result); 954 } catch (RuntimeException e) { 955 resultFuture.cancel(/* mayInterruptIfRunning */ true); 956 } 957 } 958 959 @Override getTransportFlags(AndroidFuture<Integer> resultFuture)960 public void getTransportFlags(AndroidFuture<Integer> resultFuture) throws RemoteException { 961 try { 962 int result = BackupTransport.this.getTransportFlags(); 963 resultFuture.complete(result); 964 } catch (RuntimeException e) { 965 resultFuture.cancel(/* mayInterruptIfRunning */ true); 966 } 967 } 968 969 @Override getNextFullRestoreDataChunk(ParcelFileDescriptor socket, ITransportStatusCallback callback)970 public void getNextFullRestoreDataChunk(ParcelFileDescriptor socket, 971 ITransportStatusCallback callback) throws RemoteException { 972 try { 973 int result = BackupTransport.this.getNextFullRestoreDataChunk(socket); 974 callback.onOperationCompleteWithStatus(result); 975 } catch (RuntimeException e) { 976 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 977 } 978 } 979 980 @Override abortFullRestore(ITransportStatusCallback callback)981 public void abortFullRestore(ITransportStatusCallback callback) throws RemoteException { 982 try { 983 int result = BackupTransport.this.abortFullRestore(); 984 callback.onOperationCompleteWithStatus(result); 985 } catch (RuntimeException e) { 986 callback.onOperationCompleteWithStatus(BackupTransport.TRANSPORT_ERROR); 987 } 988 } 989 990 @Override getBackupManagerMonitor(AndroidFuture<IBackupManagerMonitor> resultFuture)991 public void getBackupManagerMonitor(AndroidFuture<IBackupManagerMonitor> resultFuture) { 992 try { 993 BackupManagerMonitor result = BackupTransport.this.getBackupManagerMonitor(); 994 resultFuture.complete(new BackupManagerMonitorWrapper(result)); 995 } catch (RuntimeException e) { 996 resultFuture.cancel(/* mayInterruptIfRunning */ true); 997 } 998 } 999 1000 @Override 1001 @FlaggedApi(Flags.FLAG_ENABLE_RESTRICTED_MODE_CHANGES) getPackagesThatShouldNotUseRestrictedMode(List<String> packageNames, int operationType, AndroidFuture<List<String>> resultFuture)1002 public void getPackagesThatShouldNotUseRestrictedMode(List<String> packageNames, 1003 int operationType, AndroidFuture<List<String>> resultFuture) { 1004 try { 1005 List<String> result = 1006 BackupTransport.this.getPackagesThatShouldNotUseRestrictedMode(packageNames, 1007 operationType); 1008 resultFuture.complete(result); 1009 } catch (RuntimeException e) { 1010 resultFuture.cancel(/* mayInterruptIfRunning */ true); 1011 } 1012 } 1013 } 1014 } 1015