1 //
2 // Copyright (C) 2020 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/aosp/binder_service_stable_android.h"
18 
19 #include <memory>
20 
21 #include <base/bind.h>
22 #include <base/logging.h>
23 #include <binderwrapper/binder_wrapper.h>
24 #include <brillo/errors/error.h>
25 #include <utils/String8.h>
26 
27 #include "update_engine/aosp/binder_service_android_common.h"
28 
29 using android::binder::Status;
30 using android::os::IUpdateEngineStableCallback;
31 using android::os::ParcelFileDescriptor;
32 using std::string;
33 using std::vector;
34 using update_engine::UpdateEngineStatus;
35 
36 namespace chromeos_update_engine {
37 
BinderUpdateEngineAndroidStableService(ServiceDelegateAndroidInterface * service_delegate)38 BinderUpdateEngineAndroidStableService::BinderUpdateEngineAndroidStableService(
39     ServiceDelegateAndroidInterface* service_delegate)
40     : service_delegate_(service_delegate) {}
41 
SendStatusUpdate(const UpdateEngineStatus & update_engine_status)42 void BinderUpdateEngineAndroidStableService::SendStatusUpdate(
43     const UpdateEngineStatus& update_engine_status) {
44   last_status_ = static_cast<int>(update_engine_status.status);
45   last_progress_ = update_engine_status.progress;
46   if (callback_) {
47     callback_->onStatusUpdate(last_status_, last_progress_);
48   }
49 }
50 
SendPayloadApplicationComplete(ErrorCode error_code)51 void BinderUpdateEngineAndroidStableService::SendPayloadApplicationComplete(
52     ErrorCode error_code) {
53   if (callback_) {
54     callback_->onPayloadApplicationComplete(static_cast<int>(error_code));
55   }
56 }
57 
bind(const android::sp<IUpdateEngineStableCallback> & callback,bool * return_value)58 Status BinderUpdateEngineAndroidStableService::bind(
59     const android::sp<IUpdateEngineStableCallback>& callback,
60     bool* return_value) {
61   // Reject binding if another callback is already bound.
62   if (callback_ != nullptr) {
63     LOG(ERROR) << "Another callback is already bound. Can't bind new callback.";
64     *return_value = false;
65     return Status::ok();
66   }
67 
68   // See BinderUpdateEngineAndroidService::bind.
69   if (last_status_ != -1) {
70     auto status = callback->onStatusUpdate(last_status_, last_progress_);
71     if (!status.isOk()) {
72       LOG(ERROR) << "Failed to call onStatusUpdate() from callback: "
73                  << status.toString8();
74       *return_value = false;
75       return Status::ok();
76     }
77   }
78 
79   callback_ = callback;
80 
81   const android::sp<IBinder>& callback_binder =
82       IUpdateEngineStableCallback::asBinder(callback);
83   auto binder_wrapper = android::BinderWrapper::Get();
84   binder_wrapper->RegisterForDeathNotifications(
85       callback_binder,
86       base::Bind(base::IgnoreResult(
87                      &BinderUpdateEngineAndroidStableService::UnbindCallback),
88                  base::Unretained(this),
89                  base::Unretained(callback_binder.get())));
90 
91   *return_value = true;
92   return Status::ok();
93 }
94 
unbind(const android::sp<IUpdateEngineStableCallback> & callback,bool * return_value)95 Status BinderUpdateEngineAndroidStableService::unbind(
96     const android::sp<IUpdateEngineStableCallback>& callback,
97     bool* return_value) {
98   const android::sp<IBinder>& callback_binder =
99       IUpdateEngineStableCallback::asBinder(callback);
100   auto binder_wrapper = android::BinderWrapper::Get();
101   binder_wrapper->UnregisterForDeathNotifications(callback_binder);
102 
103   *return_value = UnbindCallback(callback_binder.get());
104   return Status::ok();
105 }
106 
applyPayloadFd(const ParcelFileDescriptor & pfd,int64_t payload_offset,int64_t payload_size,const vector<android::String16> & header_kv_pairs)107 Status BinderUpdateEngineAndroidStableService::applyPayloadFd(
108     const ParcelFileDescriptor& pfd,
109     int64_t payload_offset,
110     int64_t payload_size,
111     const vector<android::String16>& header_kv_pairs) {
112   vector<string> str_headers = ToVecString(header_kv_pairs);
113 
114   brillo::ErrorPtr error;
115   if (!service_delegate_->ApplyPayload(
116           pfd.get(), payload_offset, payload_size, str_headers, &error)) {
117     return ErrorPtrToStatus(error);
118   }
119   return Status::ok();
120 }
121 
UnbindCallback(const IBinder * callback)122 bool BinderUpdateEngineAndroidStableService::UnbindCallback(
123     const IBinder* callback) {
124   if (IUpdateEngineStableCallback::asBinder(callback_).get() != callback) {
125     LOG(ERROR) << "Unable to unbind unknown callback.";
126     return false;
127   }
128   callback_ = nullptr;
129   return true;
130 }
131 
132 }  // namespace chromeos_update_engine
133