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"><application></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