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