diff options
-rw-r--r-- | common/constants.cc | 8 | ||||
-rw-r--r-- | common/constants.h | 3 | ||||
-rw-r--r-- | common/error_code.h | 1 | ||||
-rw-r--r-- | common/error_code_utils.cc | 6 | ||||
-rw-r--r-- | metrics_constants.h | 2 | ||||
-rw-r--r-- | metrics_utils.cc | 4 | ||||
-rw-r--r-- | payload_consumer/delta_performer.cc | 1 | ||||
-rw-r--r-- | payload_consumer/install_plan.cc | 5 | ||||
-rw-r--r-- | payload_consumer/install_plan.h | 8 | ||||
-rw-r--r-- | payload_consumer/postinstall_runner_action.cc | 19 | ||||
-rw-r--r-- | payload_state.cc | 2 | ||||
-rw-r--r-- | update_attempter_android.cc | 34 | ||||
-rw-r--r-- | update_engine_client_android.cc | 5 | ||||
-rw-r--r-- | update_manager/chromeos_policy.cc | 1 |
14 files changed, 87 insertions, 12 deletions
diff --git a/common/constants.cc b/common/constants.cc index c0a6e279..5941c93b 100644 --- a/common/constants.cc +++ b/common/constants.cc @@ -57,6 +57,7 @@ const char kPrefsP2PEnabled[] = "p2p-enabled"; const char kPrefsP2PFirstAttemptTimestamp[] = "p2p-first-attempt-timestamp"; const char kPrefsP2PNumAttempts[] = "p2p-num-attempts"; const char kPrefsPayloadAttemptNumber[] = "payload-attempt-number"; +const char kPrefsPostInstallSucceeded[] = "post-install-succeeded"; const char kPrefsPreviousVersion[] = "previous-version"; const char kPrefsResumedUpdateFailures[] = "resumed-update-failures"; const char kPrefsRollbackVersion[] = "rollback-version"; @@ -103,5 +104,12 @@ const char kPayloadPropertyPowerwash[] = "POWERWASH"; // This can be used to zero-rate OTA traffic by sending it over the correct // network. const char kPayloadPropertyNetworkId[] = "NETWORK_ID"; +// Set "SWITCH_SLOT_ON_REBOOT=0" to skip marking the updated partitions active. +// The default is 1 (always switch slot if update succeeded). +const char kPayloadPropertySwitchSlotOnReboot[] = "SWITCH_SLOT_ON_REBOOT"; +// Set "RUN_POST_INSTALL=0" to skip running post install, this will only be +// honored if we're resuming an update and post install has already succeeded. +// The default is 1 (always run post install). +const char kPayloadPropertyRunPostInstall[] = "RUN_POST_INSTALL"; } // namespace chromeos_update_engine diff --git a/common/constants.h b/common/constants.h index 776e726d..fefd08cd 100644 --- a/common/constants.h +++ b/common/constants.h @@ -59,6 +59,7 @@ extern const char kPrefsP2PEnabled[]; extern const char kPrefsP2PFirstAttemptTimestamp[]; extern const char kPrefsP2PNumAttempts[]; extern const char kPrefsPayloadAttemptNumber[]; +extern const char kPrefsPostInstallSucceeded[]; extern const char kPrefsPreviousVersion[]; extern const char kPrefsResumedUpdateFailures[]; extern const char kPrefsRollbackVersion[]; @@ -96,6 +97,8 @@ extern const char kPayloadPropertyAuthorization[]; extern const char kPayloadPropertyUserAgent[]; extern const char kPayloadPropertyPowerwash[]; extern const char kPayloadPropertyNetworkId[]; +extern const char kPayloadPropertySwitchSlotOnReboot[]; +extern const char kPayloadPropertyRunPostInstall[]; // A download source is any combination of protocol and server (that's of // interest to us when looking at UMA metrics) using which we may download diff --git a/common/error_code.h b/common/error_code.h index 3800bf0f..0b08005a 100644 --- a/common/error_code.h +++ b/common/error_code.h @@ -75,6 +75,7 @@ enum class ErrorCode : int { kNonCriticalUpdateInOOBE = 49, // kOmahaUpdateIgnoredOverCellular = 50, kPayloadTimestampError = 51, + kUpdatedButNotActive = 52, // VERY IMPORTANT! When adding new error codes: // diff --git a/common/error_code_utils.cc b/common/error_code_utils.cc index 0a015eb2..313a15f8 100644 --- a/common/error_code_utils.cc +++ b/common/error_code_utils.cc @@ -146,8 +146,10 @@ string ErrorCodeToString(ErrorCode code) { return "ErrorCode::kNonCriticalUpdateInOOBE"; case ErrorCode::kPayloadTimestampError: return "ErrorCode::kPayloadTimestampError"; - // Don't add a default case to let the compiler warn about newly added - // error codes which should be added here. + case ErrorCode::kUpdatedButNotActive: + return "ErrorCode::kUpdatedButNotActive"; + // Don't add a default case to let the compiler warn about newly added + // error codes which should be added here. } return "Unknown error: " + base::UintToString(static_cast<unsigned>(code)); diff --git a/metrics_constants.h b/metrics_constants.h index f6d0c74e..abec2ad4 100644 --- a/metrics_constants.h +++ b/metrics_constants.h @@ -95,6 +95,8 @@ enum class AttemptResult { kPostInstallFailed, // The postinstall step failed. kAbnormalTermination, // The attempt ended abnormally. kUpdateCanceled, // Update canceled by the user. + kUpdateSucceededNotActive, // Update succeeded but the new slot is not + // active. kNumConstants, diff --git a/metrics_utils.cc b/metrics_utils.cc index 24212214..46530f07 100644 --- a/metrics_utils.cc +++ b/metrics_utils.cc @@ -39,6 +39,9 @@ metrics::AttemptResult GetAttemptResult(ErrorCode code) { case ErrorCode::kSuccess: return metrics::AttemptResult::kUpdateSucceeded; + case ErrorCode::kUpdatedButNotActive: + return metrics::AttemptResult::kUpdateSucceededNotActive; + case ErrorCode::kDownloadTransferError: return metrics::AttemptResult::kPayloadDownloadError; @@ -212,6 +215,7 @@ metrics::DownloadErrorCode GetDownloadErrorCode(ErrorCode code) { case ErrorCode::kFilesystemVerifierError: case ErrorCode::kUserCanceled: case ErrorCode::kPayloadTimestampError: + case ErrorCode::kUpdatedButNotActive: break; // Special flags. These can't happen (we mask them out above) but diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc index a35b41d3..3d567fa0 100644 --- a/payload_consumer/delta_performer.cc +++ b/payload_consumer/delta_performer.cc @@ -1638,6 +1638,7 @@ bool DeltaPerformer::ResetUpdateProgress(PrefsInterface* prefs, bool quick) { prefs->SetInt64(kPrefsManifestMetadataSize, -1); prefs->SetInt64(kPrefsManifestSignatureSize, -1); prefs->SetInt64(kPrefsResumedUpdateFailures, 0); + prefs->Delete(kPrefsPostInstallSucceeded); } return true; } diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc index b0dff31e..45112d6e 100644 --- a/payload_consumer/install_plan.cc +++ b/payload_consumer/install_plan.cc @@ -87,7 +87,10 @@ void InstallPlan::Dump() const { << ", url: " << download_url << payloads_str << partitions_str << ", hash_checks_mandatory: " << utils::ToString(hash_checks_mandatory) - << ", powerwash_required: " << utils::ToString(powerwash_required); + << ", powerwash_required: " << utils::ToString(powerwash_required) + << ", switch_slot_on_reboot: " + << utils::ToString(switch_slot_on_reboot) + << ", run_post_install: " << utils::ToString(run_post_install); } bool InstallPlan::LoadPartitionsFromSlots(BootControlInterface* boot_control) { diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h index 551f8c25..5cdfbc1c 100644 --- a/payload_consumer/install_plan.h +++ b/payload_consumer/install_plan.h @@ -119,6 +119,14 @@ struct InstallPlan { // False otherwise. bool powerwash_required{false}; + // True if the updated slot should be marked active on success. + // False otherwise. + bool switch_slot_on_reboot{true}; + + // True if the update should run its post-install step. + // False otherwise. + bool run_post_install{true}; + // If not blank, a base-64 encoded representation of the PEM-encoded // public key in the response. std::string public_key_rsa; diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc index 27a9ed61..cedecda9 100644 --- a/payload_consumer/postinstall_runner_action.cc +++ b/payload_consumer/postinstall_runner_action.cc @@ -82,6 +82,11 @@ void PostinstallRunnerAction::PerformAction() { } void PostinstallRunnerAction::PerformPartitionPostinstall() { + if (!install_plan_.run_post_install) { + LOG(INFO) << "Skipping post-install according to install plan."; + return CompletePostinstall(ErrorCode::kSuccess); + } + if (install_plan_.download_url.empty()) { LOG(INFO) << "Skipping post-install during rollback"; return CompletePostinstall(ErrorCode::kSuccess); @@ -331,15 +336,21 @@ void PostinstallRunnerAction::CompletePartitionPostinstall( void PostinstallRunnerAction::CompletePostinstall(ErrorCode error_code) { // We only attempt to mark the new slot as active if all the postinstall // steps succeeded. - if (error_code == ErrorCode::kSuccess && - !boot_control_->SetActiveBootSlot(install_plan_.target_slot)) { - error_code = ErrorCode::kPostinstallRunnerError; + if (error_code == ErrorCode::kSuccess) { + if (install_plan_.switch_slot_on_reboot) { + if (!boot_control_->SetActiveBootSlot(install_plan_.target_slot)) { + error_code = ErrorCode::kPostinstallRunnerError; + } + } else { + error_code = ErrorCode::kUpdatedButNotActive; + } } ScopedActionCompleter completer(processor_, this); completer.set_code(error_code); - if (error_code != ErrorCode::kSuccess) { + if (error_code != ErrorCode::kSuccess && + error_code != ErrorCode::kUpdatedButNotActive) { LOG(ERROR) << "Postinstall action failed."; // Undo any changes done to trigger Powerwash. diff --git a/payload_state.cc b/payload_state.cc index 54ced727..4992606e 100644 --- a/payload_state.cc +++ b/payload_state.cc @@ -358,6 +358,7 @@ void PayloadState::UpdateFailed(ErrorCode error) { case ErrorCode::kOmahaRequestXMLHasEntityDecl: case ErrorCode::kFilesystemVerifierError: case ErrorCode::kUserCanceled: + case ErrorCode::kUpdatedButNotActive: LOG(INFO) << "Not incrementing URL index or failure count for this error"; break; @@ -634,6 +635,7 @@ void PayloadState::CollectAndReportAttemptMetrics(ErrorCode code) { case metrics::AttemptResult::kPostInstallFailed: case metrics::AttemptResult::kAbnormalTermination: case metrics::AttemptResult::kUpdateCanceled: + case metrics::AttemptResult::kUpdateSucceededNotActive: case metrics::AttemptResult::kNumConstants: case metrics::AttemptResult::kUnset: break; diff --git a/update_attempter_android.cc b/update_attempter_android.cc index 08a5e581..82e3855f 100644 --- a/update_attempter_android.cc +++ b/update_attempter_android.cc @@ -81,6 +81,13 @@ bool LogAndSetError(brillo::ErrorPtr* error, return false; } +bool GetHeaderAsBool(const string& header, bool default_value) { + int value = 0; + if (base::StringToInt(header, &value) && (value == 0 || value == 1)) + return value == 1; + return default_value; +} + } // namespace UpdateAttempterAndroid::UpdateAttempterAndroid( @@ -193,10 +200,25 @@ bool UpdateAttempterAndroid::ApplyPayload( install_plan_.source_slot = boot_control_->GetCurrentSlot(); install_plan_.target_slot = install_plan_.source_slot == 0 ? 1 : 0; - int data_wipe = 0; install_plan_.powerwash_required = - base::StringToInt(headers[kPayloadPropertyPowerwash], &data_wipe) && - data_wipe != 0; + GetHeaderAsBool(headers[kPayloadPropertyPowerwash], false); + + install_plan_.switch_slot_on_reboot = + GetHeaderAsBool(headers[kPayloadPropertySwitchSlotOnReboot], true); + + install_plan_.run_post_install = true; + // Optionally skip post install if and only if: + // a) we're resuming + // b) post install has already succeeded before + // c) RUN_POST_INSTALL is set to 0. + if (install_plan_.is_resume && prefs_->Exists(kPrefsPostInstallSucceeded)) { + bool post_install_succeeded = false; + prefs_->GetBoolean(kPrefsPostInstallSucceeded, &post_install_succeeded); + if (post_install_succeeded) { + install_plan_.run_post_install = + GetHeaderAsBool(headers[kPayloadPropertyRunPostInstall], true); + } + } NetworkId network_id = kDefaultNetworkId; if (!headers[kPayloadPropertyNetworkId].empty()) { @@ -314,7 +336,6 @@ void UpdateAttempterAndroid::ProcessingDone(const ActionProcessor* processor, // Update succeeded. WriteUpdateCompletedMarker(); prefs_->SetInt64(kPrefsDeltaUpdateFailures, 0); - DeltaPerformer::ResetUpdateProgress(prefs_, false); LOG(INFO) << "Update successfully applied, waiting to reboot."; break; @@ -357,6 +378,11 @@ void UpdateAttempterAndroid::ActionCompleted(ActionProcessor* processor, if (type == DownloadAction::StaticType()) { download_progress_ = 0; } + if (type == PostinstallRunnerAction::StaticType()) { + bool succeeded = + code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive; + prefs_->SetBoolean(kPrefsPostInstallSucceeded, succeeded); + } if (code != ErrorCode::kSuccess) { // If an action failed, the ActionProcessor will cancel the whole thing. return; diff --git a/update_engine_client_android.cc b/update_engine_client_android.cc index 989a97e1..267f6e98 100644 --- a/update_engine_client_android.cc +++ b/update_engine_client_android.cc @@ -97,7 +97,10 @@ Status UpdateEngineClientAndroid::UECallback::onPayloadApplicationComplete( ErrorCode code = static_cast<ErrorCode>(error_code); LOG(INFO) << "onPayloadApplicationComplete(" << utils::ErrorCodeToString(code) << " (" << error_code << "))"; - client_->ExitWhenIdle(code == ErrorCode::kSuccess ? EX_OK : 1); + client_->ExitWhenIdle( + (code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive) + ? EX_OK + : 1); return Status::ok(); } diff --git a/update_manager/chromeos_policy.cc b/update_manager/chromeos_policy.cc index 81a169fb..da043727 100644 --- a/update_manager/chromeos_policy.cc +++ b/update_manager/chromeos_policy.cc @@ -135,6 +135,7 @@ bool HandleErrorCode(ErrorCode err_code, int* url_num_error_p) { case ErrorCode::kOmahaRequestXMLHasEntityDecl: case ErrorCode::kFilesystemVerifierError: case ErrorCode::kUserCanceled: + case ErrorCode::kUpdatedButNotActive: LOG(INFO) << "Not changing URL index or failure count due to error " << chromeos_update_engine::utils::ErrorCodeToString(err_code) << " (" << static_cast<int>(err_code) << ")"; |