1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <ipc_skeleton.h>
17 #include <iservice_registry.h>
18 #include <string_ex.h>
19 #include <unistd.h>
20
21 #include "hdf_log.h"
22 #include "hdf_object_manager.h"
23 #include "hdf_sbuf_ipc.h"
24 #include "hdf_remote_adapter.h"
25
26 #define HDF_LOG_TAG hdf_remote_adapter
27
28 static constexpr int32_t THREAD_POOL_BASE_THREAD_COUNT = 5;
29 static int32_t g_remoteThreadMax = THREAD_POOL_BASE_THREAD_COUNT;
30
HdfRemoteServiceStub(struct HdfRemoteService * service)31 HdfRemoteServiceStub::HdfRemoteServiceStub(struct HdfRemoteService *service)
32 : IPCObjectStub(std::u16string(u"")), service_(service)
33 {
34 }
35
OnRemoteRequest(uint32_t code,OHOS::MessageParcel & data,OHOS::MessageParcel & reply,OHOS::MessageOption & option)36 int HdfRemoteServiceStub::OnRemoteRequest(uint32_t code,
37 OHOS::MessageParcel &data, OHOS::MessageParcel &reply, OHOS::MessageOption &option)
38 {
39 (void)option;
40 if (service_ == nullptr) {
41 return HDF_ERR_INVALID_OBJECT;
42 }
43
44 int ret = HDF_FAILURE;
45 struct HdfSBuf *dataSbuf = ParcelToSbuf(&data);
46 struct HdfSBuf *replySbuf = ParcelToSbuf(&reply);
47
48 struct HdfRemoteDispatcher *dispatcher = service_->dispatcher;
49 if (dispatcher != nullptr && dispatcher->Dispatch != nullptr) {
50 ret = dispatcher->Dispatch(reinterpret_cast<HdfRemoteService *>(service_->target), code, dataSbuf, replySbuf);
51 } else {
52 HDF_LOGE("dispatcher or dispatcher->Dispatch is null, flags is: %{public}d", option.GetFlags());
53 }
54
55 HdfSbufRecycle(dataSbuf);
56 HdfSbufRecycle(replySbuf);
57 return ret;
58 }
59
~HdfRemoteServiceStub()60 HdfRemoteServiceStub::~HdfRemoteServiceStub()
61 {
62 }
63
HdfDeathNotifier(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)64 HdfDeathNotifier::HdfDeathNotifier(struct HdfRemoteService *service, struct HdfDeathRecipient *recipient)
65 : recipient_(recipient), service_(service)
66 {
67 }
68
~HdfDeathNotifier()69 HdfDeathNotifier::~HdfDeathNotifier()
70 {
71 }
72
OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> &)73 void HdfDeathNotifier::OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> &) /* who = 0 */
74 {
75 if (recipient_ != nullptr) {
76 recipient_->OnRemoteDied(recipient_, service_);
77 }
78 }
79
HdfRemoteAdapterOptionalDispatch(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply,bool sync)80 static int HdfRemoteAdapterOptionalDispatch(struct HdfRemoteService *service, int code,
81 HdfSBuf *data, HdfSBuf *reply, bool sync)
82 {
83 if (service == nullptr) {
84 return HDF_ERR_INVALID_PARAM;
85 }
86
87 OHOS::MessageParcel *dataParcel = nullptr;
88 OHOS::MessageParcel *replyParcel = nullptr;
89
90 if (reply == nullptr) {
91 static OHOS::MessageParcel dummyReply;
92 dummyReply.FlushBuffer();
93 replyParcel = &dummyReply;
94 } else if (SbufToParcel(reply, &replyParcel)) {
95 HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
96 return HDF_ERR_INVALID_PARAM;
97 }
98
99 if (SbufToParcel(data, &dataParcel)) {
100 HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
101 return HDF_ERR_INVALID_PARAM;
102 }
103 int flag = sync ? OHOS::MessageOption::TF_SYNC : OHOS::MessageOption::TF_ASYNC;
104 OHOS::MessageOption option(flag);
105 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
106 if (dataParcel != nullptr) {
107 OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
108 if (remote != nullptr) {
109 return remote->SendRequest(code, *dataParcel, *replyParcel, option);
110 }
111 }
112 return HDF_FAILURE;
113 }
114
HdfRemoteAdapterDispatch(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply)115 static int HdfRemoteAdapterDispatch(struct HdfRemoteService *service,
116 int code, HdfSBuf *data, HdfSBuf *reply)
117 {
118 return HdfRemoteAdapterOptionalDispatch(service, code, data, reply, true);
119 }
120
HdfRemoteAdapterDispatchAsync(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply)121 static int HdfRemoteAdapterDispatchAsync(struct HdfRemoteService *service,
122 int code, HdfSBuf *data, HdfSBuf *reply)
123 {
124 return HdfRemoteAdapterOptionalDispatch(service, code, data, reply, false);
125 }
126
HdfRemoteServiceHolder()127 HdfRemoteServiceHolder::HdfRemoteServiceHolder() : remote_(nullptr), deathRecipient_(nullptr)
128 {
129 service_.object_.objectId = HDF_OBJECT_ID_REMOTE_SERVICE;
130 service_.dispatcher = nullptr;
131 service_.target = nullptr;
132 service_.index = 0;
133 }
134
SetInterfaceDescriptor(const char * desc)135 bool HdfRemoteServiceHolder::SetInterfaceDescriptor(const char *desc)
136 {
137 if (desc == nullptr) {
138 return false;
139 }
140 std::u16string newDesc = OHOS::Str8ToStr16(std::string(desc));
141 if (newDesc.empty()) {
142 HDF_LOGE("failed to set interface des, error on cover str8 to str16, %{public}s", desc);
143 return false;
144 }
145
146 descriptor_.assign(newDesc);
147 return true;
148 }
149
HdfRemoteAdapterAddDeathRecipient(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)150 void HdfRemoteAdapterAddDeathRecipient(
151 struct HdfRemoteService *service, struct HdfDeathRecipient *recipient)
152 {
153 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
154 if (holder == nullptr) {
155 return;
156 }
157 OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
158 if (remote == nullptr) {
159 return;
160 }
161 if (holder->deathRecipient_ != nullptr) {
162 remote->RemoveDeathRecipient(holder->deathRecipient_);
163 }
164 holder->deathRecipient_ = new HdfDeathNotifier(service, recipient);
165 remote->AddDeathRecipient(holder->deathRecipient_);
166 }
167
HdfRemoteAdapterRemoveDeathRecipient(struct HdfRemoteService * service,const struct HdfDeathRecipient * recipient)168 void HdfRemoteAdapterRemoveDeathRecipient(
169 struct HdfRemoteService *service, const struct HdfDeathRecipient *recipient)
170 {
171 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
172 (void)recipient;
173 if (holder == nullptr) {
174 return;
175 }
176 OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
177 if (remote == nullptr) {
178 return;
179 }
180 if (holder->deathRecipient_ != nullptr) {
181 remote->RemoveDeathRecipient(holder->deathRecipient_);
182 holder->deathRecipient_ = nullptr;
183 }
184 }
185
HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)186 struct HdfRemoteService *HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)
187 {
188 struct HdfRemoteService *remoteService = nullptr;
189 static HdfRemoteDispatcher dispatcher = {
190 .Dispatch = HdfRemoteAdapterDispatch,
191 .DispatchAsync = HdfRemoteAdapterDispatchAsync,
192 };
193
194 struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
195 if (holder != nullptr) {
196 holder->remote_ = binder;
197 remoteService = &holder->service_;
198 remoteService->dispatcher = &dispatcher;
199 remoteService->index = (uint64_t)binder.GetRefPtr();
200 return remoteService;
201 }
202 return nullptr;
203 }
204
HdfRemoteAdapterObtain(void)205 struct HdfRemoteService *HdfRemoteAdapterObtain(void)
206 {
207 struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
208 holder->remote_ = new HdfRemoteServiceStub(&holder->service_);
209 return &holder->service_;
210 }
211
HdfRemoteAdapterRecycle(struct HdfRemoteService * object)212 void HdfRemoteAdapterRecycle(struct HdfRemoteService *object)
213 {
214 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(object);
215 if (holder != nullptr) {
216 holder->remote_ = nullptr;
217 delete holder;
218 }
219 }
220
HdfRemoteAdapterAddService(const char * name,struct HdfRemoteService * service)221 int HdfRemoteAdapterAddService(const char *name, struct HdfRemoteService *service)
222 {
223 if (name == nullptr || service == nullptr) {
224 return HDF_ERR_INVALID_PARAM;
225 }
226
227 OHOS::sptr<OHOS::IServiceRegistry> sr = OHOS::ServiceRegistry::GetInstance();
228 if (sr == nullptr) {
229 HDF_LOGE("failed to get service registry");
230 return HDF_FAILURE;
231 }
232 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
233 int ret = sr->AddService(OHOS::Str8ToStr16(name), holder->remote_);
234 if (ret == 0) {
235 (void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);
236 }
237 return ret;
238 }
239
HdfRemoteAdapterGetService(const char * name)240 struct HdfRemoteService *HdfRemoteAdapterGetService(const char *name)
241 {
242 if (name == nullptr) {
243 return nullptr;
244 }
245
246 OHOS::sptr<OHOS::IServiceRegistry> sr = OHOS::ServiceRegistry::GetInstance();
247 if (sr == nullptr) {
248 HDF_LOGE("failed to get service registry");
249 return nullptr;
250 }
251 OHOS::sptr<OHOS::IRemoteObject> remote = sr->GetService(OHOS::Str8ToStr16(name));
252 if (remote != nullptr) {
253 return HdfRemoteAdapterBind(remote);
254 }
255 return nullptr;
256 }
257
HdfRemoteAdapterAddSa(int32_t saId,struct HdfRemoteService * service)258 int HdfRemoteAdapterAddSa(int32_t saId, struct HdfRemoteService *service)
259 {
260 if (service == nullptr) {
261 return HDF_ERR_INVALID_PARAM;
262 }
263
264 auto saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
265 const int32_t waitTimes = 50;
266 const int32_t sleepInterval = 20000;
267 int32_t timeout = waitTimes;
268 while (saManager == nullptr && (timeout > 0)) {
269 HDF_LOGI("waiting for samgr...");
270 usleep(sleepInterval);
271 saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
272 timeout--;
273 }
274
275 if (saManager == nullptr) {
276 HDF_LOGE("failed to get sa manager, waiting timeot");
277 return HDF_FAILURE;
278 }
279 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
280 int ret = saManager->AddSystemAbility(saId, holder->remote_);
281 (void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);
282 HDF_LOGI("add sa %{public}d, ret = %{public}s", saId, (ret == 0) ? "succ" : "fail");
283
284 return HDF_SUCCESS;
285 }
286
HdfRemoteAdapterGetSa(int32_t saId)287 struct HdfRemoteService *HdfRemoteAdapterGetSa(int32_t saId)
288 {
289 auto saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
290 if (saManager == nullptr) {
291 HDF_LOGE("failed to get sa manager");
292 return nullptr;
293 }
294 OHOS::sptr<OHOS::IRemoteObject> remote = saManager->GetSystemAbility(saId);
295 constexpr int32_t waitTimes = 50;
296 constexpr int32_t sleepInterval = 20000;
297 int32_t timeout = waitTimes;
298 while (remote == nullptr && (timeout > 0)) {
299 HDF_LOGD("waiting for saId %{public}d", saId);
300 usleep(sleepInterval);
301 remote = saManager->GetSystemAbility(saId);
302 timeout--;
303 }
304 if (remote != nullptr) {
305 return HdfRemoteAdapterBind(remote);
306 } else {
307 HDF_LOGE("failed to get sa %{public}d", saId);
308 }
309 return nullptr;
310 }
311
HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService * service,const char * desc)312 bool HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService *service, const char *desc)
313 {
314 if (service == nullptr || desc == nullptr) {
315 return false;
316 }
317 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
318 return holder->SetInterfaceDescriptor(desc);
319 }
320
HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)321 bool HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
322 {
323 if (service == nullptr || data == nullptr) {
324 return false;
325 }
326 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
327 OHOS::MessageParcel *parcel = nullptr;
328
329 if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
330 HDF_LOGE("failed to write interface token, SbufToParcel error");
331 return false;
332 }
333
334 if (holder->remote_ == nullptr) {
335 HDF_LOGE("failed to write interface token, holder->remote is nullptr");
336 return false;
337 }
338 if (holder->descriptor_.empty()) {
339 HDF_LOGE("failed to write interface token, empty token");
340 return false;
341 }
342 return parcel->WriteInterfaceToken(holder->descriptor_);
343 }
344
HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)345 bool HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
346 {
347 if (service == nullptr || data == nullptr) {
348 return false;
349 }
350 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
351 if (holder->remote_ == nullptr) {
352 return false;
353 }
354 OHOS::MessageParcel *parcel = nullptr;
355
356 if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
357 return false;
358 }
359 auto desc = parcel->ReadInterfaceToken();
360 if (desc.empty()) {
361 HDF_LOGE("failed to check interface, empty token");
362 return false;
363 }
364 if (holder->descriptor_ != desc) {
365 HDF_LOGE("calling unknown interface: %{public}s", OHOS::Str16ToStr8(desc).c_str());
366 return false;
367 }
368
369 return true;
370 }
371
HdfRemoteGetCallingPid(void)372 pid_t HdfRemoteGetCallingPid(void)
373 {
374 return OHOS::IPCSkeleton::GetCallingPid();
375 }
376
HdfRemoteGetCallingUid(void)377 pid_t HdfRemoteGetCallingUid(void)
378 {
379 return OHOS::IPCSkeleton::GetCallingUid();
380 }
381
HdfRemoteAdapterDefaultDispatch(struct HdfRemoteService * service,int code,struct HdfSBuf * data,struct HdfSBuf * reply)382 int HdfRemoteAdapterDefaultDispatch(struct HdfRemoteService *service,
383 int code, struct HdfSBuf *data, struct HdfSBuf *reply)
384 {
385 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
386 if (holder == nullptr) {
387 HDF_LOGE("%{public}s: failed to converts remote to holder", __func__);
388 return HDF_ERR_INVALID_PARAM;
389 }
390
391 if (holder->remote_ == nullptr) {
392 HDF_LOGE("%{public}s: invaild holder, holder->remote is nullptr", __func__);
393 return HDF_ERR_INVALID_PARAM;
394 }
395
396 OHOS::IPCObjectStub *stub = reinterpret_cast<OHOS::IPCObjectStub *>(holder->remote_.GetRefPtr());
397 if (stub == nullptr) {
398 HDF_LOGE("%{public}s: failed to converts holder->remote to IPCObjectStub object", __func__);
399 return HDF_ERR_INVALID_PARAM;
400 }
401
402 OHOS::MessageParcel *dataParcel = nullptr;
403 OHOS::MessageParcel *replyParcel = nullptr;
404 OHOS::MessageOption option;
405
406 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
407 HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
408 return HDF_ERR_INVALID_PARAM;
409 }
410
411 if (SbufToParcel(data, &replyParcel) != HDF_SUCCESS) {
412 HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
413 return HDF_ERR_INVALID_PARAM;
414 }
415
416 return stub->IPCObjectStub::OnRemoteRequest(code, *dataParcel, *replyParcel, option);
417 }