• 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 #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 }