1 /*
2 * Copyright (c) 2021-2023 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 <regex>
19 #include <string_ex.h>
20 #include <unistd.h>
21 #include <vector>
22
23 #include "hdf_dump.h"
24 #include "hdf_log.h"
25 #include "hdf_object_manager.h"
26 #include "hdf_sbuf_ipc.h"
27 #include "hdf_remote_adapter.h"
28 #include "hdf_xcollie.h"
29
30 #define HDF_LOG_TAG hdf_remote_adapter
31
32 static constexpr int32_t THREAD_POOL_BASE_THREAD_COUNT = 5;
33 static int32_t g_remoteThreadMax = THREAD_POOL_BASE_THREAD_COUNT;
34
HdfRemoteServiceStub(struct HdfRemoteService * service)35 HdfRemoteServiceStub::HdfRemoteServiceStub(struct HdfRemoteService *service)
36 : IPCObjectStub(std::u16string(u"")), service_(service)
37 {
38 }
39
OnRemoteRequest(uint32_t code,OHOS::MessageParcel & data,OHOS::MessageParcel & reply,OHOS::MessageOption & option)40 int HdfRemoteServiceStub::OnRemoteRequest(uint32_t code,
41 OHOS::MessageParcel &data, OHOS::MessageParcel &reply, OHOS::MessageOption &option)
42 {
43 HDF_LOGI("OnRemoteRequest enter");
44 (void)option;
45 if (service_ == nullptr) {
46 HDF_LOGE("service_ is nullptr");
47 return HDF_ERR_INVALID_OBJECT;
48 }
49
50 int ret = HDF_FAILURE;
51 struct HdfSBuf *dataSbuf = ParcelToSbuf(&data);
52 struct HdfSBuf *replySbuf = ParcelToSbuf(&reply);
53
54 struct HdfRemoteDispatcher *dispatcher = service_->dispatcher;
55 if (dispatcher != nullptr && dispatcher->Dispatch != nullptr) {
56 ret = dispatcher->Dispatch(reinterpret_cast<HdfRemoteService *>(service_->target), code, dataSbuf, replySbuf);
57 } else {
58 HDF_LOGE("dispatcher or dispatcher->Dispatch is null, flags is: %{public}d", option.GetFlags());
59 }
60
61 HdfSbufRecycle(dataSbuf);
62 HdfSbufRecycle(replySbuf);
63 return ret;
64 }
65
~HdfRemoteServiceStub()66 HdfRemoteServiceStub::~HdfRemoteServiceStub()
67 {
68 HDF_LOGI("~HdfRemoteServiceStub");
69 }
70
~HdfRemoteServiceHolder()71 HdfRemoteServiceHolder::~HdfRemoteServiceHolder()
72 {
73 HDF_LOGI("~HdfRemoteServiceHolder");
74 }
75
Dump(int32_t fd,const std::vector<std::u16string> & args)76 int32_t HdfRemoteServiceStub::Dump(int32_t fd, const std::vector<std::u16string> &args)
77 {
78 return HdfDump(fd, args);
79 }
80
HdfDeathNotifier(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)81 HdfDeathNotifier::HdfDeathNotifier(struct HdfRemoteService *service, struct HdfDeathRecipient *recipient)
82 : recipient_(recipient), service_(service)
83 {
84 }
85
~HdfDeathNotifier()86 HdfDeathNotifier::~HdfDeathNotifier()
87 {
88 }
89
OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> & object)90 void HdfDeathNotifier::OnRemoteDied(const OHOS::wptr<OHOS::IRemoteObject> &object) /* who = 0 */
91 {
92 if (recipient_ != nullptr) {
93 recipient_->OnRemoteDied(recipient_, service_);
94 }
95 }
96
HdfRemoteAdapterOptionalDispatch(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply,bool sync)97 static int HdfRemoteAdapterOptionalDispatch(struct HdfRemoteService *service, int code,
98 HdfSBuf *data, HdfSBuf *reply, bool sync)
99 {
100 if (service == nullptr) {
101 return HDF_ERR_INVALID_PARAM;
102 }
103
104 OHOS::MessageParcel *dataParcel = nullptr;
105 OHOS::MessageParcel *replyParcel = nullptr;
106
107 if (reply == nullptr) {
108 static OHOS::MessageParcel dummyReply;
109 dummyReply.FlushBuffer();
110 replyParcel = &dummyReply;
111 } else if (SbufToParcel(reply, &replyParcel)) {
112 HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
113 return HDF_ERR_INVALID_PARAM;
114 }
115
116 if (SbufToParcel(data, &dataParcel)) {
117 HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
118 return HDF_ERR_INVALID_PARAM;
119 }
120 int flag = sync ? OHOS::MessageOption::TF_SYNC : OHOS::MessageOption::TF_ASYNC;
121 OHOS::MessageOption option(flag);
122 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
123 if (dataParcel != nullptr) {
124 OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
125 if (remote != nullptr) {
126 return remote->SendRequest(code, *dataParcel, *replyParcel, option);
127 }
128 }
129 return HDF_FAILURE;
130 }
131
HdfRemoteAdapterDispatch(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply)132 static int HdfRemoteAdapterDispatch(struct HdfRemoteService *service,
133 int code, HdfSBuf *data, HdfSBuf *reply)
134 {
135 return HdfRemoteAdapterOptionalDispatch(service, code, data, reply, true);
136 }
137
HdfRemoteAdapterDispatchAsync(struct HdfRemoteService * service,int code,HdfSBuf * data,HdfSBuf * reply)138 static int HdfRemoteAdapterDispatchAsync(struct HdfRemoteService *service,
139 int code, HdfSBuf *data, HdfSBuf *reply)
140 {
141 return HdfRemoteAdapterOptionalDispatch(service, code, data, reply, false);
142 }
143
HdfRemoteServiceHolder()144 HdfRemoteServiceHolder::HdfRemoteServiceHolder() : remote_(nullptr), deathRecipient_(nullptr)
145 {
146 service_.object.objectId = HDF_OBJECT_ID_REMOTE_SERVICE;
147 service_.dispatcher = nullptr;
148 service_.target = nullptr;
149 service_.index = 0;
150 }
151
SetInterfaceDescriptor(const char * desc)152 bool HdfRemoteServiceHolder::SetInterfaceDescriptor(const char *desc)
153 {
154 if (desc == nullptr) {
155 return false;
156 }
157 std::u16string newDesc = OHOS::Str8ToStr16(std::string(desc));
158 if (newDesc.empty()) {
159 HDF_LOGE("failed to set interface des, error on cover str8 to str16, %{public}s", desc);
160 return false;
161 }
162
163 descriptor_.assign(newDesc);
164 return true;
165 }
166
HdfRemoteAdapterAddDeathRecipient(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)167 void HdfRemoteAdapterAddDeathRecipient(
168 struct HdfRemoteService *service, struct HdfDeathRecipient *recipient)
169 {
170 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
171 if (holder == nullptr) {
172 return;
173 }
174 OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
175 if (remote == nullptr) {
176 return;
177 }
178 if (holder->deathRecipient_ != nullptr) {
179 remote->RemoveDeathRecipient(holder->deathRecipient_);
180 }
181 holder->deathRecipient_ = new HdfDeathNotifier(service, recipient);
182 remote->AddDeathRecipient(holder->deathRecipient_);
183 }
184
HdfRemoteAdapterRemoveDeathRecipient(struct HdfRemoteService * service,const struct HdfDeathRecipient * recipient)185 void HdfRemoteAdapterRemoveDeathRecipient(
186 struct HdfRemoteService *service, const struct HdfDeathRecipient *recipient)
187 {
188 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
189 (void)recipient;
190 if (holder == nullptr) {
191 return;
192 }
193 OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
194 if (remote == nullptr) {
195 return;
196 }
197 if (holder->deathRecipient_ != nullptr) {
198 remote->RemoveDeathRecipient(holder->deathRecipient_);
199 holder->deathRecipient_ = nullptr;
200 }
201 }
202
HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)203 struct HdfRemoteService *HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)
204 {
205 struct HdfRemoteService *remoteService = nullptr;
206 static HdfRemoteDispatcher dispatcher = {
207 .Dispatch = HdfRemoteAdapterDispatch,
208 .DispatchAsync = HdfRemoteAdapterDispatchAsync,
209 };
210
211 struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
212 if (holder != nullptr) {
213 holder->remote_ = binder;
214 remoteService = &holder->service_;
215 remoteService->dispatcher = &dispatcher;
216 remoteService->index = (uint64_t)binder.GetRefPtr();
217 return remoteService;
218 }
219 return nullptr;
220 }
221
HdfRemoteAdapterObtain(void)222 struct HdfRemoteService *HdfRemoteAdapterObtain(void)
223 {
224 struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
225 holder->remote_ = new HdfRemoteServiceStub(&holder->service_);
226 return &holder->service_;
227 }
228
HdfRemoteAdapterRecycle(struct HdfRemoteService * object)229 void HdfRemoteAdapterRecycle(struct HdfRemoteService *object)
230 {
231 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(object);
232 if (holder != nullptr) {
233 holder->service_.target = nullptr;
234 holder->service_.dispatcher = nullptr;
235 holder->descriptor_.clear();
236 holder->remote_ = nullptr;
237 delete holder;
238 }
239 }
240
HdfRemoteAdapterAddService(const char * name,struct HdfRemoteService * service)241 int HdfRemoteAdapterAddService(const char *name, struct HdfRemoteService *service)
242 {
243 if (name == nullptr || service == nullptr) {
244 return HDF_ERR_INVALID_PARAM;
245 }
246
247 OHOS::sptr<OHOS::IServiceRegistry> sr = OHOS::ServiceRegistry::GetInstance();
248 if (sr == nullptr) {
249 HDF_LOGE("failed to get service registry");
250 return HDF_FAILURE;
251 }
252 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
253 int ret = sr->AddService(OHOS::Str8ToStr16(name), holder->remote_);
254 if (ret == 0) {
255 (void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);
256 }
257 return ret;
258 }
259
HdfRemoteAdapterGetService(const char * name)260 struct HdfRemoteService *HdfRemoteAdapterGetService(const char *name)
261 {
262 if (name == nullptr) {
263 return nullptr;
264 }
265
266 OHOS::sptr<OHOS::IServiceRegistry> sr = OHOS::ServiceRegistry::GetInstance();
267 if (sr == nullptr) {
268 HDF_LOGE("failed to get service registry");
269 return nullptr;
270 }
271 OHOS::sptr<OHOS::IRemoteObject> remote = sr->GetService(OHOS::Str8ToStr16(name));
272 if (remote != nullptr) {
273 return HdfRemoteAdapterBind(remote);
274 }
275 return nullptr;
276 }
277
HdfRemoteAdapterAddSa(int32_t saId,struct HdfRemoteService * service)278 int HdfRemoteAdapterAddSa(int32_t saId, struct HdfRemoteService *service)
279 {
280 if (service == nullptr) {
281 return HDF_ERR_INVALID_PARAM;
282 }
283 OHOS::sptr<OHOS::ISystemAbilityManager> saManager;
284 {
285 OHOS::HdfXCollie hdfXCollie("HdfRemoteAdapterAddSa_" + OHOS::ToString(saId) + "_get_samgr",
286 OHOS::HdfXCollie::DEFAULT_TIMEOUT_SECONDS, nullptr, nullptr, OHOS::HdfXCollie::HDF_XCOLLIE_FLAG_RECOVERY);
287 saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
288 const int32_t waitTimes = 50;
289 const int32_t sleepInterval = 20000;
290 int32_t timeout = waitTimes;
291 while (saManager == nullptr && (timeout > 0)) {
292 HDF_LOGI("waiting for samgr...");
293 usleep(sleepInterval);
294 saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
295 timeout--;
296 }
297
298 if (saManager == nullptr) {
299 HDF_LOGE("failed to get sa manager, waiting timeot");
300 return HDF_FAILURE;
301 }
302 }
303 {
304 OHOS::HdfXCollie hdfXCollie("HdfRemoteAdapterAddSa_" + OHOS::ToString(saId) + "_add_sa",
305 OHOS::HdfXCollie::DEFAULT_TIMEOUT_SECONDS, nullptr, nullptr, OHOS::HdfXCollie::HDF_XCOLLIE_FLAG_RECOVERY);
306 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
307 int ret = saManager->AddSystemAbility(saId, holder->remote_);
308 (void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);
309 HDF_LOGI("add sa %{public}d, ret = %{public}s", saId, (ret == 0) ? "succ" : "fail");
310 }
311 return HDF_SUCCESS;
312 }
313
HdfRemoteAdapterGetSa(int32_t saId)314 struct HdfRemoteService *HdfRemoteAdapterGetSa(int32_t saId)
315 {
316 auto saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
317 if (saManager == nullptr) {
318 HDF_LOGE("failed to get sa manager");
319 return nullptr;
320 }
321 OHOS::sptr<OHOS::IRemoteObject> remote = saManager->GetSystemAbility(saId);
322 constexpr int32_t waitTimes = 50;
323 constexpr int32_t sleepInterval = 20000;
324 int32_t timeout = waitTimes;
325 while (remote == nullptr && (timeout > 0)) {
326 HDF_LOGD("waiting for saId %{public}d", saId);
327 usleep(sleepInterval);
328 remote = saManager->GetSystemAbility(saId);
329 timeout--;
330 }
331 if (remote != nullptr) {
332 return HdfRemoteAdapterBind(remote);
333 } else {
334 HDF_LOGE("failed to get sa %{public}d", saId);
335 }
336 return nullptr;
337 }
338
HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService * service,const char * desc)339 bool HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService *service, const char *desc)
340 {
341 if (service == nullptr || desc == nullptr) {
342 return false;
343 }
344 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
345 return holder->SetInterfaceDescriptor(desc);
346 }
347
HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)348 bool HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
349 {
350 if (service == nullptr || data == nullptr) {
351 return false;
352 }
353 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
354 OHOS::MessageParcel *parcel = nullptr;
355
356 if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
357 HDF_LOGE("failed to write interface token, SbufToParcel error");
358 return false;
359 }
360
361 if (holder->remote_ == nullptr) {
362 HDF_LOGE("failed to write interface token, holder->remote is nullptr");
363 return false;
364 }
365 if (holder->descriptor_.empty()) {
366 HDF_LOGE("failed to write interface token, empty token");
367 return false;
368 }
369 return parcel->WriteInterfaceToken(holder->descriptor_);
370 }
371
CheckInterfaceTokenIngoreVersion(const std::string & client,const std::string & stub)372 static bool CheckInterfaceTokenIngoreVersion(const std::string &client, const std::string &stub)
373 {
374 std::vector<std::string> clientVec;
375 OHOS::SplitStr(client, ".", clientVec);
376 std::vector<std::string> stubVec;
377 OHOS::SplitStr(stub, ".", stubVec);
378 if (clientVec.size() != stubVec.size()) {
379 HDF_LOGE("%{public}s: client desc and stub desc have different size", __func__);
380 return false;
381 }
382 std::regex rVer("[V|v][0-9]+_[0-9]+");
383 for (size_t i = 0; i < stubVec.size(); i++) {
384 if (std::regex_match(stubVec[i], rVer)) {
385 continue;
386 }
387 if (clientVec[i] != stubVec[i]) {
388 HDF_LOGE("%{public}s: mismatch between client desc and stub desc", __func__);
389 return false;
390 }
391 }
392 return true;
393 }
394
HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)395 bool HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
396 {
397 if (service == nullptr || data == nullptr) {
398 return false;
399 }
400 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
401 if (holder->remote_ == nullptr) {
402 return false;
403 }
404 OHOS::MessageParcel *parcel = nullptr;
405
406 if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
407 return false;
408 }
409 auto desc = parcel->ReadInterfaceToken();
410 if (desc.empty()) {
411 HDF_LOGE("failed to check interface, empty token");
412 return false;
413 }
414 std::string client = OHOS::Str16ToStr8(desc);
415 std::string stub = OHOS::Str16ToStr8(holder->descriptor_);
416 if (!CheckInterfaceTokenIngoreVersion(client, stub)) {
417 HDF_LOGE("calling unknown interface: %{public}s", client.c_str());
418 return false;
419 }
420 return true;
421 }
422
HdfRemoteGetCallingPid(void)423 pid_t HdfRemoteGetCallingPid(void)
424 {
425 return OHOS::IPCSkeleton::GetCallingPid();
426 }
427
HdfRemoteGetCallingUid(void)428 pid_t HdfRemoteGetCallingUid(void)
429 {
430 return OHOS::IPCSkeleton::GetCallingUid();
431 }
432
HdfRemoteAdapterDefaultDispatch(struct HdfRemoteService * service,int code,struct HdfSBuf * data,struct HdfSBuf * reply)433 int HdfRemoteAdapterDefaultDispatch(struct HdfRemoteService *service,
434 int code, struct HdfSBuf *data, struct HdfSBuf *reply)
435 {
436 struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
437 if (holder == nullptr) {
438 HDF_LOGE("%{public}s: failed to converts remote to holder", __func__);
439 return HDF_ERR_INVALID_PARAM;
440 }
441
442 if (holder->remote_ == nullptr) {
443 HDF_LOGE("%{public}s: invaild holder, holder->remote is nullptr", __func__);
444 return HDF_ERR_INVALID_PARAM;
445 }
446
447 OHOS::IPCObjectStub *stub = reinterpret_cast<OHOS::IPCObjectStub *>(holder->remote_.GetRefPtr());
448 if (stub == nullptr) {
449 HDF_LOGE("%{public}s: failed to converts holder->remote to IPCObjectStub object", __func__);
450 return HDF_ERR_INVALID_PARAM;
451 }
452
453 OHOS::MessageParcel *dataParcel = nullptr;
454 OHOS::MessageParcel *replyParcel = nullptr;
455 OHOS::MessageOption option;
456
457 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
458 HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
459 return HDF_ERR_INVALID_PARAM;
460 }
461
462 if (SbufToParcel(data, &replyParcel) != HDF_SUCCESS) {
463 HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
464 return HDF_ERR_INVALID_PARAM;
465 }
466
467 return stub->IPCObjectStub::OnRemoteRequest(code, *dataParcel, *replyParcel, option);
468 }