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