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