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 select packages from the given set onto the device, replacing the
     91      * current data of any app contained in the set with the data previously
     92      * backed up.
     93      *
     94      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
     95      *
     96      * @return Zero on success, nonzero on error. The observer will only receive
     97      *   progress callbacks if this method returned zero.
     98      * @param token The token from {@link getAvailableRestoreSets()} corresponding to
     99      *   the restore set that should be used.
    100      * @param observer If non-null, this binder points to an object that will receive
    101      *   progress callbacks during the restore operation.
    102      * @param packages The set of packages for which to attempt a restore.  Regardless of
    103      *   the contents of the actual back-end dataset named by {@code token}, only
    104      *   applications mentioned in this list will have their data restored.
    105      *
    106      * @hide
    107      */
    108     public int restoreSome(long token, RestoreObserver observer, String[] packages) {
    109         int err = -1;
    110         if (mObserver != null) {
    111             Log.d(TAG, "restoreAll() called during active restore");
    112             return -1;
    113         }
    114         mObserver = new RestoreObserverWrapper(mContext, observer);
    115         try {
    116             err = mBinder.restoreSome(token, mObserver, packages);
    117         } catch (RemoteException e) {
    118             Log.d(TAG, "Can't contact server to restore packages");
    119         }
    120         return err;
    121     }
    122 
    123     /**
    124      * Restore a single application from backup.  The data will be restored from the
    125      * current backup dataset if the given package 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 package
    128      * in either source, a nonzero value will be returned.
    129      *
    130      * @return Zero on success; nonzero on error.  The observer will only receive
    131      *   progress callbacks if this method returned zero.
    132      * @param packageName The name of the package whose data to restore.  If this is
    133      *   not the name of the caller's own package, then the android.permission.BACKUP
    134      *   permission must be held.
    135      * @param observer If non-null, this binder points to an object that will receive
    136      *   progress callbacks during the restore operation.
    137      */
    138     public int restorePackage(String packageName, RestoreObserver observer) {
    139         int err = -1;
    140         if (mObserver != null) {
    141             Log.d(TAG, "restorePackage() called during active restore");
    142             return -1;
    143         }
    144         mObserver = new RestoreObserverWrapper(mContext, observer);
    145         try {
    146             err = mBinder.restorePackage(packageName, mObserver);
    147         } catch (RemoteException e) {
    148             Log.d(TAG, "Can't contact server to restore package");
    149         }
    150         return err;
    151     }
    152 
    153     /**
    154      * End this restore session.  After this method is called, the RestoreSession
    155      * object is no longer valid.
    156      *
    157      * <p><b>Note:</b> The caller <i>must</i> invoke this method to end the restore session,
    158      *   even if {@link #restorePackage(String, RestoreObserver)} failed.
    159      */
    160     public void endRestoreSession() {
    161         try {
    162             mBinder.endRestoreSession();
    163         } catch (RemoteException e) {
    164             Log.d(TAG, "Can't contact server to get available sets");
    165         } finally {
    166             mBinder = null;
    167         }
    168     }
    169 
    170     /*
    171      * Nonpublic implementation here
    172      */
    173 
    174     RestoreSession(Context context, IRestoreSession binder) {
    175         mContext = context;
    176         mBinder = binder;
    177     }
    178 
    179     /*
    180      * We wrap incoming binder calls with a private class implementation that
    181      * redirects them into main-thread actions.  This serializes the restore
    182      * progress callbacks nicely within the usual main-thread lifecycle pattern.
    183      */
    184     private class RestoreObserverWrapper extends IRestoreObserver.Stub {
    185         final Handler mHandler;
    186         final RestoreObserver mAppObserver;
    187 
    188         static final int MSG_RESTORE_STARTING = 1;
    189         static final int MSG_UPDATE = 2;
    190         static final int MSG_RESTORE_FINISHED = 3;
    191         static final int MSG_RESTORE_SETS_AVAILABLE = 4;
    192 
    193         RestoreObserverWrapper(Context context, RestoreObserver appObserver) {
    194             mHandler = new Handler(context.getMainLooper()) {
    195                 @Override
    196                 public void handleMessage(Message msg) {
    197                     switch (msg.what) {
    198                     case MSG_RESTORE_STARTING:
    199                         mAppObserver.restoreStarting(msg.arg1);
    200                         break;
    201                     case MSG_UPDATE:
    202                         mAppObserver.onUpdate(msg.arg1, (String)msg.obj);
    203                         break;
    204                     case MSG_RESTORE_FINISHED:
    205                         mAppObserver.restoreFinished(msg.arg1);
    206                         break;
    207                     case MSG_RESTORE_SETS_AVAILABLE:
    208                         mAppObserver.restoreSetsAvailable((RestoreSet[])msg.obj);
    209                         break;
    210                     }
    211                 }
    212             };
    213             mAppObserver = appObserver;
    214         }
    215 
    216         // Binder calls into this object just enqueue on the main-thread handler
    217         public void restoreSetsAvailable(RestoreSet[] result) {
    218             mHandler.sendMessage(
    219                     mHandler.obtainMessage(MSG_RESTORE_SETS_AVAILABLE, result));
    220         }
    221 
    222         public void restoreStarting(int numPackages) {
    223             mHandler.sendMessage(
    224                     mHandler.obtainMessage(MSG_RESTORE_STARTING, numPackages, 0));
    225         }
    226 
    227         public void onUpdate(int nowBeingRestored, String currentPackage) {
    228             mHandler.sendMessage(
    229                     mHandler.obtainMessage(MSG_UPDATE, nowBeingRestored, 0, currentPackage));
    230         }
    231 
    232         public void restoreFinished(int error) {
    233             mHandler.sendMessage(
    234                     mHandler.obtainMessage(MSG_RESTORE_FINISHED, error, 0));
    235         }
    236     }
    237 }
    238