| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.app.backup; |
| |
| import android.annotation.SystemApi; |
| import android.content.Intent; |
| import android.content.pm.PackageInfo; |
| import android.os.IBinder; |
| import android.os.ParcelFileDescriptor; |
| import android.os.RemoteException; |
| |
| import com.android.internal.backup.IBackupTransport; |
| |
| /** |
| * Concrete class that provides a stable-API bridge between IBackupTransport |
| * and its implementations. |
| * |
| * @hide |
| */ |
| @SystemApi |
| public class BackupTransport { |
| // Zero return always means things are okay. If returned from |
| // getNextFullRestoreDataChunk(), it means that no data could be delivered at |
| // this time, but the restore is still running and the caller should simply |
| // retry. |
| public static final int TRANSPORT_OK = 0; |
| |
| // -1 is special; it is used in getNextFullRestoreDataChunk() to indicate that |
| // we've delivered the entire data stream for the current restore target. |
| public static final int NO_MORE_DATA = -1; |
| |
| // Result codes that indicate real errors are negative and not -1 |
| public static final int TRANSPORT_ERROR = -1000; |
| public static final int TRANSPORT_NOT_INITIALIZED = -1001; |
| public static final int TRANSPORT_PACKAGE_REJECTED = -1002; |
| public static final int AGENT_ERROR = -1003; |
| public static final int AGENT_UNKNOWN = -1004; |
| public static final int TRANSPORT_QUOTA_EXCEEDED = -1005; |
| |
| /** |
| * Indicates that the transport cannot accept a diff backup for this package. |
| * |
| * <p>Backup manager should clear its state for this package and immediately retry a |
| * non-incremental backup. This might be used if the transport no longer has data for this |
| * package in its backing store. |
| * |
| * <p>This is only valid when backup manager called {@link |
| * #performBackup(PackageInfo, ParcelFileDescriptor, int)} with {@link #FLAG_INCREMENTAL}. |
| */ |
| public static final int TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED = -1006; |
| |
| // Indicates that operation was initiated by user, not a scheduled one. |
| // Transport should ignore its own moratoriums for call with this flag set. |
| public static final int FLAG_USER_INITIATED = 1; |
| |
| /** |
| * For key value backup, indicates that the backup data is a diff from a previous backup. The |
| * transport must apply this diff to an existing backup to build the new backup set. |
| * |
| * @see #performBackup(PackageInfo, ParcelFileDescriptor, int) |
| */ |
| public static final int FLAG_INCREMENTAL = 1 << 1; |
| |
| /** |
| * For key value backup, indicates that the backup data is a complete set, not a diff from a |
| * previous backup. The transport should clear any previous backup when storing this backup. |
| * |
| * @see #performBackup(PackageInfo, ParcelFileDescriptor, int) |
| */ |
| public static final int FLAG_NON_INCREMENTAL = 1 << 2; |
| |
| /** |
| * Used as a boolean extra in the binding intent of transports. We pass {@code true} to |
| * notify transports that the current connection is used for registering the transport. |
| */ |
| public static final String EXTRA_TRANSPORT_REGISTRATION = |
| "android.app.backup.extra.TRANSPORT_REGISTRATION"; |
| |
| IBackupTransport mBinderImpl = new TransportImpl(); |
| |
| public IBinder getBinder() { |
| return mBinderImpl.asBinder(); |
| } |
| |
| // ------------------------------------------------------------------------------------ |
| // Transport self-description and general configuration interfaces |
| // |
| |
| /** |
| * Ask the transport for the name under which it should be registered. This will |
| * typically be its host service's component name, but need not be. |
| */ |
| public String name() { |
| throw new UnsupportedOperationException("Transport name() not implemented"); |
| } |
| |
| /** |
| * Ask the transport for an Intent that can be used to launch any internal |
| * configuration Activity that it wishes to present. For example, the transport |
| * may offer a UI for allowing the user to supply login credentials for the |
| * transport's off-device backend. |
| * |
| * <p>If the transport does not supply any user-facing configuration UI, it should |
| * return {@code null} from this method. |
| * |
| * @return An Intent that can be passed to Context.startActivity() in order to |
| * launch the transport's configuration UI. This method will return {@code null} |
| * if the transport does not offer any user-facing configuration UI. |
| */ |
| public Intent configurationIntent() { |
| return null; |
| } |
| |
| /** |
| * On demand, supply a one-line string that can be shown to the user that |
| * describes the current backend destination. For example, a transport that |
| * can potentially associate backup data with arbitrary user accounts should |
| * include the name of the currently-active account here. |
| * |
| * @return A string describing the destination to which the transport is currently |
| * sending data. This method should not return null. |
| */ |
| public String currentDestinationString() { |
| throw new UnsupportedOperationException( |
| "Transport currentDestinationString() not implemented"); |
| } |
| |
| /** |
| * Ask the transport for an Intent that can be used to launch a more detailed |
| * secondary data management activity. For example, the configuration intent might |
| * be one for allowing the user to select which account they wish to associate |
| * their backups with, and the management intent might be one which presents a |
| * UI for managing the data on the backend. |
| * |
| * <p>In the Settings UI, the configuration intent will typically be invoked |
| * when the user taps on the preferences item labeled with the current |
| * destination string, and the management intent will be placed in an overflow |
| * menu labelled with the management label string. |
| * |
| * <p>If the transport does not supply any user-facing data management |
| * UI, then it should return {@code null} from this method. |
| * |
| * @return An intent that can be passed to Context.startActivity() in order to |
| * launch the transport's data-management UI. This method will return |
| * {@code null} if the transport does not offer any user-facing data |
| * management UI. |
| */ |
| public Intent dataManagementIntent() { |
| return null; |
| } |
| |
| /** |
| * On demand, supply a short string that can be shown to the user as the label |
| * on an overflow menu item used to invoked the data management UI. |
| * |
| * @return A string to be used as the label for the transport's data management |
| * affordance. If the transport supplies a data management intent, this |
| * method must not return {@code null}. |
| */ |
| public String dataManagementLabel() { |
| throw new UnsupportedOperationException( |
| "Transport dataManagementLabel() not implemented"); |
| } |
| |
| /** |
| * Ask the transport where, on local device storage, to keep backup state blobs. |
| * This is per-transport so that mock transports used for testing can coexist with |
| * "live" backup services without interfering with the live bookkeeping. The |
| * returned string should be a name that is expected to be unambiguous among all |
| * available backup transports; the name of the class implementing the transport |
| * is a good choice. |
| * |
| * @return A unique name, suitable for use as a file or directory name, that the |
| * Backup Manager could use to disambiguate state files associated with |
| * different backup transports. |
| */ |
| public String transportDirName() { |
| throw new UnsupportedOperationException( |
| "Transport transportDirName() not implemented"); |
| } |
| |
| // ------------------------------------------------------------------------------------ |
| // Device-level operations common to both key/value and full-data storage |
| |
| /** |
| * Initialize the server side storage for this device, erasing all stored data. |
| * The transport may send the request immediately, or may buffer it. After |
| * this is called, {@link #finishBackup} will be called to ensure the request |
| * is sent and received successfully. |
| * |
| * <p>If the transport returns anything other than TRANSPORT_OK from this method, |
| * the OS will halt the current initialize operation and schedule a retry in the |
| * near future. Even if the transport is in a state such that attempting to |
| * "initialize" the backend storage is meaningless -- for example, if there is |
| * no current live dataset at all, or there is no authenticated account under which |
| * to store the data remotely -- the transport should return TRANSPORT_OK here |
| * and treat the initializeDevice() / finishBackup() pair as a graceful no-op. |
| * |
| * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far) or |
| * {@link BackupTransport#TRANSPORT_ERROR} (to retry following network error |
| * or other failure). |
| */ |
| public int initializeDevice() { |
| return BackupTransport.TRANSPORT_ERROR; |
| } |
| |
| /** |
| * Erase the given application's data from the backup destination. This clears |
| * out the given package's data from the current backup set, making it as though |
| * the app had never yet been backed up. After this is called, {@link finishBackup} |
| * must be called to ensure that the operation is recorded successfully. |
| * |
| * @return the same error codes as {@link #performBackup}. |
| */ |
| public int clearBackupData(PackageInfo packageInfo) { |
| return BackupTransport.TRANSPORT_ERROR; |
| } |
| |
| /** |
| * Finish sending application data to the backup destination. This must be |
| * called after {@link #performBackup}, {@link #performFullBackup}, or {@link clearBackupData} |
| * to ensure that all data is sent and the operation properly finalized. Only when this |
| * method returns true can a backup be assumed to have succeeded. |
| * |
| * @return the same error codes as {@link #performBackup} or {@link #performFullBackup}. |
| */ |
| public int finishBackup() { |
| return BackupTransport.TRANSPORT_ERROR; |
| } |
| |
| // ------------------------------------------------------------------------------------ |
| // Key/value incremental backup support interfaces |
| |
| /** |
| * Verify that this is a suitable time for a key/value backup pass. This should return zero |
| * if a backup is reasonable right now, some positive value otherwise. This method |
| * will be called outside of the {@link #performBackup}/{@link #finishBackup} pair. |
| * |
| * <p>If this is not a suitable time for a backup, the transport should return a |
| * backoff delay, in milliseconds, after which the Backup Manager should try again. |
| * |
| * @return Zero if this is a suitable time for a backup pass, or a positive time delay |
| * in milliseconds to suggest deferring the backup pass for a while. |
| */ |
| public long requestBackupTime() { |
| return 0; |
| } |
| |
| /** |
| * Send one application's key/value data update to the backup destination. The |
| * transport may send the data immediately, or may buffer it. If this method returns |
| * {@link #TRANSPORT_OK}, {@link #finishBackup} will then be called to ensure the data |
| * is sent and recorded successfully. |
| * |
| * If the backup data is a diff against the previous backup then the flag {@link |
| * BackupTransport#FLAG_INCREMENTAL} will be set. Otherwise, if the data is a complete backup |
| * set then {@link BackupTransport#FLAG_NON_INCREMENTAL} will be set. Before P neither flag will |
| * be set regardless of whether the backup is incremental or not. |
| * |
| * <p>If {@link BackupTransport#FLAG_INCREMENTAL} is set and the transport does not have data |
| * for this package in its storage backend then it cannot apply the incremental diff. Thus it |
| * should return {@link BackupTransport#TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED} to indicate |
| * that backup manager should delete its state and retry the package as a non-incremental |
| * backup. Before P, or if this is a non-incremental backup, then this return code is equivalent |
| * to {@link BackupTransport#TRANSPORT_ERROR}. |
| * |
| * @param packageInfo The identity of the application whose data is being backed up. |
| * This specifically includes the signature list for the package. |
| * @param inFd Descriptor of file with data that resulted from invoking the application's |
| * BackupService.doBackup() method. This may be a pipe rather than a file on |
| * persistent media, so it may not be seekable. |
| * @param flags a combination of {@link BackupTransport#FLAG_USER_INITIATED}, {@link |
| * BackupTransport#FLAG_NON_INCREMENTAL}, {@link BackupTransport#FLAG_INCREMENTAL}, or 0. |
| * @return one of {@link BackupTransport#TRANSPORT_OK} (OK so far), |
| * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED} (to suppress backup of this |
| * specific package, but allow others to proceed), |
| * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure), {@link |
| * BackupTransport#TRANSPORT_NON_INCREMENTAL_BACKUP_REQUIRED} (if the transport cannot accept |
| * an incremental backup for this package), or {@link |
| * BackupTransport#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has become lost due to |
| * inactivity purge or some other reason and needs re-initializing) |
| */ |
| public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags) { |
| return performBackup(packageInfo, inFd); |
| } |
| |
| /** |
| * Legacy version of {@link #performBackup(PackageInfo, ParcelFileDescriptor, int)} that |
| * doesn't use flags parameter. |
| */ |
| public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) { |
| return BackupTransport.TRANSPORT_ERROR; |
| } |
| |
| // ------------------------------------------------------------------------------------ |
| // Key/value dataset restore interfaces |
| |
| /** |
| * Get the set of all backups currently available over this transport. |
| * |
| * @return Descriptions of the set of restore images available for this device, |
| * or null if an error occurred (the attempt should be rescheduled). |
| **/ |
| public RestoreSet[] getAvailableRestoreSets() { |
| return null; |
| } |
| |
| /** |
| * Get the identifying token of the backup set currently being stored from |
| * this device. This is used in the case of applications wishing to restore |
| * their last-known-good data. |
| * |
| * @return A token that can be passed to {@link #startRestore}, or 0 if there |
| * is no backup set available corresponding to the current device state. |
| */ |
| public long getCurrentRestoreSet() { |
| return 0; |
| } |
| |
| /** |
| * Start restoring application data from backup. After calling this function, |
| * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData} |
| * to walk through the actual application data. |
| * |
| * @param token A backup token as returned by {@link #getAvailableRestoreSets} |
| * or {@link #getCurrentRestoreSet}. |
| * @param packages List of applications to restore (if data is available). |
| * Application data will be restored in the order given. |
| * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far, call |
| * {@link #nextRestorePackage}) or {@link BackupTransport#TRANSPORT_ERROR} |
| * (an error occurred, the restore should be aborted and rescheduled). |
| */ |
| public int startRestore(long token, PackageInfo[] packages) { |
| return BackupTransport.TRANSPORT_ERROR; |
| } |
| |
| /** |
| * Get the package name of the next application with data in the backup store, plus |
| * a description of the structure of the restored archive: either TYPE_KEY_VALUE for |
| * an original-API key/value dataset, or TYPE_FULL_STREAM for a tarball-type archive stream. |
| * |
| * <p>If the package name in the returned RestoreDescription object is the singleton |
| * {@link RestoreDescription#NO_MORE_PACKAGES}, it indicates that no further data is available |
| * in the current restore session: all packages described in startRestore() have been |
| * processed. |
| * |
| * <p>If this method returns {@code null}, it means that a transport-level error has |
| * occurred and the entire restore operation should be abandoned. |
| * |
| * <p class="note">The OS may call {@link #nextRestorePackage()} multiple times |
| * before calling either {@link #getRestoreData(ParcelFileDescriptor) getRestoreData()} |
| * or {@link #getNextFullRestoreDataChunk(ParcelFileDescriptor) getNextFullRestoreDataChunk()}. |
| * It does this when it has determined that it needs to skip restore of one or more |
| * packages. The transport should not actually transfer any restore data for |
| * the given package in response to {@link #nextRestorePackage()}, but rather wait |
| * for an explicit request before doing so. |
| * |
| * @return A RestoreDescription object containing the name of one of the packages |
| * supplied to {@link #startRestore} plus an indicator of the data type of that |
| * restore data; or {@link RestoreDescription#NO_MORE_PACKAGES} to indicate that |
| * no more packages can be restored in this session; or {@code null} to indicate |
| * a transport-level error. |
| */ |
| public RestoreDescription nextRestorePackage() { |
| return null; |
| } |
| |
| /** |
| * Get the data for the application returned by {@link #nextRestorePackage}, if that |
| * method reported {@link RestoreDescription#TYPE_KEY_VALUE} as its delivery type. |
| * If the package has only TYPE_FULL_STREAM data, then this method will return an |
| * error. |
| * |
| * @param data An open, writable file into which the key/value backup data should be stored. |
| * @return the same error codes as {@link #startRestore}. |
| */ |
| public int getRestoreData(ParcelFileDescriptor outFd) { |
| return BackupTransport.TRANSPORT_ERROR; |
| } |
| |
| /** |
| * End a restore session (aborting any in-process data transfer as necessary), |
| * freeing any resources and connections used during the restore process. |
| */ |
| public void finishRestore() { |
| throw new UnsupportedOperationException( |
| "Transport finishRestore() not implemented"); |
| } |
| |
| // ------------------------------------------------------------------------------------ |
| // Full backup interfaces |
| |
| /** |
| * Verify that this is a suitable time for a full-data backup pass. This should return zero |
| * if a backup is reasonable right now, some positive value otherwise. This method |
| * will be called outside of the {@link #performFullBackup}/{@link #finishBackup} pair. |
| * |
| * <p>If this is not a suitable time for a backup, the transport should return a |
| * backoff delay, in milliseconds, after which the Backup Manager should try again. |
| * |
| * @return Zero if this is a suitable time for a backup pass, or a positive time delay |
| * in milliseconds to suggest deferring the backup pass for a while. |
| * |
| * @see #requestBackupTime() |
| */ |
| public long requestFullBackupTime() { |
| return 0; |
| } |
| |
| /** |
| * Begin the process of sending an application's full-data archive to the backend. |
| * The description of the package whose data will be delivered is provided, as well as |
| * the socket file descriptor on which the transport will receive the data itself. |
| * |
| * <p>If the package is not eligible for backup, the transport should return |
| * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED}. In this case the system will |
| * simply proceed with the next candidate if any, or finish the full backup operation |
| * if all apps have been processed. |
| * |
| * <p>After the transport returns {@link BackupTransport#TRANSPORT_OK} from this |
| * method, the OS will proceed to call {@link #sendBackupData()} one or more times |
| * to deliver the application's data as a streamed tarball. The transport should not |
| * read() from the socket except as instructed to via the {@link #sendBackupData(int)} |
| * method. |
| * |
| * <p>After all data has been delivered to the transport, the system will call |
| * {@link #finishBackup()}. At this point the transport should commit the data to |
| * its datastore, if appropriate, and close the socket that had been provided in |
| * {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}. |
| * |
| * <p class="note">If the transport returns TRANSPORT_OK from this method, then the |
| * OS will always provide a matching call to {@link #finishBackup()} even if sending |
| * data via {@link #sendBackupData(int)} failed at some point. |
| * |
| * @param targetPackage The package whose data is to follow. |
| * @param socket The socket file descriptor through which the data will be provided. |
| * If the transport returns {@link #TRANSPORT_PACKAGE_REJECTED} here, it must still |
| * close this file descriptor now; otherwise it should be cached for use during |
| * succeeding calls to {@link #sendBackupData(int)}, and closed in response to |
| * {@link #finishBackup()}. |
| * @param flags {@link BackupTransport#FLAG_USER_INITIATED} or 0. |
| * @return TRANSPORT_PACKAGE_REJECTED to indicate that the stated application is not |
| * to be backed up; TRANSPORT_OK to indicate that the OS may proceed with delivering |
| * backup data; TRANSPORT_ERROR to indicate a fatal error condition that precludes |
| * performing a backup at this time. |
| */ |
| public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket, |
| int flags) { |
| return performFullBackup(targetPackage, socket); |
| } |
| |
| /** |
| * Legacy version of {@link #performFullBackup(PackageInfo, ParcelFileDescriptor, int)} that |
| * doesn't use flags parameter. |
| */ |
| public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) { |
| return BackupTransport.TRANSPORT_PACKAGE_REJECTED; |
| } |
| |
| /** |
| * Called after {@link #performFullBackup} to make sure that the transport is willing to |
| * handle a full-data backup operation of the specified size on the current package. |
| * If the transport returns anything other than TRANSPORT_OK, the package's backup |
| * operation will be skipped (and {@link #finishBackup() invoked} with no data for that |
| * package being passed to {@link #sendBackupData}. |
| * |
| * <p class="note">The platform does no size-based rejection of full backup attempts on |
| * its own: it is always the responsibility of the transport to implement its own policy. |
| * In particular, even if the preflighted payload size is zero, the platform will still call |
| * this method and will proceed to back up an archive metadata header with no file content |
| * if this method returns TRANSPORT_OK. To avoid storing such payloads the transport |
| * must recognize this case and return TRANSPORT_PACKAGE_REJECTED. |
| * |
| * Added in {@link android.os.Build.VERSION_CODES#M}. |
| * |
| * @param size The estimated size of the full-data payload for this app. This includes |
| * manifest and archive format overhead, but is not guaranteed to be precise. |
| * @return TRANSPORT_OK if the platform is to proceed with the full-data backup, |
| * TRANSPORT_PACKAGE_REJECTED if the proposed payload size is too large for |
| * the transport to handle, or TRANSPORT_ERROR to indicate a fatal error |
| * condition that means the platform cannot perform a backup at this time. |
| */ |
| public int checkFullBackupSize(long size) { |
| return BackupTransport.TRANSPORT_OK; |
| } |
| |
| /** |
| * Tells the transport to read {@code numBytes} bytes of data from the socket file |
| * descriptor provided in the {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)} |
| * call, and deliver those bytes to the datastore. |
| * |
| * @param numBytes The number of bytes of tarball data available to be read from the |
| * socket. |
| * @return TRANSPORT_OK on successful processing of the data; TRANSPORT_ERROR to |
| * indicate a fatal error situation. If an error is returned, the system will |
| * call finishBackup() and stop attempting backups until after a backoff and retry |
| * interval. |
| */ |
| public int sendBackupData(int numBytes) { |
| return BackupTransport.TRANSPORT_ERROR; |
| } |
| |
| /** |
| * Tells the transport to cancel the currently-ongoing full backup operation. This |
| * will happen between {@link #performFullBackup()} and {@link #finishBackup()} |
| * if the OS needs to abort the backup operation for any reason, such as a crash in |
| * the application undergoing backup. |
| * |
| * <p>When it receives this call, the transport should discard any partial archive |
| * that it has stored so far. If possible it should also roll back to the previous |
| * known-good archive in its datastore. |
| * |
| * <p>If the transport receives this callback, it will <em>not</em> receive a |
| * call to {@link #finishBackup()}. It needs to tear down any ongoing backup state |
| * here. |
| */ |
| public void cancelFullBackup() { |
| throw new UnsupportedOperationException( |
| "Transport cancelFullBackup() not implemented"); |
| } |
| |
| /** |
| * Ask the transport whether this app is eligible for backup. |
| * |
| * @param targetPackage The identity of the application. |
| * @param isFullBackup If set, transport should check if app is eligible for full data backup, |
| * otherwise to check if eligible for key-value backup. |
| * @return Whether this app is eligible for backup. |
| */ |
| public boolean isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup) { |
| return true; |
| } |
| |
| /** |
| * Ask the transport about current quota for backup size of the package. |
| * |
| * @param packageName ID of package to provide the quota. |
| * @param isFullBackup If set, transport should return limit for full data backup, otherwise |
| * for key-value backup. |
| * @return Current limit on backup size in bytes. |
| */ |
| public long getBackupQuota(String packageName, boolean isFullBackup) { |
| return Long.MAX_VALUE; |
| } |
| |
| // ------------------------------------------------------------------------------------ |
| // Full restore interfaces |
| |
| /** |
| * Ask the transport to provide data for the "current" package being restored. This |
| * is the package that was just reported by {@link #nextRestorePackage()} as having |
| * {@link RestoreDescription#TYPE_FULL_STREAM} data. |
| * |
| * The transport writes some data to the socket supplied to this call, and returns |
| * the number of bytes written. The system will then read that many bytes and |
| * stream them to the application's agent for restore, then will call this method again |
| * to receive the next chunk of the archive. This sequence will be repeated until the |
| * transport returns zero indicating that all of the package's data has been delivered |
| * (or returns a negative value indicating some sort of hard error condition at the |
| * transport level). |
| * |
| * <p>After this method returns zero, the system will then call |
| * {@link #nextRestorePackage()} to begin the restore process for the next |
| * application, and the sequence begins again. |
| * |
| * <p>The transport should always close this socket when returning from this method. |
| * Do not cache this socket across multiple calls or you may leak file descriptors. |
| * |
| * @param socket The file descriptor that the transport will use for delivering the |
| * streamed archive. The transport must close this socket in all cases when returning |
| * from this method. |
| * @return {@link #NO_MORE_DATA} when no more data for the current package is available. |
| * A positive value indicates the presence of that many bytes to be delivered to the app. |
| * A value of zero indicates that no data was deliverable at this time, but the restore |
| * is still running and the caller should retry. {@link #TRANSPORT_PACKAGE_REJECTED} |
| * means that the current package's restore operation should be aborted, but that |
| * the transport itself is still in a good state and so a multiple-package restore |
| * sequence can still be continued. Any other negative return value is treated as a |
| * fatal error condition that aborts all further restore operations on the current dataset. |
| */ |
| public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) { |
| return 0; |
| } |
| |
| /** |
| * If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM} |
| * data for restore, it will invoke this method to tell the transport that it should |
| * abandon the data download for the current package. The OS will then either call |
| * {@link #nextRestorePackage()} again to move on to restoring the next package in the |
| * set being iterated over, or will call {@link #finishRestore()} to shut down the restore |
| * operation. |
| * |
| * @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the |
| * current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious |
| * transport-level failure. If the transport reports an error here, the entire restore |
| * operation will immediately be finished with no further attempts to restore app data. |
| */ |
| public int abortFullRestore() { |
| return BackupTransport.TRANSPORT_OK; |
| } |
| |
| /** |
| * Returns flags with additional information about the transport, which is accessible to the |
| * {@link android.app.backup.BackupAgent}. This allows the agent to decide what to do based on |
| * properties of the transport. |
| */ |
| public int getTransportFlags() { |
| return 0; |
| } |
| |
| /** |
| * Bridge between the actual IBackupTransport implementation and the stable API. If the |
| * binder interface needs to change, we use this layer to translate so that we can |
| * (if appropriate) decouple those framework-side changes from the BackupTransport |
| * implementations. |
| */ |
| class TransportImpl extends IBackupTransport.Stub { |
| |
| @Override |
| public String name() throws RemoteException { |
| return BackupTransport.this.name(); |
| } |
| |
| @Override |
| public Intent configurationIntent() throws RemoteException { |
| return BackupTransport.this.configurationIntent(); |
| } |
| |
| @Override |
| public String currentDestinationString() throws RemoteException { |
| return BackupTransport.this.currentDestinationString(); |
| } |
| |
| @Override |
| public Intent dataManagementIntent() { |
| return BackupTransport.this.dataManagementIntent(); |
| } |
| |
| @Override |
| public String dataManagementLabel() { |
| return BackupTransport.this.dataManagementLabel(); |
| } |
| |
| @Override |
| public String transportDirName() throws RemoteException { |
| return BackupTransport.this.transportDirName(); |
| } |
| |
| @Override |
| public long requestBackupTime() throws RemoteException { |
| return BackupTransport.this.requestBackupTime(); |
| } |
| |
| @Override |
| public int initializeDevice() throws RemoteException { |
| return BackupTransport.this.initializeDevice(); |
| } |
| |
| @Override |
| public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags) |
| throws RemoteException { |
| return BackupTransport.this.performBackup(packageInfo, inFd, flags); |
| } |
| |
| @Override |
| public int clearBackupData(PackageInfo packageInfo) throws RemoteException { |
| return BackupTransport.this.clearBackupData(packageInfo); |
| } |
| |
| @Override |
| public int finishBackup() throws RemoteException { |
| return BackupTransport.this.finishBackup(); |
| } |
| |
| @Override |
| public RestoreSet[] getAvailableRestoreSets() throws RemoteException { |
| return BackupTransport.this.getAvailableRestoreSets(); |
| } |
| |
| @Override |
| public long getCurrentRestoreSet() throws RemoteException { |
| return BackupTransport.this.getCurrentRestoreSet(); |
| } |
| |
| @Override |
| public int startRestore(long token, PackageInfo[] packages) throws RemoteException { |
| return BackupTransport.this.startRestore(token, packages); |
| } |
| |
| @Override |
| public RestoreDescription nextRestorePackage() throws RemoteException { |
| return BackupTransport.this.nextRestorePackage(); |
| } |
| |
| @Override |
| public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException { |
| return BackupTransport.this.getRestoreData(outFd); |
| } |
| |
| @Override |
| public void finishRestore() throws RemoteException { |
| BackupTransport.this.finishRestore(); |
| } |
| |
| @Override |
| public long requestFullBackupTime() throws RemoteException { |
| return BackupTransport.this.requestFullBackupTime(); |
| } |
| |
| @Override |
| public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket, |
| int flags) throws RemoteException { |
| return BackupTransport.this.performFullBackup(targetPackage, socket, flags); |
| } |
| |
| @Override |
| public int checkFullBackupSize(long size) { |
| return BackupTransport.this.checkFullBackupSize(size); |
| } |
| |
| @Override |
| public int sendBackupData(int numBytes) throws RemoteException { |
| return BackupTransport.this.sendBackupData(numBytes); |
| } |
| |
| @Override |
| public void cancelFullBackup() throws RemoteException { |
| BackupTransport.this.cancelFullBackup(); |
| } |
| |
| @Override |
| public boolean isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup) |
| throws RemoteException { |
| return BackupTransport.this.isAppEligibleForBackup(targetPackage, isFullBackup); |
| } |
| |
| @Override |
| public long getBackupQuota(String packageName, boolean isFullBackup) { |
| return BackupTransport.this.getBackupQuota(packageName, isFullBackup); |
| } |
| |
| @Override |
| public int getTransportFlags() { |
| return BackupTransport.this.getTransportFlags(); |
| } |
| |
| @Override |
| public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) { |
| return BackupTransport.this.getNextFullRestoreDataChunk(socket); |
| } |
| |
| @Override |
| public int abortFullRestore() { |
| return BackupTransport.this.abortFullRestore(); |
| } |
| } |
| } |