1 // 2 // Copyright (C) 2012 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/real_system_state.h" 18 19 #include <string> 20 21 #include <base/bind.h> 22 #include <base/files/file_util.h> 23 #include <base/location.h> 24 #include <base/time/time.h> 25 #include <brillo/make_unique_ptr.h> 26 #include <brillo/message_loops/message_loop.h> 27 #if USE_LIBCROS 28 #include <chromeos/dbus/service_constants.h> 29 #endif // USE_LIBCROS 30 31 #include "update_engine/common/boot_control.h" 32 #include "update_engine/common/boot_control_stub.h" 33 #include "update_engine/common/constants.h" 34 #include "update_engine/common/hardware.h" 35 #include "update_engine/common/utils.h" 36 #if USE_DBUS 37 #include "update_engine/dbus_connection.h" 38 #endif // USE_DBUS 39 #include "update_engine/update_manager/state_factory.h" 40 41 using brillo::MessageLoop; 42 43 namespace chromeos_update_engine { 44 45 RealSystemState::~RealSystemState() { 46 // Prevent any DBus communication from UpdateAttempter when shutting down the 47 // daemon. 48 if (update_attempter_) 49 update_attempter_->ClearObservers(); 50 } 51 52 bool RealSystemState::Initialize() { 53 metrics_lib_.Init(); 54 55 boot_control_ = boot_control::CreateBootControl(); 56 if (!boot_control_) { 57 LOG(WARNING) << "Unable to create BootControl instance, using stub " 58 << "instead. All update attempts will fail."; 59 boot_control_ = brillo::make_unique_ptr(new BootControlStub()); 60 } 61 62 hardware_ = hardware::CreateHardware(); 63 if (!hardware_) { 64 LOG(ERROR) << "Error intializing the HardwareInterface."; 65 return false; 66 } 67 68 #if USE_LIBCROS 69 libcros_proxy_.reset(new org::chromium::LibCrosServiceInterfaceProxy( 70 DBusConnection::Get()->GetDBus(), chromeos::kLibCrosServiceName)); 71 network_proxy_service_proxy_.reset( 72 new org::chromium::NetworkProxyServiceInterfaceProxy( 73 DBusConnection::Get()->GetDBus(), 74 chromeos::kNetworkProxyServiceName)); 75 #endif // USE_LIBCROS 76 77 LOG_IF(INFO, !hardware_->IsNormalBootMode()) << "Booted in dev mode."; 78 LOG_IF(INFO, !hardware_->IsOfficialBuild()) << "Booted non-official build."; 79 80 connection_manager_ = connection_manager::CreateConnectionManager(this); 81 if (!connection_manager_) { 82 LOG(ERROR) << "Error intializing the ConnectionManagerInterface."; 83 return false; 84 } 85 86 power_manager_ = power_manager::CreatePowerManager(); 87 if (!power_manager_) { 88 LOG(ERROR) << "Error intializing the PowerManagerInterface."; 89 return false; 90 } 91 92 // Initialize standard and powerwash-safe prefs. 93 base::FilePath non_volatile_path; 94 // TODO(deymo): Fall back to in-memory prefs if there's no physical directory 95 // available. 96 if (!hardware_->GetNonVolatileDirectory(&non_volatile_path)) { 97 LOG(ERROR) << "Failed to get a non-volatile directory."; 98 return false; 99 } 100 Prefs* prefs; 101 prefs_.reset(prefs = new Prefs()); 102 if (!prefs->Init(non_volatile_path.Append(kPrefsSubDirectory))) { 103 LOG(ERROR) << "Failed to initialize preferences."; 104 return false; 105 } 106 107 base::FilePath powerwash_safe_path; 108 if (!hardware_->GetPowerwashSafeDirectory(&powerwash_safe_path)) { 109 // TODO(deymo): Fall-back to in-memory prefs if there's no powerwash-safe 110 // directory, or disable powerwash feature. 111 powerwash_safe_path = non_volatile_path.Append("powerwash-safe"); 112 LOG(WARNING) << "No powerwash-safe directory, using non-volatile one."; 113 } 114 powerwash_safe_prefs_.reset(prefs = new Prefs()); 115 if (!prefs->Init( 116 powerwash_safe_path.Append(kPowerwashSafePrefsSubDirectory))) { 117 LOG(ERROR) << "Failed to initialize powerwash preferences."; 118 return false; 119 } 120 121 // Check the system rebooted marker file. 122 std::string boot_id; 123 if (utils::GetBootId(&boot_id)) { 124 std::string prev_boot_id; 125 system_rebooted_ = (!prefs_->GetString(kPrefsBootId, &prev_boot_id) || 126 prev_boot_id != boot_id); 127 prefs_->SetString(kPrefsBootId, boot_id); 128 } else { 129 LOG(WARNING) << "Couldn't detect the bootid, assuming system was rebooted."; 130 system_rebooted_ = true; 131 } 132 133 // Initialize the OmahaRequestParams with the default settings. These settings 134 // will be re-initialized before every request using the actual request 135 // options. This initialization here pre-loads current channel and version, so 136 // the DBus service can access it. 137 if (!request_params_.Init("", "", false)) { 138 LOG(WARNING) << "Ignoring OmahaRequestParams initialization error. Some " 139 "features might not work properly."; 140 } 141 142 certificate_checker_.reset( 143 new CertificateChecker(prefs_.get(), &openssl_wrapper_)); 144 certificate_checker_->Init(); 145 146 #if USE_LIBCROS 147 org::chromium::NetworkProxyServiceInterfaceProxyInterface* net_proxy = 148 network_proxy_service_proxy_.get(); 149 org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy = 150 libcros_proxy_.get(); 151 #else 152 org::chromium::NetworkProxyServiceInterfaceProxyInterface* net_proxy = 153 nullptr; 154 org::chromium::LibCrosServiceInterfaceProxyInterface* libcros_proxy = 155 nullptr; 156 #endif // USE_LIBCROS 157 158 // Initialize the UpdateAttempter before the UpdateManager. 159 update_attempter_.reset(new UpdateAttempter(this, certificate_checker_.get(), 160 net_proxy)); 161 update_attempter_->Init(); 162 163 // Initialize the Update Manager using the default state factory. 164 chromeos_update_manager::State* um_state = 165 chromeos_update_manager::DefaultStateFactory( 166 &policy_provider_, libcros_proxy, this); 167 if (!um_state) { 168 LOG(ERROR) << "Failed to initialize the Update Manager."; 169 return false; 170 } 171 update_manager_.reset( 172 new chromeos_update_manager::UpdateManager( 173 &clock_, base::TimeDelta::FromSeconds(5), 174 base::TimeDelta::FromHours(12), um_state)); 175 176 // The P2P Manager depends on the Update Manager for its initialization. 177 p2p_manager_.reset(P2PManager::Construct( 178 nullptr, &clock_, update_manager_.get(), "cros_au", 179 kMaxP2PFilesToKeep, base::TimeDelta::FromDays(kMaxP2PFileAgeDays))); 180 181 if (!payload_state_.Initialize(this)) { 182 LOG(ERROR) << "Failed to initialize the payload state object."; 183 return false; 184 } 185 186 // All is well. Initialization successful. 187 return true; 188 } 189 190 bool RealSystemState::StartUpdater() { 191 // Initiate update checks. 192 update_attempter_->ScheduleUpdates(); 193 194 // Update boot flags after 45 seconds. 195 MessageLoop::current()->PostDelayedTask( 196 FROM_HERE, 197 base::Bind(&UpdateAttempter::UpdateBootFlags, 198 base::Unretained(update_attempter_.get())), 199 base::TimeDelta::FromSeconds(45)); 200 201 // Broadcast the update engine status on startup to ensure consistent system 202 // state on crashes. 203 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 204 &UpdateAttempter::BroadcastStatus, 205 base::Unretained(update_attempter_.get()))); 206 207 // Run the UpdateEngineStarted() method on |update_attempter|. 208 MessageLoop::current()->PostTask(FROM_HERE, base::Bind( 209 &UpdateAttempter::UpdateEngineStarted, 210 base::Unretained(update_attempter_.get()))); 211 return true; 212 } 213 214 void RealSystemState::AddObserver(ServiceObserverInterface* observer) { 215 CHECK(update_attempter_.get()); 216 update_attempter_->AddObserver(observer); 217 } 218 219 void RealSystemState::RemoveObserver(ServiceObserverInterface* observer) { 220 CHECK(update_attempter_.get()); 221 update_attempter_->RemoveObserver(observer); 222 } 223 224 } // namespace chromeos_update_engine 225