Add binder_service_stable_android am: 2562cf2960 am: 29b8115b51

Original change: https://android-review.googlesource.com/c/platform/system/update_engine/+/1371070

Change-Id: Ib82492ea3446fe92b8294f0df9b4feafa6bc4b6f
diff --git a/Android.bp b/Android.bp
index 4e3e248..b8cff0a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -272,6 +272,7 @@
         "libbrillo-binder",
         "libcurl",
         "libcutils",
+        "libupdate_engine_stable-cpp",
         "liblog",
         "libssl",
         "libstatslog",
@@ -298,6 +299,7 @@
     srcs: [
         ":libupdate_engine_aidl",
         "binder_service_android.cc",
+        "binder_service_stable_android.cc",
         "certificate_checker.cc",
         "daemon_android.cc",
         "daemon_state_android.cc",
diff --git a/binder_service_android.cc b/binder_service_android.cc
index 6b8a552..0c8bc2f 100644
--- a/binder_service_android.cc
+++ b/binder_service_android.cc
@@ -24,6 +24,8 @@
 #include <brillo/errors/error.h>
 #include <utils/String8.h>
 
+#include "update_engine/binder_service_android_common.h"
+
 using android::binder::Status;
 using android::os::IUpdateEngineCallback;
 using android::os::ParcelFileDescriptor;
@@ -31,23 +33,6 @@
 using std::vector;
 using update_engine::UpdateEngineStatus;
 
-namespace {
-Status ErrorPtrToStatus(const brillo::ErrorPtr& error) {
-  return Status::fromServiceSpecificError(
-      1, android::String8{error->GetMessage().c_str()});
-}
-
-vector<string> ToVecString(const vector<android::String16>& inp) {
-  vector<string> out;
-  out.reserve(inp.size());
-  for (const auto& e : inp) {
-    out.emplace_back(android::String8{e}.string());
-  }
-  return out;
-}
-
-}  // namespace
-
 namespace chromeos_update_engine {
 
 BinderUpdateEngineAndroidService::BinderUpdateEngineAndroidService(
diff --git a/binder_service_android_common.h b/binder_service_android_common.h
new file mode 100644
index 0000000..fc621d9
--- /dev/null
+++ b/binder_service_android_common.h
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2020 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_BINDER_SERVICE_ANDROID_COMMON_H_
+#define UPDATE_ENGINE_BINDER_SERVICE_ANDROID_COMMON_H_
+
+#include <string>
+#include <vector>
+
+#include <binder/Status.h>
+
+namespace chromeos_update_engine {
+
+static inline android::binder::Status ErrorPtrToStatus(
+    const brillo::ErrorPtr& error) {
+  return android::binder::Status::fromServiceSpecificError(
+      1, android::String8{error->GetMessage().c_str()});
+}
+
+static inline std::vector<std::string> ToVecString(
+    const std::vector<android::String16>& inp) {
+  std::vector<std::string> out;
+  out.reserve(inp.size());
+  for (const auto& e : inp) {
+    out.emplace_back(android::String8{e}.string());
+  }
+  return out;
+}
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_BINDER_SERVICE_ANDROID_COMMON_H_
diff --git a/binder_service_stable_android.cc b/binder_service_stable_android.cc
new file mode 100644
index 0000000..a12b349
--- /dev/null
+++ b/binder_service_stable_android.cc
@@ -0,0 +1,132 @@
+//
+// Copyright (C) 2020 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.
+//
+
+#include "update_engine/binder_service_stable_android.h"
+
+#include <memory>
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <binderwrapper/binder_wrapper.h>
+#include <brillo/errors/error.h>
+#include <utils/String8.h>
+
+#include "update_engine/binder_service_android_common.h"
+
+using android::binder::Status;
+using android::os::IUpdateEngineStableCallback;
+using android::os::ParcelFileDescriptor;
+using std::string;
+using std::vector;
+using update_engine::UpdateEngineStatus;
+
+namespace chromeos_update_engine {
+
+BinderUpdateEngineAndroidStableService::BinderUpdateEngineAndroidStableService(
+    ServiceDelegateAndroidInterface* service_delegate)
+    : service_delegate_(service_delegate) {}
+
+void BinderUpdateEngineAndroidStableService::SendStatusUpdate(
+    const UpdateEngineStatus& update_engine_status) {
+  last_status_ = static_cast<int>(update_engine_status.status);
+  last_progress_ = update_engine_status.progress;
+  if (callback_) {
+    callback_->onStatusUpdate(last_status_, last_progress_);
+  }
+}
+
+void BinderUpdateEngineAndroidStableService::SendPayloadApplicationComplete(
+    ErrorCode error_code) {
+  if (callback_) {
+    callback_->onPayloadApplicationComplete(static_cast<int>(error_code));
+  }
+}
+
+Status BinderUpdateEngineAndroidStableService::bind(
+    const android::sp<IUpdateEngineStableCallback>& callback,
+    bool* return_value) {
+  // Reject binding if another callback is already bound.
+  if (callback_ != nullptr) {
+    LOG(ERROR) << "Another callback is already bound. Can't bind new callback.";
+    *return_value = false;
+    return Status::ok();
+  }
+
+  // See BinderUpdateEngineAndroidService::bind.
+  if (last_status_ != -1) {
+    auto status = callback->onStatusUpdate(last_status_, last_progress_);
+    if (!status.isOk()) {
+      LOG(ERROR) << "Failed to call onStatusUpdate() from callback: "
+                 << status.toString8();
+      *return_value = false;
+      return Status::ok();
+    }
+  }
+
+  callback_ = callback;
+
+  const android::sp<IBinder>& callback_binder =
+      IUpdateEngineStableCallback::asBinder(callback);
+  auto binder_wrapper = android::BinderWrapper::Get();
+  binder_wrapper->RegisterForDeathNotifications(
+      callback_binder,
+      base::Bind(base::IgnoreResult(
+                     &BinderUpdateEngineAndroidStableService::UnbindCallback),
+                 base::Unretained(this),
+                 base::Unretained(callback_binder.get())));
+
+  *return_value = true;
+  return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidStableService::unbind(
+    const android::sp<IUpdateEngineStableCallback>& callback,
+    bool* return_value) {
+  const android::sp<IBinder>& callback_binder =
+      IUpdateEngineStableCallback::asBinder(callback);
+  auto binder_wrapper = android::BinderWrapper::Get();
+  binder_wrapper->UnregisterForDeathNotifications(callback_binder);
+
+  *return_value = UnbindCallback(callback_binder.get());
+  return Status::ok();
+}
+
+Status BinderUpdateEngineAndroidStableService::applyPayloadFd(
+    const ParcelFileDescriptor& pfd,
+    int64_t payload_offset,
+    int64_t payload_size,
+    const vector<android::String16>& header_kv_pairs) {
+  vector<string> str_headers = ToVecString(header_kv_pairs);
+
+  brillo::ErrorPtr error;
+  if (!service_delegate_->ApplyPayload(
+          pfd.get(), payload_offset, payload_size, str_headers, &error)) {
+    return ErrorPtrToStatus(error);
+  }
+  return Status::ok();
+}
+
+bool BinderUpdateEngineAndroidStableService::UnbindCallback(
+    const IBinder* callback) {
+  if (IUpdateEngineStableCallback::asBinder(callback_).get() != callback) {
+    LOG(ERROR) << "Unable to unbind unknown callback.";
+    return false;
+  }
+  callback_ = nullptr;
+  return true;
+}
+
+}  // namespace chromeos_update_engine
diff --git a/binder_service_stable_android.h b/binder_service_stable_android.h
new file mode 100644
index 0000000..1667798
--- /dev/null
+++ b/binder_service_stable_android.h
@@ -0,0 +1,85 @@
+//
+// Copyright (C) 2020 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_BINDER_SERVICE_STABLE_ANDROID_H_
+#define UPDATE_ENGINE_BINDER_SERVICE_STABLE_ANDROID_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+#include "android/os/BnUpdateEngineStable.h"
+#include "android/os/IUpdateEngineStableCallback.h"
+#include "update_engine/service_delegate_android_interface.h"
+#include "update_engine/service_observer_interface.h"
+
+namespace chromeos_update_engine {
+
+class BinderUpdateEngineAndroidStableService
+    : public android::os::BnUpdateEngineStable,
+      public ServiceObserverInterface {
+ public:
+  explicit BinderUpdateEngineAndroidStableService(
+      ServiceDelegateAndroidInterface* service_delegate);
+  ~BinderUpdateEngineAndroidStableService() override = default;
+
+  const char* ServiceName() const {
+    return "android.os.UpdateEngineStableService";
+  }
+
+  // ServiceObserverInterface overrides.
+  void SendStatusUpdate(
+      const update_engine::UpdateEngineStatus& update_engine_status) override;
+  void SendPayloadApplicationComplete(ErrorCode error_code) override;
+
+  // android::os::BnUpdateEngineStable overrides.
+  android::binder::Status applyPayloadFd(
+      const ::android::os::ParcelFileDescriptor& pfd,
+      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::IUpdateEngineStableCallback>& callback,
+      bool* return_value) override;
+  android::binder::Status unbind(
+      const android::sp<android::os::IUpdateEngineStableCallback>& callback,
+      bool* return_value) override;
+
+ private:
+  // Remove the passed |callback| from the list of registered callbacks. Called
+  // on unbind() or whenever the callback object is destroyed.
+  // Returns true on success.
+  bool UnbindCallback(const IBinder* callback);
+
+  // Bound callback. The stable interface only supports one callback at a time.
+  android::sp<android::os::IUpdateEngineStableCallback> callback_;
+
+  // Cached copy of the last status update sent. Used to send an initial
+  // notification when bind() is called from the client.
+  int last_status_{-1};
+  double last_progress_{0.0};
+
+  ServiceDelegateAndroidInterface* service_delegate_;
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // UPDATE_ENGINE_BINDER_SERVICE_STABLE_ANDROID_H_
diff --git a/daemon_android.cc b/daemon_android.cc
index 1aa921f..313d7dd 100644
--- a/daemon_android.cc
+++ b/daemon_android.cc
@@ -47,16 +47,26 @@
   LOG_IF(ERROR, !daemon_state_android->Initialize())
       << "Failed to initialize system state.";
 
+  auto binder_wrapper = android::BinderWrapper::Get();
+
   // Create the Binder Service.
   binder_service_ = new BinderUpdateEngineAndroidService{
       daemon_state_android->service_delegate()};
-  auto binder_wrapper = android::BinderWrapper::Get();
   if (!binder_wrapper->RegisterService(binder_service_->ServiceName(),
                                        binder_service_)) {
     LOG(ERROR) << "Failed to register binder service.";
   }
-
   daemon_state_->AddObserver(binder_service_.get());
+
+  // Create the stable binder service.
+  stable_binder_service_ = new BinderUpdateEngineAndroidStableService{
+      daemon_state_android->service_delegate()};
+  if (!binder_wrapper->RegisterService(stable_binder_service_->ServiceName(),
+                                       stable_binder_service_)) {
+    LOG(ERROR) << "Failed to register stable binder service.";
+  }
+  daemon_state_->AddObserver(stable_binder_service_.get());
+
   daemon_state_->StartUpdater();
   return EX_OK;
 }
diff --git a/daemon_android.h b/daemon_android.h
index baead37..f0c028e 100644
--- a/daemon_android.h
+++ b/daemon_android.h
@@ -22,6 +22,7 @@
 #include <brillo/binder_watcher.h>
 
 #include "update_engine/binder_service_android.h"
+#include "update_engine/binder_service_stable_android.h"
 #include "update_engine/common/subprocess.h"
 #include "update_engine/daemon_base.h"
 #include "update_engine/daemon_state_interface.h"
@@ -43,6 +44,7 @@
 
   brillo::BinderWatcher binder_watcher_;
   android::sp<BinderUpdateEngineAndroidService> binder_service_;
+  android::sp<BinderUpdateEngineAndroidStableService> stable_binder_service_;
 
   // The daemon state with all the required daemon classes for the configured
   // platform.