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 "ohos_rpc_remote_object.h"
17 #include <mutex>
18 #include <set>
19 #include "ipc_debug.h"
20 #include "jni_helper.h"
21 #include "ohos_utils_parcel.h"
22 #include "ohos_rpc_message_option.h"
23 #include "ohos_rpc_message_parcel.h"
24 #include "ipc_object_stub.h"
25 #include "ipc_object_proxy.h"
26 #include "ipc_thread_skeleton.h"
27 #include "ipc_skeleton.h"
28 #include "ipc_types.h"
29 #include "log_tags.h"
30 #include "jkit_utils.h"
31
32 using namespace OHOS;
33 using namespace OHOS::HiviewDFX;
34
35 namespace OHOS {
36 static constexpr HiLogLabel LABEL = { LOG_CORE, LOG_ID_IPC_OTHER, "IPCJni" };
37
38 class JDeathRecipientList;
39 class JRemoteObjectHolder;
40 struct JRemoteObjectDesc {
41 jclass klass;
42 jmethodID methodDispatchRequest;
43 jfieldID fieldNativeHolder;
44 jmethodID methodDispatchDump;
45 };
46
47 struct JRemoteProxyDesc {
48 jclass klass;
49 jmethodID methodGetInstance;
50 jmethodID methodSendObituary;
51 jfieldID fieldNativeData;
52 };
53
54 class JRemoteProxyHolder {
55 public:
56 JRemoteProxyHolder();
57 ~JRemoteProxyHolder();
58 sptr<JDeathRecipientList> list_;
59 sptr<IRemoteObject> object_;
60 };
61 /*
62 * the native RemoteObject act as bridger between java and native.
63 * It received the request from client and pass it Java Layer.
64 */
65 class JRemoteObject : public IPCObjectStub {
66 public:
67 JRemoteObject(jobject object, const std::u16string &descriptor);
68
69 ~JRemoteObject() override;
70
71 bool CheckObjectLegality() const override;
72
73 int GetObjectType() const override;
74
75 int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
76
77 int OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override;
78
79 jobject GetJObject() const;
80
81 private:
82 jobject object_;
83 };
84
85 /*
86 * To ensure a better consistency of the life time of
87 * Java IPC Object and native object we designed
88 * a container to save the native object.
89 */
90 class JRemoteObjectHolder : public RefBase {
91 public:
92 explicit JRemoteObjectHolder(const std::u16string &descriptor);
93 ~JRemoteObjectHolder();
94 sptr<JRemoteObject> Get(jobject object);
95
96 private:
97 std::mutex mutex_;
98 std::u16string descriptor_;
99 sptr<JRemoteObject> cachedObject_;
100 };
101
102 /*
103 * the native DeathRecipient container.
104 * As an recipient of Obituary of service death.
105 * and pass the message to Java Layer.
106 */
107 class JDeathRecipient : public IRemoteObject::DeathRecipient {
108 public:
109 explicit JDeathRecipient(jobject object);
110
111 void OnRemoteDied(const wptr<IRemoteObject> &object) override;
112
113 bool Matches(jobject object);
114
115 protected:
116 virtual ~JDeathRecipient();
117
118 private:
119 std::mutex mutex_;
120 jobject refObject_;
121 jweak weakRefObject_ {};
122 };
123
124 /*
125 * the native DeathRecipient container
126 */
127 class JDeathRecipientList : public RefBase {
128 std::set<sptr<JDeathRecipient>> set_;
129 std::mutex mutex_;
130
131 public:
132 JDeathRecipientList();
133
134 ~JDeathRecipientList();
135
136 bool Add(const sptr<JDeathRecipient> &recipient);
137
138 bool Remove(const sptr<JDeathRecipient> &recipient);
139
140 sptr<JDeathRecipient> Find(jobject recipient);
141 };
142
143 // Global variable definition.
144 static JRemoteProxyHolder *g_cachedProxyHolder;
145 static struct JRemoteObjectDesc g_jRemoteStub;
146 static struct JRemoteProxyDesc g_jRemoteProxy;
147 static std::mutex g_proxyMutex_;
148 static bool g_ipcNativeMethodsLoaded = false;
149
JRemoteObject(jobject object,const std::u16string & descriptor)150 JRemoteObject::JRemoteObject(jobject object, const std::u16string &descriptor) : IPCObjectStub(descriptor)
151 {
152 JNIEnvHelper env;
153 if (env.Get() != nullptr && object != nullptr) {
154 object_ = env->NewGlobalRef(object);
155 } else {
156 object_ = nullptr;
157 }
158 }
159
CheckObjectLegality() const160 bool JRemoteObject::CheckObjectLegality() const
161 {
162 return true;
163 }
164
GetObjectType() const165 int JRemoteObject::GetObjectType() const
166 {
167 return OBJECT_TYPE_JAVA;
168 }
169
~JRemoteObject()170 JRemoteObject::~JRemoteObject()
171 {
172 JNIEnvHelper env;
173 if (env.Get() != nullptr && object_ != nullptr) {
174 env->DeleteGlobalRef(object_);
175 }
176 }
177
GetJObject() const178 jobject JRemoteObject::GetJObject() const
179 {
180 return object_;
181 }
182
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)183 int JRemoteObject::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
184 {
185 JNIEnvHelper env;
186 if (env.Get() == nullptr) {
187 return ERR_TRANSACTION_FAILED;
188 }
189
190 if (code == DUMP_TRANSACTION) {
191 ZLOGE(LABEL, "DUMP_TRANSACTION data size:%{public}zu", data.GetReadableBytes());
192 }
193
194 jobject javaOption = JavaOhosRpcMessageOptionNewJavaObject(env.Get(), option.GetFlags(), option.GetWaitTime());
195 jboolean res = env->CallBooleanMethod(object_, g_jRemoteStub.methodDispatchRequest, code,
196 reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(&reply), javaOption);
197
198 env->DeleteLocalRef(javaOption);
199 if (JniHelperCheckAndClearLocalException(env.Get())) {
200 ZLOGE(LABEL, "OnRemoteRequest found exception, res:%{public}d", res);
201 return ERR_UNKNOWN_TRANSACTION;
202 }
203 if (code == SYSPROPS_TRANSACTION) {
204 int result = IPCObjectStub::OnRemoteRequest(code, data, reply, option);
205 if (result != ERR_NONE) {
206 ZLOGE(LABEL, "result:%{public}d", result);
207 return ERR_INVALID_DATA;
208 }
209 }
210 if (!res) {
211 ZLOGE(LABEL, "res:%{public}d", res);
212 return ERR_UNKNOWN_TRANSACTION;
213 }
214 return ERR_NONE;
215 }
216
OnRemoteDump(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)217 int JRemoteObject::OnRemoteDump(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option)
218 {
219 JNIEnvHelper env;
220 if (env.Get() == nullptr) {
221 return ERR_TRANSACTION_FAILED;
222 }
223
224 jobject javaOption = JavaOhosRpcMessageOptionNewJavaObject(env.Get(), option.GetFlags(), option.GetWaitTime());
225 jboolean res = env->CallBooleanMethod(object_, g_jRemoteStub.methodDispatchDump, code,
226 reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(&reply), javaOption);
227
228 if (JniHelperCheckAndClearLocalException(env.Get())) {
229 res = JNI_FALSE;
230 }
231 env->DeleteLocalRef(javaOption);
232 ZLOGD(LABEL, "res:%{public}d", res);
233 return res ? ERR_NONE : ERR_UNKNOWN_TRANSACTION;
234 }
235
JRemoteObjectHolder(const std::u16string & descriptor)236 JRemoteObjectHolder::JRemoteObjectHolder(const std::u16string &descriptor)
237 : descriptor_(descriptor), cachedObject_(nullptr)
238 {}
239
~JRemoteObjectHolder()240 JRemoteObjectHolder::~JRemoteObjectHolder()
241 {
242 // free the reference of object.
243 cachedObject_ = nullptr;
244 }
245
Get(jobject object)246 sptr<JRemoteObject> JRemoteObjectHolder::Get(jobject object)
247 {
248 std::lock_guard<std::mutex> lockGuard(mutex_);
249 // grab an strong reference to the object,
250 // so it will not be freed util this reference released.
251 sptr<JRemoteObject> remoteObject = nullptr;
252 if (cachedObject_ != nullptr) {
253 remoteObject = cachedObject_;
254 }
255
256 if (remoteObject == nullptr) {
257 remoteObject = new JRemoteObject(object, descriptor_);
258 cachedObject_ = remoteObject;
259 }
260 return remoteObject;
261 }
262
JRemoteProxyHolder()263 JRemoteProxyHolder::JRemoteProxyHolder() : list_(nullptr), object_(nullptr) {}
264
~JRemoteProxyHolder()265 JRemoteProxyHolder::~JRemoteProxyHolder()
266 {
267 list_ = nullptr;
268 object_ = nullptr;
269 }
270
JDeathRecipient(jobject object)271 JDeathRecipient::JDeathRecipient(jobject object)
272 {
273 JNIEnvHelper env;
274 if (env.Get() != nullptr) {
275 refObject_ = env->NewGlobalRef(object);
276 } else {
277 refObject_ = nullptr;
278 }
279 }
280
OnRemoteDied(const wptr<IRemoteObject> & object)281 void JDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
282 {
283 ZLOGD(LABEL, "called");
284 if (refObject_ == nullptr) {
285 ZLOGE(LABEL, "Object has already removed");
286 return;
287 }
288
289 JNIEnvHelper env;
290 if (env.Get() == nullptr) {
291 return;
292 }
293
294 env->CallStaticVoidMethod(g_jRemoteProxy.klass, g_jRemoteProxy.methodSendObituary, refObject_);
295 JniHelperCheckAndClearLocalException(env.Get());
296
297 weakRefObject_ = env->NewWeakGlobalRef(refObject_);
298 env->DeleteGlobalRef(refObject_);
299 std::lock_guard<std::mutex> lockGuard(mutex_);
300 refObject_ = nullptr;
301 }
302
Matches(jobject object)303 bool JDeathRecipient::Matches(jobject object)
304 {
305 JNIEnvHelper env;
306 if (env.Get() == nullptr) {
307 return false;
308 }
309
310 bool result = false;
311 if (object != nullptr) {
312 std::lock_guard<std::mutex> lockGuard(mutex_);
313 if (refObject_ != nullptr) {
314 result = env->IsSameObject(object, refObject_);
315 }
316 } else {
317 if (weakRefObject_ == nullptr) {
318 return false;
319 }
320 jobject me = env->NewLocalRef(weakRefObject_);
321 result = env->IsSameObject(object, me);
322 env->DeleteLocalRef(me);
323 }
324 return result;
325 }
326
~JDeathRecipient()327 JDeathRecipient::~JDeathRecipient()
328 {
329 ZLOGD(LABEL, "enter");
330 JNIEnvHelper env;
331
332 if (env.Get() != nullptr) {
333 if (refObject_ != nullptr) {
334 env->DeleteGlobalRef(refObject_);
335 } else {
336 if (weakRefObject_ != nullptr) {
337 env->DeleteWeakGlobalRef(weakRefObject_);
338 }
339 }
340 }
341 }
342
JDeathRecipientList()343 JDeathRecipientList::JDeathRecipientList() {}
344
~JDeathRecipientList()345 JDeathRecipientList::~JDeathRecipientList()
346 {
347 std::lock_guard<std::mutex> lockGuard(mutex_);
348 set_.clear();
349 }
350
Add(const sptr<JDeathRecipient> & recipient)351 bool JDeathRecipientList::Add(const sptr<JDeathRecipient> &recipient)
352 {
353 std::lock_guard<std::mutex> lockGuard(mutex_);
354 auto ret = set_.insert(recipient);
355 return ret.second;
356 }
357
Remove(const sptr<JDeathRecipient> & recipient)358 bool JDeathRecipientList::Remove(const sptr<JDeathRecipient> &recipient)
359 {
360 std::lock_guard<std::mutex> lockGuard(mutex_);
361 return (set_.erase(recipient) > 0);
362 }
363
Find(jobject recipient)364 sptr<JDeathRecipient> JDeathRecipientList::Find(jobject recipient)
365 {
366 std::lock_guard<std::mutex> lockGuard(mutex_);
367
368 for (auto it = set_.begin(); it != set_.end(); it++) {
369 if ((*it)->Matches(recipient)) {
370 return *it;
371 }
372 }
373 return nullptr;
374 }
375
Java_ohos_rpc_getRemoteProxyHolder(JNIEnv * env,jobject object)376 JRemoteProxyHolder *Java_ohos_rpc_getRemoteProxyHolder(JNIEnv *env, jobject object)
377 {
378 return reinterpret_cast<JRemoteProxyHolder *>(env->GetLongField(object, g_jRemoteProxy.fieldNativeData));
379 }
380
Java_ohos_rpc_getJavaRemoteObject(JNIEnv * env,const sptr<IRemoteObject> target)381 jobject Java_ohos_rpc_getJavaRemoteObject(JNIEnv *env, const sptr<IRemoteObject> target)
382 {
383 ZLOGD(LABEL, "enter");
384 if (env == nullptr) {
385 ZLOGE(LABEL, "env is null");
386 return nullptr;
387 }
388 if (target == nullptr) {
389 ZLOGE(LABEL, "RemoteObject is null");
390 return nullptr;
391 }
392
393 if (target->CheckObjectLegality()) {
394 IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
395 ZLOGW(LABEL, "object type:%{public}d", tmp->GetObjectType());
396 if (tmp->GetObjectType() == IPCObjectStub::OBJECT_TYPE_JAVA) {
397 ZLOGW(LABEL, "native Get Java RemoteObject");
398 auto object = static_cast<JRemoteObject *>(tmp);
399 return object->GetJObject();
400 }
401 }
402
403 std::lock_guard<std::mutex> lockGuard(g_proxyMutex_);
404 JRemoteProxyHolder *cachedHolder = g_cachedProxyHolder;
405 if (cachedHolder == nullptr) {
406 cachedHolder = new JRemoteProxyHolder();
407 }
408
409 jobject object = env->CallStaticObjectMethod(g_jRemoteProxy.klass, g_jRemoteProxy.methodGetInstance,
410 reinterpret_cast<jlong>(cachedHolder));
411 if (object == nullptr) {
412 if (g_cachedProxyHolder == nullptr) {
413 delete cachedHolder;
414 }
415 return nullptr;
416 }
417 if (JniHelperCheckAndClearLocalException(env)) {
418 if (g_cachedProxyHolder == nullptr) {
419 delete cachedHolder;
420 }
421 env->DeleteLocalRef(object);
422 return nullptr;
423 }
424
425 JRemoteProxyHolder *objectHolder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
426 // If the objects holder is same as the cached holder it should be a new create holder.
427 if (cachedHolder == objectHolder) {
428 objectHolder->object_ = target;
429 objectHolder->list_ = new JDeathRecipientList();
430 g_cachedProxyHolder = nullptr;
431 } else {
432 g_cachedProxyHolder = cachedHolder;
433 }
434 return object;
435 }
436
Java_ohos_rpc_getNativeRemoteObject(JNIEnv * env,jobject object)437 sptr<IRemoteObject> Java_ohos_rpc_getNativeRemoteObject(JNIEnv *env, jobject object)
438 {
439 ZLOGD(LABEL, "enter");
440 if (env == nullptr) {
441 ZLOGE(LABEL, "env is null");
442 return nullptr;
443 }
444 if (object != nullptr) {
445 if (env->IsInstanceOf(object, g_jRemoteStub.klass)) {
446 JRemoteObjectHolder *holder =
447 reinterpret_cast<JRemoteObjectHolder *>(env->GetLongField(object, g_jRemoteStub.fieldNativeHolder));
448 return holder != nullptr ? holder->Get(object) : nullptr;
449 }
450
451 if (env->IsInstanceOf(object, g_jRemoteProxy.klass)) {
452 JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
453 return holder != nullptr ? holder->object_ : nullptr;
454 }
455 }
456 return nullptr;
457 }
458 } // namespace OHOS
459
460 /*
461 * Class: ohos.rpc.IPCSkeleton
462 * Method: nativeGetContextObject
463 * Signature: ()Lohos/rpc/IRemoteObject;
464 */
Java_ohos_rpc_IPCSkeleton_nativeGetContextObject(JNIEnv * env,jclass clazz)465 jobject JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetContextObject(JNIEnv *env, jclass clazz)
466 {
467 ZLOGD(LABEL, "enter");
468 if (env == nullptr) {
469 ZLOGE(LABEL, "env is null");
470 return nullptr;
471 }
472 sptr<IRemoteObject> object = IPCSkeleton::GetContextObject();
473 if (object == nullptr) {
474 ZLOGE(LABEL, "fatal error, could not get registry object");
475 return nullptr;
476 }
477 return Java_ohos_rpc_getJavaRemoteObject(env, object);
478 }
479
480 /*
481 * Class: ohos.rpc.IPCSkeleton
482 * Method: nativeGetCallingPid
483 * Signature: ()I;
484 */
Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid(JNIEnv * env,jclass clazz)485 jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid(JNIEnv *env, jclass clazz)
486 {
487 pid_t pid = IPCSkeleton::GetCallingPid();
488 return static_cast<jint>(pid);
489 }
490
491 /*
492 * Class: ohos.rpc.IPCSkeleton
493 * Method: nativeGetCallingUid
494 * Signature: ()I;
495 */
Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid(JNIEnv * env,jclass clazz)496 jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid(JNIEnv *env, jclass clazz)
497 {
498 uid_t uid = IPCSkeleton::GetCallingUid();
499 return static_cast<jint>(uid);
500 }
501
502 /*
503 * Class: ohos.rpc.IPCSkeleton
504 * Method: nativeGetCallingDeviceID
505 * Signature: (V)Ljava/lang/String;
506 */
Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID(JNIEnv * env,jclass clazz)507 jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID(JNIEnv *env, jclass clazz)
508 {
509 if (env == nullptr) {
510 ZLOGE(LABEL, "env is null");
511 return nullptr;
512 }
513 std::string deviceId = IPCSkeleton::GetCallingDeviceID();
514 return env->NewStringUTF(deviceId.c_str());
515 }
516
517 /*
518 * Class: ohos.rpc.IPCSkeleton
519 * Method: nativeGetLocalDeviceID
520 * Signature: (V)Ljava/lang/String;
521 */
Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID(JNIEnv * env,jclass clazz)522 jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID(JNIEnv *env, jclass clazz)
523 {
524 if (env == nullptr) {
525 ZLOGE(LABEL, "env is null");
526 return nullptr;
527 }
528 std::string deviceId = IPCSkeleton::GetLocalDeviceID();
529 return env->NewStringUTF(deviceId.c_str());
530 }
531
532 /*
533 * Class: ohos.rpc.IPCSkeleton
534 * Method: nativeIsLocalCalling
535 * Signature: ()Z;
536 */
Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling(JNIEnv * env,jclass clazz)537 jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling(JNIEnv *env, jclass clazz)
538 {
539 return (IPCSkeleton::IsLocalCalling() == true) ? JNI_TRUE : JNI_FALSE;
540 }
541
542 /*
543 * Class: ohos.rpc.IPCSkeleton
544 * Method: nativeIsLocalCalling
545 * Signature: (Lohos/rpc/IRemoteObject;)I;
546 */
Java_ohos_rpc_IPCSkeleton_nativeFlushCommands(JNIEnv * env,jclass clazz,jobject object)547 jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeFlushCommands(JNIEnv *env, jclass clazz, jobject object)
548 {
549 if (env == nullptr) {
550 ZLOGE(LABEL, "env is null");
551 return JNI_ERR;
552 }
553 sptr<IRemoteObject> target = Java_ohos_rpc_getNativeRemoteObject(env, object);
554 return static_cast<jint>(IPCSkeleton::FlushCommands(target));
555 }
556
557 /*
558 * Class: ohos.rpc.IPCSkeleton
559 * Method: nativeResetCallingIdentity
560 * Signature: ()Ljava/lang/String;
561 */
Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity(JNIEnv * env,jclass clazz)562 jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity(JNIEnv *env, jclass clazz)
563 {
564 if (env == nullptr) {
565 ZLOGE(LABEL, "env is null");
566 return nullptr;
567 }
568 std::string identity = IPCSkeleton::ResetCallingIdentity();
569 return env->NewStringUTF(identity.c_str());
570 }
571
572 /*
573 * Class: ohos.rpc.IPCSkeleton
574 * Method: nativeSetCallingIdentity
575 * Signature: ((Ljava/lang/String;I)Z
576 */
Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity(JNIEnv * env,jclass clazz,jstring identity,jint len)577 jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity(JNIEnv *env, jclass clazz, jstring identity,
578 jint len)
579 {
580 if (env == nullptr || len < 0) {
581 ZLOGE(LABEL, "env is null or len < 0");
582 return JNI_FALSE;
583 }
584 const char *identityUtf = env->GetStringUTFChars(identity, JNI_FALSE);
585
586 if (identityUtf != nullptr) {
587 std::string token = std::string(identityUtf, len);
588 env->ReleaseStringUTFChars(identity, identityUtf);
589
590 return (IPCSkeleton::SetCallingIdentity(token) == true) ? JNI_TRUE : JNI_FALSE;
591 }
592
593 return JNI_FALSE;
594 }
595
596 /*
597 * Class: ohos.rpc.RemoteObject
598 * Method: nativeGetObjectHolder
599 * Signature: (Ljava/lang/String;I)J
600 */
Java_ohos_rpc_RemoteObject_nativeGetObjectHolder(JNIEnv * env,jclass clazz,jstring value,jint len)601 jlong JNICALL Java_ohos_rpc_RemoteObject_nativeGetObjectHolder(JNIEnv *env, jclass clazz, jstring value, jint len)
602 {
603 std::u16string descriptor = std::u16string();
604 if (value != nullptr) {
605 const jchar *jcharStr = env->GetStringCritical(value, 0);
606 if (jcharStr != nullptr) {
607 descriptor.assign(reinterpret_cast<const char16_t *>(jcharStr), reinterpret_cast<int32_t>(len));
608 env->ReleaseStringCritical(value, jcharStr);
609 }
610 }
611 return (jlong)(new JRemoteObjectHolder(descriptor));
612 }
613
614 /*
615 * Get calling pid from native.
616 * Class: ohos.rpc.RemoteObject
617 * Method: nativeGetCallingPid
618 * Signature: ()I
619 */
Java_ohos_rpc_RemoteObject_nativeGetCallingPid(JNIEnv * env,jclass object)620 jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingPid(JNIEnv *env, jclass object)
621 {
622 sptr<IRemoteObject> nativeObject = Java_ohos_rpc_getNativeRemoteObject(env, object);
623 if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
624 IPCObjectStub *target = reinterpret_cast<IPCObjectStub *>(nativeObject.GetRefPtr());
625 return target->GetCallingPid();
626 }
627 return getpid();
628 }
629
630 /*
631 * Get calling uid from native.
632 * Class: ohos.rpc.RemoteObject
633 * Method: nativeGetCallingUid
634 * Signature: ()I
635 */
Java_ohos_rpc_RemoteObject_nativeGetCallingUid(JNIEnv * env,jclass object)636 jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingUid(JNIEnv *env, jclass object)
637 {
638 sptr<IRemoteObject> nativeObject = Java_ohos_rpc_getNativeRemoteObject(env, object);
639 if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
640 IPCObjectStub *target = reinterpret_cast<IPCObjectStub *>(nativeObject.GetRefPtr());
641 return target->GetCallingUid();
642 }
643 return getuid();
644 }
645
646 /*
647 * Free local Object Holder of RemoteObject.
648 * Class: ohos.rpc.RemoteObject
649 * Method: nativeFreeObjectHolder
650 * Signature: (J)V
651 */
Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder(JNIEnv * env,jclass clazz,jlong holder)652 void JNICALL Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder(JNIEnv *env, jclass clazz, jlong holder)
653 {
654 // Delegate sptr to manage memory,
655 // it will automatically release managed memory when the life cycle ends.
656 ZLOGD(LABEL, "Call Free Object Holder");
657 std::unique_ptr<JRemoteObjectHolder> nativeHolder(reinterpret_cast<JRemoteObjectHolder *>(holder));
658 }
659
660 /*
661 * Free local Object Holder of RemoteObject.
662 * Class: ohos.rpc.RemoteProxy
663 * Method: nativeFreeProxyHolder
664 * Signature: (J)V
665 */
Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder(JNIEnv * env,jclass clazz,jlong holder)666 void JNICALL Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder(JNIEnv *env, jclass clazz, jlong holder)
667 {
668 // Delegate sptr to manage memory,
669 // it will automatically release managed memory when the life cycle ends.
670 JRemoteProxyHolder *proxyHolder = reinterpret_cast<JRemoteProxyHolder *>(holder);
671 if (proxyHolder == nullptr) {
672 ZLOGE(LABEL, "proxyHolder is null");
673 return;
674 }
675 IPCObjectProxy *proxy = reinterpret_cast<IPCObjectProxy *>(proxyHolder->object_.GetRefPtr());
676 if (proxy == nullptr) {
677 ZLOGE(LABEL, "proxy is null");
678 return;
679 }
680 ZLOGD(LABEL, "handle:%{public}u", proxy->GetHandle());
681 std::unique_ptr<JRemoteProxyHolder> nativeHolder(reinterpret_cast<JRemoteProxyHolder *>(holder));
682 }
683
684 /*
685 * Class: ohos.rpc.RemoteProxy
686 * Method: nativeSendRequest
687 * Signature: (ILohos/rpc/MessageParcel;Lohos/rpc/Parcel;Lohos/rpc/MessageOption;)Z
688 */
Java_ohos_rpc_RemoteProxy_nativeSendRequest(JNIEnv * env,jobject object,jint code,jobject data,jobject reply,jobject option)689 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeSendRequest(JNIEnv *env, jobject object, jint code, jobject data,
690 jobject reply, jobject option)
691 {
692 if (env == nullptr) {
693 ZLOGE(LABEL, "env is null");
694 return JNI_FALSE;
695 }
696 MessageParcel *nativeData = JavaOhosRpcMessageParcelGetNative(env, data);
697 if (nativeData == nullptr) {
698 JniHelperThrowNullPointerException(env, "data field is null");
699 return JNI_FALSE;
700 }
701
702 MessageParcel *nativeReply = JavaOhosRpcMessageParcelGetNative(env, reply);
703 if (nativeReply == nullptr) {
704 ZLOGE(LABEL, "Fail to get native parcel for reply");
705 return JNI_FALSE;
706 }
707
708 MessageOptionPtr nativeOption = JavaOhosRpcMessageOptionGetNative(env, option);
709 if (nativeOption == nullptr) {
710 ZLOGE(LABEL, "Fail to get native parcel for reply");
711 return JNI_FALSE;
712 }
713
714 JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
715 if (holder == nullptr) {
716 JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
717 return JNI_FALSE;
718 }
719
720 sptr<IRemoteObject> target = holder->object_;
721 if (target == nullptr) {
722 ZLOGE(LABEL, "Invalid proxy object");
723 return JNI_FALSE;
724 }
725
726 int result = target->SendRequest(code, *nativeData, *nativeReply, *nativeOption.get());
727 if (result != ERR_NONE) {
728 ZLOGE(LABEL, "failed, result:%{public}d", result);
729 return JNI_FALSE;
730 }
731 ZLOGD(LABEL, "success");
732
733 return JNI_TRUE;
734 }
735
736 /*
737 * Class: ohos.rpc.RemoteProxy
738 * Method: nativeAddDeathRecipient
739 * Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
740 */
Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient(JNIEnv * env,jobject object,jobject recipient,jint flags)741 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient(JNIEnv *env, jobject object, jobject recipient,
742 jint flags)
743 {
744 ZLOGD(LABEL, "enter");
745 if (recipient == nullptr) {
746 JniHelperThrowNullPointerException(env, "the recipient is null");
747 return JNI_FALSE;
748 }
749
750 JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
751 if (holder == nullptr) {
752 JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
753 return JNI_FALSE;
754 }
755
756 sptr<IRemoteObject> target = holder->object_;
757 if ((target == nullptr) || !target->IsProxyObject()) {
758 ZLOGE(LABEL, "could not add recipient from invalid target");
759 return JNI_FALSE;
760 }
761
762 sptr<JDeathRecipient> nativeRecipient = new JDeathRecipient(recipient);
763 if (target->AddDeathRecipient(nativeRecipient)) {
764 JDeathRecipientList *list = holder->list_;
765 return (list->Add(nativeRecipient) ? JNI_TRUE : JNI_FALSE);
766 }
767
768 return JNI_FALSE;
769 }
770
771 /*
772 * Class: ohos.rpc.RemoteProxy
773 * Method: nativeRemoveDeathRecipient
774 * Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
775 */
Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient(JNIEnv * env,jobject object,jobject recipient,jint flags)776 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient(JNIEnv *env, jobject object, jobject recipient,
777 jint flags)
778 {
779 ZLOGD(LABEL, "enter");
780 if (recipient == nullptr) {
781 JniHelperThrowNullPointerException(env, "the recipient is null");
782 return JNI_FALSE;
783 }
784
785 JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
786 if (holder == nullptr) {
787 JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
788 return JNI_FALSE;
789 }
790
791 sptr<IRemoteObject> target = holder->object_;
792 if ((target == nullptr) || !target->IsProxyObject()) {
793 ZLOGE(LABEL, "could not remove recipient from invalid target");
794 return JNI_FALSE;
795 }
796
797 // list should not be null here, it should be alloc at create proxy object.
798 sptr<JDeathRecipientList> list = holder->list_;
799 sptr<JDeathRecipient> nativeRecipient = list->Find(recipient);
800 if (nativeRecipient == nullptr) {
801 ZLOGE(LABEL, "recipient not found");
802 return JNI_FALSE;
803 }
804
805 target->RemoveDeathRecipient(nativeRecipient);
806 return (list->Remove(nativeRecipient) ? JNI_TRUE : JNI_FALSE);
807 }
808
809 /*
810 * Class: ohos.rpc.RemoteProxy
811 * Method: nativeGetInterfaceDescriptor
812 * Signature: ()Ljava/lang/String;
813 */
Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor(JNIEnv * env,jobject object)814 jstring JNICALL Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor(JNIEnv *env, jobject object)
815 {
816 if (env == nullptr) {
817 ZLOGE(LABEL, "env is null");
818 return nullptr;
819 }
820 JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
821 if (holder == nullptr) {
822 JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
823 return env->NewStringUTF("");
824 }
825
826 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
827 if (target == nullptr) {
828 ZLOGE(LABEL, "Invalid proxy object");
829 return env->NewStringUTF("");
830 }
831 std::u16string remoteDescriptor = target->GetInterfaceDescriptor();
832
833 return env->NewStringUTF(Str16ToStr8(remoteDescriptor).c_str());
834 }
835
836 /*
837 * Class: ohos.rpc.RemoteProxy
838 * Method: nativeIsObjectDead
839 * Signature: ()Z
840 */
Java_ohos_rpc_RemoteProxy_nativeIsObjectDead(JNIEnv * env,jobject object)841 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeIsObjectDead(JNIEnv *env, jobject object)
842 {
843 JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
844 if (holder == nullptr) {
845 JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
846 return JNI_TRUE;
847 }
848
849 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
850 if (target == nullptr) {
851 ZLOGE(LABEL, "Invalid proxy object");
852 return JNI_TRUE;
853 }
854
855 return (target->IsObjectDead() == true) ? JNI_TRUE : JNI_FALSE;
856 }
857
858 /*
859 * Class: ohos.rpc.RemoteProxy
860 * Method: nativeGetHandle
861 * Signature: ()J
862 */
Java_ohos_rpc_RemoteProxy_nativeGetHandle(JNIEnv * env,jobject object)863 jlong JNICALL Java_ohos_rpc_RemoteProxy_nativeGetHandle(JNIEnv *env, jobject object)
864 {
865 JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
866 if (holder == nullptr) {
867 JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
868 return 0;
869 }
870
871 IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
872 if (target == nullptr) {
873 ZLOGE(LABEL, "Invalid proxy object");
874 return 0;
875 }
876
877 return (jlong)target->GetHandle();
878 }
879
880 static const JNINativeMethod sMethods[] = {
881 /* Name, Signature, FunctionPointer */
882 { "nativeGetContextObject", "()Lohos/rpc/IRemoteObject;",
883 (void *)Java_ohos_rpc_IPCSkeleton_nativeGetContextObject },
884 { "nativeGetCallingPid", "()I", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid },
885 { "nativeGetCallingUid", "()I", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid },
886 { "nativeGetCallingDeviceID", "()Ljava/lang/String;", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID },
887 { "nativeGetLocalDeviceID", "()Ljava/lang/String;", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID },
888 { "nativeIsLocalCalling", "()Z", (void *)Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling },
889 { "nativeFlushCommands", "(Lohos/rpc/IRemoteObject;)I", (void *)Java_ohos_rpc_IPCSkeleton_nativeFlushCommands },
890 { "nativeResetCallingIdentity", "()Ljava/lang/String;",
891 (void *)Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity },
892 { "nativeSetCallingIdentity", "(Ljava/lang/String;I)Z",
893 (void *)Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity },
894 };
895
896 static const JNINativeMethod sObjectMethods[] = {
897 /* Name, Signature, FunctionPointer */
898 { "nativeGetObjectHolder", "(Ljava/lang/String;I)J", (void *)Java_ohos_rpc_RemoteObject_nativeGetObjectHolder },
899 { "nativeFreeObjectHolder", "(J)V", (void *)Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder },
900 { "nativeGetCallingPid", "()I", (void *)Java_ohos_rpc_RemoteObject_nativeGetCallingPid },
901 { "nativeGetCallingUid", "()I", (void *)Java_ohos_rpc_RemoteObject_nativeGetCallingUid },
902 };
903
904 static const JNINativeMethod sProxyMethods[] = {
905 /* Name, Signature, FunctionPointer */
906 { "nativeFreeProxyHolder", "(J)V", (void *)Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder },
907 { "nativeGetInterfaceDescriptor", "()Ljava/lang/String;",
908 (void *)Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor },
909 { "nativeSendRequest", "(ILohos/rpc/MessageParcel;Lohos/rpc/MessageParcel;Lohos/rpc/MessageOption;)Z",
910 (void *)Java_ohos_rpc_RemoteProxy_nativeSendRequest },
911 { "nativeAddDeathRecipient", "(Lohos/rpc/IRemoteObject$DeathRecipient;I)Z",
912 (void *)Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient },
913 { "nativeRemoveDeathRecipient", "(Lohos/rpc/IRemoteObject$DeathRecipient;I)Z",
914 (void *)Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient },
915 { "nativeIsObjectDead", "()Z", (void *)Java_ohos_rpc_RemoteProxy_nativeIsObjectDead },
916 { "nativeGetHandle", "()J", (void *)Java_ohos_rpc_RemoteProxy_nativeGetHandle }
917 };
918
JavaOhosRpcIpcSkeletonRegisterNativeMethods(JNIEnv * env)919 int JavaOhosRpcIpcSkeletonRegisterNativeMethods(JNIEnv *env)
920 {
921 if (env == nullptr) {
922 ZLOGE(LABEL, "env is null");
923 return JNI_ERR;
924 }
925 return JkitRegisterNativeMethods(env, "ohos/rpc/IPCSkeleton", sMethods, NUM_METHODS(sMethods));
926 }
927
JavaOhosRpcRemoteObjectRegisterNativeMethods(JNIEnv * env)928 int JavaOhosRpcRemoteObjectRegisterNativeMethods(JNIEnv *env)
929 {
930 if (env == nullptr) {
931 ZLOGE(LABEL, "env is null");
932 return JNI_ERR;
933 }
934 jclass clazz = env->FindClass("ohos/rpc/RemoteObject");
935 if (clazz == nullptr) {
936 ZLOGE(LABEL, "Could not find class:RemoteObject");
937 return JNI_ERR;
938 }
939
940 g_jRemoteStub.klass = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
941 if (g_jRemoteStub.klass == nullptr) {
942 ZLOGE(LABEL, "JRemoteObject NewGlobalRef failed");
943 env->DeleteLocalRef(clazz);
944 return JNI_ERR;
945 }
946
947 g_jRemoteStub.methodDispatchRequest = env->GetMethodID(clazz, "dispatchRequest", "(IJJLohos/rpc/MessageOption;)Z");
948 if (g_jRemoteStub.methodDispatchRequest == nullptr) {
949 ZLOGE(LABEL, "JRemoteObject get method execTransact failed");
950 env->DeleteGlobalRef(g_jRemoteStub.klass);
951 env->DeleteLocalRef(clazz);
952 return JNI_ERR;
953 }
954
955 g_jRemoteStub.methodDispatchDump = env->GetMethodID(clazz, "dispatchDump", "(IJJLohos/rpc/MessageOption;)Z");
956 if (g_jRemoteStub.methodDispatchDump == nullptr) {
957 ZLOGE(LABEL, "JRemoteObject get method execTransact failed");
958 env->DeleteGlobalRef(g_jRemoteStub.klass);
959 env->DeleteLocalRef(clazz);
960 return JNI_ERR;
961 }
962
963 g_jRemoteStub.fieldNativeHolder = env->GetFieldID(clazz, "mNativeHolder", "J");
964 if (g_jRemoteStub.fieldNativeHolder == nullptr) {
965 ZLOGE(LABEL, "JRemoteObject get field mNativeHolder failed");
966 env->DeleteGlobalRef(g_jRemoteStub.klass);
967 env->DeleteLocalRef(clazz);
968 return JNI_ERR;
969 }
970
971 return JkitRegisterNativeMethods(env, "ohos/rpc/RemoteObject", sObjectMethods, NUM_METHODS(sObjectMethods));
972 }
973
JavaOhosRpcRemoteProxyRegisterNativeMethods(JNIEnv * env)974 int JavaOhosRpcRemoteProxyRegisterNativeMethods(JNIEnv *env)
975 {
976 jclass clazz = env->FindClass("ohos/rpc/RemoteProxy");
977 if (clazz == nullptr) {
978 ZLOGE(LABEL, "Could not find class:RemoteProxy");
979 return JNI_ERR;
980 }
981
982 g_jRemoteProxy.klass = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
983 g_jRemoteProxy.methodGetInstance = env->GetStaticMethodID(clazz, "getInstance", "(J)Lohos/rpc/RemoteProxy;");
984 if (g_jRemoteProxy.methodGetInstance == nullptr) {
985 ZLOGE(LABEL, "JRemoteProxy get method getInstance failed");
986 env->DeleteGlobalRef(g_jRemoteProxy.klass);
987 env->DeleteLocalRef(clazz);
988 return JNI_ERR;
989 }
990
991 g_jRemoteProxy.methodSendObituary =
992 env->GetStaticMethodID(clazz, "sendObituary", "(Lohos/rpc/IRemoteObject$DeathRecipient;)V");
993 if (g_jRemoteProxy.methodSendObituary == nullptr) {
994 env->DeleteGlobalRef(g_jRemoteProxy.klass);
995 env->DeleteLocalRef(clazz);
996 ZLOGE(LABEL, "JRemoteProxy get method sendObituary failed");
997 return JNI_ERR;
998 }
999
1000 g_jRemoteProxy.fieldNativeData = env->GetFieldID(clazz, "mNativeData", "J");
1001 if (g_jRemoteProxy.fieldNativeData == nullptr) {
1002 env->DeleteGlobalRef(g_jRemoteProxy.klass);
1003 env->DeleteLocalRef(clazz);
1004 ZLOGE(LABEL, "JRemoteProxy get field mNativeData failed");
1005 return JNI_ERR;
1006 }
1007
1008 return JkitRegisterNativeMethods(env, "ohos/rpc/RemoteProxy", sProxyMethods, NUM_METHODS(sProxyMethods));
1009 }
1010
RegisterJavaRpcNativeMethods(JNIEnv * env)1011 int RegisterJavaRpcNativeMethods(JNIEnv *env)
1012 {
1013 if (JniHelperRegisterNativeMethods(env) < 0) {
1014 ZLOGE(LABEL, "Register JniHelper Native Methods failed");
1015 return JNI_ERR;
1016 }
1017
1018 if (JavaOhosRpcMessageOptionRegisterNativeMethods(env) < 0) {
1019 ZLOGE(LABEL, "Register MessageOption Native Methods failed");
1020 return JNI_ERR;
1021 }
1022
1023 if (JavaOhosRpcMessageParcelRegisterNativeMethods(env) < 0) {
1024 ZLOGE(LABEL, "Register MessageParcel Native Methods failed");
1025 return JNI_ERR;
1026 }
1027
1028 if (JavaOhosRpcIpcSkeletonRegisterNativeMethods(env) < 0) {
1029 ZLOGE(LABEL, "Register IPCSkeleton Native Methods failed");
1030 return JNI_ERR;
1031 }
1032
1033 if (JavaOhosRpcRemoteObjectRegisterNativeMethods(env) < 0) {
1034 ZLOGE(LABEL, "Register JRemoteObject Native Methods failed");
1035 return JNI_ERR;
1036 }
1037
1038 if (JavaOhosRpcRemoteProxyRegisterNativeMethods(env) < 0) {
1039 ZLOGE(LABEL, "Register JRemoteProxy Native Methods failed");
1040 return JNI_ERR;
1041 }
1042
1043 if (Java_ohos_utils_Parcel_registerNativeMethods(env) < 0) {
1044 ZLOGE(LABEL, "Register JParcel Native Methods failed");
1045 return JNI_ERR;
1046 }
1047
1048 return JNI_OK;
1049 }
1050
JNI_OnLoad(JavaVM * vm,void * reserved)1051 jint JNI_OnLoad(JavaVM *vm, void *reserved)
1052 {
1053 if (vm == nullptr) {
1054 return JNI_ERR;
1055 }
1056 if (!g_ipcNativeMethodsLoaded) {
1057 JNIEnv *env = NULL;
1058 if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) {
1059 return JNI_ERR;
1060 }
1061
1062 if (RegisterJavaRpcNativeMethods(env) < 0) {
1063 return JNI_ERR;
1064 }
1065
1066 JNIEnvHelper::nativeInit(vm);
1067 g_ipcNativeMethodsLoaded = true;
1068 }
1069 return JNI_VERSION_1_4;
1070 }
1071