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