Home | History | Annotate | Download | only in restore
      1 /*
      2  * Copyright (C) 2017 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 com.android.server.backup.restore;
     18 
     19 import static com.android.server.backup.BackupManagerService.DEBUG;
     20 import static com.android.server.backup.BackupManagerService.KEY_WIDGET_STATE;
     21 import static com.android.server.backup.BackupManagerService.MORE_DEBUG;
     22 import static com.android.server.backup.BackupManagerService.OP_TYPE_RESTORE_WAIT;
     23 import static com.android.server.backup.BackupManagerService.PACKAGE_MANAGER_SENTINEL;
     24 import static com.android.server.backup.BackupManagerService.SETTINGS_PACKAGE;
     25 import static com.android.server.backup.BackupManagerService.TAG;
     26 import static com.android.server.backup.internal.BackupHandler.MSG_BACKUP_RESTORE_STEP;
     27 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
     28 import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
     29 
     30 import android.annotation.Nullable;
     31 import android.app.ApplicationThreadConstants;
     32 import android.app.IBackupAgent;
     33 import android.app.backup.BackupDataInput;
     34 import android.app.backup.BackupDataOutput;
     35 import android.app.backup.BackupManagerMonitor;
     36 import android.app.backup.BackupTransport;
     37 import android.app.backup.IBackupManagerMonitor;
     38 import android.app.backup.IRestoreObserver;
     39 import android.app.backup.RestoreDescription;
     40 import android.content.pm.ApplicationInfo;
     41 import android.content.pm.PackageInfo;
     42 import android.content.pm.PackageManager;
     43 import android.content.pm.PackageManagerInternal;
     44 import android.content.pm.PackageManager.NameNotFoundException;
     45 import android.os.Bundle;
     46 import android.os.Message;
     47 import android.os.ParcelFileDescriptor;
     48 import android.os.Process;
     49 import android.os.RemoteException;
     50 import android.os.SystemClock;
     51 import android.os.UserHandle;
     52 import android.util.EventLog;
     53 import android.util.Slog;
     54 
     55 import com.android.internal.backup.IBackupTransport;
     56 import com.android.internal.util.Preconditions;
     57 import com.android.server.AppWidgetBackupBridge;
     58 import com.android.server.EventLogTags;
     59 import com.android.server.LocalServices;
     60 import com.android.server.backup.BackupAgentTimeoutParameters;
     61 import com.android.server.backup.BackupRestoreTask;
     62 import com.android.server.backup.BackupUtils;
     63 import com.android.server.backup.PackageManagerBackupAgent;
     64 import com.android.server.backup.PackageManagerBackupAgent.Metadata;
     65 import com.android.server.backup.BackupManagerService;
     66 import com.android.server.backup.TransportManager;
     67 import com.android.server.backup.internal.OnTaskFinishedListener;
     68 import com.android.server.backup.transport.TransportClient;
     69 import com.android.server.backup.utils.AppBackupUtils;
     70 import com.android.server.backup.utils.BackupManagerMonitorUtils;
     71 
     72 import libcore.io.IoUtils;
     73 
     74 import java.io.File;
     75 import java.io.FileInputStream;
     76 import java.io.FileOutputStream;
     77 import java.io.IOException;
     78 import java.util.ArrayList;
     79 import java.util.List;
     80 
     81 public class PerformUnifiedRestoreTask implements BackupRestoreTask {
     82 
     83     private BackupManagerService backupManagerService;
     84     private final TransportManager mTransportManager;
     85     // Transport client we're working with to do the restore
     86     private final TransportClient mTransportClient;
     87 
     88     // Where per-transport saved state goes
     89     File mStateDir;
     90 
     91     // Restore observer; may be null
     92     private IRestoreObserver mObserver;
     93 
     94     // BackuoManagerMonitor; may be null
     95     private IBackupManagerMonitor mMonitor;
     96 
     97     // Token identifying the dataset to the transport
     98     private long mToken;
     99 
    100     // When this is a restore-during-install, this is the token identifying the
    101     // operation to the Package Manager, and we must ensure that we let it know
    102     // when we're finished.
    103     private int mPmToken;
    104 
    105     // When this is restore-during-install, we need to tell the package manager
    106     // whether we actually launched the app, because this affects notifications
    107     // around externally-visible state transitions.
    108     private boolean mDidLaunch;
    109 
    110     // Is this a whole-system restore, i.e. are we establishing a new ancestral
    111     // dataset to base future restore-at-install operations from?
    112     private boolean mIsSystemRestore;
    113 
    114     // If this is a single-package restore, what package are we interested in?
    115     private PackageInfo mTargetPackage;
    116 
    117     // In all cases, the calculated list of packages that we are trying to restore
    118     private List<PackageInfo> mAcceptSet;
    119 
    120     // Our bookkeeping about the ancestral dataset
    121     private PackageManagerBackupAgent mPmAgent;
    122 
    123     // Currently-bound backup agent for restore + restoreFinished purposes
    124     private IBackupAgent mAgent;
    125 
    126     // What sort of restore we're doing now
    127     private RestoreDescription mRestoreDescription;
    128 
    129     // The package we're currently restoring
    130     private PackageInfo mCurrentPackage;
    131 
    132     // Widget-related data handled as part of this restore operation
    133     private byte[] mWidgetData;
    134 
    135     // Number of apps restored in this pass
    136     private int mCount;
    137 
    138     // When did we start?
    139     private long mStartRealtime;
    140 
    141     // State machine progress
    142     private UnifiedRestoreState mState;
    143 
    144     // How are things going?
    145     private int mStatus;
    146 
    147     // Done?
    148     private boolean mFinished;
    149 
    150     // When finished call listener
    151     private final OnTaskFinishedListener mListener;
    152 
    153     // Key/value: bookkeeping about staged data and files for agent access
    154     private File mBackupDataName;
    155     private File mStageName;
    156     private File mSavedStateName;
    157     private File mNewStateName;
    158     ParcelFileDescriptor mBackupData;
    159     ParcelFileDescriptor mNewState;
    160 
    161     private final int mEphemeralOpToken;
    162     private final BackupAgentTimeoutParameters mAgentTimeoutParameters;
    163 
    164     // This task can assume that the wakelock is properly held for it and doesn't have to worry
    165     // about releasing it.
    166     public PerformUnifiedRestoreTask(
    167             BackupManagerService backupManagerService,
    168             TransportClient transportClient,
    169             IRestoreObserver observer,
    170             IBackupManagerMonitor monitor,
    171             long restoreSetToken,
    172             @Nullable PackageInfo targetPackage,
    173             int pmToken,
    174             boolean isFullSystemRestore,
    175             @Nullable String[] filterSet,
    176             OnTaskFinishedListener listener) {
    177         this.backupManagerService = backupManagerService;
    178         mTransportManager = backupManagerService.getTransportManager();
    179         mEphemeralOpToken = backupManagerService.generateRandomIntegerToken();
    180         mState = UnifiedRestoreState.INITIAL;
    181         mStartRealtime = SystemClock.elapsedRealtime();
    182 
    183         mTransportClient = transportClient;
    184         mObserver = observer;
    185         mMonitor = monitor;
    186         mToken = restoreSetToken;
    187         mPmToken = pmToken;
    188         mTargetPackage = targetPackage;
    189         mIsSystemRestore = isFullSystemRestore;
    190         mFinished = false;
    191         mDidLaunch = false;
    192         mListener = listener;
    193         mAgentTimeoutParameters = Preconditions.checkNotNull(
    194                 backupManagerService.getAgentTimeoutParameters(),
    195                 "Timeout parameters cannot be null");
    196 
    197         if (targetPackage != null) {
    198             // Single package restore
    199             mAcceptSet = new ArrayList<>();
    200             mAcceptSet.add(targetPackage);
    201         } else {
    202             // Everything possible, or a target set
    203             if (filterSet == null) {
    204                 // We want everything and a pony
    205                 List<PackageInfo> apps =
    206                         PackageManagerBackupAgent.getStorableApplications(
    207                                 backupManagerService.getPackageManager());
    208                 filterSet = packagesToNames(apps);
    209                 if (DEBUG) {
    210                     Slog.i(TAG, "Full restore; asking about " + filterSet.length + " apps");
    211                 }
    212             }
    213 
    214             mAcceptSet = new ArrayList<>(filterSet.length);
    215 
    216             // Pro tem, we insist on moving the settings provider package to last place.
    217             // Keep track of whether it's in the list, and bump it down if so.  We also
    218             // want to do the system package itself first if it's called for.
    219             boolean hasSystem = false;
    220             boolean hasSettings = false;
    221             for (int i = 0; i < filterSet.length; i++) {
    222                 try {
    223                     PackageManager pm = backupManagerService.getPackageManager();
    224                     PackageInfo info = pm.getPackageInfo(filterSet[i], 0);
    225                     if ("android".equals(info.packageName)) {
    226                         hasSystem = true;
    227                         continue;
    228                     }
    229                     if (SETTINGS_PACKAGE.equals(info.packageName)) {
    230                         hasSettings = true;
    231                         continue;
    232                     }
    233 
    234                     if (AppBackupUtils.appIsEligibleForBackup(info.applicationInfo, pm)) {
    235                         mAcceptSet.add(info);
    236                     }
    237                 } catch (NameNotFoundException e) {
    238                     // requested package name doesn't exist; ignore it
    239                 }
    240             }
    241             if (hasSystem) {
    242                 try {
    243                     mAcceptSet.add(0,
    244                             backupManagerService.getPackageManager().getPackageInfo("android", 0));
    245                 } catch (NameNotFoundException e) {
    246                     // won't happen; we know a priori that it's valid
    247                 }
    248             }
    249             if (hasSettings) {
    250                 try {
    251                     mAcceptSet.add(backupManagerService.getPackageManager().getPackageInfo(
    252                             SETTINGS_PACKAGE, 0));
    253                 } catch (NameNotFoundException e) {
    254                     // this one is always valid too
    255                 }
    256             }
    257         }
    258 
    259         if (MORE_DEBUG) {
    260             Slog.v(TAG, "Restore; accept set size is " + mAcceptSet.size());
    261             for (PackageInfo info : mAcceptSet) {
    262                 Slog.v(TAG, "   " + info.packageName);
    263             }
    264         }
    265     }
    266 
    267     private String[] packagesToNames(List<PackageInfo> apps) {
    268         final int N = apps.size();
    269         String[] names = new String[N];
    270         for (int i = 0; i < N; i++) {
    271             names[i] = apps.get(i).packageName;
    272         }
    273         return names;
    274     }
    275 
    276     // Execute one tick of whatever state machine the task implements
    277     @Override
    278     public void execute() {
    279         if (MORE_DEBUG) {
    280             Slog.v(TAG, "*** Executing restore step " + mState);
    281         }
    282         switch (mState) {
    283             case INITIAL:
    284                 startRestore();
    285                 break;
    286 
    287             case RUNNING_QUEUE:
    288                 dispatchNextRestore();
    289                 break;
    290 
    291             case RESTORE_KEYVALUE:
    292                 restoreKeyValue();
    293                 break;
    294 
    295             case RESTORE_FULL:
    296                 restoreFull();
    297                 break;
    298 
    299             case RESTORE_FINISHED:
    300                 restoreFinished();
    301                 break;
    302 
    303             case FINAL:
    304                 if (!mFinished) {
    305                     finalizeRestore();
    306                 } else {
    307                     Slog.e(TAG, "Duplicate finish");
    308                 }
    309                 mFinished = true;
    310                 break;
    311         }
    312     }
    313 
    314     /*
    315      * SKETCH OF OPERATION
    316      *
    317      * create one of these PerformUnifiedRestoreTask objects, telling it which
    318      * dataset & transport to address, and then parameters within the restore
    319      * operation: single target package vs many, etc.
    320      *
    321      * 1. transport.startRestore(token, list-of-packages).  If we need @pm@  it is
    322      * always placed first and the settings provider always placed last [for now].
    323      *
    324      * 1a [if we needed @pm@ then nextRestorePackage() and restore the PMBA inline]
    325      *
    326      *   [ state change => RUNNING_QUEUE ]
    327      *
    328      * NOW ITERATE:
    329      *
    330      * { 3. t.nextRestorePackage()
    331      *   4. does the metadata for this package allow us to restore it?
    332      *      does the on-disk app permit us to restore it? [re-check allowBackup etc]
    333      *   5. is this a key/value dataset?  => key/value agent restore
    334      *       [ state change => RESTORE_KEYVALUE ]
    335      *       5a. spin up agent
    336      *       5b. t.getRestoreData() to stage it properly
    337      *       5c. call into agent to perform restore
    338      *       5d. tear down agent
    339      *       [ state change => RUNNING_QUEUE ]
    340      *
    341      *   6. else it's a stream dataset:
    342      *       [ state change => RESTORE_FULL ]
    343      *       6a. instantiate the engine for a stream restore: engine handles agent lifecycles
    344      *       6b. spin off engine runner on separate thread
    345      *       6c. ITERATE getNextFullRestoreDataChunk() and copy data to engine runner socket
    346      *       [ state change => RUNNING_QUEUE ]
    347      * }
    348      *
    349      *   [ state change => FINAL ]
    350      *
    351      * 7. t.finishRestore(), call listeners, etc.
    352      *
    353      *
    354      */
    355 
    356     // state INITIAL : set up for the restore and read the metadata if necessary
    357     private void startRestore() {
    358         sendStartRestore(mAcceptSet.size());
    359 
    360         // If we're starting a full-system restore, set up to begin widget ID remapping
    361         if (mIsSystemRestore) {
    362             // TODO: http://b/22388012
    363             AppWidgetBackupBridge.restoreStarting(UserHandle.USER_SYSTEM);
    364         }
    365 
    366         try {
    367             String transportDirName =
    368                     mTransportManager.getTransportDirName(mTransportClient.getTransportComponent());
    369             mStateDir = new File(backupManagerService.getBaseStateDir(), transportDirName);
    370 
    371             // Fetch the current metadata from the dataset first
    372             PackageInfo pmPackage = new PackageInfo();
    373             pmPackage.packageName = PACKAGE_MANAGER_SENTINEL;
    374             mAcceptSet.add(0, pmPackage);
    375 
    376             PackageInfo[] packages = mAcceptSet.toArray(new PackageInfo[0]);
    377 
    378             IBackupTransport transport =
    379                     mTransportClient.connectOrThrow("PerformUnifiedRestoreTask.startRestore()");
    380 
    381             mStatus = transport.startRestore(mToken, packages);
    382             if (mStatus != BackupTransport.TRANSPORT_OK) {
    383                 Slog.e(TAG, "Transport error " + mStatus + "; no restore possible");
    384                 mStatus = BackupTransport.TRANSPORT_ERROR;
    385                 executeNextState(UnifiedRestoreState.FINAL);
    386                 return;
    387             }
    388 
    389             RestoreDescription desc = transport.nextRestorePackage();
    390             if (desc == null) {
    391                 Slog.e(TAG, "No restore metadata available; halting");
    392                 mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    393                         BackupManagerMonitor.LOG_EVENT_ID_NO_RESTORE_METADATA_AVAILABLE,
    394                         mCurrentPackage,
    395                         BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
    396                 mStatus = BackupTransport.TRANSPORT_ERROR;
    397                 executeNextState(UnifiedRestoreState.FINAL);
    398                 return;
    399             }
    400             if (!PACKAGE_MANAGER_SENTINEL.equals(
    401                     desc.getPackageName())) {
    402                 Slog.e(TAG, "Required package metadata but got "
    403                         + desc.getPackageName());
    404                 mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    405                         BackupManagerMonitor.LOG_EVENT_ID_NO_PM_METADATA_RECEIVED,
    406                         mCurrentPackage,
    407                         BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
    408                 mStatus = BackupTransport.TRANSPORT_ERROR;
    409                 executeNextState(UnifiedRestoreState.FINAL);
    410                 return;
    411             }
    412 
    413             // Pull the Package Manager metadata from the restore set first
    414             mCurrentPackage = new PackageInfo();
    415             mCurrentPackage.packageName = PACKAGE_MANAGER_SENTINEL;
    416             mPmAgent = backupManagerService.makeMetadataAgent(null);
    417             mAgent = IBackupAgent.Stub.asInterface(mPmAgent.onBind());
    418             if (MORE_DEBUG) {
    419                 Slog.v(TAG, "initiating restore for PMBA");
    420             }
    421             initiateOneRestore(mCurrentPackage, 0);
    422             // The PM agent called operationComplete() already, because our invocation
    423             // of it is process-local and therefore synchronous.  That means that the
    424             // next-state message (RUNNING_QUEUE) is already enqueued.  Only if we're
    425             // unable to proceed with running the queue do we remove that pending
    426             // message and jump straight to the FINAL state.  Because this was
    427             // synchronous we also know that we should cancel the pending timeout
    428             // message.
    429             backupManagerService.getBackupHandler().removeMessages(
    430                     MSG_RESTORE_OPERATION_TIMEOUT);
    431 
    432             // Verify that the backup set includes metadata.  If not, we can't do
    433             // signature/version verification etc, so we simply do not proceed with
    434             // the restore operation.
    435             if (!mPmAgent.hasMetadata()) {
    436                 Slog.e(TAG, "PM agent has no metadata, so not restoring");
    437                 mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    438                         BackupManagerMonitor.LOG_EVENT_ID_PM_AGENT_HAS_NO_METADATA,
    439                         mCurrentPackage,
    440                         BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
    441                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
    442                         PACKAGE_MANAGER_SENTINEL,
    443                         "Package manager restore metadata missing");
    444                 mStatus = BackupTransport.TRANSPORT_ERROR;
    445                 backupManagerService.getBackupHandler().removeMessages(
    446                         MSG_BACKUP_RESTORE_STEP, this);
    447                 executeNextState(UnifiedRestoreState.FINAL);
    448                 return;
    449             }
    450 
    451             // Success; cache the metadata and continue as expected with the
    452             // next state already enqueued
    453 
    454         } catch (Exception e) {
    455             // If we lost the transport at any time, halt
    456             Slog.e(TAG, "Unable to contact transport for restore: " + e.getMessage());
    457             mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    458                     BackupManagerMonitor.LOG_EVENT_ID_LOST_TRANSPORT,
    459                     null,
    460                     BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT, null);
    461             mStatus = BackupTransport.TRANSPORT_ERROR;
    462             backupManagerService.getBackupHandler().removeMessages(
    463                     MSG_BACKUP_RESTORE_STEP, this);
    464             executeNextState(UnifiedRestoreState.FINAL);
    465             return;
    466         }
    467     }
    468 
    469     // state RUNNING_QUEUE : figure out what the next thing to be restored is,
    470     // and fire the appropriate next step
    471     private void dispatchNextRestore() {
    472         UnifiedRestoreState nextState = UnifiedRestoreState.FINAL;
    473         try {
    474             IBackupTransport transport =
    475                     mTransportClient.connectOrThrow(
    476                             "PerformUnifiedRestoreTask.dispatchNextRestore()");
    477             mRestoreDescription = transport.nextRestorePackage();
    478             final String pkgName = (mRestoreDescription != null)
    479                     ? mRestoreDescription.getPackageName() : null;
    480             if (pkgName == null) {
    481                 Slog.e(TAG, "Failure getting next package name");
    482                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
    483                 nextState = UnifiedRestoreState.FINAL;
    484                 return;
    485             } else if (mRestoreDescription == RestoreDescription.NO_MORE_PACKAGES) {
    486                 // Yay we've reached the end cleanly
    487                 if (DEBUG) {
    488                     Slog.v(TAG, "No more packages; finishing restore");
    489                 }
    490                 int millis = (int) (SystemClock.elapsedRealtime() - mStartRealtime);
    491                 EventLog.writeEvent(EventLogTags.RESTORE_SUCCESS, mCount, millis);
    492                 nextState = UnifiedRestoreState.FINAL;
    493                 return;
    494             }
    495 
    496             if (DEBUG) {
    497                 Slog.i(TAG, "Next restore package: " + mRestoreDescription);
    498             }
    499             sendOnRestorePackage(pkgName);
    500 
    501             Metadata metaInfo = mPmAgent.getRestoredMetadata(pkgName);
    502             if (metaInfo == null) {
    503                 Slog.e(TAG, "No metadata for " + pkgName);
    504                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName,
    505                         "Package metadata missing");
    506                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
    507                 return;
    508             }
    509 
    510             try {
    511                 mCurrentPackage = backupManagerService.getPackageManager().getPackageInfo(
    512                         pkgName, PackageManager.GET_SIGNING_CERTIFICATES);
    513             } catch (NameNotFoundException e) {
    514                 // Whoops, we thought we could restore this package but it
    515                 // turns out not to be present.  Skip it.
    516                 Slog.e(TAG, "Package not present: " + pkgName);
    517                 mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    518                         BackupManagerMonitor.LOG_EVENT_ID_PACKAGE_NOT_PRESENT,
    519                         mCurrentPackage,
    520                         BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
    521                         null);
    522                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, pkgName,
    523                         "Package missing on device");
    524                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
    525                 return;
    526             }
    527 
    528             if (metaInfo.versionCode > mCurrentPackage.getLongVersionCode()) {
    529                 // Data is from a "newer" version of the app than we have currently
    530                 // installed.  If the app has not declared that it is prepared to
    531                 // handle this case, we do not attempt the restore.
    532                 if ((mCurrentPackage.applicationInfo.flags
    533                         & ApplicationInfo.FLAG_RESTORE_ANY_VERSION) == 0) {
    534                     String message = "Source version " + metaInfo.versionCode
    535                             + " > installed version " + mCurrentPackage.getLongVersionCode();
    536                     Slog.w(TAG, "Package " + pkgName + ": " + message);
    537                     Bundle monitoringExtras = BackupManagerMonitorUtils.putMonitoringExtra(null,
    538                             BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
    539                             metaInfo.versionCode);
    540                     monitoringExtras = BackupManagerMonitorUtils.putMonitoringExtra(
    541                             monitoringExtras,
    542                             BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, false);
    543                     mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    544                             BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
    545                             mCurrentPackage,
    546                             BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
    547                             monitoringExtras);
    548                     EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
    549                             pkgName, message);
    550                     nextState = UnifiedRestoreState.RUNNING_QUEUE;
    551                     return;
    552                 } else {
    553                     if (DEBUG) {
    554                         Slog.v(TAG, "Source version " + metaInfo.versionCode
    555                                 + " > installed version " + mCurrentPackage.getLongVersionCode()
    556                                 + " but restoreAnyVersion");
    557                     }
    558                     Bundle monitoringExtras = BackupManagerMonitorUtils.putMonitoringExtra(null,
    559                             BackupManagerMonitor.EXTRA_LOG_RESTORE_VERSION,
    560                             metaInfo.versionCode);
    561                     monitoringExtras = BackupManagerMonitorUtils.putMonitoringExtra(
    562                             monitoringExtras,
    563                             BackupManagerMonitor.EXTRA_LOG_RESTORE_ANYWAY, true);
    564                     mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    565                             BackupManagerMonitor.LOG_EVENT_ID_RESTORE_VERSION_HIGHER,
    566                             mCurrentPackage,
    567                             BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
    568                             monitoringExtras);
    569                 }
    570             }
    571 
    572             if (MORE_DEBUG) {
    573                 Slog.v(TAG, "Package " + pkgName
    574                         + " restore version [" + metaInfo.versionCode
    575                         + "] is compatible with installed version ["
    576                         + mCurrentPackage.getLongVersionCode() + "]");
    577             }
    578 
    579             // Reset per-package preconditions and fire the appropriate next state
    580             mWidgetData = null;
    581             final int type = mRestoreDescription.getDataType();
    582             if (type == RestoreDescription.TYPE_KEY_VALUE) {
    583                 nextState = UnifiedRestoreState.RESTORE_KEYVALUE;
    584             } else if (type == RestoreDescription.TYPE_FULL_STREAM) {
    585                 nextState = UnifiedRestoreState.RESTORE_FULL;
    586             } else {
    587                 // Unknown restore type; ignore this package and move on
    588                 Slog.e(TAG, "Unrecognized restore type " + type);
    589                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
    590                 return;
    591             }
    592         } catch (Exception e) {
    593             Slog.e(TAG, "Can't get next restore target from transport; halting: "
    594                     + e.getMessage());
    595             EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
    596             nextState = UnifiedRestoreState.FINAL;
    597             return;
    598         } finally {
    599             executeNextState(nextState);
    600         }
    601     }
    602 
    603     // state RESTORE_KEYVALUE : restore one package via key/value API set
    604     private void restoreKeyValue() {
    605         // Initiating the restore will pass responsibility for the state machine's
    606         // progress to the agent callback, so we do not always execute the
    607         // next state here.
    608         final String packageName = mCurrentPackage.packageName;
    609         // Validate some semantic requirements that apply in this way
    610         // only to the key/value restore API flow
    611         if (mCurrentPackage.applicationInfo.backupAgentName == null
    612                 || "".equals(mCurrentPackage.applicationInfo.backupAgentName)) {
    613             if (MORE_DEBUG) {
    614                 Slog.i(TAG, "Data exists for package " + packageName
    615                         + " but app has no agent; skipping");
    616             }
    617             mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    618                     BackupManagerMonitor.LOG_EVENT_ID_APP_HAS_NO_AGENT, mCurrentPackage,
    619                     BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
    620             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
    621                     "Package has no agent");
    622             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
    623             return;
    624         }
    625 
    626         Metadata metaInfo = mPmAgent.getRestoredMetadata(packageName);
    627         PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
    628         if (!BackupUtils.signaturesMatch(metaInfo.sigHashes, mCurrentPackage, pmi)) {
    629             Slog.w(TAG, "Signature mismatch restoring " + packageName);
    630             mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    631                     BackupManagerMonitor.LOG_EVENT_ID_SIGNATURE_MISMATCH, mCurrentPackage,
    632                     BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
    633             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
    634                     "Signature mismatch");
    635             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
    636             return;
    637         }
    638 
    639         // Good to go!  Set up and bind the agent...
    640         mAgent = backupManagerService.bindToAgentSynchronous(
    641                 mCurrentPackage.applicationInfo,
    642                 ApplicationThreadConstants.BACKUP_MODE_INCREMENTAL);
    643         if (mAgent == null) {
    644             Slog.w(TAG, "Can't find backup agent for " + packageName);
    645             mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
    646                     BackupManagerMonitor.LOG_EVENT_ID_CANT_FIND_AGENT, mCurrentPackage,
    647                     BackupManagerMonitor.LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY, null);
    648             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, packageName,
    649                     "Restore agent missing");
    650             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
    651             return;
    652         }
    653 
    654         // Whatever happens next, we've launched the target app now; remember that.
    655         mDidLaunch = true;
    656 
    657         // And then finally start the restore on this agent
    658         try {
    659             initiateOneRestore(mCurrentPackage, metaInfo.versionCode);
    660             ++mCount;
    661         } catch (Exception e) {
    662             Slog.e(TAG, "Error when attempting restore: " + e.toString());
    663             keyValueAgentErrorCleanup();
    664             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
    665         }
    666     }
    667 
    668     // Guts of a key/value restore operation
    669     void initiateOneRestore(PackageInfo app, long appVersionCode) {
    670         final String packageName = app.packageName;
    671 
    672         if (DEBUG) {
    673             Slog.d(TAG, "initiateOneRestore packageName=" + packageName);
    674         }
    675 
    676         // !!! TODO: get the dirs from the transport
    677         mBackupDataName = new File(backupManagerService.getDataDir(), packageName + ".restore");
    678         mStageName = new File(backupManagerService.getDataDir(), packageName + ".stage");
    679         mNewStateName = new File(mStateDir, packageName + ".new");
    680         mSavedStateName = new File(mStateDir, packageName);
    681 
    682         // don't stage the 'android' package where the wallpaper data lives.  this is
    683         // an optimization: we know there's no widget data hosted/published by that
    684         // package, and this way we avoid doing a spurious copy of MB-sized wallpaper
    685         // data following the download.
    686         boolean staging = !packageName.equals("android");
    687         ParcelFileDescriptor stage;
    688         File downloadFile = (staging) ? mStageName : mBackupDataName;
    689 
    690         try {
    691             IBackupTransport transport =
    692                     mTransportClient.connectOrThrow(
    693                             "PerformUnifiedRestoreTask.initiateOneRestore()");
    694 
    695             // Run the transport's restore pass
    696             stage = ParcelFileDescriptor.open(downloadFile,
    697                     ParcelFileDescriptor.MODE_READ_WRITE |
    698                             ParcelFileDescriptor.MODE_CREATE |
    699                             ParcelFileDescriptor.MODE_TRUNCATE);
    700 
    701             if (transport.getRestoreData(stage) != BackupTransport.TRANSPORT_OK) {
    702                 // Transport-level failure, so we wind everything up and
    703                 // terminate the restore operation.
    704                 Slog.e(TAG, "Error getting restore data for " + packageName);
    705                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
    706                 stage.close();
    707                 downloadFile.delete();
    708                 executeNextState(UnifiedRestoreState.FINAL);
    709                 return;
    710             }
    711 
    712             // We have the data from the transport. Now we extract and strip
    713             // any per-package metadata (typically widget-related information)
    714             // if appropriate
    715             if (staging) {
    716                 stage.close();
    717                 stage = ParcelFileDescriptor.open(downloadFile,
    718                         ParcelFileDescriptor.MODE_READ_ONLY);
    719 
    720                 mBackupData = ParcelFileDescriptor.open(mBackupDataName,
    721                         ParcelFileDescriptor.MODE_READ_WRITE |
    722                                 ParcelFileDescriptor.MODE_CREATE |
    723                                 ParcelFileDescriptor.MODE_TRUNCATE);
    724 
    725                 BackupDataInput in = new BackupDataInput(stage.getFileDescriptor());
    726                 BackupDataOutput out = new BackupDataOutput(mBackupData.getFileDescriptor());
    727                 byte[] buffer = new byte[8192]; // will grow when needed
    728                 while (in.readNextHeader()) {
    729                     final String key = in.getKey();
    730                     final int size = in.getDataSize();
    731 
    732                     // is this a special key?
    733                     if (key.equals(KEY_WIDGET_STATE)) {
    734                         if (DEBUG) {
    735                             Slog.i(TAG, "Restoring widget state for " + packageName);
    736                         }
    737                         mWidgetData = new byte[size];
    738                         in.readEntityData(mWidgetData, 0, size);
    739                     } else {
    740                         if (size > buffer.length) {
    741                             buffer = new byte[size];
    742                         }
    743                         in.readEntityData(buffer, 0, size);
    744                         out.writeEntityHeader(key, size);
    745                         out.writeEntityData(buffer, size);
    746                     }
    747                 }
    748 
    749                 mBackupData.close();
    750             }
    751 
    752             // Okay, we have the data.  Now have the agent do the restore.
    753             stage.close();
    754 
    755             mBackupData = ParcelFileDescriptor.open(mBackupDataName,
    756                     ParcelFileDescriptor.MODE_READ_ONLY);
    757 
    758             mNewState = ParcelFileDescriptor.open(mNewStateName,
    759                     ParcelFileDescriptor.MODE_READ_WRITE |
    760                             ParcelFileDescriptor.MODE_CREATE |
    761                             ParcelFileDescriptor.MODE_TRUNCATE);
    762 
    763             // Kick off the restore, checking for hung agents.  The timeout or
    764             // the operationComplete() callback will schedule the next step,
    765             // so we do not do that here.
    766             long restoreAgentTimeoutMillis = mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
    767             backupManagerService.prepareOperationTimeout(
    768                     mEphemeralOpToken, restoreAgentTimeoutMillis, this, OP_TYPE_RESTORE_WAIT);
    769             mAgent.doRestore(mBackupData, appVersionCode, mNewState,
    770                     mEphemeralOpToken, backupManagerService.getBackupManagerBinder());
    771         } catch (Exception e) {
    772             Slog.e(TAG, "Unable to call app for restore: " + packageName, e);
    773             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
    774                     packageName, e.toString());
    775             keyValueAgentErrorCleanup();    // clears any pending timeout messages as well
    776 
    777             // After a restore failure we go back to running the queue.  If there
    778             // are no more packages to be restored that will be handled by the
    779             // next step.
    780             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
    781         }
    782     }
    783 
    784     // state RESTORE_FULL : restore one package via streaming engine
    785     private void restoreFull() {
    786         // None of this can run on the work looper here, so we spin asynchronous
    787         // work like this:
    788         //
    789         //   StreamFeederThread: read data from transport.getNextFullRestoreDataChunk()
    790         //                       write it into the pipe to the engine
    791         //   EngineThread: FullRestoreEngine thread communicating with the target app
    792         //
    793         // When finished, StreamFeederThread executes next state as appropriate on the
    794         // backup looper, and the overall unified restore task resumes
    795         try {
    796             StreamFeederThread feeder = new StreamFeederThread();
    797             if (MORE_DEBUG) {
    798                 Slog.i(TAG, "Spinning threads for stream restore of "
    799                         + mCurrentPackage.packageName);
    800             }
    801             new Thread(feeder, "unified-stream-feeder").start();
    802 
    803             // At this point the feeder is responsible for advancing the restore
    804             // state, so we're done here.
    805         } catch (IOException e) {
    806             // Unable to instantiate the feeder thread -- we need to bail on the
    807             // current target.  We haven't asked the transport for data yet, though,
    808             // so we can do that simply by going back to running the restore queue.
    809             Slog.e(TAG, "Unable to construct pipes for stream restore!");
    810             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
    811         }
    812     }
    813 
    814     // state RESTORE_FINISHED : provide the "no more data" signpost callback at the end
    815     private void restoreFinished() {
    816         if (DEBUG) {
    817             Slog.d(TAG, "restoreFinished packageName=" + mCurrentPackage.packageName);
    818         }
    819         try {
    820             long restoreAgentFinishedTimeoutMillis =
    821                     mAgentTimeoutParameters.getRestoreAgentFinishedTimeoutMillis();
    822             backupManagerService
    823                     .prepareOperationTimeout(mEphemeralOpToken,
    824                             restoreAgentFinishedTimeoutMillis, this,
    825                             OP_TYPE_RESTORE_WAIT);
    826             mAgent.doRestoreFinished(mEphemeralOpToken,
    827                     backupManagerService.getBackupManagerBinder());
    828             // If we get this far, the callback or timeout will schedule the
    829             // next restore state, so we're done
    830         } catch (Exception e) {
    831             final String packageName = mCurrentPackage.packageName;
    832             Slog.e(TAG, "Unable to finalize restore of " + packageName);
    833             EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
    834                     packageName, e.toString());
    835             keyValueAgentErrorCleanup();
    836             executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
    837         }
    838     }
    839 
    840     class StreamFeederThread extends RestoreEngine implements Runnable, BackupRestoreTask {
    841 
    842         final String TAG = "StreamFeederThread";
    843         FullRestoreEngine mEngine;
    844         EngineThread mEngineThread;
    845 
    846         // pipe through which we read data from the transport. [0] read, [1] write
    847         ParcelFileDescriptor[] mTransportPipes;
    848 
    849         // pipe through which the engine will read data.  [0] read, [1] write
    850         ParcelFileDescriptor[] mEnginePipes;
    851 
    852         private final int mEphemeralOpToken;
    853 
    854         public StreamFeederThread() throws IOException {
    855             mEphemeralOpToken = backupManagerService.generateRandomIntegerToken();
    856             mTransportPipes = ParcelFileDescriptor.createPipe();
    857             mEnginePipes = ParcelFileDescriptor.createPipe();
    858             setRunning(true);
    859         }
    860 
    861         @Override
    862         public void run() {
    863             UnifiedRestoreState nextState = UnifiedRestoreState.RUNNING_QUEUE;
    864             int status = BackupTransport.TRANSPORT_OK;
    865 
    866             EventLog.writeEvent(EventLogTags.FULL_RESTORE_PACKAGE,
    867                     mCurrentPackage.packageName);
    868 
    869             mEngine = new FullRestoreEngine(backupManagerService, this, null,
    870                     mMonitor, mCurrentPackage, false, false, mEphemeralOpToken);
    871             mEngineThread = new EngineThread(mEngine, mEnginePipes[0]);
    872 
    873             ParcelFileDescriptor eWriteEnd = mEnginePipes[1];
    874             ParcelFileDescriptor tReadEnd = mTransportPipes[0];
    875             ParcelFileDescriptor tWriteEnd = mTransportPipes[1];
    876 
    877             int bufferSize = 32 * 1024;
    878             byte[] buffer = new byte[bufferSize];
    879             FileOutputStream engineOut = new FileOutputStream(eWriteEnd.getFileDescriptor());
    880             FileInputStream transportIn = new FileInputStream(tReadEnd.getFileDescriptor());
    881 
    882             // spin up the engine and start moving data to it
    883             new Thread(mEngineThread, "unified-restore-engine").start();
    884 
    885             String callerLogString = "PerformUnifiedRestoreTask$StreamFeederThread.run()";
    886             try {
    887                 IBackupTransport transport = mTransportClient.connectOrThrow(callerLogString);
    888                 while (status == BackupTransport.TRANSPORT_OK) {
    889                     // have the transport write some of the restoring data to us
    890                     int result = transport.getNextFullRestoreDataChunk(tWriteEnd);
    891                     if (result > 0) {
    892                         // The transport wrote this many bytes of restore data to the
    893                         // pipe, so pass it along to the engine.
    894                         if (MORE_DEBUG) {
    895                             Slog.v(TAG, "  <- transport provided chunk size " + result);
    896                         }
    897                         if (result > bufferSize) {
    898                             bufferSize = result;
    899                             buffer = new byte[bufferSize];
    900                         }
    901                         int toCopy = result;
    902                         while (toCopy > 0) {
    903                             int n = transportIn.read(buffer, 0, toCopy);
    904                             engineOut.write(buffer, 0, n);
    905                             toCopy -= n;
    906                             if (MORE_DEBUG) {
    907                                 Slog.v(TAG, "  -> wrote " + n + " to engine, left=" + toCopy);
    908                             }
    909                         }
    910                     } else if (result == BackupTransport.NO_MORE_DATA) {
    911                         // Clean finish.  Wind up and we're done!
    912                         if (MORE_DEBUG) {
    913                             Slog.i(TAG, "Got clean full-restore EOF for "
    914                                     + mCurrentPackage.packageName);
    915                         }
    916                         status = BackupTransport.TRANSPORT_OK;
    917                         break;
    918                     } else {
    919                         // Transport reported some sort of failure; the fall-through
    920                         // handling will deal properly with that.
    921                         Slog.e(TAG, "Error " + result + " streaming restore for "
    922                                 + mCurrentPackage.packageName);
    923                         EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
    924                         status = result;
    925                     }
    926                 }
    927                 if (MORE_DEBUG) {
    928                     Slog.v(TAG, "Done copying to engine, falling through");
    929                 }
    930             } catch (IOException e) {
    931                 // We lost our ability to communicate via the pipes.  That's worrying
    932                 // but potentially recoverable; abandon this package's restore but
    933                 // carry on with the next restore target.
    934                 Slog.e(TAG, "Unable to route data for restore");
    935                 EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
    936                         mCurrentPackage.packageName, "I/O error on pipes");
    937                 status = BackupTransport.AGENT_ERROR;
    938             } catch (Exception e) {
    939                 // The transport threw; terminate the whole operation.  Closing
    940                 // the sockets will wake up the engine and it will then tidy up the
    941                 // remote end.
    942                 Slog.e(TAG, "Transport failed during restore: " + e.getMessage());
    943                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
    944                 status = BackupTransport.TRANSPORT_ERROR;
    945             } finally {
    946                 // Close the transport pipes and *our* end of the engine pipe,
    947                 // but leave the engine thread's end open so that it properly
    948                 // hits EOF and winds up its operations.
    949                 IoUtils.closeQuietly(mEnginePipes[1]);
    950                 IoUtils.closeQuietly(mTransportPipes[0]);
    951                 IoUtils.closeQuietly(mTransportPipes[1]);
    952 
    953                 // Don't proceed until the engine has wound up operations
    954                 mEngineThread.waitForResult();
    955 
    956                 // Now we're really done with this one too
    957                 IoUtils.closeQuietly(mEnginePipes[0]);
    958 
    959                 // In all cases we want to remember whether we launched
    960                 // the target app as part of our work so far.
    961                 mDidLaunch = (mEngine.getAgent() != null);
    962 
    963                 // If we hit a transport-level error, we are done with everything;
    964                 // if we hit an agent error we just go back to running the queue.
    965                 if (status == BackupTransport.TRANSPORT_OK) {
    966                     // Clean finish means we issue the restore-finished callback
    967                     nextState = UnifiedRestoreState.RESTORE_FINISHED;
    968 
    969                     // the engine bound the target's agent, so recover that binding
    970                     // to use for the callback.
    971                     mAgent = mEngine.getAgent();
    972 
    973                     // and the restored widget data, if any
    974                     mWidgetData = mEngine.getWidgetData();
    975                 } else {
    976                     // Something went wrong somewhere.  Whether it was at the transport
    977                     // level is immaterial; we need to tell the transport to bail
    978                     try {
    979                         IBackupTransport transport =
    980                                 mTransportClient.connectOrThrow(callerLogString);
    981                         transport.abortFullRestore();
    982                     } catch (Exception e) {
    983                         // transport itself is dead; make sure we handle this as a
    984                         // fatal error
    985                         Slog.e(TAG, "Transport threw from abortFullRestore: " + e.getMessage());
    986                         status = BackupTransport.TRANSPORT_ERROR;
    987                     }
    988 
    989                     // We also need to wipe the current target's data, as it's probably
    990                     // in an incoherent state.
    991                     backupManagerService.clearApplicationDataSynchronous(
    992                             mCurrentPackage.packageName, false);
    993 
    994                     // Schedule the next state based on the nature of our failure
    995                     if (status == BackupTransport.TRANSPORT_ERROR) {
    996                         nextState = UnifiedRestoreState.FINAL;
    997                     } else {
    998                         nextState = UnifiedRestoreState.RUNNING_QUEUE;
    999                     }
   1000                 }
   1001                 executeNextState(nextState);
   1002                 setRunning(false);
   1003             }
   1004         }
   1005 
   1006         // BackupRestoreTask interface, specifically for timeout handling
   1007 
   1008         @Override
   1009         public void execute() { /* intentionally empty */ }
   1010 
   1011         @Override
   1012         public void operationComplete(long result) { /* intentionally empty */ }
   1013 
   1014         // The app has timed out handling a restoring file
   1015         @Override
   1016         public void handleCancel(boolean cancelAll) {
   1017             backupManagerService.removeOperation(mEphemeralOpToken);
   1018             if (DEBUG) {
   1019                 Slog.w(TAG, "Full-data restore target timed out; shutting down");
   1020             }
   1021 
   1022             mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
   1023                     BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_TIMEOUT,
   1024                     mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
   1025             mEngineThread.handleTimeout();
   1026 
   1027             IoUtils.closeQuietly(mEnginePipes[1]);
   1028             mEnginePipes[1] = null;
   1029             IoUtils.closeQuietly(mEnginePipes[0]);
   1030             mEnginePipes[0] = null;
   1031         }
   1032     }
   1033 
   1034     class EngineThread implements Runnable {
   1035 
   1036         FullRestoreEngine mEngine;
   1037         FileInputStream mEngineStream;
   1038 
   1039         EngineThread(FullRestoreEngine engine, ParcelFileDescriptor engineSocket) {
   1040             mEngine = engine;
   1041             engine.setRunning(true);
   1042             // We *do* want this FileInputStream to own the underlying fd, so that
   1043             // when we are finished with it, it closes this end of the pipe in a way
   1044             // that signals its other end.
   1045             mEngineStream = new FileInputStream(engineSocket.getFileDescriptor(), true);
   1046         }
   1047 
   1048         public boolean isRunning() {
   1049             return mEngine.isRunning();
   1050         }
   1051 
   1052         public int waitForResult() {
   1053             return mEngine.waitForResult();
   1054         }
   1055 
   1056         @Override
   1057         public void run() {
   1058             try {
   1059                 while (mEngine.isRunning()) {
   1060                     // Tell it to be sure to leave the agent instance up after finishing
   1061                     mEngine.restoreOneFile(mEngineStream, false, mEngine.mBuffer,
   1062                             mEngine.mOnlyPackage, mEngine.mAllowApks, mEngine.mEphemeralOpToken,
   1063                             mEngine.mMonitor);
   1064                 }
   1065             } finally {
   1066                 // Because mEngineStream adopted its underlying FD, this also
   1067                 // closes this end of the pipe.
   1068                 IoUtils.closeQuietly(mEngineStream);
   1069             }
   1070         }
   1071 
   1072         public void handleTimeout() {
   1073             IoUtils.closeQuietly(mEngineStream);
   1074             mEngine.handleTimeout();
   1075         }
   1076     }
   1077 
   1078     // state FINAL : tear everything down and we're done.
   1079     private void finalizeRestore() {
   1080         if (MORE_DEBUG) {
   1081             Slog.d(TAG, "finishing restore mObserver=" + mObserver);
   1082         }
   1083 
   1084         String callerLogString = "PerformUnifiedRestoreTask.finalizeRestore()";
   1085         try {
   1086             IBackupTransport transport =
   1087                     mTransportClient.connectOrThrow(callerLogString);
   1088             transport.finishRestore();
   1089         } catch (Exception e) {
   1090             Slog.e(TAG, "Error finishing restore", e);
   1091         }
   1092 
   1093         // Tell the observer we're done
   1094         if (mObserver != null) {
   1095             try {
   1096                 mObserver.restoreFinished(mStatus);
   1097             } catch (RemoteException e) {
   1098                 Slog.d(TAG, "Restore observer died at restoreFinished");
   1099             }
   1100         }
   1101 
   1102         // Clear any ongoing session timeout.
   1103         backupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_SESSION_TIMEOUT);
   1104 
   1105         // If we have a PM token, we must under all circumstances be sure to
   1106         // handshake when we've finished.
   1107         if (mPmToken > 0) {
   1108             if (MORE_DEBUG) {
   1109                 Slog.v(TAG, "finishing PM token " + mPmToken);
   1110             }
   1111             try {
   1112                 backupManagerService.getPackageManagerBinder().finishPackageInstall(mPmToken,
   1113                         mDidLaunch);
   1114             } catch (RemoteException e) { /* can't happen */ }
   1115         } else {
   1116             // We were invoked via an active restore session, not by the Package
   1117             // Manager, so start up the session timeout again.
   1118             long restoreAgentTimeoutMillis = mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
   1119             backupManagerService.getBackupHandler().sendEmptyMessageDelayed(
   1120                     MSG_RESTORE_SESSION_TIMEOUT,
   1121                     restoreAgentTimeoutMillis);
   1122         }
   1123 
   1124         // Kick off any work that may be needed regarding app widget restores
   1125         // TODO: http://b/22388012
   1126         AppWidgetBackupBridge.restoreFinished(UserHandle.USER_SYSTEM);
   1127 
   1128         // If this was a full-system restore, record the ancestral
   1129         // dataset information
   1130         if (mIsSystemRestore && mPmAgent != null) {
   1131             backupManagerService.setAncestralPackages(mPmAgent.getRestoredPackages());
   1132             backupManagerService.setAncestralToken(mToken);
   1133             backupManagerService.writeRestoreTokens();
   1134         }
   1135 
   1136         synchronized (backupManagerService.getPendingRestores()) {
   1137             if (backupManagerService.getPendingRestores().size() > 0) {
   1138                 if (DEBUG) {
   1139                     Slog.d(TAG, "Starting next pending restore.");
   1140                 }
   1141                 PerformUnifiedRestoreTask task = backupManagerService.getPendingRestores().remove();
   1142                 backupManagerService.getBackupHandler().sendMessage(
   1143                         backupManagerService.getBackupHandler().obtainMessage(
   1144                                 MSG_BACKUP_RESTORE_STEP, task));
   1145 
   1146             } else {
   1147                 backupManagerService.setRestoreInProgress(false);
   1148                 if (MORE_DEBUG) {
   1149                     Slog.d(TAG, "No pending restores.");
   1150                 }
   1151             }
   1152         }
   1153 
   1154         Slog.i(TAG, "Restore complete.");
   1155         mListener.onFinished(callerLogString);
   1156     }
   1157 
   1158     void keyValueAgentErrorCleanup() {
   1159         // If the agent fails restore, it might have put the app's data
   1160         // into an incoherent state.  For consistency we wipe its data
   1161         // again in this case before continuing with normal teardown
   1162         backupManagerService.clearApplicationDataSynchronous(mCurrentPackage.packageName, false);
   1163         keyValueAgentCleanup();
   1164     }
   1165 
   1166     // TODO: clean up naming; this is now used at finish by both k/v and stream restores
   1167     void keyValueAgentCleanup() {
   1168         mBackupDataName.delete();
   1169         mStageName.delete();
   1170         try {
   1171             if (mBackupData != null) {
   1172                 mBackupData.close();
   1173             }
   1174         } catch (IOException e) {
   1175         }
   1176         try {
   1177             if (mNewState != null) {
   1178                 mNewState.close();
   1179             }
   1180         } catch (IOException e) {
   1181         }
   1182         mBackupData = mNewState = null;
   1183 
   1184         // if everything went okay, remember the recorded state now
   1185         //
   1186         // !!! TODO: the restored data could be migrated on the server
   1187         // side into the current dataset.  In that case the new state file
   1188         // we just created would reflect the data already extant in the
   1189         // backend, so there'd be nothing more to do.  Until that happens,
   1190         // however, we need to make sure that we record the data to the
   1191         // current backend dataset.  (Yes, this means shipping the data over
   1192         // the wire in both directions.  That's bad, but consistency comes
   1193         // first, then efficiency.)  Once we introduce server-side data
   1194         // migration to the newly-restored device's dataset, we will change
   1195         // the following from a discard of the newly-written state to the
   1196         // "correct" operation of renaming into the canonical state blob.
   1197         mNewStateName.delete();                      // TODO: remove; see above comment
   1198         //mNewStateName.renameTo(mSavedStateName);   // TODO: replace with this
   1199 
   1200         // If this wasn't the PM pseudopackage, tear down the agent side
   1201         if (mCurrentPackage.applicationInfo != null) {
   1202             // unbind and tidy up even on timeout or failure
   1203             try {
   1204                 backupManagerService.getActivityManager().unbindBackupAgent(
   1205                         mCurrentPackage.applicationInfo);
   1206 
   1207                 // The agent was probably running with a stub Application object,
   1208                 // which isn't a valid run mode for the main app logic.  Shut
   1209                 // down the app so that next time it's launched, it gets the
   1210                 // usual full initialization.  Note that this is only done for
   1211                 // full-system restores: when a single app has requested a restore,
   1212                 // it is explicitly not killed following that operation.
   1213                 //
   1214                 // We execute this kill when these conditions hold:
   1215                 //    1. it's not a system-uid process,
   1216                 //    2. the app did not request its own restore (mTargetPackage == null), and
   1217                 // either
   1218                 //    3a. the app is a full-data target (TYPE_FULL_STREAM) or
   1219                 //     b. the app does not state android:killAfterRestore="false" in its manifest
   1220                 final int appFlags = mCurrentPackage.applicationInfo.flags;
   1221                 final boolean killAfterRestore =
   1222                         (mCurrentPackage.applicationInfo.uid >= Process.FIRST_APPLICATION_UID)
   1223                                 && ((mRestoreDescription.getDataType()
   1224                                 == RestoreDescription.TYPE_FULL_STREAM)
   1225                                 || ((appFlags & ApplicationInfo.FLAG_KILL_AFTER_RESTORE) != 0));
   1226 
   1227                 if (mTargetPackage == null && killAfterRestore) {
   1228                     if (DEBUG) {
   1229                         Slog.d(TAG, "Restore complete, killing host process of "
   1230                                 + mCurrentPackage.applicationInfo.processName);
   1231                     }
   1232                     backupManagerService.getActivityManager().killApplicationProcess(
   1233                             mCurrentPackage.applicationInfo.processName,
   1234                             mCurrentPackage.applicationInfo.uid);
   1235                 }
   1236             } catch (RemoteException e) {
   1237                 // can't happen; we run in the same process as the activity manager
   1238             }
   1239         }
   1240 
   1241         // The caller is responsible for reestablishing the state machine; our
   1242         // responsibility here is to clear the decks for whatever comes next.
   1243         backupManagerService.getBackupHandler().removeMessages(MSG_RESTORE_OPERATION_TIMEOUT, this);
   1244     }
   1245 
   1246     @Override
   1247     public void operationComplete(long unusedResult) {
   1248         backupManagerService.removeOperation(mEphemeralOpToken);
   1249         if (MORE_DEBUG) {
   1250             Slog.i(TAG, "operationComplete() during restore: target="
   1251                     + mCurrentPackage.packageName
   1252                     + " state=" + mState);
   1253         }
   1254 
   1255         final UnifiedRestoreState nextState;
   1256         switch (mState) {
   1257             case INITIAL:
   1258                 // We've just (manually) restored the PMBA.  It doesn't need the
   1259                 // additional restore-finished callback so we bypass that and go
   1260                 // directly to running the queue.
   1261                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
   1262                 break;
   1263 
   1264             case RESTORE_KEYVALUE:
   1265             case RESTORE_FULL: {
   1266                 // Okay, we've just heard back from the agent that it's done with
   1267                 // the restore itself.  We now have to send the same agent its
   1268                 // doRestoreFinished() callback, so roll into that state.
   1269                 nextState = UnifiedRestoreState.RESTORE_FINISHED;
   1270                 break;
   1271             }
   1272 
   1273             case RESTORE_FINISHED: {
   1274                 // Okay, we're done with this package.  Tidy up and go on to the next
   1275                 // app in the queue.
   1276                 int size = (int) mBackupDataName.length();
   1277                 EventLog.writeEvent(EventLogTags.RESTORE_PACKAGE,
   1278                         mCurrentPackage.packageName, size);
   1279 
   1280                 // Just go back to running the restore queue
   1281                 keyValueAgentCleanup();
   1282 
   1283                 // If there was widget state associated with this app, get the OS to
   1284                 // incorporate it into current bookeeping and then pass that along to
   1285                 // the app as part of the restore-time work.
   1286                 if (mWidgetData != null) {
   1287                     backupManagerService.restoreWidgetData(mCurrentPackage.packageName,
   1288                             mWidgetData);
   1289                 }
   1290 
   1291                 nextState = UnifiedRestoreState.RUNNING_QUEUE;
   1292                 break;
   1293             }
   1294 
   1295             default: {
   1296                 // Some kind of horrible semantic error; we're in an unexpected state.
   1297                 // Back off hard and wind up.
   1298                 Slog.e(TAG, "Unexpected restore callback into state " + mState);
   1299                 keyValueAgentErrorCleanup();
   1300                 nextState = UnifiedRestoreState.FINAL;
   1301                 break;
   1302             }
   1303         }
   1304 
   1305         executeNextState(nextState);
   1306     }
   1307 
   1308     // A call to agent.doRestore() or agent.doRestoreFinished() has timed out
   1309     @Override
   1310     public void handleCancel(boolean cancelAll) {
   1311         backupManagerService.removeOperation(mEphemeralOpToken);
   1312         Slog.e(TAG, "Timeout restoring application " + mCurrentPackage.packageName);
   1313         mMonitor = BackupManagerMonitorUtils.monitorEvent(mMonitor,
   1314                 BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_RESTORE_TIMEOUT,
   1315                 mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT, null);
   1316         EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
   1317                 mCurrentPackage.packageName, "restore timeout");
   1318         // Handle like an agent that threw on invocation: wipe it and go on to the next
   1319         keyValueAgentErrorCleanup();
   1320         executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
   1321     }
   1322 
   1323     void executeNextState(UnifiedRestoreState nextState) {
   1324         if (MORE_DEBUG) {
   1325             Slog.i(TAG, " => executing next step on "
   1326                     + this + " nextState=" + nextState);
   1327         }
   1328         mState = nextState;
   1329         Message msg = backupManagerService.getBackupHandler().obtainMessage(
   1330                 MSG_BACKUP_RESTORE_STEP, this);
   1331         backupManagerService.getBackupHandler().sendMessage(msg);
   1332     }
   1333 
   1334     // restore observer support
   1335     void sendStartRestore(int numPackages) {
   1336         if (mObserver != null) {
   1337             try {
   1338                 mObserver.restoreStarting(numPackages);
   1339             } catch (RemoteException e) {
   1340                 Slog.w(TAG, "Restore observer went away: startRestore");
   1341                 mObserver = null;
   1342             }
   1343         }
   1344     }
   1345 
   1346     void sendOnRestorePackage(String name) {
   1347         if (mObserver != null) {
   1348             try {
   1349                 mObserver.onUpdate(mCount, name);
   1350             } catch (RemoteException e) {
   1351                 Slog.d(TAG, "Restore observer died in onUpdate");
   1352                 mObserver = null;
   1353             }
   1354         }
   1355     }
   1356 
   1357     void sendEndRestore() {
   1358         if (mObserver != null) {
   1359             try {
   1360                 mObserver.restoreFinished(mStatus);
   1361             } catch (RemoteException e) {
   1362                 Slog.w(TAG, "Restore observer went away: endRestore");
   1363                 mObserver = null;
   1364             }
   1365         }
   1366     }
   1367 }
   1368