• 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 = 1;
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((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 }
133 
SetInterfaceDescriptor(const char * desc)134 bool HdfRemoteServiceHolder::SetInterfaceDescriptor(const char *desc)
135 {
136     if (remote_ == nullptr || desc == nullptr) {
137         return false;
138     }
139     std::u16string newDesc = OHOS::Str8ToStr16(std::string(desc));
140     if (newDesc.empty()) {
141         HDF_LOGE("failed to set interface des, error on cover str8 to str16, %{public}s", desc);
142         return false;
143     }
144     (const_cast<std::u16string *>(&remote_->descriptor_))->assign(newDesc);
145 
146     return true;
147 }
148 
HdfRemoteAdapterAddDeathRecipient(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)149 void HdfRemoteAdapterAddDeathRecipient(
150     struct HdfRemoteService *service, struct HdfDeathRecipient *recipient)
151 {
152     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
153     if (holder == nullptr) {
154         return;
155     }
156     OHOS::sptr<OHOS::IRemoteObject> remote = holder->remote_;
157     if (remote == nullptr) {
158         return;
159     }
160     if (holder->deathRecipient_ != nullptr) {
161         remote->RemoveDeathRecipient(holder->deathRecipient_);
162     }
163     holder->deathRecipient_ = new HdfDeathNotifier(service, recipient);
164     remote->AddDeathRecipient(holder->deathRecipient_);
165 }
166 
HdfRemoteAdapterRemoveDeathRecipient(struct HdfRemoteService * service,struct HdfDeathRecipient * recipient)167 void HdfRemoteAdapterRemoveDeathRecipient(
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         holder->deathRecipient_ = nullptr;
181     }
182 }
183 
HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)184 struct HdfRemoteService *HdfRemoteAdapterBind(OHOS::sptr<OHOS::IRemoteObject> binder)
185 {
186     struct HdfRemoteService *remoteService = nullptr;
187     static HdfRemoteDispatcher dispatcher = {
188         .Dispatch = HdfRemoteAdapterDispatch,
189         .DispatchAsync = HdfRemoteAdapterDispatchAsync,
190     };
191 
192     struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
193     if (holder != nullptr) {
194         holder->remote_ = binder;
195         remoteService = &holder->service_;
196         remoteService->dispatcher = &dispatcher;
197         remoteService->index = (uint64_t)binder.GetRefPtr();
198         return remoteService;
199     }
200     return nullptr;
201 }
202 
HdfRemoteAdapterObtain(void)203 struct HdfRemoteService *HdfRemoteAdapterObtain(void)
204 {
205     struct HdfRemoteServiceHolder *holder = new HdfRemoteServiceHolder();
206     holder->remote_ = new HdfRemoteServiceStub(&holder->service_);
207     return &holder->service_;
208 }
209 
HdfRemoteAdapterRecycle(struct HdfRemoteService * object)210 void HdfRemoteAdapterRecycle(struct HdfRemoteService *object)
211 {
212     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(object);
213     if (holder != nullptr) {
214         if (holder->remote_ != nullptr) {
215             holder->remote_ = nullptr;
216         }
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     }
273 
274     if (saManager == nullptr) {
275         HDF_LOGE("failed to get sa manager, waiting timeot");
276         return HDF_FAILURE;
277     }
278     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
279     int ret = saManager->AddSystemAbility(saId, holder->remote_);
280     (void)OHOS::IPCSkeleton::GetInstance().SetMaxWorkThreadNum(g_remoteThreadMax++);
281     HDF_LOGI("add sa %{public}d, ret = %{public}s", saId, (ret == 0) ? "succ" : "fail");
282 
283     return HDF_SUCCESS;
284 }
285 
HdfRemoteAdapterGetSa(int32_t saId)286 struct HdfRemoteService *HdfRemoteAdapterGetSa(int32_t saId)
287 {
288     auto saManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
289     if (saManager == nullptr) {
290         HDF_LOGE("failed to get sa manager");
291         return nullptr;
292     }
293     OHOS::sptr<OHOS::IRemoteObject> remote = saManager->GetSystemAbility(saId);
294     if (remote != nullptr) {
295         return HdfRemoteAdapterBind(remote);
296     } else {
297         HDF_LOGE("failed to get sa %{public}d", saId);
298     }
299     return nullptr;
300 }
301 
HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService * service,const char * desc)302 bool HdfRemoteAdapterSetInterfaceDesc(struct HdfRemoteService *service, const char *desc)
303 {
304     if (service == nullptr || desc == nullptr) {
305         return false;
306     }
307     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
308     return holder->SetInterfaceDescriptor(desc);
309 }
310 
HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)311 bool HdfRemoteAdapterWriteInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
312 {
313     if (service == nullptr || data == nullptr) {
314         return false;
315     }
316     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
317     OHOS::MessageParcel *parcel = nullptr;
318 
319     if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
320         HDF_LOGE("failed to write interface token, SbufToParcel error");
321         return false;
322     }
323 
324     if (holder->remote_ == nullptr) {
325         HDF_LOGE("failed to write interface token, holder->remote is nullptr");
326         return false;
327     }
328     if (holder->remote_->GetObjectDescriptor().empty()) {
329         HDF_LOGE("failed to write interface token, empty token");
330         return false;
331     }
332     return parcel->WriteInterfaceToken(holder->remote_->GetObjectDescriptor());
333 }
334 
HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService * service,struct HdfSBuf * data)335 bool HdfRemoteAdapterCheckInterfaceToken(struct HdfRemoteService *service, struct HdfSBuf *data)
336 {
337     if (service == nullptr || data == nullptr) {
338         return false;
339     }
340     struct HdfRemoteServiceHolder *holder = reinterpret_cast<struct HdfRemoteServiceHolder *>(service);
341     if (holder == nullptr || holder->remote_ == nullptr) {
342         return false;
343     }
344     OHOS::MessageParcel *parcel = nullptr;
345 
346     if (SbufToParcel(data, &parcel) != HDF_SUCCESS) {
347         return false;
348     }
349     auto desc = parcel->ReadInterfaceToken();
350     if (desc.empty()) {
351         HDF_LOGE("failed to check interface, empty token");
352         return false;
353     }
354     if (holder->remote_->GetObjectDescriptor() != desc) {
355         std::string descStr8 = OHOS::Str16ToStr8(desc);
356         HDF_LOGE("calling unknown interface: %{public}s", descStr8.c_str());
357         return false;
358     }
359 
360     return true;
361 }
362