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