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