Introduce status handlers and use them in client
We introduce a StatusUpdateHandler class which can be overridden to
provide a method with which to react to status updates. This replaces
manual dbus logic in several places in update_engine_client with a
consistent interface for asynchronously handling status updates.
Change-Id: Idca4229de82074fb7a87a315b45dd0292c1b1f16
Test: Confirmed --update blocks and resumes correctly
Bug: 26233663
diff --git a/client_library/client_impl.cc b/client_library/client_impl.cc
index 7b80025..247f8f0 100644
--- a/client_library/client_impl.cc
+++ b/client_library/client_impl.cc
@@ -40,10 +40,8 @@
const string& in_omaha_url,
bool at_user_request) {
return proxy_->AttemptUpdateWithFlags(
- in_app_version,
- in_omaha_url,
- (at_user_request) ? 0 : kAttemptUpdateFlagNonInteractive,
- nullptr);
+ in_app_version, in_omaha_url,
+ (at_user_request) ? 0 : kAttemptUpdateFlagNonInteractive, nullptr);
}
bool UpdateEngineClientImpl::GetStatus(int64_t* out_last_checked_time,
@@ -52,13 +50,9 @@
string* out_new_version,
int64_t* out_new_size) {
string status_as_string;
- const bool success = proxy_->GetStatus(
- out_last_checked_time,
- out_progress,
- &status_as_string,
- out_new_version,
- out_new_size,
- nullptr);
+ const bool success =
+ proxy_->GetStatus(out_last_checked_time, out_progress, &status_as_string,
+ out_new_version, out_new_size, nullptr);
if (!success) {
return false;
}
@@ -70,7 +64,7 @@
return proxy_->SetUpdateOverCellularPermission(allowed, nullptr);
}
-bool UpdateEngineClientImpl::GetUpdateOverCellularPermission(bool *allowed) {
+bool UpdateEngineClientImpl::GetUpdateOverCellularPermission(bool* allowed) {
return proxy_->GetUpdateOverCellularPermission(allowed, nullptr);
}
@@ -108,26 +102,63 @@
return proxy_->ResetStatus(nullptr);
}
+void UpdateEngineClientImpl::StatusUpdateHandlerRegistered(
+ StatusUpdateHandler* handler, const std::string& interface,
+ const std::string& signal_name, bool success) {
+ if (!success) {
+ handler->IPCError("Could not connect to" + signal_name);
+ return;
+ }
+
+ int64_t last_checked_time;
+ double progress;
+ UpdateStatus update_status;
+ string new_version;
+ int64_t new_size;
+
+ if (GetStatus(&last_checked_time, &progress, &update_status, &new_version,
+ &new_size)) {
+ handler->HandleStatusUpdate(last_checked_time, progress, update_status,
+ new_version, new_size);
+ return;
+ }
+
+ handler->IPCError("Could not query current status");
+}
+
+void UpdateEngineClientImpl::RunStatusUpdateHandler(
+ StatusUpdateHandler* h, int64_t last_checked_time, double progress,
+ const std::string& current_operation, const std::string& new_version,
+ int64_t new_size) {
+ UpdateStatus status;
+ StringToUpdateStatus(current_operation, &status);
+
+ h->HandleStatusUpdate(last_checked_time, progress, status, new_version,
+ new_size);
+}
+
+void UpdateEngineClientImpl::RegisterStatusUpdateHandler(
+ StatusUpdateHandler* handler) {
+ proxy_->RegisterStatusUpdateSignalHandler(
+ base::Bind(&UpdateEngineClientImpl::RunStatusUpdateHandler,
+ base::Unretained(this), base::Unretained(handler)),
+ base::Bind(&UpdateEngineClientImpl::StatusUpdateHandlerRegistered,
+ base::Unretained(this), base::Unretained(handler)));
+}
+
bool UpdateEngineClientImpl::SetTargetChannel(const string& in_target_channel,
bool allow_powerwash) {
- return proxy_->SetChannel(
- in_target_channel,
- allow_powerwash,
- nullptr);
+ return proxy_->SetChannel(in_target_channel, allow_powerwash, nullptr);
}
bool UpdateEngineClientImpl::GetTargetChannel(string* out_channel) {
- return proxy_->GetChannel(
- false, // Get the target channel.
- out_channel,
- nullptr);
+ return proxy_->GetChannel(false, // Get the target channel.
+ out_channel, nullptr);
}
bool UpdateEngineClientImpl::GetChannel(string* out_channel) {
- return proxy_->GetChannel(
- true, // Get the current channel.
- out_channel,
- nullptr);
+ return proxy_->GetChannel(true, // Get the current channel.
+ out_channel, nullptr);
}
} // namespace internal
diff --git a/client_library/client_impl.h b/client_library/client_impl.h
index 4886692..03c8f3c 100644
--- a/client_library/client_impl.h
+++ b/client_library/client_impl.h
@@ -67,9 +67,23 @@
bool GetChannel(std::string* out_channel) override;
+ void RegisterStatusUpdateHandler(StatusUpdateHandler* handler) override;
+
private:
std::unique_ptr<org::chromium::UpdateEngineInterfaceProxy> proxy_;
+ void StatusUpdateHandlerRegistered(StatusUpdateHandler* handler,
+ const std::string& interface,
+ const std::string& signal_name,
+ bool success);
+
+ void RunStatusUpdateHandler(StatusUpdateHandler* handler,
+ int64_t last_checked_time,
+ double progress,
+ const std::string& current_operation,
+ const std::string& new_version,
+ int64_t new_size);
+
DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientImpl);
}; // class UpdateEngineClientImpl
diff --git a/client_library/include/update_engine/client.h b/client_library/include/update_engine/client.h
index 604cc5a..4d264c8 100644
--- a/client_library/include/update_engine/client.h
+++ b/client_library/include/update_engine/client.h
@@ -21,6 +21,7 @@
#include <memory>
#include <string>
+#include "update_engine/status_update_handler.h"
#include "update_engine/update_status.h"
namespace update_engine {
@@ -100,6 +101,13 @@
// Get the channel the device is currently on.
virtual bool GetChannel(std::string* out_channel) = 0;
+ // Handle status updates. The handler must exist until the client is
+ // destroyed. Its IPCError method will be called if the handler could
+ // not be registered. Otherwise its HandleStatusUpdate method will be called
+ // every time update_engine's status changes. Will always report the status
+ // on registration to prevent race conditions.
+ virtual void RegisterStatusUpdateHandler(StatusUpdateHandler* handler) = 0;
+
protected:
// Use CreateInstance().
UpdateEngineClient() = default;
diff --git a/client_library/include/update_engine/status_update_handler.h b/client_library/include/update_engine/status_update_handler.h
new file mode 100644
index 0000000..d5b8cdb
--- /dev/null
+++ b/client_library/include/update_engine/status_update_handler.h
@@ -0,0 +1,47 @@
+//
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_CLIENT_LIBRARY_INCLUDE_STATUS_UPDATE_HANDLER_H_
+#define UPDATE_ENGINE_CLIENT_LIBRARY_INCLUDE_STATUS_UPDATE_HANDLER_H_
+
+#include <string>
+
+#include "update_engine/client.h"
+#include "update_engine/update_status.h"
+
+namespace update_engine {
+
+// Handles update_engine status changes. An instance of this class can be
+// registered with UpdateEngineClient and will respond to any update_engine
+// status changes.
+class StatusUpdateHandler {
+ public:
+ virtual ~StatusUpdateHandler() = default;
+
+ // Runs when we fail to register the handler due to an IPC error.
+ virtual void IPCError(const std::string& error) = 0;
+
+ // Runs every time update_engine reports a status change.
+ virtual void HandleStatusUpdate(int64_t last_checked_time,
+ double progress,
+ UpdateStatus current_operation,
+ const std::string& new_version,
+ int64_t new_size) = 0;
+};
+
+} // namespace update_engine
+
+#endif // UPDATE_ENGINE_CLIENT_LIBRARY_INCLUDE_STATUS_UPDATE_HANDLER_H_