1 //
2 // Copyright (C) 2015 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/binder_service_brillo.h"
18 
19 #include <base/bind.h>
20 
21 #include <binderwrapper/binder_wrapper.h>
22 
23 #include <utils/String16.h>
24 #include <utils/StrongPointer.h>
25 
26 #include "update_engine/update_status_utils.h"
27 
28 using android::sp;
29 using android::String16;
30 using android::String8;
31 using android::binder::Status;
32 using android::brillo::IUpdateEngineStatusCallback;
33 using android::brillo::ParcelableUpdateEngineStatus;
34 using brillo::ErrorPtr;
35 using std::string;
36 using update_engine::UpdateEngineStatus;
37 
38 namespace chromeos_update_engine {
39 
40 namespace {
41 string NormalString(const String16& in) {
42   return string{String8{in}.string()};
43 }
44 
45 Status ToStatus(ErrorPtr* error) {
46   return Status::fromServiceSpecificError(
47       1, String8{error->get()->GetMessage().c_str()});
48 }
49 }  // namespace
50 
51 template <typename... Parameters, typename... Arguments>
52 Status BinderUpdateEngineBrilloService::CallCommonHandler(
53     bool (UpdateEngineService::*Handler)(ErrorPtr*, Parameters...),
54     Arguments... arguments) {
55   ErrorPtr error;
56   if (((common_.get())->*Handler)(&error, arguments...))
57     return Status::ok();
58   return ToStatus(&error);
59 }
60 
61 Status BinderUpdateEngineBrilloService::SetUpdateAttemptFlags(int flags) {
62   return CallCommonHandler(&UpdateEngineService::SetUpdateAttemptFlags, flags);
63 }
64 
65 Status BinderUpdateEngineBrilloService::AttemptUpdate(
66     const String16& app_version,
67     const String16& omaha_url,
68     int flags,
69     bool* out_result) {
70   return CallCommonHandler(&UpdateEngineService::AttemptUpdate,
71                            NormalString(app_version),
72                            NormalString(omaha_url),
73                            flags,
74                            out_result);
75 }
76 
77 Status BinderUpdateEngineBrilloService::AttemptRollback(bool powerwash) {
78   return CallCommonHandler(&UpdateEngineService::AttemptRollback, powerwash);
79 }
80 
81 Status BinderUpdateEngineBrilloService::CanRollback(bool* out_can_rollback) {
82   return CallCommonHandler(&UpdateEngineService::CanRollback, out_can_rollback);
83 }
84 
85 Status BinderUpdateEngineBrilloService::ResetStatus() {
86   return CallCommonHandler(&UpdateEngineService::ResetStatus);
87 }
88 
89 Status BinderUpdateEngineBrilloService::GetStatus(
90     ParcelableUpdateEngineStatus* status) {
91   UpdateEngineStatus update_engine_status;
92   auto ret =
93       CallCommonHandler(&UpdateEngineService::GetStatus, &update_engine_status);
94 
95   if (ret.isOk()) {
96     *status = ParcelableUpdateEngineStatus(update_engine_status);
97   }
98 
99   return ret;
100 }
101 
102 Status BinderUpdateEngineBrilloService::RebootIfNeeded() {
103   return CallCommonHandler(&UpdateEngineService::RebootIfNeeded);
104 }
105 
106 Status BinderUpdateEngineBrilloService::SetChannel(
107     const String16& target_channel, bool powerwash) {
108   return CallCommonHandler(&UpdateEngineService::SetChannel,
109                            NormalString(target_channel),
110                            powerwash);
111 }
112 
113 Status BinderUpdateEngineBrilloService::GetChannel(bool get_current_channel,
114                                                    String16* out_channel) {
115   string channel_string;
116   auto ret = CallCommonHandler(
117       &UpdateEngineService::GetChannel, get_current_channel, &channel_string);
118 
119   *out_channel = String16(channel_string.c_str());
120   return ret;
121 }
122 
123 Status BinderUpdateEngineBrilloService::SetCohortHint(
124     const String16& in_cohort_hint) {
125   return CallCommonHandler(&UpdateEngineService::SetCohortHint,
126                            NormalString(in_cohort_hint));
127 }
128 
129 Status BinderUpdateEngineBrilloService::GetCohortHint(
130     String16* out_cohort_hint) {
131   string cohort_hint;
132   auto ret =
133       CallCommonHandler(&UpdateEngineService::GetCohortHint, &cohort_hint);
134 
135   *out_cohort_hint = String16(cohort_hint.c_str());
136   return ret;
137 }
138 
139 Status BinderUpdateEngineBrilloService::SetP2PUpdatePermission(bool enabled) {
140   return CallCommonHandler(&UpdateEngineService::SetP2PUpdatePermission,
141                            enabled);
142 }
143 
144 Status BinderUpdateEngineBrilloService::GetP2PUpdatePermission(
145     bool* out_p2p_permission) {
146   return CallCommonHandler(&UpdateEngineService::GetP2PUpdatePermission,
147                            out_p2p_permission);
148 }
149 
150 Status BinderUpdateEngineBrilloService::SetUpdateOverCellularPermission(
151     bool enabled) {
152   return CallCommonHandler(
153       &UpdateEngineService::SetUpdateOverCellularPermission, enabled);
154 }
155 
156 Status BinderUpdateEngineBrilloService::SetUpdateOverCellularTarget(
157     const String16& target_version, int64_t target_size) {
158   return CallCommonHandler(&UpdateEngineService::SetUpdateOverCellularTarget,
159                            NormalString(target_version),
160                            target_size);
161 }
162 
163 Status BinderUpdateEngineBrilloService::GetUpdateOverCellularPermission(
164     bool* out_cellular_permission) {
165   return CallCommonHandler(
166       &UpdateEngineService::GetUpdateOverCellularPermission,
167       out_cellular_permission);
168 }
169 
170 Status BinderUpdateEngineBrilloService::GetDurationSinceUpdate(
171     int64_t* out_duration) {
172   return CallCommonHandler(&UpdateEngineService::GetDurationSinceUpdate,
173                            out_duration);
174 }
175 
176 Status BinderUpdateEngineBrilloService::GetPrevVersion(
177     String16* out_prev_version) {
178   string version_string;
179   auto ret =
180       CallCommonHandler(&UpdateEngineService::GetPrevVersion, &version_string);
181 
182   *out_prev_version = String16(version_string.c_str());
183   return ret;
184 }
185 
186 Status BinderUpdateEngineBrilloService::GetRollbackPartition(
187     String16* out_rollback_partition) {
188   string partition_string;
189   auto ret = CallCommonHandler(&UpdateEngineService::GetRollbackPartition,
190                                &partition_string);
191 
192   if (ret.isOk()) {
193     *out_rollback_partition = String16(partition_string.c_str());
194   }
195 
196   return ret;
197 }
198 
199 Status BinderUpdateEngineBrilloService::RegisterStatusCallback(
200     const sp<IUpdateEngineStatusCallback>& callback) {
201   callbacks_.emplace_back(callback);
202 
203   auto binder_wrapper = android::BinderWrapper::Get();
204 
205   binder_wrapper->RegisterForDeathNotifications(
206       IUpdateEngineStatusCallback::asBinder(callback),
207       base::Bind(&BinderUpdateEngineBrilloService::UnregisterStatusCallback,
208                  base::Unretained(this),
209                  base::Unretained(callback.get())));
210 
211   return Status::ok();
212 }
213 
214 Status BinderUpdateEngineBrilloService::GetLastAttemptError(
215     int* out_last_attempt_error) {
216   return CallCommonHandler(&UpdateEngineService::GetLastAttemptError,
217                            out_last_attempt_error);
218 }
219 
220 Status BinderUpdateEngineBrilloService::GetEolStatus(int* out_eol_status) {
221   return CallCommonHandler(&UpdateEngineService::GetEolStatus, out_eol_status);
222 }
223 
224 void BinderUpdateEngineBrilloService::UnregisterStatusCallback(
225     IUpdateEngineStatusCallback* callback) {
226   auto it = callbacks_.begin();
227   while (it != callbacks_.end() && it->get() != callback)
228     it++;
229 
230   if (it == callbacks_.end()) {
231     LOG(ERROR) << "Got death notification for unknown callback.";
232     return;
233   }
234 
235   LOG(INFO) << "Erasing orphan callback";
236   callbacks_.erase(it);
237 }
238 
239 void BinderUpdateEngineBrilloService::SendStatusUpdate(
240     const UpdateEngineStatus& update_engine_status) {
241   ParcelableUpdateEngineStatus parcelable_status(update_engine_status);
242   for (auto& callback : callbacks_) {
243     callback->HandleStatusUpdate(parcelable_status);
244   }
245 }
246 
247 }  // namespace chromeos_update_engine
248