1 /* 2 * Copyright (C) 2010 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.SystemApi; 22 import android.content.Context; 23 import android.os.Bundle; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.os.RemoteException; 27 import android.util.Log; 28 29 import java.util.Arrays; 30 import java.util.HashSet; 31 import java.util.Set; 32 33 /** 34 * Interface for managing a restore session. 35 * @hide 36 */ 37 @SystemApi 38 public class RestoreSession { 39 static final String TAG = "RestoreSession"; 40 41 final Context mContext; 42 IRestoreSession mBinder; 43 RestoreObserverWrapper mObserver = null; 44 45 /** 46 * Ask the current transport what the available restore sets are. 47 * 48 * @param observer a RestoreObserver object whose restoreSetsAvailable() method will 49 * be called on the application's main thread in order to supply the results of 50 * the restore set lookup by the backup transport. This parameter must not be 51 * null. 52 * @param monitor a BackupManagerMonitor object will supply data about important events. 53 * @return Zero on success, nonzero on error. The observer's restoreSetsAvailable() 54 * method will only be called if this method returned zero. 55 */ getAvailableRestoreSets(RestoreObserver observer, BackupManagerMonitor monitor)56 public int getAvailableRestoreSets(RestoreObserver observer, BackupManagerMonitor monitor) { 57 int err = -1; 58 RestoreObserverWrapper obsWrapper = new RestoreObserverWrapper(mContext, observer); 59 BackupManagerMonitorWrapper monitorWrapper = monitor == null 60 ? null 61 : new BackupManagerMonitorWrapper(monitor); 62 try { 63 err = mBinder.getAvailableRestoreSets(obsWrapper, monitorWrapper); 64 } catch (RemoteException e) { 65 Log.d(TAG, "Can't contact server to get available sets"); 66 } 67 return err; 68 } 69 70 /** 71 * Ask the current transport what the available restore sets are. 72 * 73 * @param observer a RestoreObserver object whose restoreSetsAvailable() method will 74 * be called on the application's main thread in order to supply the results of 75 * the restore set lookup by the backup transport. This parameter must not be 76 * null. 77 * @return Zero on success, nonzero on error. The observer's restoreSetsAvailable() 78 * method will only be called if this method returned zero. 79 */ getAvailableRestoreSets(RestoreObserver observer)80 public int getAvailableRestoreSets(RestoreObserver observer) { 81 return getAvailableRestoreSets(observer, null); 82 } 83 84 /** 85 * Restore the given set onto the device, replacing the current data of any app 86 * contained in the restore set with the data previously backed up. 87 * 88 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 89 * 90 * @return Zero on success; nonzero on error. The observer will only receive 91 * progress callbacks if this method returned zero. 92 * @param token The token from {@link #getAvailableRestoreSets()} corresponding to 93 * the restore set that should be used. 94 * @param observer If non-null, this binder points to an object that will receive 95 * progress callbacks during the restore operation. 96 * @param monitor If non-null, this binder points to an object that will receive 97 * progress callbacks during the restore operation. 98 */ restoreAll(long token, RestoreObserver observer, BackupManagerMonitor monitor)99 public int restoreAll(long token, RestoreObserver observer, BackupManagerMonitor monitor) { 100 int err = -1; 101 if (mObserver != null) { 102 Log.d(TAG, "restoreAll() called during active restore"); 103 return -1; 104 } 105 mObserver = new RestoreObserverWrapper(mContext, observer); 106 BackupManagerMonitorWrapper monitorWrapper = monitor == null 107 ? null 108 : new BackupManagerMonitorWrapper(monitor); 109 try { 110 err = mBinder.restoreAll(token, mObserver, monitorWrapper); 111 } catch (RemoteException e) { 112 Log.d(TAG, "Can't contact server to restore"); 113 } 114 return err; 115 } 116 117 /** 118 * Restore the given set onto the device, replacing the current data of any app 119 * contained in the restore set with the data previously backed up. 120 * 121 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 122 * 123 * @return Zero on success; nonzero on error. The observer will only receive 124 * progress callbacks if this method returned zero. 125 * @param token The token from {@link #getAvailableRestoreSets()} corresponding to 126 * the restore set that should be used. 127 * @param observer If non-null, this binder points to an object that will receive 128 * progress callbacks during the restore operation. 129 */ restoreAll(long token, RestoreObserver observer)130 public int restoreAll(long token, RestoreObserver observer) { 131 return restoreAll(token, observer, null); 132 } 133 134 /** 135 * Restore select packages from the given set onto the device, replacing the 136 * current data of any app contained in the set with the data previously 137 * backed up. 138 * 139 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 140 * 141 * @return Zero on success, nonzero on error. The observer will only receive 142 * progress callbacks if this method returned zero. 143 * @param token The token from {@link getAvailableRestoreSets()} corresponding to 144 * the restore set that should be used. 145 * @param observer If non-null, this binder points to an object that will receive 146 * progress callbacks during the restore operation. 147 * @param packages The set of packages for which to attempt a restore. Regardless of 148 * the contents of the actual back-end dataset named by {@code token}, only 149 * applications mentioned in this list will have their data restored. 150 * @param monitor If non-null, this binder points to an object that will receive 151 * progress callbacks during the restore operation containing detailed information on any 152 * failures or important decisions made by {@link BackupManager}. 153 */ restorePackages(long token, @Nullable RestoreObserver observer, @NonNull Set<String> packages, @Nullable BackupManagerMonitor monitor)154 public int restorePackages(long token, @Nullable RestoreObserver observer, 155 @NonNull Set<String> packages, @Nullable BackupManagerMonitor monitor) { 156 int err = -1; 157 if (mObserver != null) { 158 Log.d(TAG, "restoreAll() called during active restore"); 159 return -1; 160 } 161 mObserver = new RestoreObserverWrapper(mContext, observer); 162 BackupManagerMonitorWrapper monitorWrapper = monitor == null 163 ? null 164 : new BackupManagerMonitorWrapper(monitor); 165 try { 166 err = mBinder.restorePackages(token, mObserver, packages.toArray(new String[] {}), 167 monitorWrapper); 168 } catch (RemoteException e) { 169 Log.d(TAG, "Can't contact server to restore packages"); 170 } 171 return err; 172 } 173 174 /** 175 * Restore select packages from the given set onto the device, replacing the 176 * current data of any app contained in the set with the data previously 177 * backed up. 178 * 179 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 180 * 181 * @return Zero on success, nonzero on error. The observer will only receive 182 * progress callbacks if this method returned zero. 183 * @param token The token from {@link getAvailableRestoreSets()} corresponding to 184 * the restore set that should be used. 185 * @param observer If non-null, this binder points to an object that will receive 186 * progress callbacks during the restore operation. 187 * @param packages The set of packages for which to attempt a restore. Regardless of 188 * the contents of the actual back-end dataset named by {@code token}, only 189 * applications mentioned in this list will have their data restored. 190 */ restorePackages(long token, @Nullable RestoreObserver observer, @NonNull Set<String> packages)191 public int restorePackages(long token, @Nullable RestoreObserver observer, 192 @NonNull Set<String> packages) { 193 return restorePackages(token, observer, packages, null); 194 } 195 196 /** 197 * Restore select packages from the given set onto the device, replacing the 198 * current data of any app contained in the set with the data previously 199 * backed up. 200 * 201 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 202 * 203 * @return Zero on success, nonzero on error. The observer will only receive 204 * progress callbacks if this method returned zero. 205 * @param token The token from {@link getAvailableRestoreSets()} corresponding to 206 * the restore set that should be used. 207 * @param observer If non-null, this binder points to an object that will receive 208 * progress callbacks during the restore operation. 209 * @param monitor If non-null, this binder points to an object that will receive 210 * progress callbacks during the restore operation. 211 * @param packages The set of packages for which to attempt a restore. Regardless of 212 * the contents of the actual back-end dataset named by {@code token}, only 213 * applications mentioned in this list will have their data restored. 214 * 215 * @deprecated use {@link RestoreSession#restorePackages(long, RestoreObserver, 216 * BackupManagerMonitor, Set)} instead. 217 * @removed 218 */ 219 @Deprecated restoreSome(long token, RestoreObserver observer, BackupManagerMonitor monitor, String[] packages)220 public int restoreSome(long token, RestoreObserver observer, BackupManagerMonitor monitor, 221 String[] packages) { 222 return restorePackages(token, observer, new HashSet<>(Arrays.asList(packages)), monitor); 223 } 224 225 /** 226 * Restore select packages from the given set onto the device, replacing the 227 * current data of any app contained in the set with the data previously 228 * backed up. 229 * 230 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 231 * 232 * @return Zero on success, nonzero on error. The observer will only receive 233 * progress callbacks if this method returned zero. 234 * @param token The token from {@link getAvailableRestoreSets()} corresponding to 235 * the restore set that should be used. 236 * @param observer If non-null, this binder points to an object that will receive 237 * progress callbacks during the restore operation. 238 * @param packages The set of packages for which to attempt a restore. Regardless of 239 * the contents of the actual back-end dataset named by {@code token}, only 240 * applications mentioned in this list will have their data restored. 241 * 242 * @deprecated use {@link RestoreSession#restorePackages(long, RestoreObserver, Set)} 243 * instead. 244 * @removed 245 */ 246 @Deprecated restoreSome(long token, RestoreObserver observer, String[] packages)247 public int restoreSome(long token, RestoreObserver observer, String[] packages) { 248 return restoreSome(token, observer, null, packages); 249 } 250 251 /** 252 * Restore a single application from backup. The data will be restored from the 253 * current backup dataset if the given package has stored data there, or from 254 * the dataset used during the last full device setup operation if the current 255 * backup dataset has no matching data. If no backup data exists for this package 256 * in either source, a nonzero value will be returned. 257 * 258 * <p class="caution">Note: Unlike other restore operations, this method doesn't terminate the 259 * application after the restore. The application continues running to receive the 260 * {@link RestoreObserver} callbacks on the {@code observer} argument. 261 * 262 * @return Zero on success; nonzero on error. The observer will only receive 263 * progress callbacks if this method returned zero. 264 * @param packageName The name of the package whose data to restore. If this is 265 * not the name of the caller's own package, then the android.permission.BACKUP 266 * permission must be held. 267 * @param observer If non-null, this binder points to an object that will receive 268 * progress callbacks during the restore operation. 269 * 270 * @param monitor If non-null, this binder points to an object that will receive 271 * event callbacks during the restore operation. 272 */ restorePackage(String packageName, RestoreObserver observer, BackupManagerMonitor monitor)273 public int restorePackage(String packageName, RestoreObserver observer, 274 BackupManagerMonitor monitor) { 275 int err = -1; 276 if (mObserver != null) { 277 Log.d(TAG, "restorePackage() called during active restore"); 278 return -1; 279 } 280 mObserver = new RestoreObserverWrapper(mContext, observer); 281 BackupManagerMonitorWrapper monitorWrapper = monitor == null 282 ? null 283 : new BackupManagerMonitorWrapper(monitor); 284 try { 285 err = mBinder.restorePackage(packageName, mObserver, monitorWrapper); 286 } catch (RemoteException e) { 287 Log.d(TAG, "Can't contact server to restore package"); 288 } 289 return err; 290 } 291 292 293 /** 294 * Restore a single application from backup. The data will be restored from the 295 * current backup dataset if the given package has stored data there, or from 296 * the dataset used during the last full device setup operation if the current 297 * backup dataset has no matching data. If no backup data exists for this package 298 * in either source, a nonzero value will be returned. 299 * 300 * @return Zero on success; nonzero on error. The observer will only receive 301 * progress callbacks if this method returned zero. 302 * @param packageName The name of the package whose data to restore. If this is 303 * not the name of the caller's own package, then the android.permission.BACKUP 304 * permission must be held. 305 * @param observer If non-null, this binder points to an object that will receive 306 * progress callbacks during the restore operation. 307 */ restorePackage(String packageName, RestoreObserver observer)308 public int restorePackage(String packageName, RestoreObserver observer) { 309 return restorePackage(packageName, observer, null); 310 } 311 312 /** 313 * End this restore session. After this method is called, the RestoreSession 314 * object is no longer valid. 315 * 316 * <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session, 317 * even if {@link #restorePackage(String, RestoreObserver)} failed. 318 */ endRestoreSession()319 public void endRestoreSession() { 320 try { 321 mBinder.endRestoreSession(); 322 } catch (RemoteException e) { 323 Log.d(TAG, "Can't contact server to get available sets"); 324 } finally { 325 mBinder = null; 326 } 327 } 328 329 /* 330 * Nonpublic implementation here 331 */ 332 RestoreSession(Context context, IRestoreSession binder)333 RestoreSession(Context context, IRestoreSession binder) { 334 mContext = context; 335 mBinder = binder; 336 } 337 338 /* 339 * We wrap incoming binder calls with a private class implementation that 340 * redirects them into main-thread actions. This serializes the restore 341 * progress callbacks nicely within the usual main-thread lifecycle pattern. 342 */ 343 private class RestoreObserverWrapper extends IRestoreObserver.Stub { 344 final Handler mHandler; 345 final RestoreObserver mAppObserver; 346 347 static final int MSG_RESTORE_STARTING = 1; 348 static final int MSG_UPDATE = 2; 349 static final int MSG_RESTORE_FINISHED = 3; 350 static final int MSG_RESTORE_SETS_AVAILABLE = 4; 351 RestoreObserverWrapper(Context context, RestoreObserver appObserver)352 RestoreObserverWrapper(Context context, RestoreObserver appObserver) { 353 mHandler = new Handler(context.getMainLooper()) { 354 @Override 355 public void handleMessage(Message msg) { 356 switch (msg.what) { 357 case MSG_RESTORE_STARTING: 358 mAppObserver.restoreStarting(msg.arg1); 359 break; 360 case MSG_UPDATE: 361 mAppObserver.onUpdate(msg.arg1, (String)msg.obj); 362 break; 363 case MSG_RESTORE_FINISHED: 364 mAppObserver.restoreFinished(msg.arg1); 365 break; 366 case MSG_RESTORE_SETS_AVAILABLE: 367 mAppObserver.restoreSetsAvailable((RestoreSet[])msg.obj); 368 break; 369 } 370 } 371 }; 372 mAppObserver = appObserver; 373 } 374 375 // Binder calls into this object just enqueue on the main-thread handler restoreSetsAvailable(RestoreSet[] result)376 public void restoreSetsAvailable(RestoreSet[] result) { 377 mHandler.sendMessage( 378 mHandler.obtainMessage(MSG_RESTORE_SETS_AVAILABLE, result)); 379 } 380 restoreStarting(int numPackages)381 public void restoreStarting(int numPackages) { 382 mHandler.sendMessage( 383 mHandler.obtainMessage(MSG_RESTORE_STARTING, numPackages, 0)); 384 } 385 onUpdate(int nowBeingRestored, String currentPackage)386 public void onUpdate(int nowBeingRestored, String currentPackage) { 387 mHandler.sendMessage( 388 mHandler.obtainMessage(MSG_UPDATE, nowBeingRestored, 0, currentPackage)); 389 } 390 restoreFinished(int error)391 public void restoreFinished(int error) { 392 mHandler.sendMessage( 393 mHandler.obtainMessage(MSG_RESTORE_FINISHED, error, 0)); 394 } 395 } 396 397 private class BackupManagerMonitorWrapper extends IBackupManagerMonitor.Stub { 398 final BackupManagerMonitor mMonitor; 399 BackupManagerMonitorWrapper(BackupManagerMonitor monitor)400 BackupManagerMonitorWrapper(BackupManagerMonitor monitor) { 401 mMonitor = monitor; 402 } 403 404 @Override onEvent(final Bundle event)405 public void onEvent(final Bundle event) throws RemoteException { 406 mMonitor.onEvent(event); 407 } 408 } 409 } 410