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