1// 2// Copyright (C) 2015 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/client_library/client_dbus.h" 18 19#include <base/message_loop/message_loop.h> 20 21#include <dbus/bus.h> 22#include <update_engine/dbus-constants.h> 23 24#include "update_engine/update_status_utils.h" 25 26using chromeos_update_engine::StringToUpdateStatus; 27using dbus::Bus; 28using org::chromium::UpdateEngineInterfaceProxy; 29using std::string; 30 31namespace update_engine { 32namespace internal { 33 34bool DBusUpdateEngineClient::Init() { 35 Bus::Options options; 36 options.bus_type = Bus::SYSTEM; 37 scoped_refptr<Bus> bus{new Bus{options}}; 38 39 if (!bus->Connect()) 40 return false; 41 42 proxy_.reset(new UpdateEngineInterfaceProxy{bus}); 43 return true; 44} 45 46bool DBusUpdateEngineClient::AttemptUpdate(const string& in_app_version, 47 const string& in_omaha_url, 48 bool at_user_request) { 49 return proxy_->AttemptUpdateWithFlags( 50 in_app_version, 51 in_omaha_url, 52 (at_user_request) 53 ? 0 54 : update_engine::UpdateAttemptFlags::kFlagNonInteractive, 55 nullptr); 56} 57 58bool DBusUpdateEngineClient::GetStatus(int64_t* out_last_checked_time, 59 double* out_progress, 60 UpdateStatus* out_update_status, 61 string* out_new_version, 62 int64_t* out_new_size) const { 63 string status_as_string; 64 const bool success = proxy_->GetStatus(out_last_checked_time, 65 out_progress, 66 &status_as_string, 67 out_new_version, 68 out_new_size, 69 nullptr); 70 if (!success) { 71 return false; 72 } 73 74 return StringToUpdateStatus(status_as_string, out_update_status); 75} 76 77bool DBusUpdateEngineClient::SetCohortHint(const string& cohort_hint) { 78 return proxy_->SetCohortHint(cohort_hint, nullptr); 79} 80 81bool DBusUpdateEngineClient::GetCohortHint(string* cohort_hint) const { 82 return proxy_->GetCohortHint(cohort_hint, nullptr); 83} 84 85bool DBusUpdateEngineClient::SetUpdateOverCellularPermission(bool allowed) { 86 return proxy_->SetUpdateOverCellularPermission(allowed, nullptr); 87} 88 89bool DBusUpdateEngineClient::GetUpdateOverCellularPermission( 90 bool* allowed) const { 91 return proxy_->GetUpdateOverCellularPermission(allowed, nullptr); 92} 93 94bool DBusUpdateEngineClient::SetP2PUpdatePermission(bool enabled) { 95 return proxy_->SetP2PUpdatePermission(enabled, nullptr); 96} 97 98bool DBusUpdateEngineClient::GetP2PUpdatePermission(bool* enabled) const { 99 return proxy_->GetP2PUpdatePermission(enabled, nullptr); 100} 101 102bool DBusUpdateEngineClient::Rollback(bool powerwash) { 103 return proxy_->AttemptRollback(powerwash, nullptr); 104} 105 106bool DBusUpdateEngineClient::GetRollbackPartition( 107 string* rollback_partition) const { 108 return proxy_->GetRollbackPartition(rollback_partition, nullptr); 109} 110 111bool DBusUpdateEngineClient::GetPrevVersion(string* prev_version) const { 112 return proxy_->GetPrevVersion(prev_version, nullptr); 113} 114 115void DBusUpdateEngineClient::RebootIfNeeded() { 116 bool ret = proxy_->RebootIfNeeded(nullptr); 117 if (!ret) { 118 // Reboot error code doesn't necessarily mean that a reboot 119 // failed. For example, D-Bus may be shutdown before we receive the 120 // result. 121 LOG(INFO) << "RebootIfNeeded() failure ignored."; 122 } 123} 124 125bool DBusUpdateEngineClient::ResetStatus() { 126 return proxy_->ResetStatus(nullptr); 127} 128 129void DBusUpdateEngineClient::DBusStatusHandlersRegistered( 130 const string& interface, 131 const string& signal_name, 132 bool success) const { 133 if (!success) { 134 for (auto handler : handlers_) { 135 handler->IPCError("Could not connect to" + signal_name + 136 " on " + interface); 137 } 138 } else { 139 StatusUpdateHandlersRegistered(nullptr); 140 } 141} 142 143void DBusUpdateEngineClient::StatusUpdateHandlersRegistered( 144 StatusUpdateHandler* handler) const { 145 int64_t last_checked_time; 146 double progress; 147 UpdateStatus update_status; 148 string new_version; 149 int64_t new_size; 150 151 if (!GetStatus(&last_checked_time, 152 &progress, 153 &update_status, 154 &new_version, 155 &new_size)) { 156 handler->IPCError("Could not query current status"); 157 return; 158 } 159 160 std::vector<update_engine::StatusUpdateHandler*> just_handler = {handler}; 161 for (auto h : handler ? just_handler : handlers_) { 162 h->HandleStatusUpdate( 163 last_checked_time, progress, update_status, new_version, new_size); 164 } 165} 166 167void DBusUpdateEngineClient::RunStatusUpdateHandlers( 168 int64_t last_checked_time, 169 double progress, 170 const string& current_operation, 171 const string& new_version, 172 int64_t new_size) { 173 UpdateStatus status; 174 StringToUpdateStatus(current_operation, &status); 175 176 for (auto handler : handlers_) { 177 handler->HandleStatusUpdate( 178 last_checked_time, progress, status, new_version, new_size); 179 } 180} 181 182bool DBusUpdateEngineClient::UnregisterStatusUpdateHandler( 183 StatusUpdateHandler* handler) { 184 auto it = std::find(handlers_.begin(), handlers_.end(), handler); 185 if (it != handlers_.end()) { 186 handlers_.erase(it); 187 return true; 188 } 189 190 return false; 191} 192 193bool DBusUpdateEngineClient::RegisterStatusUpdateHandler( 194 StatusUpdateHandler* handler) { 195 if (!base::MessageLoopForIO::current()) { 196 LOG(FATAL) << "Cannot get UpdateEngineClient outside of message loop."; 197 return false; 198 } 199 200 handlers_.push_back(handler); 201 202 if (dbus_handler_registered_) { 203 StatusUpdateHandlersRegistered(handler); 204 return true; 205 } 206 207 proxy_->RegisterStatusUpdateSignalHandler( 208 base::Bind(&DBusUpdateEngineClient::RunStatusUpdateHandlers, 209 base::Unretained(this)), 210 base::Bind(&DBusUpdateEngineClient::DBusStatusHandlersRegistered, 211 base::Unretained(this))); 212 213 dbus_handler_registered_ = true; 214 215 return true; 216} 217 218bool DBusUpdateEngineClient::SetTargetChannel(const string& in_target_channel, 219 bool allow_powerwash) { 220 return proxy_->SetChannel(in_target_channel, allow_powerwash, nullptr); 221} 222 223bool DBusUpdateEngineClient::GetTargetChannel(string* out_channel) const { 224 return proxy_->GetChannel(false, // Get the target channel. 225 out_channel, 226 nullptr); 227} 228 229bool DBusUpdateEngineClient::GetChannel(string* out_channel) const { 230 return proxy_->GetChannel(true, // Get the current channel. 231 out_channel, 232 nullptr); 233} 234 235bool DBusUpdateEngineClient::GetLastAttemptError( 236 int32_t* last_attempt_error) const { 237 return proxy_->GetLastAttemptError(last_attempt_error, nullptr); 238} 239 240bool DBusUpdateEngineClient::GetEolStatus(int32_t* eol_status) const { 241 return proxy_->GetEolStatus(eol_status, nullptr); 242} 243 244} // namespace internal 245} // namespace update_engine 246