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