• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }