|  | // | 
|  | // 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 <base/bind.h> | 
|  | #include <base/callback.h> | 
|  | #include <base/logging.h> | 
|  | #include <base/time/time.h> | 
|  |  | 
|  | #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 <typename T> | 
|  | class RetryPollVariable : public Variable<T> { | 
|  | public: | 
|  | RetryPollVariable(const string& name, | 
|  | const base::TimeDelta poll_interval, | 
|  | base::Callback<bool(T* res)> func) | 
|  | : Variable<T>(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<T> 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<bool(T*)> 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<bool>("is_normal_boot_mode", | 
|  | hardware_->IsNormalBootMode())); | 
|  |  | 
|  | var_is_official_build_.reset( | 
|  | new ConstCopyVariable<bool>("is_official_build", | 
|  | hardware_->IsOfficialBuild())); | 
|  |  | 
|  | var_is_oobe_complete_.reset( | 
|  | new CallCopyVariable<bool>( | 
|  | "is_oobe_complete", | 
|  | base::Bind(&chromeos_update_engine::HardwareInterface::IsOOBEComplete, | 
|  | base::Unretained(hardware_), nullptr))); | 
|  |  | 
|  | var_num_slots_.reset( | 
|  | new ConstCopyVariable<unsigned int>( | 
|  | "num_slots", boot_control_->GetNumSlots())); | 
|  |  | 
|  | var_kiosk_required_platform_version_.reset(new RetryPollVariable<string>( | 
|  | "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 |