• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "remote_object_impl.h"
17 
18 #include <cinttypes>
19 #include <hitrace_meter.h>
20 #include <string_ex.h>
21 
22 #include "cj_lambda.h"
23 #include "ipc_utils_ffi.h"
24 #include "iremote_invoker.h"
25 #include "remote_object_internal_impl.h"
26 #include "remote_proxy_holder_impl.h"
27 
28 using namespace OHOS::FFI;
29 
30 namespace OHOS {
31 static const uint64_t HITRACE_TAG_RPC = (1ULL << 46); // RPC and IPC tag.
32 
33 static std::atomic<int32_t> bytraceId = 1000;
34 
RemoteObjectImpl(std::thread::id jsThreadId,const std::u16string & descriptor)35 RemoteObjectImpl::RemoteObjectImpl(std::thread::id jsThreadId, const std::u16string& descriptor)
36     : IPCObjectStub(descriptor)
37 {
38     jsThreadId_ = jsThreadId;
39 }
40 
CjRemoteObjectImpl(RemoteObjectHolderImpl * holder)41 CjRemoteObjectImpl::CjRemoteObjectImpl(RemoteObjectHolderImpl* holder)
42 {
43     holder_ = holder;
44 }
45 
~CjRemoteObjectImpl()46 CjRemoteObjectImpl::~CjRemoteObjectImpl()
47 {
48     if (holder_ == nullptr) {
49         ZLOGW(LOG_LABEL, "~CjRemoteObjectImpl null holder");
50         return;
51     }
52     holder_->Lock();
53     int32_t curAttachCount = holder_->DecAttachCount();
54     holder_->Unlock();
55     ZLOGD(LOG_LABEL, "~CjRemoteObjectImpl, curAttachCount:%{public}d", curAttachCount);
56     if (curAttachCount == 0) {
57         delete holder_;
58     }
59 }
60 
GetDescriptor(int32_t * errCode)61 char* CjRemoteObjectImpl::GetDescriptor(int32_t* errCode)
62 {
63     if (holder_ == nullptr) {
64         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
65         *errCode = errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
66         return nullptr;
67     }
68     sptr<IRemoteObject> nativeObject = holder_->Get();
69     if (nativeObject == nullptr) {
70         ZLOGE(LOG_LABEL, "native stub object is nullptr");
71         *errCode = errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
72         return nullptr;
73     }
74     std::u16string descriptor = nativeObject->GetObjectDescriptor();
75     std::string str = Str16ToStr8(descriptor);
76     return MallocCString(str);
77 }
78 
ModifyLocalInterface(char * stringValue)79 int32_t CjRemoteObjectImpl::ModifyLocalInterface(char* stringValue)
80 {
81     size_t maxLen = 40960;
82     if (strlen(stringValue) >= maxLen) {
83         ZLOGE(LOG_LABEL, "string length too large");
84         return errorDesc::CHECK_PARAM_ERROR;
85     }
86     if (holder_ == nullptr) {
87         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
88         return errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
89     }
90     std::string descriptor = stringValue;
91     holder_->attachLocalInterface(descriptor);
92     return 0;
93 }
94 
StubExecuteSendRequest(CJSendRequestParam * param)95 void StubExecuteSendRequest(CJSendRequestParam* param)
96 {
97     if (param == nullptr) {
98         ZLOGE(LOG_LABEL, "param is null");
99         return;
100     }
101     param->errCode =
102         param->target->SendRequest(param->code, *(param->data.get()), *(param->reply.get()), param->option);
103     uint64_t curTime = static_cast<uint64_t>(
104         std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch())
105             .count());
106     ZLOGI(LOG_LABEL, "sendRequest done, errCode:%{public}d time:%{public}" PRIu64, param->errCode, curTime);
107     if (param->traceId != 0) {
108         FinishAsyncTrace(HITRACE_TAG_RPC, (param->traceValue).c_str(), param->traceId);
109     }
110     auto callback = CJLambda::Create(reinterpret_cast<void (*)(RequestResult)>(param->callback));
111     if (callback) {
112         ZLOGI(LOG_LABEL, "callback started");
113         RequestResult result = RequestResult {
114             .errCode = param->errCode, .code = param->code, .data = param->cjDataRef, .reply = param->cjReplyRef
115         };
116         callback(result);
117     }
118     delete param;
119 }
120 
SendMessageRequest(uint32_t code,int64_t dataId,int64_t replyId,MessageOption option,int64_t funcId)121 int32_t CjRemoteObjectImpl::SendMessageRequest(
122     uint32_t code, int64_t dataId, int64_t replyId, MessageOption option, int64_t funcId)
123 {
124     auto data = FFIData::GetData<MessageSequenceImpl>(dataId);
125     if (!data) {
126         ZLOGE(LOG_LABEL, "[RPC] failed to get data message parcel");
127         return errorDesc::CHECK_PARAM_ERROR;
128     }
129     auto reply = FFIData::GetData<MessageSequenceImpl>(replyId);
130     if (!reply) {
131         ZLOGE(LOG_LABEL, "[RPC] failed to get reply message parcel");
132         return errorDesc::CHECK_PARAM_ERROR;
133     }
134     if (holder_ == nullptr) {
135         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
136         return errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
137     }
138     sptr<IRemoteObject> target = holder_->Get();
139     if (target == nullptr) {
140         ZLOGE(LOG_LABEL, "native stub object is nullptr");
141         return errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
142     }
143     CJSendRequestParam* sendRequestParam = new (std::nothrow) CJSendRequestParam {
144         .target = target,
145         .code = code,
146         .data = data->GetMessageParcel(),
147         .reply = reply->GetMessageParcel(),
148         .option = option,
149         .errCode = -1,
150         .cjDataRef = dataId,
151         .cjReplyRef = replyId,
152         .callback = funcId,
153         .traceId = 0,
154     };
155     if (sendRequestParam == nullptr) {
156         ZLOGE(LOG_LABEL, "new SendRequestParam failed");
157         return errorDesc::PROXY_OR_REMOTE_OBJECT_INVALID_ERROR;
158     }
159     std::string remoteDescriptor = Str16ToStr8(target->GetObjectDescriptor());
160     if (!remoteDescriptor.empty()) {
161         std::string traceValue = remoteDescriptor + std::to_string(code);
162         int32_t traceId = bytraceId.fetch_add(1, std::memory_order_seq_cst);
163         StartAsyncTrace(HITRACE_TAG_RPC, traceValue.c_str(), traceId);
164     }
165     std::thread t(StubExecuteSendRequest, sendRequestParam);
166     t.detach();
167     return 0;
168 }
169 
GetHolder()170 RemoteObjectHolderImpl* CjRemoteObjectImpl::GetHolder()
171 {
172     return holder_;
173 }
174 
IsProxyObject()175 bool CjRemoteObjectImpl::IsProxyObject()
176 {
177     if (holder_ == nullptr) {
178         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
179         return false;
180     }
181     sptr<IRemoteObject> target = holder_->Get();
182     if (target == nullptr) {
183         ZLOGE(LOG_LABEL, "native stub object is nullptr");
184         return false;
185     }
186     return target->IsProxyObject();
187 }
188 
GetRemoteObject()189 sptr<IRemoteObject> CjRemoteObjectImpl::GetRemoteObject()
190 {
191     if (holder_ == nullptr) {
192         ZLOGE(LOG_LABEL, "failed to get napi remote object holder");
193         return nullptr;
194     }
195     return holder_->Get();
196 }
197 
CreateStubRemoteObject(const sptr<IRemoteObject> target)198 int64_t CreateStubRemoteObject(const sptr<IRemoteObject> target)
199 {
200     std::u16string descriptor = target->GetObjectDescriptor();
201     RemoteObjectHolderImpl* holder = new (std::nothrow) RemoteObjectHolderImpl(descriptor);
202     if (holder == nullptr) {
203         return 0;
204     }
205     holder->Set(target);
206     auto remotrObject = FFIData::Create<CjRemoteObjectImpl>(holder);
207     if (!remotrObject) {
208         delete holder;
209         return 0;
210     }
211     return remotrObject->GetID();
212 }
213 
CreateProxyRemoteObject(const sptr<IRemoteObject> target)214 int64_t CreateProxyRemoteObject(const sptr<IRemoteObject> target)
215 {
216     auto proxyHolder = FFIData::Create<RemoteProxyHolderImpl>();
217     if (proxyHolder == nullptr) {
218         return 0;
219     }
220     proxyHolder->object_ = target;
221     proxyHolder->list_ = new (std::nothrow) CJDeathRecipientList();
222     if (proxyHolder->list_ == nullptr) {
223         ZLOGE(LOG_LABEL, "new NAPIDeathRecipientList failed");
224         FFIData::Release(proxyHolder->GetID());
225         return 0;
226     }
227     return proxyHolder->GetID();
228 }
229 
CJ_rpc_CreateRemoteObject(const sptr<IRemoteObject> target)230 int64_t CJ_rpc_CreateRemoteObject(const sptr<IRemoteObject> target)
231 {
232     if (target == nullptr) {
233         uint64_t curTime = static_cast<uint64_t>(
234             std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch())
235                 .count());
236         ZLOGE(LOG_LABEL, "RemoteObject is null time:%{public}" PRIu64, curTime);
237         return 0;
238     }
239     if (!target->IsProxyObject()) {
240         IPCObjectStub* tmp = static_cast<IPCObjectStub*>(target.GetRefPtr());
241         uint32_t objectType = static_cast<uint32_t>(tmp->GetObjectType());
242         ZLOGD(LOG_LABEL, "create js object, type:%{public}d", objectType);
243         if (objectType == IPCObjectStub::OBJECT_TYPE_JAVASCRIPT || objectType == IPCObjectStub::OBJECT_TYPE_NATIVE) {
244             return CreateStubRemoteObject(target);
245         }
246     }
247 
248     return CreateProxyRemoteObject(target);
249 }
250 
CJ_rpc_getNativeRemoteObject(int64_t object)251 sptr<IRemoteObject> CJ_rpc_getNativeRemoteObject(int64_t object)
252 {
253     auto remoteObject = FFIData::GetData<CjIRemoteObjectImpl>(object);
254     if (!remoteObject) {
255         ZLOGE(LOG_LABEL, "get stub constructor failed");
256         return nullptr;
257     }
258     return remoteObject->GetRemoteObject();
259 }
260 
261 extern "C" {
OHOS_CallCreateRemoteObject(void * param)262 FFI_EXPORT int64_t OHOS_CallCreateRemoteObject(void* param)
263 {
264     auto remoteObject = reinterpret_cast<sptr<IRemoteObject>*>(param);
265     if (remoteObject == nullptr) {
266         return 0;
267     }
268     return CJ_rpc_CreateRemoteObject(*remoteObject);
269 }
270 
OHOS_CallGetNativeRemoteObject(int64_t object,void * param)271 FFI_EXPORT void OHOS_CallGetNativeRemoteObject(int64_t object, void* param)
272 {
273     if (param == nullptr) {
274         return;
275     }
276     auto ret = CJ_rpc_getNativeRemoteObject(object);
277     auto remoteObject = reinterpret_cast<sptr<IRemoteObject>*>(param);
278     *remoteObject = ret;
279     return;
280 }
281 }
282 } // namespace OHOS