Android: Implement the binder service.
This patch introduces the service delegate interface for non-Brillo
targets, which is the class in charge of implementing the API exposed
by the service. The binder service for non-Brillo targets is now
completed using this interface.
The other side of this interface will be implemented in a follow up CL,
while this CL includes only the interface and its usage.
To accomodate non-Brillo targets, the generic ServiceObserverInterface
is extended with the PayloadApplicationComplete message, which will be
implemented for all targets in the future.
Bug: 25631949
TEST=`mmma system/update_engine` on aosp_arm-eng and edison-eng
Change-Id: I9fa8e9565ae92515e81e07d2cef562fc4e11a7ba
diff --git a/binder_service_android.cc b/binder_service_android.cc
index 98943a2..3c679da 100644
--- a/binder_service_android.cc
+++ b/binder_service_android.cc
@@ -16,53 +16,116 @@
#include "update_engine/binder_service_android.h"
-using android::String16;
+#include <base/bind.h>
+#include <base/logging.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <brillo/errors/error.h>
+#include <utils/String8.h>
+
using android::binder::Status;
using android::os::IUpdateEngineCallback;
-using android::sp;
-using std::vector;
+
+namespace {
+Status ErrorPtrToStatus(const brillo::ErrorPtr& error) {
+ return Status::fromServiceSpecificError(
+ 1, android::String8{error->GetMessage().c_str()});
+}
+} // namespace
namespace chromeos_update_engine {
BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
- DaemonStateAndroid* /* daemon_state */) {
- // TODO(deymo): Hook this interface calls to the daemon_state.
+ ServiceDelegateAndroidInterface* service_delegate)
+ : service_delegate_(service_delegate) {
}
void BinderUpdateEngineAndroidService::SendStatusUpdate(
- int64_t last_checked_time,
+ int64_t /* last_checked_time */,
double progress,
update_engine::UpdateStatus status,
- const std::string& new_version,
- int64_t new_size) {
- // TODO(deymo): Notify registered callers.
+ const std::string& /* new_version */,
+ int64_t /* new_size */) {
+ for (auto& callback : callbacks_) {
+ callback->onStatusUpdate(static_cast<int>(status), progress);
+ }
+}
+
+void BinderUpdateEngineAndroidService::SendPayloadApplicationComplete(
+ ErrorCode error_code) {
+ for (auto& callback : callbacks_) {
+ callback->onPayloadApplicationComplete(static_cast<int>(error_code));
+ }
}
Status BinderUpdateEngineAndroidService::bind(
- const sp<IUpdateEngineCallback>& callback,
- bool* return_value) {
+ const android::sp<IUpdateEngineCallback>& callback, bool* return_value) {
+ callbacks_.emplace_back(callback);
+
+ auto binder_wrapper = android::BinderWrapper::Get();
+ binder_wrapper->RegisterForDeathNotifications(
+ IUpdateEngineCallback::asBinder(callback),
+ base::Bind(&BinderUpdateEngineAndroidService::UnbindCallback,
+ base::Unretained(this),
+ base::Unretained(callback.get())));
+
*return_value = true;
return Status::ok();
}
Status BinderUpdateEngineAndroidService::applyPayload(
- const String16& url,
+ const android::String16& url,
int64_t payload_offset,
int64_t payload_size,
- const vector<String16>& header_kv_pairs) {
+ const std::vector<android::String16>& header_kv_pairs) {
+ const std::string payload_url{android::String8{url}.string()};
+ std::vector<std::string> str_headers;
+ str_headers.reserve(header_kv_pairs.size());
+ for (const auto& header : header_kv_pairs) {
+ str_headers.emplace_back(android::String8{header}.string());
+ }
+
+ brillo::ErrorPtr error;
+ if (!service_delegate_->ApplyPayload(
+ payload_url, payload_offset, payload_size, str_headers, &error)) {
+ return ErrorPtrToStatus(error);
+ }
return Status::ok();
}
Status BinderUpdateEngineAndroidService::suspend() {
+ brillo::ErrorPtr error;
+ if (!service_delegate_->SuspendUpdate(&error))
+ return ErrorPtrToStatus(error);
return Status::ok();
}
Status BinderUpdateEngineAndroidService::resume() {
+ brillo::ErrorPtr error;
+ if (!service_delegate_->ResumeUpdate(&error))
+ return ErrorPtrToStatus(error);
return Status::ok();
}
Status BinderUpdateEngineAndroidService::cancel() {
+ brillo::ErrorPtr error;
+ if (!service_delegate_->CancelUpdate(&error))
+ return ErrorPtrToStatus(error);
return Status::ok();
}
+void BinderUpdateEngineAndroidService::UnbindCallback(
+ IUpdateEngineCallback* callback) {
+ auto it =
+ std::find_if(callbacks_.begin(),
+ callbacks_.end(),
+ [&callback](const android::sp<IUpdateEngineCallback>& elem) {
+ return elem.get() == callback;
+ });
+ if (it == callbacks_.end()) {
+ LOG(ERROR) << "Got death notification for unknown callback.";
+ return;
+ }
+ callbacks_.erase(it);
+}
+
} // namespace chromeos_update_engine
diff --git a/binder_service_android.h b/binder_service_android.h
index 4ab19b3..3e256e0 100644
--- a/binder_service_android.h
+++ b/binder_service_android.h
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include <string>
#include <vector>
#include <utils/Errors.h>
@@ -27,7 +28,7 @@
#include "android/os/BnUpdateEngine.h"
#include "android/os/IUpdateEngineCallback.h"
-#include "update_engine/daemon_state_android.h"
+#include "update_engine/service_delegate_android_interface.h"
#include "update_engine/service_observer_interface.h"
namespace chromeos_update_engine {
@@ -35,7 +36,8 @@
class BinderUpdateEngineAndroidService : public android::os::BnUpdateEngine,
public ServiceObserverInterface {
public:
- BinderUpdateEngineAndroidService(DaemonStateAndroid* daemon_state);
+ BinderUpdateEngineAndroidService(
+ ServiceDelegateAndroidInterface* service_delegate);
~BinderUpdateEngineAndroidService() override = default;
const char* ServiceName() const {
@@ -48,6 +50,7 @@
update_engine::UpdateStatus status,
const std::string& new_version,
int64_t new_size) override;
+ void SendPayloadApplicationComplete(ErrorCode error_code) override;
// Channel tracking changes are ignored.
void SendChannelChangeUpdate(const std::string& tracking_channel) override {}
@@ -58,16 +61,22 @@
int64_t payload_offset,
int64_t payload_size,
const std::vector<android::String16>& header_kv_pairs) override;
-
android::binder::Status bind(
const android::sp<android::os::IUpdateEngineCallback>& callback,
bool* return_value) override;
-
android::binder::Status suspend() override;
-
android::binder::Status resume() override;
-
android::binder::Status cancel() override;
+
+ private:
+ // Remove the passed |callback| from the list of registered callbacks. Called
+ // whenever the callback object is destroyed.
+ void UnbindCallback(android::os::IUpdateEngineCallback* callback);
+
+ // List of currently bound callbacks.
+ std::vector<android::sp<android::os::IUpdateEngineCallback>> callbacks_;
+
+ ServiceDelegateAndroidInterface* service_delegate_;
};
} // namespace chromeos_update_engine
diff --git a/binder_service_brillo.h b/binder_service_brillo.h
index 99aa76b..178305b 100644
--- a/binder_service_brillo.h
+++ b/binder_service_brillo.h
@@ -19,6 +19,7 @@
#include <utils/Errors.h>
+#include <string>
#include <vector>
#include <utils/RefBase.h>
@@ -35,7 +36,7 @@
class BinderUpdateEngineBrilloService : public android::brillo::BnUpdateEngine,
public ServiceObserverInterface {
public:
- BinderUpdateEngineBrilloService(SystemState* system_state)
+ explicit BinderUpdateEngineBrilloService(SystemState* system_state)
: common_(new UpdateEngineService(system_state)) {}
virtual ~BinderUpdateEngineBrilloService() = default;
@@ -49,6 +50,7 @@
update_engine::UpdateStatus status,
const std::string& new_version,
int64_t new_size) override;
+ void SendPayloadApplicationComplete(ErrorCode error_code) override {}
// Channel tracking changes are ignored.
void SendChannelChangeUpdate(const std::string& tracking_channel) override {}
diff --git a/daemon.cc b/daemon.cc
index 27000d5..4c0c52f 100644
--- a/daemon.cc
+++ b/daemon.cc
@@ -90,7 +90,8 @@
#if defined(__BRILLO__) || defined(__CHROMEOS__)
binder_service_ = new BinderUpdateEngineBrilloService{real_system_state};
#else // !(defined(__BRILLO__) || defined(__CHROMEOS__))
- binder_service_ = new BinderUpdateEngineAndroidService{daemon_state_android};
+ binder_service_ = new BinderUpdateEngineAndroidService{
+ daemon_state_android->service_delegate()};
#endif // defined(__BRILLO__) || defined(__CHROMEOS__)
auto binder_wrapper = android::BinderWrapper::Get();
if (!binder_wrapper->RegisterService(binder_service_->ServiceName(),
diff --git a/daemon_state_android.cc b/daemon_state_android.cc
index 3e89ad0..c1d9fcc 100644
--- a/daemon_state_android.cc
+++ b/daemon_state_android.cc
@@ -35,4 +35,9 @@
service_observers_.erase(observer);
}
+ServiceDelegateAndroidInterface* DaemonStateAndroid::service_delegate() {
+ // TODO(deymo): Implement a service delegate and return it here.
+ return nullptr;
+}
+
} // namespace chromeos_update_engine
diff --git a/daemon_state_android.h b/daemon_state_android.h
index 2b8926c..e0fac00 100644
--- a/daemon_state_android.h
+++ b/daemon_state_android.h
@@ -20,6 +20,7 @@
#include <set>
#include "update_engine/daemon_state_interface.h"
+#include "update_engine/service_delegate_android_interface.h"
#include "update_engine/service_observer_interface.h"
namespace chromeos_update_engine {
@@ -27,6 +28,7 @@
class DaemonStateAndroid : public DaemonStateInterface {
public:
DaemonStateAndroid() = default;
+ ~DaemonStateAndroid() override = default;
bool Initialize();
@@ -35,6 +37,13 @@
void AddObserver(ServiceObserverInterface* observer) override;
void RemoveObserver(ServiceObserverInterface* observer) override;
+ const std::set<ServiceObserverInterface*>& service_observers() {
+ return service_observers_;
+ }
+
+ // Return a pointer to the service delegate.
+ ServiceDelegateAndroidInterface* service_delegate();
+
protected:
std::set<ServiceObserverInterface*> service_observers_;
};
diff --git a/dbus_service.h b/dbus_service.h
index fe250c8..b0c68e5 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -159,6 +159,8 @@
const std::string& new_version,
int64_t new_size) override;
+ void SendPayloadApplicationComplete(ErrorCode error_code) override {}
+
// Channel tracking changes are ignored.
void SendChannelChangeUpdate(const std::string& tracking_channel) override {}
diff --git a/service_delegate_android_interface.h b/service_delegate_android_interface.h
new file mode 100644
index 0000000..62e6540
--- /dev/null
+++ b/service_delegate_android_interface.h
@@ -0,0 +1,73 @@
+//
+// Copyright (C) 2016 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_SERVICE_DELEGATE_ANDROID_INTERFACE_H_
+#define UPDATE_ENGINE_SERVICE_DELEGATE_ANDROID_INTERFACE_H_
+
+#include <inttypes.h>
+
+#include <string>
+#include <vector>
+
+#include <brillo/errors/error.h>
+
+namespace chromeos_update_engine {
+
+// This class defines the interface exposed by the Android version of the
+// daemon service. This interface only includes the method calls that such
+// daemon exposes. For asynchronous events initiated by a class implementing
+// this interface see the ServiceObserverInterface class.
+class ServiceDelegateAndroidInterface {
+ public:
+ virtual ~ServiceDelegateAndroidInterface() = default;
+
+ // Start an update attempt to download an apply the provided |payload_url| if
+ // no other update is running. The extra |key_value_pair_headers| will be
+ // included when fetching the payload. Returns whether the update was started
+ // successfully, which means that no other update was running and the passed
+ // parameters were correct, but not necessarily that the update finished
+ // correctly.
+ virtual bool ApplyPayload(
+ const std::string& payload_url,
+ int64_t payload_offset,
+ int64_t payload_size,
+ const std::vector<std::string>& key_value_pair_headers,
+ brillo::ErrorPtr* error) = 0;
+
+ // Suspend an ongoing update. Returns true if there was an update ongoing and
+ // it was suspended. In case of failure, it returns false and sets |error|
+ // accordingly.
+ virtual bool SuspendUpdate(brillo::ErrorPtr* error) = 0;
+
+ // Resumes an update suspended with SuspendUpdate(). The update can't be
+ // suspended after it finished and this method will fail in that case.
+ // Returns whether the resume operation was successful, which only implies
+ // that there was a suspended update. In case of error, returns false and sets
+ // |error| accordingly.
+ virtual bool ResumeUpdate(brillo::ErrorPtr* error) = 0;
+
+ // Cancel the ongoing update. The update could be running or suspended, but it
+ // can't be canceled after it was done. In case of error, returns false and
+ // sets |error| accordingly.
+ virtual bool CancelUpdate(brillo::ErrorPtr* error) = 0;
+
+ protected:
+ ServiceDelegateAndroidInterface() = default;
+};
+
+} // namespace chromeos_update_engine
+
+#endif // UPDATE_ENGINE_SERVICE_DELEGATE_ANDROID_INTERFACE_H_
diff --git a/service_observer_interface.h b/service_observer_interface.h
index 73d8350..75a739f 100644
--- a/service_observer_interface.h
+++ b/service_observer_interface.h
@@ -21,6 +21,7 @@
#include <string>
#include "update_engine/client_library/include/update_engine/update_status.h"
+#include "update_engine/common/error_code.h"
namespace chromeos_update_engine {
@@ -36,6 +37,9 @@
const std::string& new_version,
int64_t new_size) = 0;
+ // Called whenever an update attempt is completed.
+ virtual void SendPayloadApplicationComplete(ErrorCode error_code) = 0;
+
// Called whenever the channel we are tracking changes.
virtual void SendChannelChangeUpdate(const std::string& tracking_channel) = 0;
diff --git a/weave_service.h b/weave_service.h
index b1068e7..5a3aff3 100644
--- a/weave_service.h
+++ b/weave_service.h
@@ -42,6 +42,7 @@
const std::string& new_version,
int64_t new_size) override;
void SendChannelChangeUpdate(const std::string& tracking_channel) override;
+ void SendPayloadApplicationComplete(ErrorCode error_code) override {}
private:
// Force a weave update.