Home | History | Annotate | Download | only in update_engine
      1 //
      2 // Copyright (C) 2016 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 <sysexits.h>
     18 #include <unistd.h>
     19 
     20 #include <string>
     21 #include <vector>
     22 
     23 #include <base/bind.h>
     24 #include <base/callback.h>
     25 #include <base/command_line.h>
     26 #include <base/logging.h>
     27 #include <base/strings/string_split.h>
     28 #include <binder/IServiceManager.h>
     29 #include <binderwrapper/binder_wrapper.h>
     30 #include <brillo/binder_watcher.h>
     31 #include <brillo/daemons/daemon.h>
     32 #include <brillo/flag_helper.h>
     33 #include <brillo/message_loops/message_loop.h>
     34 #include <brillo/syslog_logging.h>
     35 #include <utils/String16.h>
     36 #include <utils/StrongPointer.h>
     37 
     38 #include "android/os/BnUpdateEngineCallback.h"
     39 #include "android/os/IUpdateEngine.h"
     40 #include "update_engine/client_library/include/update_engine/update_status.h"
     41 #include "update_engine/common/error_code.h"
     42 #include "update_engine/common/error_code_utils.h"
     43 #include "update_engine/update_status_utils.h"
     44 
     45 using android::binder::Status;
     46 
     47 namespace chromeos_update_engine {
     48 namespace internal {
     49 
     50 class UpdateEngineClientAndroid : public brillo::Daemon {
     51  public:
     52   UpdateEngineClientAndroid(int argc, char** argv) : argc_(argc), argv_(argv) {
     53   }
     54 
     55   int ExitWhenIdle(const Status& status);
     56   int ExitWhenIdle(int return_code);
     57 
     58  private:
     59   class UECallback : public android::os::BnUpdateEngineCallback {
     60    public:
     61     explicit UECallback(UpdateEngineClientAndroid* client) : client_(client) {}
     62 
     63     // android::os::BnUpdateEngineCallback overrides.
     64     Status onStatusUpdate(int status_code, float progress) override;
     65     Status onPayloadApplicationComplete(int error_code) override;
     66 
     67    private:
     68     UpdateEngineClientAndroid* client_;
     69   };
     70 
     71   int OnInit() override;
     72 
     73   // Called whenever the UpdateEngine daemon dies.
     74   void UpdateEngineServiceDied();
     75 
     76   // Copy of argc and argv passed to main().
     77   int argc_;
     78   char** argv_;
     79 
     80   android::sp<android::os::IUpdateEngine> service_;
     81   android::sp<android::os::BnUpdateEngineCallback> callback_;
     82 
     83   brillo::BinderWatcher binder_watcher_;
     84 };
     85 
     86 Status UpdateEngineClientAndroid::UECallback::onStatusUpdate(
     87     int status_code, float progress) {
     88   update_engine::UpdateStatus status =
     89       static_cast<update_engine::UpdateStatus>(status_code);
     90   LOG(INFO) << "onStatusUpdate(" << UpdateStatusToString(status) << " ("
     91             << status_code << "), " << progress << ")";
     92   return Status::ok();
     93 }
     94 
     95 Status UpdateEngineClientAndroid::UECallback::onPayloadApplicationComplete(
     96     int error_code) {
     97   ErrorCode code = static_cast<ErrorCode>(error_code);
     98   LOG(INFO) << "onPayloadApplicationComplete(" << utils::ErrorCodeToString(code)
     99             << " (" << error_code << "))";
    100   client_->ExitWhenIdle(
    101       (code == ErrorCode::kSuccess || code == ErrorCode::kUpdatedButNotActive)
    102           ? EX_OK
    103           : 1);
    104   return Status::ok();
    105 }
    106 
    107 int UpdateEngineClientAndroid::OnInit() {
    108   int ret = Daemon::OnInit();
    109   if (ret != EX_OK)
    110     return ret;
    111 
    112   DEFINE_bool(update, false, "Start a new update, if no update in progress.");
    113   DEFINE_string(payload,
    114                 "http://127.0.0.1:8080/payload",
    115                 "The URI to the update payload to use.");
    116   DEFINE_int64(offset, 0,
    117                "The offset in the payload where the CrAU update starts. "
    118                "Used when --update is passed.");
    119   DEFINE_int64(size, 0,
    120                "The size of the CrAU part of the payload. If 0 is passed, it "
    121                "will be autodetected. Used when --update is passed.");
    122   DEFINE_string(headers,
    123                 "",
    124                 "A list of key-value pairs, one element of the list per line. "
    125                 "Used when --update is passed.");
    126 
    127   DEFINE_bool(suspend, false, "Suspend an ongoing update and exit.");
    128   DEFINE_bool(resume, false, "Resume a suspended update.");
    129   DEFINE_bool(cancel, false, "Cancel the ongoing update and exit.");
    130   DEFINE_bool(reset_status, false, "Reset an already applied update and exit.");
    131   DEFINE_bool(follow,
    132               false,
    133               "Follow status update changes until a final state is reached. "
    134               "Exit status is 0 if the update succeeded, and 1 otherwise.");
    135 
    136   // Boilerplate init commands.
    137   base::CommandLine::Init(argc_, argv_);
    138   brillo::FlagHelper::Init(argc_, argv_, "Android Update Engine Client");
    139   if (argc_ == 1) {
    140     LOG(ERROR) << "Nothing to do. Run with --help for help.";
    141     return 1;
    142   }
    143 
    144   // Ensure there are no positional arguments.
    145   const std::vector<std::string> positional_args =
    146       base::CommandLine::ForCurrentProcess()->GetArgs();
    147   if (!positional_args.empty()) {
    148     LOG(ERROR) << "Found a positional argument '" << positional_args.front()
    149                << "'. If you want to pass a value to a flag, pass it as "
    150                   "--flag=value.";
    151     return 1;
    152   }
    153 
    154   bool keep_running = false;
    155   brillo::InitLog(brillo::kLogToStderr);
    156 
    157   // Initialize a binder watcher early in the process before any interaction
    158   // with the binder driver.
    159   binder_watcher_.Init();
    160 
    161   android::status_t status = android::getService(
    162       android::String16("android.os.UpdateEngineService"), &service_);
    163   if (status != android::OK) {
    164     LOG(ERROR) << "Failed to get IUpdateEngine binder from service manager: "
    165                << Status::fromStatusT(status).toString8();
    166     return ExitWhenIdle(1);
    167   }
    168 
    169   if (FLAGS_suspend) {
    170     return ExitWhenIdle(service_->suspend());
    171   }
    172 
    173   if (FLAGS_resume) {
    174     return ExitWhenIdle(service_->resume());
    175   }
    176 
    177   if (FLAGS_cancel) {
    178     return ExitWhenIdle(service_->cancel());
    179   }
    180 
    181   if (FLAGS_reset_status) {
    182     return ExitWhenIdle(service_->resetStatus());
    183   }
    184 
    185   if (FLAGS_follow) {
    186     // Register a callback object with the service.
    187     callback_ = new UECallback(this);
    188     bool bound;
    189     if (!service_->bind(callback_, &bound).isOk() || !bound) {
    190       LOG(ERROR) << "Failed to bind() the UpdateEngine daemon.";
    191       return 1;
    192     }
    193     keep_running = true;
    194   }
    195 
    196   if (FLAGS_update) {
    197     std::vector<std::string> headers = base::SplitString(
    198         FLAGS_headers, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
    199     std::vector<android::String16> and_headers;
    200     for (const auto& header : headers) {
    201       and_headers.push_back(android::String16{header.data(), header.size()});
    202     }
    203     Status status = service_->applyPayload(
    204         android::String16{FLAGS_payload.data(), FLAGS_payload.size()},
    205         FLAGS_offset,
    206         FLAGS_size,
    207         and_headers);
    208     if (!status.isOk())
    209       return ExitWhenIdle(status);
    210   }
    211 
    212   if (!keep_running)
    213     return ExitWhenIdle(EX_OK);
    214 
    215   // When following updates status changes, exit if the update_engine daemon
    216   // dies.
    217   android::BinderWrapper::Create();
    218   android::BinderWrapper::Get()->RegisterForDeathNotifications(
    219       android::os::IUpdateEngine::asBinder(service_),
    220       base::Bind(&UpdateEngineClientAndroid::UpdateEngineServiceDied,
    221                  base::Unretained(this)));
    222 
    223   return EX_OK;
    224 }
    225 
    226 int UpdateEngineClientAndroid::ExitWhenIdle(const Status& status) {
    227   if (status.isOk())
    228     return ExitWhenIdle(EX_OK);
    229   LOG(ERROR) << status.toString8();
    230   return ExitWhenIdle(status.exceptionCode());
    231 }
    232 
    233 int UpdateEngineClientAndroid::ExitWhenIdle(int return_code) {
    234   auto delayed_exit = base::Bind(
    235       &Daemon::QuitWithExitCode, base::Unretained(this), return_code);
    236   if (!brillo::MessageLoop::current()->PostTask(delayed_exit))
    237     return 1;
    238   return EX_OK;
    239 }
    240 
    241 void UpdateEngineClientAndroid::UpdateEngineServiceDied() {
    242   LOG(ERROR) << "UpdateEngineService died.";
    243   QuitWithExitCode(1);
    244 }
    245 
    246 }  // namespace internal
    247 }  // namespace chromeos_update_engine
    248 
    249 int main(int argc, char** argv) {
    250   chromeos_update_engine::internal::UpdateEngineClientAndroid client(
    251       argc, argv);
    252   return client.Run();
    253 }
    254