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.SystemApi;
20 import android.app.backup.RestoreSession;
21 import android.app.backup.IBackupManager;
22 import android.app.backup.IRestoreSession;
23 import android.content.Context;
24 import android.os.RemoteException;
25 import android.os.ServiceManager;
26 import android.util.Log;
27 
28 /**
29  * The interface through which an application interacts with the Android backup service to
30  * request backup and restore operations.
31  * Applications instantiate it using the constructor and issue calls through that instance.
32  * <p>
33  * When an application has made changes to data which should be backed up, a
34  * call to {@link #dataChanged()} will notify the backup service. The system
35  * will then schedule a backup operation to occur in the near future. Repeated
36  * calls to {@link #dataChanged()} have no further effect until the backup
37  * operation actually occurs.
38  * <p>
39  * A backup or restore operation for your application begins when the system launches the
40  * {@link android.app.backup.BackupAgent} subclass you've declared in your manifest. See the
41  * documentation for {@link android.app.backup.BackupAgent} for a detailed description
42  * of how the operation then proceeds.
43  * <p>
44  * Several attributes affecting the operation of the backup and restore mechanism
45  * can be set on the <code>
46  * <a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code>
47  * tag in your application's AndroidManifest.xml file.
48  *
49  * <div class="special reference">
50  * <h3>Developer Guides</h3>
51  * <p>For more information about using BackupManager, read the
52  * <a href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p></div>
53  *
54  * @attr ref android.R.styleable#AndroidManifestApplication_allowBackup
55  * @attr ref android.R.styleable#AndroidManifestApplication_backupAgent
56  * @attr ref android.R.styleable#AndroidManifestApplication_killAfterRestore
57  * @attr ref android.R.styleable#AndroidManifestApplication_restoreAnyVersion
58  */
59 public class BackupManager {
60     private static final String TAG = "BackupManager";
61 
62     private Context mContext;
63     private static IBackupManager sService;
64 
checkServiceBinder()65     private static void checkServiceBinder() {
66         if (sService == null) {
67             sService = IBackupManager.Stub.asInterface(
68                     ServiceManager.getService(Context.BACKUP_SERVICE));
69         }
70     }
71 
72     /**
73      * Constructs a BackupManager object through which the application can
74      * communicate with the Android backup system.
75      *
76      * @param context The {@link android.content.Context} that was provided when
77      *                one of your application's {@link android.app.Activity Activities}
78      *                was created.
79      */
BackupManager(Context context)80     public BackupManager(Context context) {
81         mContext = context;
82     }
83 
84     /**
85      * Notifies the Android backup system that your application wishes to back up
86      * new changes to its data.  A backup operation using your application's
87      * {@link android.app.backup.BackupAgent} subclass will be scheduled when you
88      * call this method.
89      */
dataChanged()90     public void dataChanged() {
91         checkServiceBinder();
92         if (sService != null) {
93             try {
94                 sService.dataChanged(mContext.getPackageName());
95             } catch (RemoteException e) {
96                 Log.d(TAG, "dataChanged() couldn't connect");
97             }
98         }
99     }
100 
101     /**
102      * Convenience method for callers who need to indicate that some other package
103      * needs a backup pass.  This can be useful in the case of groups of packages
104      * that share a uid.
105      * <p>
106      * This method requires that the application hold the "android.permission.BACKUP"
107      * permission if the package named in the argument does not run under the same uid
108      * as the caller.
109      *
110      * @param packageName The package name identifying the application to back up.
111      */
dataChanged(String packageName)112     public static void dataChanged(String packageName) {
113         checkServiceBinder();
114         if (sService != null) {
115             try {
116                 sService.dataChanged(packageName);
117             } catch (RemoteException e) {
118                 Log.e(TAG, "dataChanged(pkg) couldn't connect");
119             }
120         }
121     }
122 
123     /**
124      * Restore the calling application from backup.  The data will be restored from the
125      * current backup dataset if the application has stored data there, or from
126      * the dataset used during the last full device setup operation if the current
127      * backup dataset has no matching data.  If no backup data exists for this application
128      * in either source, a nonzero value will be returned.
129      *
130      * <p>If this method returns zero (meaning success), the OS will attempt to retrieve
131      * a backed-up dataset from the remote transport, instantiate the application's
132      * backup agent, and pass the dataset to the agent's
133      * {@link android.app.backup.BackupAgent#onRestore(BackupDataInput, int, android.os.ParcelFileDescriptor) onRestore()}
134      * method.
135      *
136      * @param observer The {@link RestoreObserver} to receive callbacks during the restore
137      * operation. This must not be null.
138      *
139      * @return Zero on success; nonzero on error.
140      */
requestRestore(RestoreObserver observer)141     public int requestRestore(RestoreObserver observer) {
142         int result = -1;
143         checkServiceBinder();
144         if (sService != null) {
145             RestoreSession session = null;
146             try {
147                 IRestoreSession binder = sService.beginRestoreSession(mContext.getPackageName(),
148                         null);
149                 if (binder != null) {
150                     session = new RestoreSession(mContext, binder);
151                     result = session.restorePackage(mContext.getPackageName(), observer);
152                 }
153             } catch (RemoteException e) {
154                 Log.e(TAG, "restoreSelf() unable to contact service");
155             } finally {
156                 if (session != null) {
157                     session.endRestoreSession();
158                 }
159             }
160         }
161         return result;
162     }
163 
164     // system APIs start here
165 
166     /**
167      * Begin the process of restoring data from backup.  See the
168      * {@link android.app.backup.RestoreSession} class for documentation on that process.
169      * @hide
170      */
171     @SystemApi
beginRestoreSession()172     public RestoreSession beginRestoreSession() {
173         RestoreSession session = null;
174         checkServiceBinder();
175         if (sService != null) {
176             try {
177                 // All packages, current transport
178                 IRestoreSession binder = sService.beginRestoreSession(null, null);
179                 if (binder != null) {
180                     session = new RestoreSession(mContext, binder);
181                 }
182             } catch (RemoteException e) {
183                 Log.e(TAG, "beginRestoreSession() couldn't connect");
184             }
185         }
186         return session;
187     }
188 
189     /**
190      * Enable/disable the backup service entirely.  When disabled, no backup
191      * or restore operations will take place.  Data-changed notifications will
192      * still be observed and collected, however, so that changes made while the
193      * mechanism was disabled will still be backed up properly if it is enabled
194      * at some point in the future.
195      *
196      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
197      *
198      * @hide
199      */
200     @SystemApi
setBackupEnabled(boolean isEnabled)201     public void setBackupEnabled(boolean isEnabled) {
202         checkServiceBinder();
203         if (sService != null) {
204             try {
205                 sService.setBackupEnabled(isEnabled);
206             } catch (RemoteException e) {
207                 Log.e(TAG, "setBackupEnabled() couldn't connect");
208             }
209         }
210     }
211 
212     /**
213      * Report whether the backup mechanism is currently enabled.
214      *
215      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
216      *
217      * @hide
218      */
219     @SystemApi
isBackupEnabled()220     public boolean isBackupEnabled() {
221         checkServiceBinder();
222         if (sService != null) {
223             try {
224                 return sService.isBackupEnabled();
225             } catch (RemoteException e) {
226                 Log.e(TAG, "isBackupEnabled() couldn't connect");
227             }
228         }
229         return false;
230     }
231 
232     /**
233      * Enable/disable data restore at application install time.  When enabled, app
234      * installation will include an attempt to fetch the app's historical data from
235      * the archival restore dataset (if any).  When disabled, no such attempt will
236      * be made.
237      *
238      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
239      *
240      * @hide
241      */
242     @SystemApi
setAutoRestore(boolean isEnabled)243     public void setAutoRestore(boolean isEnabled) {
244         checkServiceBinder();
245         if (sService != null) {
246             try {
247                 sService.setAutoRestore(isEnabled);
248             } catch (RemoteException e) {
249                 Log.e(TAG, "setAutoRestore() couldn't connect");
250             }
251         }
252     }
253 
254     /**
255      * Identify the currently selected transport.  Callers must hold the
256      * android.permission.BACKUP permission to use this method.
257      * @return The name of the currently active backup transport.  In case of
258      *   failure or if no transport is currently active, this method returns {@code null}.
259      *
260      * @hide
261      */
262     @SystemApi
getCurrentTransport()263     public String getCurrentTransport() {
264         checkServiceBinder();
265         if (sService != null) {
266             try {
267                 return sService.getCurrentTransport();
268             } catch (RemoteException e) {
269                 Log.e(TAG, "getCurrentTransport() couldn't connect");
270             }
271         }
272         return null;
273     }
274 
275     /**
276      * Request a list of all available backup transports' names.  Callers must
277      * hold the android.permission.BACKUP permission to use this method.
278      *
279      * @hide
280      */
281     @SystemApi
listAllTransports()282     public String[] listAllTransports() {
283         checkServiceBinder();
284         if (sService != null) {
285             try {
286                 return sService.listAllTransports();
287             } catch (RemoteException e) {
288                 Log.e(TAG, "listAllTransports() couldn't connect");
289             }
290         }
291         return null;
292     }
293 
294     /**
295      * Specify the current backup transport.  Callers must hold the
296      * android.permission.BACKUP permission to use this method.
297      *
298      * @param transport The name of the transport to select.  This should be one
299      *   of the names returned by {@link #listAllTransports()}.
300      * @return The name of the previously selected transport.  If the given transport
301      *   name is not one of the currently available transports, no change is made to
302      *   the current transport setting and the method returns null.
303      *
304      * @hide
305      */
306     @SystemApi
selectBackupTransport(String transport)307     public String selectBackupTransport(String transport) {
308         checkServiceBinder();
309         if (sService != null) {
310             try {
311                 return sService.selectBackupTransport(transport);
312             } catch (RemoteException e) {
313                 Log.e(TAG, "selectBackupTransport() couldn't connect");
314             }
315         }
316         return null;
317     }
318 
319     /**
320      * Schedule an immediate backup attempt for all pending key/value updates.  This
321      * is primarily intended for transports to use when they detect a suitable
322      * opportunity for doing a backup pass.  If there are no pending updates to
323      * be sent, no action will be taken.  Even if some updates are pending, the
324      * transport will still be asked to confirm via the usual requestBackupTime()
325      * method.
326      *
327      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
328      *
329      * @hide
330      */
331     @SystemApi
backupNow()332     public void backupNow() {
333         checkServiceBinder();
334         if (sService != null) {
335             try {
336                 sService.backupNow();
337             } catch (RemoteException e) {
338                 Log.e(TAG, "backupNow() couldn't connect");
339             }
340         }
341     }
342 
343     /**
344      * Ask the framework which dataset, if any, the given package's data would be
345      * restored from if we were to install it right now.
346      *
347      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
348      *
349      * @param packageName The name of the package whose most-suitable dataset we
350      *     wish to look up
351      * @return The dataset token from which a restore should be attempted, or zero if
352      *     no suitable data is available.
353      *
354      * @hide
355      */
356     @SystemApi
getAvailableRestoreToken(String packageName)357     public long getAvailableRestoreToken(String packageName) {
358         checkServiceBinder();
359         if (sService != null) {
360             try {
361                 return sService.getAvailableRestoreToken(packageName);
362             } catch (RemoteException e) {
363                 Log.e(TAG, "getAvailableRestoreToken() couldn't connect");
364             }
365         }
366         return 0;
367     }
368 }
369