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_CHROME_KIOSK_APP 24 #include <kiosk-app/dbus-proxies.h> 25 #endif // USE_CHROME_KIOSK_APP 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 31 using std::string; 32 33 namespace chromeos_update_manager { 34 35 namespace { 36 37 // The maximum number of consecutive failures before returning the default 38 // constructor value for T instead of failure. 39 const int kRetryPollVariableMaxRetry = 5; 40 41 // The polling interval to be used whenever GetValue() returns an error. 42 const 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. 47 template <typename T> 48 class 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 97 bool RealSystemProvider::Init() { 98 var_is_normal_boot_mode_.reset(new ConstCopyVariable<bool>( 99 "is_normal_boot_mode", hardware_->IsNormalBootMode())); 100 101 var_is_official_build_.reset(new ConstCopyVariable<bool>( 102 "is_official_build", hardware_->IsOfficialBuild())); 103 104 var_is_oobe_complete_.reset(new CallCopyVariable<bool>( 105 "is_oobe_complete", 106 base::Bind(&chromeos_update_engine::HardwareInterface::IsOOBEComplete, 107 base::Unretained(hardware_), 108 nullptr))); 109 110 var_num_slots_.reset(new ConstCopyVariable<unsigned int>( 111 "num_slots", boot_control_->GetNumSlots())); 112 113 var_kiosk_required_platform_version_.reset(new RetryPollVariable<string>( 114 "kiosk_required_platform_version", 115 base::TimeDelta::FromHours(5), // Same as Chrome's CWS poll. 116 base::Bind(&RealSystemProvider::GetKioskAppRequiredPlatformVersion, 117 base::Unretained(this)))); 118 119 return true; 120 } 121 122 bool RealSystemProvider::GetKioskAppRequiredPlatformVersion( 123 string* required_platform_version) { 124 #if USE_CHROME_KIOSK_APP 125 brillo::ErrorPtr error; 126 if (!kiosk_app_proxy_->GetRequiredPlatformVersion(required_platform_version, 127 &error)) { 128 LOG(WARNING) << "Failed to get kiosk required platform version"; 129 required_platform_version->clear(); 130 return false; 131 } 132 #endif // USE_CHROME_KIOSK_APP 133 134 return true; 135 } 136 137 } // namespace chromeos_update_manager 138