1 /*
2  * Copyright (C) 2009 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.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.RequiresPermission;
22 import android.annotation.SystemApi;
23 import android.app.backup.BackupAnnotations.OperationType;
24 import android.app.compat.CompatChanges;
25 import android.compat.annotation.ChangeId;
26 import android.compat.annotation.EnabledAfter;
27 import android.compat.annotation.UnsupportedAppUsage;
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.os.Build;
32 import android.os.Handler;
33 import android.os.Message;
34 import android.os.RemoteException;
35 import android.os.ServiceManager;
36 import android.os.UserHandle;
37 import android.util.Log;
38 import android.util.Pair;
39 
40 import com.android.internal.annotations.VisibleForTesting;
41 
42 import java.util.List;
43 
44 /**
45  * The interface through which an application interacts with the Android backup service to
46  * request backup and restore operations.
47  * Applications instantiate it using the constructor and issue calls through that instance.
48  * <p>
49  * When an application has made changes to data which should be backed up, a
50  * call to {@link #dataChanged()} will notify the backup service. The system
51  * will then schedule a backup operation to occur in the near future. Repeated
52  * calls to {@link #dataChanged()} have no further effect until the backup
53  * operation actually occurs.
54  * <p>
55  * A backup or restore operation for your application begins when the system launches the
56  * {@link android.app.backup.BackupAgent} subclass you've declared in your manifest. See the
57  * documentation for {@link android.app.backup.BackupAgent} for a detailed description
58  * of how the operation then proceeds.
59  * <p>
60  * Several attributes affecting the operation of the backup and restore mechanism
61  * can be set on the <code>
62  * <a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
63  * tag in your application's AndroidManifest.xml file.
64  *
65  * <div class="special reference">
66  * <h3>Developer Guides</h3>
67  * <p>For more information about using BackupManager, read the
68  * <a href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p></div>
69  *
70  * @attr ref android.R.styleable#AndroidManifestApplication_allowBackup
71  * @attr ref android.R.styleable#AndroidManifestApplication_backupAgent
72  * @attr ref android.R.styleable#AndroidManifestApplication_killAfterRestore
73  * @attr ref android.R.styleable#AndroidManifestApplication_restoreAnyVersion
74  */
75 public class BackupManager {
76     private static final String TAG = "BackupManager";
77 
78     // BackupObserver status codes
79     /**
80      * Indicates that backup succeeded.
81      *
82      * @hide
83      */
84     @SystemApi
85     public static final int SUCCESS = 0;
86 
87     /**
88      * Indicates that backup is either not enabled at all or
89      * backup for the package was rejected by backup service
90      * or backup transport,
91      *
92      * @hide
93      */
94     @SystemApi
95     public static final int ERROR_BACKUP_NOT_ALLOWED = -2001;
96 
97     /**
98      * The requested app is not installed on the device.
99      *
100      * @hide
101      */
102     @SystemApi
103     public static final int ERROR_PACKAGE_NOT_FOUND = -2002;
104 
105     /**
106      * The backup operation was cancelled.
107      *
108      * @hide
109      */
110     @SystemApi
111     public static final int ERROR_BACKUP_CANCELLED = -2003;
112 
113     /**
114      * The transport for some reason was not in a good state and
115      * aborted the entire backup request. This is a transient
116      * failure and should not be retried immediately.
117      *
118      * @hide
119      */
120     @SystemApi
121     public static final int ERROR_TRANSPORT_ABORTED = BackupTransport.TRANSPORT_ERROR;
122 
123     /**
124      * Returned when the transport was unable to process the
125      * backup request for a given package, for example if the
126      * transport hit a transient network failure. The remaining
127      * packages provided to {@link #requestBackup(String[], BackupObserver)}
128      * will still be attempted.
129      *
130      * @hide
131      */
132     @SystemApi
133     public static final int ERROR_TRANSPORT_PACKAGE_REJECTED =
134             BackupTransport.TRANSPORT_PACKAGE_REJECTED;
135 
136     /**
137      * Returned when the transport reject the attempt to backup because
138      * backup data size exceeded current quota limit for this package.
139      *
140      * @hide
141      */
142     @SystemApi
143     public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED =
144             BackupTransport.TRANSPORT_QUOTA_EXCEEDED;
145 
146     /**
147      * The {@link BackupAgent} for the requested package failed for some reason
148      * and didn't provide appropriate backup data.
149      *
150      * @hide
151      */
152     @SystemApi
153     public static final int ERROR_AGENT_FAILURE = BackupTransport.AGENT_ERROR;
154 
155     /**
156      * Intent extra when any subsidiary backup-related UI is launched from Settings:  does
157      * device policy or configuration permit backup operations to run at all?
158      *
159      * @hide
160      */
161     public static final String EXTRA_BACKUP_SERVICES_AVAILABLE = "backup_services_available";
162 
163     /**
164      * If this flag is passed to {@link #requestBackup(String[], BackupObserver, int)},
165      * BackupManager will pass a blank old state to BackupAgents of requested packages.
166      *
167      * @hide
168      */
169     @SystemApi
170     public static final int FLAG_NON_INCREMENTAL_BACKUP = 1;
171 
172     /**
173      * Use with {@link #requestBackup} to force backup of
174      * package meta data. Typically you do not need to explicitly request this be backed up as it is
175      * handled internally by the BackupManager. If you are requesting backups with
176      * FLAG_NON_INCREMENTAL, this package won't automatically be backed up and you have to
177      * explicitly request for its backup.
178      *
179      * @hide
180      */
181     @SystemApi
182     public static final String PACKAGE_MANAGER_SENTINEL = "@pm@";
183 
184 
185     /**
186      * This error code is passed to {@link SelectBackupTransportCallback#onFailure(int)}
187      * if the requested transport is unavailable.
188      *
189      * @hide
190      */
191     @SystemApi
192     public static final int ERROR_TRANSPORT_UNAVAILABLE = -1;
193 
194     /**
195      * This error code is passed to {@link SelectBackupTransportCallback#onFailure(int)} if the
196      * requested transport is not a valid BackupTransport.
197      *
198      * @hide
199      */
200     @SystemApi
201     public static final int ERROR_TRANSPORT_INVALID = -2;
202 
203     private Context mContext;
204 
205     /**
206      * @hide Making this package private is not sufficient for the test to access it, that's because
207      * the test is in the same package but is loaded with a different class loader. Package
208      * private members are not accessible across class loaders. So we make it public and @hide it.
209      */
210     @UnsupportedAppUsage
211     @VisibleForTesting
212     public static IBackupManager sService;
213 
214     @UnsupportedAppUsage
checkServiceBinder()215     private static void checkServiceBinder() {
216         if (sService == null) {
217             sService = IBackupManager.Stub.asInterface(
218                     ServiceManager.getService(Context.BACKUP_SERVICE));
219         }
220     }
221 
222     /**
223      * Constructs a BackupManager object through which the application can
224      * communicate with the Android backup system.
225      *
226      * @param context The {@link android.content.Context} that was provided when
227      *                one of your application's {@link android.app.Activity Activities}
228      *                was created.
229      */
BackupManager(Context context)230     public BackupManager(Context context) {
231         mContext = context;
232     }
233 
234     /**
235      * Notifies the Android backup system that your application wishes to back up
236      * new changes to its data.  A backup operation using your application's
237      * {@link android.app.backup.BackupAgent} subclass will be scheduled when you
238      * call this method.
239      *
240      * <p>
241      * Note: This only works if your application is performing Key/Value backups.
242      */
dataChanged()243     public void dataChanged() {
244         checkServiceBinder();
245         if (sService != null) {
246             try {
247                 sService.dataChanged(mContext.getPackageName());
248             } catch (RemoteException e) {
249                 Log.d(TAG, "dataChanged() couldn't connect");
250             }
251         }
252     }
253 
254     /**
255      * Convenience method for callers who need to indicate that some other package
256      * needs a backup pass.  This can be useful in the case of groups of packages
257      * that share a uid.
258      * <p>
259      * This method requires that the application hold the "android.permission.BACKUP"
260      * permission if the package named in the argument does not run under the same uid
261      * as the caller.
262      *
263      * @param packageName The package name identifying the application to back up.
264      * <p>
265      * Note: Only works for packages performing Key/Value backups.
266      */
dataChanged(String packageName)267     public static void dataChanged(String packageName) {
268         checkServiceBinder();
269         if (sService != null) {
270             try {
271                 sService.dataChanged(packageName);
272             } catch (RemoteException e) {
273                 Log.e(TAG, "dataChanged(pkg) couldn't connect");
274             }
275         }
276     }
277 
278     /**
279      * Convenience method for callers who need to indicate that some other package or
280      * some other user needs a backup pass. This can be useful in the case of groups of
281      * packages that share a uid and/or have user-specific data.
282      * <p>
283      * This method requires that the application hold the "android.permission.BACKUP"
284      * permission if the package named in the package argument does not run under the
285      * same uid as the caller. This method also requires that the application hold the
286      * "android.permission.INTERACT_ACROSS_USERS_FULL" if the user argument is not the
287      * same as the user the caller is running under.
288      * @param userId The user to back up
289      * @param packageName The package name identifying the application to back up.
290      *
291      * @hide
292      */
dataChangedForUser(int userId, String packageName)293     public static void dataChangedForUser(int userId, String packageName) {
294         checkServiceBinder();
295         if (sService != null) {
296             try {
297                 sService.dataChangedForUser(userId, packageName);
298             } catch (RemoteException e) {
299                 Log.e(TAG, "dataChanged(userId,pkg) couldn't connect");
300             }
301         }
302     }
303 
304     /**
305      * @deprecated Applications shouldn't request a restore operation using this method. In Android
306      * P and later, this method is a no-op.
307      *
308      * <p>Restore the calling application from backup. The data will be restored from the
309      * current backup dataset if the application has stored data there, or from
310      * the dataset used during the last full device setup operation if the current
311      * backup dataset has no matching data.  If no backup data exists for this application
312      * in either source, a non-zero value is returned.
313      *
314      * <p>If this method returns zero (meaning success), the OS attempts to retrieve a backed-up
315      * dataset from the remote transport, instantiate the application's backup agent, and pass the
316      * dataset to the agent's
317      * {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) onRestore()}
318      * method.
319      *
320      * <p class="caution">Unlike other restore operations, this method doesn't terminate the
321      * application after the restore. The application continues running to receive the
322      * {@link RestoreObserver} callbacks on the {@code observer} argument. Full backups use an
323      * {@link android.app.Application Application} base class while key-value backups use the
324      * application subclass declared in the AndroidManifest.xml {@code <application>} tag.
325      *
326      * @param observer The {@link RestoreObserver} to receive callbacks during the restore
327      * operation. This must not be null.
328      *
329      * @return Zero on success; nonzero on error.
330      */
331     @Deprecated
requestRestore(RestoreObserver observer)332     public int requestRestore(RestoreObserver observer) {
333         return requestRestore(observer, null);
334     }
335 
336     // system APIs start here
337 
338     /**
339      * @deprecated Since Android P app can no longer request restoring of its backup.
340      *
341      * <p>Restore the calling application from backup.  The data will be restored from the
342      * current backup dataset if the application has stored data there, or from
343      * the dataset used during the last full device setup operation if the current
344      * backup dataset has no matching data.  If no backup data exists for this application
345      * in either source, a nonzero value will be returned.
346      *
347      * <p>If this method returns zero (meaning success), the OS will attempt to retrieve
348      * a backed-up dataset from the remote transport, instantiate the application's
349      * backup agent, and pass the dataset to the agent's
350      * {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) onRestore()}
351      * method.
352      *
353      * @param observer The {@link RestoreObserver} to receive callbacks during the restore
354      * operation. This must not be null.
355      *
356      * @param monitor the {@link BackupManagerMonitor} to receive callbacks during the restore
357      * operation.
358      *
359      * @return Zero on success; nonzero on error.
360      *
361      * @hide
362      */
363     @Deprecated
364     @SystemApi
requestRestore(RestoreObserver observer, BackupManagerMonitor monitor)365     public int requestRestore(RestoreObserver observer, BackupManagerMonitor monitor) {
366         Log.w(TAG, "requestRestore(): Since Android P app can no longer request restoring"
367                 + " of its backup.");
368         return -1;
369     }
370 
371     /**
372      * Begin the process of restoring data from backup.  See the
373      * {@link android.app.backup.RestoreSession} class for documentation on that process.
374      * @hide
375      */
376     @SystemApi
377     @RequiresPermission(android.Manifest.permission.BACKUP)
beginRestoreSession()378     public RestoreSession beginRestoreSession() {
379         RestoreSession session = null;
380         checkServiceBinder();
381         if (sService != null) {
382             try {
383                 // All packages, current transport
384                 IRestoreSession binder =
385                         sService.beginRestoreSessionForUser(mContext.getUserId(), null, null);
386                 if (binder != null) {
387                     session = new RestoreSession(mContext, binder);
388                 }
389             } catch (RemoteException e) {
390                 Log.e(TAG, "beginRestoreSession() couldn't connect");
391             }
392         }
393         return session;
394     }
395 
396     /**
397      * Enable/disable the backup service entirely.  When disabled, no backup
398      * or restore operations will take place.  Data-changed notifications will
399      * still be observed and collected, however, so that changes made while the
400      * mechanism was disabled will still be backed up properly if it is enabled
401      * at some point in the future.
402      *
403      * @hide
404      */
405     @SystemApi
406     @RequiresPermission(android.Manifest.permission.BACKUP)
setBackupEnabled(boolean isEnabled)407     public void setBackupEnabled(boolean isEnabled) {
408         checkServiceBinder();
409         if (sService != null) {
410             try {
411                 sService.setBackupEnabled(isEnabled);
412             } catch (RemoteException e) {
413                 Log.e(TAG, "setBackupEnabled() couldn't connect");
414             }
415         }
416     }
417 
418     /**
419      * Enable/disable the framework backup scheduling entirely for the context user. When disabled,
420      * no Key/Value or Full backup jobs will be scheduled by the Android framework.
421      *
422      * <p>Note: This does not disable backups: only their scheduling is affected and backups can
423      * still be triggered manually.
424      *
425      * <p>Callers must hold the android.permission.BACKUP permission to use this method. If the
426      * context user is different from the calling user, then the caller must additionally hold the
427      * android.permission.INTERACT_ACROSS_USERS_FULL permission.
428      *
429      * @hide
430      */
431     @SystemApi
432     @RequiresPermission(allOf = {android.Manifest.permission.BACKUP,
433             android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}, conditional = true)
setFrameworkSchedulingEnabled(boolean isEnabled)434     public void setFrameworkSchedulingEnabled(boolean isEnabled) {
435         checkServiceBinder();
436         if (sService == null) {
437             Log.e(TAG, "setFrameworkSchedulingEnabled() couldn't connect");
438             return;
439         }
440 
441         try {
442             sService.setFrameworkSchedulingEnabledForUser(mContext.getUserId(), isEnabled);
443         } catch (RemoteException e) {
444             Log.e(TAG, "setFrameworkSchedulingEnabled() couldn't connect");
445         }
446     }
447 
448     /**
449      * Report whether the backup mechanism is currently enabled.
450      *
451      * @hide
452      */
453     @SystemApi
454     @RequiresPermission(android.Manifest.permission.BACKUP)
isBackupEnabled()455     public boolean isBackupEnabled() {
456         checkServiceBinder();
457         if (sService != null) {
458             try {
459                 return sService.isBackupEnabled();
460             } catch (RemoteException e) {
461                 Log.e(TAG, "isBackupEnabled() couldn't connect");
462             }
463         }
464         return false;
465     }
466 
467 
468     /**
469      * If this change is enabled, the {@code BACKUP} permission needed for
470      * {@code isBackupServiceActive()} will be enforced on the service end
471      * rather than client-side in {@link BackupManager}.
472      * @hide
473      */
474     @ChangeId
475     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
476     public static final long IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE = 158482162;
477 
478     /**
479      * Report whether the backup mechanism is currently active.
480      * When it is inactive, the device will not perform any backup operations, nor will it
481      * deliver data for restore, although clients can still safely call BackupManager methods.
482      *
483      * @hide
484      */
485     @SystemApi
486     @RequiresPermission(android.Manifest.permission.BACKUP)
isBackupServiceActive(UserHandle user)487     public boolean isBackupServiceActive(UserHandle user) {
488         if (!CompatChanges.isChangeEnabled(
489                 IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE)) {
490             mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
491                     "isBackupServiceActive");
492         }
493         checkServiceBinder();
494         if (sService != null) {
495             try {
496                 return sService.isBackupServiceActive(user.getIdentifier());
497             } catch (RemoteException e) {
498                 Log.e(TAG, "isBackupEnabled() couldn't connect");
499             }
500         }
501         return false;
502     }
503 
504     /**
505      * Enable/disable data restore at application install time.  When enabled, app
506      * installation will include an attempt to fetch the app's historical data from
507      * the archival restore dataset (if any).  When disabled, no such attempt will
508      * be made.
509      *
510      * @hide
511      */
512     @SystemApi
513     @RequiresPermission(android.Manifest.permission.BACKUP)
setAutoRestore(boolean isEnabled)514     public void setAutoRestore(boolean isEnabled) {
515         checkServiceBinder();
516         if (sService != null) {
517             try {
518                 sService.setAutoRestore(isEnabled);
519             } catch (RemoteException e) {
520                 Log.e(TAG, "setAutoRestore() couldn't connect");
521             }
522         }
523     }
524 
525     /**
526      * Identify the currently selected transport.
527      * @return The name of the currently active backup transport.  In case of
528      *   failure or if no transport is currently active, this method returns {@code null}.
529      *
530      * @hide
531      */
532     @SystemApi
533     @RequiresPermission(android.Manifest.permission.BACKUP)
getCurrentTransport()534     public String getCurrentTransport() {
535         checkServiceBinder();
536         if (sService != null) {
537             try {
538                 return sService.getCurrentTransport();
539             } catch (RemoteException e) {
540                 Log.e(TAG, "getCurrentTransport() couldn't connect");
541             }
542         }
543         return null;
544     }
545 
546     /**
547      * Returns the {@link ComponentName} of the host service of the selected transport or {@code
548      * null} if no transport selected or if the transport selected is not registered.
549      *
550      * @hide
551      */
552     @SystemApi
553     @RequiresPermission(android.Manifest.permission.BACKUP)
554     @Nullable
getCurrentTransportComponent()555     public ComponentName getCurrentTransportComponent() {
556         checkServiceBinder();
557         if (sService != null) {
558             try {
559                 return sService.getCurrentTransportComponentForUser(mContext.getUserId());
560             } catch (RemoteException e) {
561                 Log.e(TAG, "getCurrentTransportComponent() couldn't connect");
562             }
563         }
564         return null;
565     }
566 
567     /**
568      * Request a list of all available backup transports' names.
569      *
570      * @hide
571      */
572     @SystemApi
573     @RequiresPermission(android.Manifest.permission.BACKUP)
listAllTransports()574     public String[] listAllTransports() {
575         checkServiceBinder();
576         if (sService != null) {
577             try {
578                 return sService.listAllTransports();
579             } catch (RemoteException e) {
580                 Log.e(TAG, "listAllTransports() couldn't connect");
581             }
582         }
583         return null;
584     }
585 
586     /**
587      * Update the attributes of the transport identified by {@code transportComponent}. If the
588      * specified transport has not been bound at least once (for registration), this call will be
589      * ignored. Only the host process of the transport can change its description, otherwise a
590      * {@link SecurityException} will be thrown.
591      *
592      * @param transportComponent The identity of the transport being described.
593      * @param name A {@link String} with the new name for the transport. This is NOT for
594      *     identification. MUST NOT be {@code null}.
595      * @param configurationIntent An {@link Intent} that can be passed to {@link
596      *     Context#startActivity} in order to launch the transport's configuration UI. It may be
597      *     {@code null} if the transport does not offer any user-facing configuration UI.
598      * @param currentDestinationString A {@link String} describing the destination to which the
599      *     transport is currently sending data. MUST NOT be {@code null}.
600      * @param dataManagementIntent An {@link Intent} that can be passed to {@link
601      *     Context#startActivity} in order to launch the transport's data-management UI. It may be
602      *     {@code null} if the transport does not offer any user-facing data management UI.
603      * @param dataManagementLabel A {@link String} to be used as the label for the transport's data
604      *     management affordance. This MUST be {@code null} when dataManagementIntent is {@code
605      *     null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
606      * @throws SecurityException If the UID of the calling process differs from the package UID of
607      *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
608      * @deprecated Since Android Q, please use the variant {@link
609      *     #updateTransportAttributes(ComponentName, String, Intent, String, Intent, CharSequence)}
610      *     instead.
611      * @hide
612      */
613     @Deprecated
614     @SystemApi
615     @RequiresPermission(android.Manifest.permission.BACKUP)
updateTransportAttributes( @onNull ComponentName transportComponent, @NonNull String name, @Nullable Intent configurationIntent, @NonNull String currentDestinationString, @Nullable Intent dataManagementIntent, @Nullable String dataManagementLabel)616     public void updateTransportAttributes(
617             @NonNull ComponentName transportComponent,
618             @NonNull String name,
619             @Nullable Intent configurationIntent,
620             @NonNull String currentDestinationString,
621             @Nullable Intent dataManagementIntent,
622             @Nullable String dataManagementLabel) {
623         updateTransportAttributes(
624                 transportComponent,
625                 name,
626                 configurationIntent,
627                 currentDestinationString,
628                 dataManagementIntent,
629                 (CharSequence) dataManagementLabel);
630     }
631 
632     /**
633      * Update the attributes of the transport identified by {@code transportComponent}. If the
634      * specified transport has not been bound at least once (for registration), this call will be
635      * ignored. Only the host process of the transport can change its description, otherwise a
636      * {@link SecurityException} will be thrown.
637      *
638      * @param transportComponent The identity of the transport being described.
639      * @param name A {@link String} with the new name for the transport. This is NOT for
640      *     identification. MUST NOT be {@code null}.
641      * @param configurationIntent An {@link Intent} that can be passed to {@link
642      *     Context#startActivity} in order to launch the transport's configuration UI. It may be
643      *     {@code null} if the transport does not offer any user-facing configuration UI.
644      * @param currentDestinationString A {@link String} describing the destination to which the
645      *     transport is currently sending data. MUST NOT be {@code null}.
646      * @param dataManagementIntent An {@link Intent} that can be passed to {@link
647      *     Context#startActivity} in order to launch the transport's data-management UI. It may be
648      *     {@code null} if the transport does not offer any user-facing data management UI.
649      * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
650      *     data management affordance. This MUST be {@code null} when dataManagementIntent is {@code
651      *     null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
652      * @throws SecurityException If the UID of the calling process differs from the package UID of
653      *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
654      * @hide
655      */
656     @SystemApi
657     @RequiresPermission(android.Manifest.permission.BACKUP)
updateTransportAttributes( @onNull ComponentName transportComponent, @NonNull String name, @Nullable Intent configurationIntent, @NonNull String currentDestinationString, @Nullable Intent dataManagementIntent, @Nullable CharSequence dataManagementLabel)658     public void updateTransportAttributes(
659             @NonNull ComponentName transportComponent,
660             @NonNull String name,
661             @Nullable Intent configurationIntent,
662             @NonNull String currentDestinationString,
663             @Nullable Intent dataManagementIntent,
664             @Nullable CharSequence dataManagementLabel) {
665         checkServiceBinder();
666         if (sService != null) {
667             try {
668                 sService.updateTransportAttributesForUser(
669                         mContext.getUserId(),
670                         transportComponent,
671                         name,
672                         configurationIntent,
673                         currentDestinationString,
674                         dataManagementIntent,
675                         dataManagementLabel);
676             } catch (RemoteException e) {
677                 Log.e(TAG, "describeTransport() couldn't connect");
678             }
679         }
680     }
681 
682     /**
683      * Specify the current backup transport.
684      *
685      * @param transport The name of the transport to select.  This should be one
686      *   of the names returned by {@link #listAllTransports()}. This is the String returned by
687      *   {@link BackupTransport#name()} for the particular transport.
688      * @return The name of the previously selected transport.  If the given transport
689      *   name is not one of the currently available transports, no change is made to
690      *   the current transport setting and the method returns null.
691      *
692      * @hide
693      */
694     @Deprecated
695     @SystemApi
696     @RequiresPermission(android.Manifest.permission.BACKUP)
selectBackupTransport(String transport)697     public String selectBackupTransport(String transport) {
698         checkServiceBinder();
699         if (sService != null) {
700             try {
701                 return sService.selectBackupTransport(transport);
702             } catch (RemoteException e) {
703                 Log.e(TAG, "selectBackupTransport() couldn't connect");
704             }
705         }
706         return null;
707     }
708 
709     /**
710      * Specify the current backup transport and get notified when the transport is ready to be used.
711      * This method is async because BackupManager might need to bind to the specified transport
712      * which is in a separate process.
713      *
714      * @param transport ComponentName of the service hosting the transport. This is different from
715      *                  the transport's name that is returned by {@link BackupTransport#name()}.
716      * @param listener A listener object to get a callback on the transport being selected.
717      *
718      * @hide
719      */
720     @SystemApi
721     @RequiresPermission(android.Manifest.permission.BACKUP)
selectBackupTransport(ComponentName transport, SelectBackupTransportCallback listener)722     public void selectBackupTransport(ComponentName transport,
723             SelectBackupTransportCallback listener) {
724         checkServiceBinder();
725         if (sService != null) {
726             try {
727                 SelectTransportListenerWrapper wrapper = listener == null ?
728                         null : new SelectTransportListenerWrapper(mContext, listener);
729                 sService.selectBackupTransportAsyncForUser(
730                         mContext.getUserId(), transport, wrapper);
731             } catch (RemoteException e) {
732                 Log.e(TAG, "selectBackupTransportAsync() couldn't connect");
733             }
734         }
735     }
736 
737     /**
738      * Schedule an immediate backup attempt for all pending key/value updates.  This
739      * is primarily intended for transports to use when they detect a suitable
740      * opportunity for doing a backup pass.  If there are no pending updates to
741      * be sent, no action will be taken.  Even if some updates are pending, the
742      * transport will still be asked to confirm via the usual requestBackupTime()
743      * method.
744      *
745      * @hide
746      */
747     @SystemApi
748     @RequiresPermission(android.Manifest.permission.BACKUP)
backupNow()749     public void backupNow() {
750         checkServiceBinder();
751         if (sService != null) {
752             try {
753                 sService.backupNow();
754             } catch (RemoteException e) {
755                 Log.e(TAG, "backupNow() couldn't connect");
756             }
757         }
758     }
759 
760     /**
761      * Ask the framework which dataset, if any, the given package's data would be
762      * restored from if we were to install it right now.
763      *
764      * @param packageName The name of the package whose most-suitable dataset we
765      *     wish to look up
766      * @return The dataset token from which a restore should be attempted, or zero if
767      *     no suitable data is available.
768      *
769      * @hide
770      */
771     @SystemApi
772     @RequiresPermission(android.Manifest.permission.BACKUP)
getAvailableRestoreToken(String packageName)773     public long getAvailableRestoreToken(String packageName) {
774         checkServiceBinder();
775         if (sService != null) {
776             try {
777                 return sService.getAvailableRestoreTokenForUser(mContext.getUserId(), packageName);
778             } catch (RemoteException e) {
779                 Log.e(TAG, "getAvailableRestoreToken() couldn't connect");
780             }
781         }
782         return 0;
783     }
784 
785     /**
786      * Ask the framework whether this app is eligible for backup.
787      *
788      * @param packageName The name of the package.
789      * @return Whether this app is eligible for backup.
790      *
791      * @hide
792      */
793     @SystemApi
794     @RequiresPermission(android.Manifest.permission.BACKUP)
isAppEligibleForBackup(String packageName)795     public boolean isAppEligibleForBackup(String packageName) {
796         checkServiceBinder();
797         if (sService != null) {
798             try {
799                 return sService.isAppEligibleForBackupForUser(mContext.getUserId(), packageName);
800             } catch (RemoteException e) {
801                 Log.e(TAG, "isAppEligibleForBackup(pkg) couldn't connect");
802             }
803         }
804         return false;
805     }
806 
807     /**
808      * Request an immediate backup, providing an observer to which results of the backup operation
809      * will be published. The Android backup system will decide for each package whether it will
810      * be full app data backup or key/value-pair-based backup.
811      *
812      * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all
813      * provided packages using the remote transport.
814      *
815      * @param packages List of package names to backup.
816      * @param observer The {@link BackupObserver} to receive callbacks during the backup
817      * operation. Could be {@code null}.
818      * @return {@link BackupManager#SUCCESS} on success; nonzero on error.
819      * @exception  IllegalArgumentException on null or empty {@code packages} param.
820      *
821      * @hide
822      */
823     @SystemApi
824     @RequiresPermission(android.Manifest.permission.BACKUP)
requestBackup(String[] packages, BackupObserver observer)825     public int requestBackup(String[] packages, BackupObserver observer) {
826         return requestBackup(packages, observer, null, 0);
827     }
828 
829     /**
830      * Request an immediate backup, providing an observer to which results of the backup operation
831      * will be published. The Android backup system will decide for each package whether it will
832      * be full app data backup or key/value-pair-based backup.
833      *
834      * <p>If this method returns {@link BackupManager#SUCCESS}, the OS will attempt to backup all
835      * provided packages using the remote transport.
836      *
837      * @param packages List of package names to backup.
838      * @param observer The {@link BackupObserver} to receive callbacks during the backup
839      *                 operation. Could be {@code null}.
840      * @param monitor  The {@link BackupManagerMonitorWrapper} to receive callbacks of important
841      *                 events during the backup operation. Could be {@code null}.
842      * @param flags    {@link #FLAG_NON_INCREMENTAL_BACKUP}.
843      * @return {@link BackupManager#SUCCESS} on success; nonzero on error.
844      * @throws IllegalArgumentException on null or empty {@code packages} param.
845      * @hide
846      */
847     @SystemApi
848     @RequiresPermission(android.Manifest.permission.BACKUP)
requestBackup(String[] packages, BackupObserver observer, BackupManagerMonitor monitor, int flags)849     public int requestBackup(String[] packages, BackupObserver observer,
850             BackupManagerMonitor monitor, int flags) {
851         checkServiceBinder();
852         if (sService != null) {
853             try {
854                 BackupObserverWrapper observerWrapper = observer == null
855                         ? null
856                         : new BackupObserverWrapper(mContext, observer);
857                 BackupManagerMonitorWrapper monitorWrapper = monitor == null
858                         ? null
859                         : new BackupManagerMonitorWrapper(monitor);
860                 return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags);
861             } catch (RemoteException e) {
862                 Log.e(TAG, "requestBackup() couldn't connect");
863             }
864         }
865         return -1;
866     }
867 
868     /**
869      * Cancel all running backups. After this call returns, no currently running backups will
870      * interact with the selected transport.
871      *
872      * @hide
873      */
874     @SystemApi
875     @RequiresPermission(android.Manifest.permission.BACKUP)
cancelBackups()876     public void cancelBackups() {
877         checkServiceBinder();
878         if (sService != null) {
879             try {
880                 sService.cancelBackups();
881             } catch (RemoteException e) {
882                 Log.e(TAG, "cancelBackups() couldn't connect.");
883             }
884         }
885     }
886 
887     /**
888      * Returns a {@link UserHandle} for the user that has {@code ancestralSerialNumber} as the
889      * serial number of the its ancestral work profile or {@code null} if there is none.
890      *
891      * <p> The ancestral serial number will have a corresponding {@link UserHandle} if the device
892      * has a work profile that was restored from another work profile with serial number
893      * {@code ancestralSerialNumber}.
894      *
895      * @see android.os.UserManager#getSerialNumberForUser(UserHandle)
896      */
897     @Nullable
getUserForAncestralSerialNumber(long ancestralSerialNumber)898     public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
899         checkServiceBinder();
900         if (sService != null) {
901             try {
902                 return sService.getUserForAncestralSerialNumber(ancestralSerialNumber);
903             } catch (RemoteException e) {
904                 Log.e(TAG, "getUserForAncestralSerialNumber() couldn't connect");
905             }
906         }
907         return null;
908     }
909 
910     /**
911      * Sets the ancestral work profile for the calling user.
912      *
913      * <p> The ancestral work profile corresponds to the profile that was used to restore to the
914      * callers profile.
915      * @hide
916      */
917     @SystemApi
918     @RequiresPermission(android.Manifest.permission.BACKUP)
setAncestralSerialNumber(long ancestralSerialNumber)919     public void setAncestralSerialNumber(long ancestralSerialNumber) {
920         checkServiceBinder();
921         if (sService != null) {
922             try {
923                 sService.setAncestralSerialNumber(ancestralSerialNumber);
924             } catch (RemoteException e) {
925                 Log.e(TAG, "setAncestralSerialNumber() couldn't connect");
926             }
927         }
928     }
929 
930     /**
931      * Returns an {@link Intent} for the specified transport's configuration UI.
932      * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String,
933      * Intent, CharSequence)}.
934      * @param transportName The name of the registered transport.
935      * @hide
936      */
937     @SystemApi
938     @RequiresPermission(android.Manifest.permission.BACKUP)
getConfigurationIntent(String transportName)939     public Intent getConfigurationIntent(String transportName) {
940         checkServiceBinder();
941         if (sService != null) {
942             try {
943                 return sService.getConfigurationIntentForUser(mContext.getUserId(), transportName);
944             } catch (RemoteException e) {
945                 Log.e(TAG, "getConfigurationIntent() couldn't connect");
946             }
947         }
948         return null;
949     }
950 
951     /**
952      * Returns a {@link String} describing where the specified transport is sending data.
953      * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String,
954      * Intent, CharSequence)}.
955      * @param transportName The name of the registered transport.
956      * @hide
957      */
958     @SystemApi
959     @RequiresPermission(android.Manifest.permission.BACKUP)
getDestinationString(String transportName)960     public String getDestinationString(String transportName) {
961         checkServiceBinder();
962         if (sService != null) {
963             try {
964                 return sService.getDestinationStringForUser(mContext.getUserId(), transportName);
965             } catch (RemoteException e) {
966                 Log.e(TAG, "getDestinationString() couldn't connect");
967             }
968         }
969         return null;
970     }
971 
972     /**
973      * Returns an {@link Intent} for the specified transport's data management UI.
974      * This value is set by {@link #updateTransportAttributes(ComponentName, String, Intent, String,
975      * Intent, CharSequence)}.
976      * @param transportName The name of the registered transport.
977      * @hide
978      */
979     @SystemApi
980     @RequiresPermission(android.Manifest.permission.BACKUP)
getDataManagementIntent(String transportName)981     public Intent getDataManagementIntent(String transportName) {
982         checkServiceBinder();
983         if (sService != null) {
984             try {
985                 return sService.getDataManagementIntentForUser(mContext.getUserId(), transportName);
986             } catch (RemoteException e) {
987                 Log.e(TAG, "getDataManagementIntent() couldn't connect");
988             }
989         }
990         return null;
991     }
992 
993     /**
994      * Returns a {@link String} describing what the specified transport's data management intent is
995      * used for. This value is set by {@link #updateTransportAttributes(ComponentName, String,
996      * Intent, String, Intent, CharSequence)}.
997      *
998      * @param transportName The name of the registered transport.
999      * @deprecated Since Android Q, please use the variant {@link
1000      *     #getDataManagementIntentLabel(String)} instead.
1001      * @hide
1002      */
1003     @Deprecated
1004     @SystemApi
1005     @RequiresPermission(android.Manifest.permission.BACKUP)
1006     @Nullable
getDataManagementLabel(@onNull String transportName)1007     public String getDataManagementLabel(@NonNull String transportName) {
1008         CharSequence label = getDataManagementIntentLabel(transportName);
1009         return label == null ? null : label.toString();
1010     }
1011 
1012     /**
1013      * Returns a {@link CharSequence} describing what the specified transport's data management
1014      * intent is used for. This value is set by {@link #updateTransportAttributes(ComponentName,
1015      * String, Intent, String, Intent, CharSequence)}.
1016      *
1017      * @param transportName The name of the registered transport.
1018      * @hide
1019      */
1020     @SystemApi
1021     @RequiresPermission(android.Manifest.permission.BACKUP)
1022     @Nullable
getDataManagementIntentLabel(@onNull String transportName)1023     public CharSequence getDataManagementIntentLabel(@NonNull String transportName) {
1024         checkServiceBinder();
1025         if (sService != null) {
1026             try {
1027                 return sService.getDataManagementLabelForUser(mContext.getUserId(), transportName);
1028             } catch (RemoteException e) {
1029                 Log.e(TAG, "getDataManagementIntentLabel() couldn't connect");
1030             }
1031         }
1032         return null;
1033     }
1034 
1035     /**
1036      * Excludes keys from KV restore for a given package. The corresponding data will be excluded
1037      * from the data set available the backup agent during restore. However,  final list  of keys
1038      * that have been excluded will be passed to the agent to make it aware of the exclusions.
1039      *
1040      * @param packageName The name of the package for which to exclude keys.
1041      * @param keys The list of keys to exclude.
1042      *
1043      * @hide
1044      */
1045     @SystemApi
1046     @RequiresPermission(android.Manifest.permission.BACKUP)
excludeKeysFromRestore(@onNull String packageName, @NonNull List<String> keys)1047     public void excludeKeysFromRestore(@NonNull String packageName, @NonNull List<String> keys) {
1048         checkServiceBinder();
1049         if (sService != null) {
1050             try {
1051                 sService.excludeKeysFromRestore(packageName, keys);
1052             } catch (RemoteException e) {
1053                 Log.e(TAG, "excludeKeysFromRestore() couldn't connect");
1054             }
1055         }
1056     }
1057 
1058     /**
1059      * Get an instance of {@link BackupRestoreEventLogger} to report B&R related events during an
1060      * ongoing backup or restore operation.
1061      *
1062      * @param backupAgent the agent currently running a B&R operation.
1063      *
1064      * @return an instance of {@code BackupRestoreEventLogger} or {@code null} if the agent has not
1065      *         finished initialisation, i.e. {@link BackupAgent#onCreate()} has not been called yet.
1066      * @throws IllegalStateException if called before the agent has finished initialisation.
1067      *
1068      * @hide
1069      */
1070     @NonNull
1071     @SystemApi
getBackupRestoreEventLogger(@onNull BackupAgent backupAgent)1072     public BackupRestoreEventLogger getBackupRestoreEventLogger(@NonNull BackupAgent backupAgent) {
1073         BackupRestoreEventLogger logger = backupAgent.getBackupRestoreEventLogger();
1074         if (logger == null) {
1075             throw new IllegalStateException("Attempting to get logger on an uninitialised "
1076                     + "BackupAgent");
1077         }
1078         return backupAgent.getBackupRestoreEventLogger();
1079     }
1080 
1081     /**
1082      * Get an instance of {@link BackupRestoreEventLogger} to report B&R related events during a
1083      * delayed restore operation.
1084      *
1085      * @return an instance of {@link BackupRestoreEventLogger}.
1086      *
1087      * @hide
1088      */
1089     @NonNull
1090     @SystemApi
getDelayedRestoreLogger()1091     public BackupRestoreEventLogger getDelayedRestoreLogger() {
1092         return new BackupRestoreEventLogger(OperationType.RESTORE);
1093     }
1094 
1095     /**
1096      * Report B&R related events following a delayed restore operation.
1097      *
1098      * @param logger an instance of {@link BackupRestoreEventLogger} to which the corresponding
1099      *               events have been logged.
1100      *
1101      * @hide
1102      */
1103     @SystemApi
reportDelayedRestoreResult(@onNull BackupRestoreEventLogger logger)1104     public void reportDelayedRestoreResult(@NonNull BackupRestoreEventLogger logger) {
1105         checkServiceBinder();
1106         if (sService != null) {
1107             try {
1108                 sService.reportDelayedRestoreResult(mContext.getPackageName(),
1109                         logger.getLoggingResults());
1110             } catch (RemoteException e) {
1111                 Log.w(TAG, "reportDelayedRestoreResult() couldn't connect");
1112             }
1113         }
1114     }
1115 
1116     /*
1117      * We wrap incoming binder calls with a private class implementation that
1118      * redirects them into main-thread actions.  This serializes the backup
1119      * progress callbacks nicely within the usual main-thread lifecycle pattern.
1120      */
1121     private class BackupObserverWrapper extends IBackupObserver.Stub {
1122         final Handler mHandler;
1123         final BackupObserver mObserver;
1124 
1125         static final int MSG_UPDATE = 1;
1126         static final int MSG_RESULT = 2;
1127         static final int MSG_FINISHED = 3;
1128 
BackupObserverWrapper(Context context, BackupObserver observer)1129         BackupObserverWrapper(Context context, BackupObserver observer) {
1130             mHandler = new Handler(context.getMainLooper()) {
1131                 @Override
1132                 public void handleMessage(Message msg) {
1133                     switch (msg.what) {
1134                         case MSG_UPDATE:
1135                             Pair<String, BackupProgress> obj =
1136                                 (Pair<String, BackupProgress>) msg.obj;
1137                             mObserver.onUpdate(obj.first, obj.second);
1138                             break;
1139                         case MSG_RESULT:
1140                             mObserver.onResult((String)msg.obj, msg.arg1);
1141                             break;
1142                         case MSG_FINISHED:
1143                             mObserver.backupFinished(msg.arg1);
1144                             break;
1145                         default:
1146                             Log.w(TAG, "Unknown message: " + msg);
1147                             break;
1148                     }
1149                 }
1150             };
1151             mObserver = observer;
1152         }
1153 
1154         // Binder calls into this object just enqueue on the main-thread handler
1155         @Override
onUpdate(String currentPackage, BackupProgress backupProgress)1156         public void onUpdate(String currentPackage, BackupProgress backupProgress) {
1157             mHandler.sendMessage(
1158                 mHandler.obtainMessage(MSG_UPDATE, Pair.create(currentPackage, backupProgress)));
1159         }
1160 
1161         @Override
onResult(String currentPackage, int status)1162         public void onResult(String currentPackage, int status) {
1163             mHandler.sendMessage(
1164                 mHandler.obtainMessage(MSG_RESULT, status, 0, currentPackage));
1165         }
1166 
1167         @Override
backupFinished(int status)1168         public void backupFinished(int status) {
1169             mHandler.sendMessage(
1170                 mHandler.obtainMessage(MSG_FINISHED, status, 0));
1171         }
1172     }
1173 
1174     private class SelectTransportListenerWrapper extends ISelectBackupTransportCallback.Stub {
1175 
1176         private final Handler mHandler;
1177         private final SelectBackupTransportCallback mListener;
1178 
SelectTransportListenerWrapper(Context context, SelectBackupTransportCallback listener)1179         SelectTransportListenerWrapper(Context context, SelectBackupTransportCallback listener) {
1180             mHandler = new Handler(context.getMainLooper());
1181             mListener = listener;
1182         }
1183 
1184         @Override
onSuccess(final String transportName)1185         public void onSuccess(final String transportName) {
1186             mHandler.post(new Runnable() {
1187                 @Override
1188                 public void run() {
1189                     mListener.onSuccess(transportName);
1190                 }
1191             });
1192         }
1193 
1194         @Override
onFailure(final int reason)1195         public void onFailure(final int reason) {
1196             mHandler.post(new Runnable() {
1197                 @Override
1198                 public void run() {
1199                     mListener.onFailure(reason);
1200                 }
1201             });
1202         }
1203     }
1204 }
1205