1 // 2 // Copyright (C) 2018 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 #include "update_engine/update_boot_flags_action.h" 18 19 #include <base/bind.h> 20 #include <base/logging.h> 21 22 #include "update_engine/common/boot_control.h" 23 24 namespace chromeos_update_engine { 25 26 bool UpdateBootFlagsAction::updated_boot_flags_ = false; 27 bool UpdateBootFlagsAction::is_running_ = false; 28 29 void UpdateBootFlagsAction::PerformAction() { 30 if (is_running_) { 31 LOG(INFO) << "Update boot flags running, nothing to do."; 32 processor_->ActionComplete(this, ErrorCode::kSuccess); 33 return; 34 } 35 if (updated_boot_flags_) { 36 LOG(INFO) << "Already updated boot flags. Skipping."; 37 processor_->ActionComplete(this, ErrorCode::kSuccess); 38 return; 39 } 40 41 // This is purely best effort. Failures should be logged by Subprocess. Run 42 // the script asynchronously to avoid blocking the event loop regardless of 43 // the script runtime. 44 is_running_ = true; 45 LOG(INFO) << "Marking booted slot as good."; 46 if (!boot_control_->MarkBootSuccessfulAsync( 47 base::Bind(&UpdateBootFlagsAction::CompleteUpdateBootFlags, 48 base::Unretained(this)))) { 49 CompleteUpdateBootFlags(false); 50 } 51 } 52 53 void UpdateBootFlagsAction::TerminateProcessing() { 54 is_running_ = false; 55 } 56 57 void UpdateBootFlagsAction::CompleteUpdateBootFlags(bool successful) { 58 if (!successful) { 59 // We ignore the failure for now because if the updating boot flags is flaky 60 // or has a bug in a specific release, then blocking the update can cause 61 // devices to stay behind even though we could have updated the system and 62 // fixed the issue regardless of this failure. 63 // 64 // TODO(ahassani): Add new error code metric for kUpdateBootFlagsFailed. 65 LOG(ERROR) << "Updating boot flags failed, but ignoring its failure."; 66 } 67 68 // As the callback to MarkBootSuccessfulAsync, this function can still be 69 // called even after the current UpdateBootFlagsAction object get destroyed by 70 // the action processor. In this case, check the value of the static variable 71 // |is_running_| and skip executing the callback function. 72 if (!is_running_) { 73 LOG(INFO) << "UpdateBootFlagsAction is no longer running."; 74 return; 75 } 76 77 is_running_ = false; 78 79 updated_boot_flags_ = true; 80 processor_->ActionComplete(this, ErrorCode::kSuccess); 81 } 82 83 } // namespace chromeos_update_engine 84