1// 2// Copyright (C) 2014 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_manager/real_system_provider.h" 18 19#include <base/bind.h> 20#include <base/callback.h> 21#include <base/logging.h> 22#include <base/time/time.h> 23#if USE_LIBCROS 24#include <libcros/dbus-proxies.h> 25#endif 26 27#include "update_engine/common/utils.h" 28#include "update_engine/update_manager/generic_variables.h" 29#include "update_engine/update_manager/variable.h" 30 31using std::string; 32 33namespace chromeos_update_manager { 34 35namespace { 36 37// The maximum number of consecutive failures before returning the default 38// constructor value for T instead of failure. 39const int kRetryPollVariableMaxRetry = 5; 40 41// The polling interval to be used whenever GetValue() returns an error. 42const int kRetryPollVariableRetryIntervalSeconds = 5 * 60; 43 44// The RetryPollVariable variable is a polling variable that allows the function 45// returning the value to fail a few times and shortens the polling rate when 46// that happens. 47template <typename T> 48class RetryPollVariable : public Variable<T> { 49 public: 50 RetryPollVariable(const string& name, 51 const base::TimeDelta poll_interval, 52 base::Callback<bool(T* res)> func) 53 : Variable<T>(name, poll_interval), 54 func_(func), 55 base_interval_(poll_interval) { 56 DCHECK_LT(kRetryPollVariableRetryIntervalSeconds, 57 base_interval_.InSeconds()); 58 } 59 60 protected: 61 // Variable override. 62 const T* GetValue(base::TimeDelta /* timeout */, 63 string* /* errmsg */) override { 64 std::unique_ptr<T> result(new T()); 65 if (!func_.Run(result.get())) { 66 if (failed_attempts_ >= kRetryPollVariableMaxRetry) { 67 // Give up on the retries, set back the desired polling interval and 68 // return the default. 69 this->SetPollInterval(base_interval_); 70 return result.release(); 71 } 72 this->SetPollInterval( 73 base::TimeDelta::FromSeconds(kRetryPollVariableRetryIntervalSeconds)); 74 failed_attempts_++; 75 return nullptr; 76 } 77 failed_attempts_ = 0; 78 this->SetPollInterval(base_interval_); 79 return result.release(); 80 } 81 82 private: 83 // The function to be called, stored as a base::Callback. 84 base::Callback<bool(T*)> func_; 85 86 // The desired polling interval when |func_| works and returns true. 87 base::TimeDelta base_interval_; 88 89 // The number of consecutive failed attempts made. 90 int failed_attempts_ = 0; 91 92 DISALLOW_COPY_AND_ASSIGN(RetryPollVariable); 93}; 94 95} // namespace 96 97bool RealSystemProvider::Init() { 98 var_is_normal_boot_mode_.reset( 99 new ConstCopyVariable<bool>("is_normal_boot_mode", 100 hardware_->IsNormalBootMode())); 101 102 var_is_official_build_.reset( 103 new ConstCopyVariable<bool>("is_official_build", 104 hardware_->IsOfficialBuild())); 105 106 var_is_oobe_complete_.reset( 107 new CallCopyVariable<bool>( 108 "is_oobe_complete", 109 base::Bind(&chromeos_update_engine::HardwareInterface::IsOOBEComplete, 110 base::Unretained(hardware_), nullptr))); 111 112 var_num_slots_.reset( 113 new ConstCopyVariable<unsigned int>( 114 "num_slots", boot_control_->GetNumSlots())); 115 116 var_kiosk_required_platform_version_.reset(new RetryPollVariable<string>( 117 "kiosk_required_platform_version", 118 base::TimeDelta::FromHours(5), // Same as Chrome's CWS poll. 119 base::Bind(&RealSystemProvider::GetKioskAppRequiredPlatformVersion, 120 base::Unretained(this)))); 121 122 return true; 123} 124 125bool RealSystemProvider::GetKioskAppRequiredPlatformVersion( 126 string* required_platform_version) { 127#if USE_LIBCROS 128 brillo::ErrorPtr error; 129 if (!libcros_proxy_->GetKioskAppRequiredPlatformVersion( 130 required_platform_version, &error)) { 131 LOG(WARNING) << "Failed to get kiosk required platform version"; 132 required_platform_version->clear(); 133 return false; 134 } 135#endif 136 137 return true; 138} 139 140} // namespace chromeos_update_manager 141