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