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 17package android.app.backup; 18 19import android.annotation.SystemApi; 20import android.app.backup.RestoreObserver; 21import android.app.backup.RestoreSet; 22import android.app.backup.IRestoreObserver; 23import android.app.backup.IRestoreSession; 24import android.content.Context; 25import android.os.Handler; 26import android.os.Message; 27import android.os.RemoteException; 28import android.util.Log; 29 30/** 31 * Interface for managing a restore session. 32 * @hide 33 */ 34@SystemApi 35public class RestoreSession { 36 static final String TAG = "RestoreSession"; 37 38 final Context mContext; 39 IRestoreSession mBinder; 40 RestoreObserverWrapper mObserver = null; 41 42 /** 43 * Ask the current transport what the available restore sets are. 44 * 45 * @param observer a RestoreObserver object whose restoreSetsAvailable() method will 46 * be called on the application's main thread in order to supply the results of 47 * the restore set lookup by the backup transport. This parameter must not be 48 * null. 49 * @return Zero on success, nonzero on error. The observer's restoreSetsAvailable() 50 * method will only be called if this method returned zero. 51 */ 52 public int getAvailableRestoreSets(RestoreObserver observer) { 53 int err = -1; 54 RestoreObserverWrapper obsWrapper = new RestoreObserverWrapper(mContext, observer); 55 try { 56 err = mBinder.getAvailableRestoreSets(obsWrapper); 57 } catch (RemoteException e) { 58 Log.d(TAG, "Can't contact server to get available sets"); 59 } 60 return err; 61 } 62 63 /** 64 * Restore the given set onto the device, replacing the current data of any app 65 * contained in the restore set with the data previously backed up. 66 * 67 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 68 * 69 * @return Zero on success; nonzero on error. The observer will only receive 70 * progress callbacks if this method returned zero. 71 * @param token The token from {@link #getAvailableRestoreSets()} corresponding to 72 * the restore set that should be used. 73 * @param observer If non-null, this binder points to an object that will receive 74 * progress callbacks during the restore operation. 75 */ 76 public int restoreAll(long token, RestoreObserver observer) { 77 int err = -1; 78 if (mObserver != null) { 79 Log.d(TAG, "restoreAll() called during active restore"); 80 return -1; 81 } 82 mObserver = new RestoreObserverWrapper(mContext, observer); 83 try { 84 err = mBinder.restoreAll(token, mObserver); 85 } catch (RemoteException e) { 86 Log.d(TAG, "Can't contact server to restore"); 87 } 88 return err; 89 } 90 91 /** 92 * Restore select packages from the given set onto the device, replacing the 93 * current data of any app contained in the set with the data previously 94 * backed up. 95 * 96 * <p>Callers must hold the android.permission.BACKUP permission to use this method. 97 * 98 * @return Zero on success, nonzero on error. The observer will only receive 99 * progress callbacks if this method returned zero. 100 * @param token The token from {@link getAvailableRestoreSets()} corresponding to 101 * the restore set that should be used. 102 * @param observer If non-null, this binder points to an object that will receive 103 * progress callbacks during the restore operation. 104 * @param packages The set of packages for which to attempt a restore. Regardless of 105 * the contents of the actual back-end dataset named by {@code token}, only 106 * applications mentioned in this list will have their data restored. 107 * 108 * @hide 109 */ 110 public int restoreSome(long token, RestoreObserver observer, String[] packages) { 111 int err = -1; 112 if (mObserver != null) { 113 Log.d(TAG, "restoreAll() called during active restore"); 114 return -1; 115 } 116 mObserver = new RestoreObserverWrapper(mContext, observer); 117 try { 118 err = mBinder.restoreSome(token, mObserver, packages); 119 } catch (RemoteException e) { 120 Log.d(TAG, "Can't contact server to restore packages"); 121 } 122 return err; 123 } 124 125 /** 126 * Restore a single application from backup. The data will be restored from the 127 * current backup dataset if the given package has stored data there, or from 128 * the dataset used during the last full device setup operation if the current 129 * backup dataset has no matching data. If no backup data exists for this package 130 * in either source, a nonzero value will be returned. 131 * 132 * @return Zero on success; nonzero on error. The observer will only receive 133 * progress callbacks if this method returned zero. 134 * @param packageName The name of the package whose data to restore. If this is 135 * not the name of the caller's own package, then the android.permission.BACKUP 136 * permission must be held. 137 * @param observer If non-null, this binder points to an object that will receive 138 * progress callbacks during the restore operation. 139 */ 140 public int restorePackage(String packageName, RestoreObserver observer) { 141 int err = -1; 142 if (mObserver != null) { 143 Log.d(TAG, "restorePackage() called during active restore"); 144 return -1; 145 } 146 mObserver = new RestoreObserverWrapper(mContext, observer); 147 try { 148 err = mBinder.restorePackage(packageName, mObserver); 149 } catch (RemoteException e) { 150 Log.d(TAG, "Can't contact server to restore package"); 151 } 152 return err; 153 } 154 155 /** 156 * End this restore session. After this method is called, the RestoreSession 157 * object is no longer valid. 158 * 159 * <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session, 160 * even if {@link #restorePackage(String, RestoreObserver)} failed. 161 */ 162 public void endRestoreSession() { 163 try { 164 mBinder.endRestoreSession(); 165 } catch (RemoteException e) { 166 Log.d(TAG, "Can't contact server to get available sets"); 167 } finally { 168 mBinder = null; 169 } 170 } 171 172 /* 173 * Nonpublic implementation here 174 */ 175 176 RestoreSession(Context context, IRestoreSession binder) { 177 mContext = context; 178 mBinder = binder; 179 } 180 181 /* 182 * We wrap incoming binder calls with a private class implementation that 183 * redirects them into main-thread actions. This serializes the restore 184 * progress callbacks nicely within the usual main-thread lifecycle pattern. 185 */ 186 private class RestoreObserverWrapper extends IRestoreObserver.Stub { 187 final Handler mHandler; 188 final RestoreObserver mAppObserver; 189 190 static final int MSG_RESTORE_STARTING = 1; 191 static final int MSG_UPDATE = 2; 192 static final int MSG_RESTORE_FINISHED = 3; 193 static final int MSG_RESTORE_SETS_AVAILABLE = 4; 194 195 RestoreObserverWrapper(Context context, RestoreObserver appObserver) { 196 mHandler = new Handler(context.getMainLooper()) { 197 @Override 198 public void handleMessage(Message msg) { 199 switch (msg.what) { 200 case MSG_RESTORE_STARTING: 201 mAppObserver.restoreStarting(msg.arg1); 202 break; 203 case MSG_UPDATE: 204 mAppObserver.onUpdate(msg.arg1, (String)msg.obj); 205 break; 206 case MSG_RESTORE_FINISHED: 207 mAppObserver.restoreFinished(msg.arg1); 208 break; 209 case MSG_RESTORE_SETS_AVAILABLE: 210 mAppObserver.restoreSetsAvailable((RestoreSet[])msg.obj); 211 break; 212 } 213 } 214 }; 215 mAppObserver = appObserver; 216 } 217 218 // Binder calls into this object just enqueue on the main-thread handler 219 public void restoreSetsAvailable(RestoreSet[] result) { 220 mHandler.sendMessage( 221 mHandler.obtainMessage(MSG_RESTORE_SETS_AVAILABLE, result)); 222 } 223 224 public void restoreStarting(int numPackages) { 225 mHandler.sendMessage( 226 mHandler.obtainMessage(MSG_RESTORE_STARTING, numPackages, 0)); 227 } 228 229 public void onUpdate(int nowBeingRestored, String currentPackage) { 230 mHandler.sendMessage( 231 mHandler.obtainMessage(MSG_UPDATE, nowBeingRestored, 0, currentPackage)); 232 } 233 234 public void restoreFinished(int error) { 235 mHandler.sendMessage( 236 mHandler.obtainMessage(MSG_RESTORE_FINISHED, error, 0)); 237 } 238 } 239} 240