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