// // Copyright (C) 2014 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "update_engine/update_manager/real_system_provider.h" #include #include #include #include #include "update_engine/common/utils.h" #if USE_LIBCROS #include "update_engine/libcros_proxy.h" #endif #include "update_engine/update_manager/generic_variables.h" #include "update_engine/update_manager/variable.h" using std::string; namespace chromeos_update_manager { namespace { // The maximum number of consecutive failures before returning the default // constructor value for T instead of failure. const int kRetryPollVariableMaxRetry = 5; // The polling interval to be used whenever GetValue() returns an error. const int kRetryPollVariableRetryIntervalSeconds = 5 * 60; // The RetryPollVariable variable is a polling variable that allows the function // returning the value to fail a few times and shortens the polling rate when // that happens. template class RetryPollVariable : public Variable { public: RetryPollVariable(const string& name, const base::TimeDelta poll_interval, base::Callback func) : Variable(name, poll_interval), func_(func), base_interval_(poll_interval) { DCHECK_LT(kRetryPollVariableRetryIntervalSeconds, base_interval_.InSeconds()); } protected: // Variable override. const T* GetValue(base::TimeDelta /* timeout */, string* /* errmsg */) override { std::unique_ptr result(new T()); if (!func_.Run(result.get())) { if (failed_attempts_ >= kRetryPollVariableMaxRetry) { // Give up on the retries, set back the desired polling interval and // return the default. this->SetPollInterval(base_interval_); return result.release(); } this->SetPollInterval( base::TimeDelta::FromSeconds(kRetryPollVariableRetryIntervalSeconds)); failed_attempts_++; return nullptr; } failed_attempts_ = 0; this->SetPollInterval(base_interval_); return result.release(); } private: // The function to be called, stored as a base::Callback. base::Callback func_; // The desired polling interval when |func_| works and returns true. base::TimeDelta base_interval_; // The number of consecutive failed attempts made. int failed_attempts_ = 0; DISALLOW_COPY_AND_ASSIGN(RetryPollVariable); }; } // namespace bool RealSystemProvider::Init() { var_is_normal_boot_mode_.reset( new ConstCopyVariable("is_normal_boot_mode", hardware_->IsNormalBootMode())); var_is_official_build_.reset( new ConstCopyVariable("is_official_build", hardware_->IsOfficialBuild())); var_is_oobe_complete_.reset( new CallCopyVariable( "is_oobe_complete", base::Bind(&chromeos_update_engine::HardwareInterface::IsOOBEComplete, base::Unretained(hardware_), nullptr))); var_num_slots_.reset( new ConstCopyVariable( "num_slots", boot_control_->GetNumSlots())); var_kiosk_required_platform_version_.reset(new RetryPollVariable( "kiosk_required_platform_version", base::TimeDelta::FromHours(5), // Same as Chrome's CWS poll. base::Bind(&RealSystemProvider::GetKioskAppRequiredPlatformVersion, base::Unretained(this)))); return true; } bool RealSystemProvider::GetKioskAppRequiredPlatformVersion( string* required_platform_version) { #if USE_LIBCROS brillo::ErrorPtr error; if (!libcros_proxy_->service_interface_proxy() ->GetKioskAppRequiredPlatformVersion(required_platform_version, &error)) { LOG(WARNING) << "Failed to get kiosk required platform version"; required_platform_version->clear(); return false; } #endif return true; } } // namespace chromeos_update_manager