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