Home | History | Annotate | Download | only in client_library
      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 
     26 using chromeos_update_engine::StringToUpdateStatus;
     27 using dbus::Bus;
     28 using org::chromium::UpdateEngineInterfaceProxy;
     29 using std::string;
     30 
     31 namespace update_engine {
     32 namespace internal {
     33 
     34 bool 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 
     46 bool 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 
     58 bool 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 
     77 bool DBusUpdateEngineClient::SetCohortHint(const string& cohort_hint) {
     78   return proxy_->SetCohortHint(cohort_hint, nullptr);
     79 }
     80 
     81 bool DBusUpdateEngineClient::GetCohortHint(string* cohort_hint) const {
     82   return proxy_->GetCohortHint(cohort_hint, nullptr);
     83 }
     84 
     85 bool DBusUpdateEngineClient::SetUpdateOverCellularPermission(bool allowed) {
     86   return proxy_->SetUpdateOverCellularPermission(allowed, nullptr);
     87 }
     88 
     89 bool DBusUpdateEngineClient::GetUpdateOverCellularPermission(
     90     bool* allowed) const {
     91   return proxy_->GetUpdateOverCellularPermission(allowed, nullptr);
     92 }
     93 
     94 bool DBusUpdateEngineClient::SetP2PUpdatePermission(bool enabled) {
     95   return proxy_->SetP2PUpdatePermission(enabled, nullptr);
     96 }
     97 
     98 bool DBusUpdateEngineClient::GetP2PUpdatePermission(bool* enabled) const {
     99   return proxy_->GetP2PUpdatePermission(enabled, nullptr);
    100 }
    101 
    102 bool DBusUpdateEngineClient::Rollback(bool powerwash) {
    103   return proxy_->AttemptRollback(powerwash, nullptr);
    104 }
    105 
    106 bool DBusUpdateEngineClient::GetRollbackPartition(
    107     string* rollback_partition) const {
    108   return proxy_->GetRollbackPartition(rollback_partition, nullptr);
    109 }
    110 
    111 bool DBusUpdateEngineClient::GetPrevVersion(string* prev_version) const {
    112   return proxy_->GetPrevVersion(prev_version, nullptr);
    113 }
    114 
    115 void 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 
    125 bool DBusUpdateEngineClient::ResetStatus() {
    126   return proxy_->ResetStatus(nullptr);
    127 }
    128 
    129 void 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 
    143 void 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 
    167 void 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 
    182 bool 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 
    193 bool 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 
    218 bool DBusUpdateEngineClient::SetTargetChannel(const string& in_target_channel,
    219                                               bool allow_powerwash) {
    220   return proxy_->SetChannel(in_target_channel, allow_powerwash, nullptr);
    221 }
    222 
    223 bool DBusUpdateEngineClient::GetTargetChannel(string* out_channel) const {
    224   return proxy_->GetChannel(false,  // Get the target channel.
    225                             out_channel,
    226                             nullptr);
    227 }
    228 
    229 bool DBusUpdateEngineClient::GetChannel(string* out_channel) const {
    230   return proxy_->GetChannel(true,  // Get the current channel.
    231                             out_channel,
    232                             nullptr);
    233 }
    234 
    235 bool DBusUpdateEngineClient::GetLastAttemptError(
    236     int32_t* last_attempt_error) const {
    237   return proxy_->GetLastAttemptError(last_attempt_error, nullptr);
    238 }
    239 
    240 bool DBusUpdateEngineClient::GetEolStatus(int32_t* eol_status) const {
    241   return proxy_->GetEolStatus(eol_status, nullptr);
    242 }
    243 
    244 }  // namespace internal
    245 }  // namespace update_engine
    246