• 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 "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, "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:%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, "OnRemoteRequest res:%{public}d", result);
207             return ERR_INVALID_DATA;
208         }
209     }
210     if (!res) {
211         ZLOGE(LABEL, "OnRemoteRequest 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, "OnRemoteDump res:%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, "OnRemoteDied 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     JNIEnvHelper env;
330 
331     if (env.Get() != nullptr) {
332         if (refObject_ != nullptr) {
333             env->DeleteGlobalRef(refObject_);
334         } else {
335             if (weakRefObject_ != nullptr) {
336                 env->DeleteWeakGlobalRef(weakRefObject_);
337             }
338         }
339     }
340 }
341 
JDeathRecipientList()342 JDeathRecipientList::JDeathRecipientList() {}
343 
~JDeathRecipientList()344 JDeathRecipientList::~JDeathRecipientList()
345 {
346     std::lock_guard<std::mutex> lockGuard(mutex_);
347     set_.clear();
348 }
349 
Add(const sptr<JDeathRecipient> & recipient)350 bool JDeathRecipientList::Add(const sptr<JDeathRecipient> &recipient)
351 {
352     std::lock_guard<std::mutex> lockGuard(mutex_);
353     auto ret = set_.insert(recipient);
354     return ret.second;
355 }
356 
Remove(const sptr<JDeathRecipient> & recipient)357 bool JDeathRecipientList::Remove(const sptr<JDeathRecipient> &recipient)
358 {
359     std::lock_guard<std::mutex> lockGuard(mutex_);
360     return (set_.erase(recipient) > 0);
361 }
362 
Find(jobject recipient)363 sptr<JDeathRecipient> JDeathRecipientList::Find(jobject recipient)
364 {
365     std::lock_guard<std::mutex> lockGuard(mutex_);
366 
367     for (auto it = set_.begin(); it != set_.end(); it++) {
368         if ((*it)->Matches(recipient)) {
369             return *it;
370         }
371     }
372     return nullptr;
373 }
374 
Java_ohos_rpc_getRemoteProxyHolder(JNIEnv * env,jobject object)375 JRemoteProxyHolder *Java_ohos_rpc_getRemoteProxyHolder(JNIEnv *env, jobject object)
376 {
377     return reinterpret_cast<JRemoteProxyHolder *>(env->GetLongField(object, g_jRemoteProxy.fieldNativeData));
378 }
379 
Java_ohos_rpc_getJavaRemoteObject(JNIEnv * env,const sptr<IRemoteObject> target)380 jobject Java_ohos_rpc_getJavaRemoteObject(JNIEnv *env, const sptr<IRemoteObject> target)
381 {
382     ZLOGD(LABEL, "%s", __func__);
383     if (target == nullptr) {
384         ZLOGE(LABEL, "RemoteObject is null");
385         return nullptr;
386     }
387 
388     if (target->CheckObjectLegality()) {
389         IPCObjectStub *tmp = static_cast<IPCObjectStub *>(target.GetRefPtr());
390         ZLOGW(LABEL, "object type:%{public}d", tmp->GetObjectType());
391         if (tmp->GetObjectType() == IPCObjectStub::OBJECT_TYPE_JAVA) {
392             ZLOGW(LABEL, "native Get Java RemoteObject");
393             auto object = static_cast<JRemoteObject *>(tmp);
394             return object->GetJObject();
395         }
396     }
397 
398     std::lock_guard<std::mutex> lockGuard(g_proxyMutex_);
399     JRemoteProxyHolder *cachedHolder = g_cachedProxyHolder;
400     if (cachedHolder == nullptr) {
401         cachedHolder = new JRemoteProxyHolder();
402     }
403 
404     jobject object = env->CallStaticObjectMethod(g_jRemoteProxy.klass, g_jRemoteProxy.methodGetInstance,
405         reinterpret_cast<jlong>(cachedHolder));
406     if (object == nullptr) {
407         if (g_cachedProxyHolder == nullptr) {
408             delete cachedHolder;
409         }
410         return nullptr;
411     }
412     if (JniHelperCheckAndClearLocalException(env)) {
413         if (g_cachedProxyHolder == nullptr) {
414             delete cachedHolder;
415         }
416         env->DeleteLocalRef(object);
417         return nullptr;
418     }
419 
420     JRemoteProxyHolder *objectHolder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
421     // If the objects holder is same as the cached holder it should be a new create holder.
422     if (cachedHolder == objectHolder) {
423         objectHolder->object_ = target;
424         objectHolder->list_ = new JDeathRecipientList();
425         g_cachedProxyHolder = nullptr;
426     } else {
427         g_cachedProxyHolder = cachedHolder;
428     }
429     return object;
430 }
431 
Java_ohos_rpc_getNativeRemoteObject(JNIEnv * env,jobject object)432 sptr<IRemoteObject> Java_ohos_rpc_getNativeRemoteObject(JNIEnv *env, jobject object)
433 {
434     ZLOGD(LABEL, "%s", __func__);
435     if (object != nullptr) {
436         if (env->IsInstanceOf(object, g_jRemoteStub.klass)) {
437             JRemoteObjectHolder *holder =
438                 reinterpret_cast<JRemoteObjectHolder *>(env->GetLongField(object, g_jRemoteStub.fieldNativeHolder));
439             return holder != nullptr ? holder->Get(object) : nullptr;
440         }
441 
442         if (env->IsInstanceOf(object, g_jRemoteProxy.klass)) {
443             JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
444             return holder != nullptr ? holder->object_ : nullptr;
445         }
446     }
447     return nullptr;
448 }
449 } // namespace OHOS
450 
451 /*
452  * Class:     ohos.rpc.IPCSkeleton
453  * Method:    nativeGetContextObject
454  * Signature: ()Lohos/rpc/IRemoteObject;
455  */
Java_ohos_rpc_IPCSkeleton_nativeGetContextObject(JNIEnv * env,jclass clazz)456 jobject JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetContextObject(JNIEnv *env, jclass clazz)
457 {
458     ZLOGD(LABEL, "%s", __func__);
459     sptr<IRemoteObject> object = IPCSkeleton::GetContextObject();
460     if (object == nullptr) {
461         ZLOGE(LABEL, "fatal error, could not get registry object");
462         return nullptr;
463     }
464     return Java_ohos_rpc_getJavaRemoteObject(env, object);
465 }
466 
467 /*
468  * Class:     ohos.rpc.IPCSkeleton
469  * Method:    nativeGetCallingPid
470  * Signature: ()I;
471  */
Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid(JNIEnv * env,jclass clazz)472 jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid(JNIEnv *env, jclass clazz)
473 {
474     pid_t pid = IPCSkeleton::GetCallingPid();
475     return static_cast<jint>(pid);
476 }
477 
478 /*
479  * Class:     ohos.rpc.IPCSkeleton
480  * Method:    nativeGetCallingUid
481  * Signature: ()I;
482  */
Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid(JNIEnv * env,jclass clazz)483 jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid(JNIEnv *env, jclass clazz)
484 {
485     uid_t uid = IPCSkeleton::GetCallingUid();
486     return static_cast<jint>(uid);
487 }
488 
489 /*
490  * Class:     ohos.rpc.IPCSkeleton
491  * Method:    nativeGetCallingDeviceID
492  * Signature: (V)Ljava/lang/String;
493  */
Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID(JNIEnv * env,jclass clazz)494 jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID(JNIEnv *env, jclass clazz)
495 {
496     std::string deviceId = IPCSkeleton::GetCallingDeviceID();
497     return env->NewStringUTF(deviceId.c_str());
498 }
499 
500 /*
501  * Class:     ohos.rpc.IPCSkeleton
502  * Method:    nativeGetLocalDeviceID
503  * Signature: (V)Ljava/lang/String;
504  */
Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID(JNIEnv * env,jclass clazz)505 jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID(JNIEnv *env, jclass clazz)
506 {
507     std::string deviceId = IPCSkeleton::GetLocalDeviceID();
508     return env->NewStringUTF(deviceId.c_str());
509 }
510 
511 /*
512  * Class:     ohos.rpc.IPCSkeleton
513  * Method:    nativeIsLocalCalling
514  * Signature: ()Z;
515  */
Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling(JNIEnv * env,jclass clazz)516 jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling(JNIEnv *env, jclass clazz)
517 {
518     return (IPCSkeleton::IsLocalCalling() == true) ? JNI_TRUE : JNI_FALSE;
519 }
520 
521 /*
522  * Class:     ohos.rpc.IPCSkeleton
523  * Method:    nativeIsLocalCalling
524  * Signature: (Lohos/rpc/IRemoteObject;)I;
525  */
Java_ohos_rpc_IPCSkeleton_nativeFlushCommands(JNIEnv * env,jclass clazz,jobject object)526 jint JNICALL Java_ohos_rpc_IPCSkeleton_nativeFlushCommands(JNIEnv *env, jclass clazz, jobject object)
527 {
528     sptr<IRemoteObject> target = Java_ohos_rpc_getNativeRemoteObject(env, object);
529     return static_cast<jint>(IPCSkeleton::FlushCommands(target));
530 }
531 
532 /*
533  * Class:     ohos.rpc.IPCSkeleton
534  * Method:    nativeResetCallingIdentity
535  * Signature: ()Ljava/lang/String;
536  */
Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity(JNIEnv * env,jclass clazz)537 jstring JNICALL Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity(JNIEnv *env, jclass clazz)
538 {
539     std::string identity = IPCSkeleton::ResetCallingIdentity();
540     return env->NewStringUTF(identity.c_str());
541 }
542 
543 /*
544  * Class:     ohos.rpc.IPCSkeleton
545  * Method:    nativeSetCallingIdentity
546  * Signature: ((Ljava/lang/String;I)Z
547  */
Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity(JNIEnv * env,jclass clazz,jstring identity,jint len)548 jboolean JNICALL Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity(JNIEnv *env, jclass clazz, jstring identity,
549     jint len)
550 {
551     const char *identityUtf = env->GetStringUTFChars(identity, JNI_FALSE);
552 
553     if (identityUtf != nullptr) {
554         std::string token = std::string(identityUtf, len);
555         env->ReleaseStringUTFChars(identity, identityUtf);
556 
557         return (IPCSkeleton::SetCallingIdentity(token) == true) ? JNI_TRUE : JNI_FALSE;
558     }
559 
560     return JNI_FALSE;
561 }
562 
563 /*
564  * Class:     ohos.rpc.RemoteObject
565  * Method:    nativeGetObjectHolder
566  * Signature: (Ljava/lang/String;I)J
567  */
Java_ohos_rpc_RemoteObject_nativeGetObjectHolder(JNIEnv * env,jclass clazz,jstring value,jint len)568 jlong JNICALL Java_ohos_rpc_RemoteObject_nativeGetObjectHolder(JNIEnv *env, jclass clazz, jstring value, jint len)
569 {
570     std::u16string descriptor = std::u16string();
571     if (value != nullptr) {
572         const jchar *jcharStr = env->GetStringCritical(value, 0);
573         if (jcharStr != nullptr) {
574             descriptor.assign(reinterpret_cast<const char16_t *>(jcharStr), reinterpret_cast<int32_t>(len));
575             env->ReleaseStringCritical(value, jcharStr);
576         }
577     }
578     return (jlong)(new JRemoteObjectHolder(descriptor));
579 }
580 
581 /*
582  * Get calling pid from native.
583  * Class:     ohos.rpc.RemoteObject
584  * Method:    nativeGetCallingPid
585  * Signature: ()I
586  */
Java_ohos_rpc_RemoteObject_nativeGetCallingPid(JNIEnv * env,jclass object)587 jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingPid(JNIEnv *env, jclass object)
588 {
589     sptr<IRemoteObject> nativeObject = Java_ohos_rpc_getNativeRemoteObject(env, object);
590     if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
591         IPCObjectStub *target = reinterpret_cast<IPCObjectStub *>(nativeObject.GetRefPtr());
592         return target->GetCallingPid();
593     }
594     return getpid();
595 }
596 
597 /*
598  * Get calling uid from native.
599  * Class:     ohos.rpc.RemoteObject
600  * Method:    nativeGetCallingUid
601  * Signature: ()I
602  */
Java_ohos_rpc_RemoteObject_nativeGetCallingUid(JNIEnv * env,jclass object)603 jint JNICALL Java_ohos_rpc_RemoteObject_nativeGetCallingUid(JNIEnv *env, jclass object)
604 {
605     sptr<IRemoteObject> nativeObject = Java_ohos_rpc_getNativeRemoteObject(env, object);
606     if ((nativeObject != nullptr) && (!nativeObject->IsProxyObject())) {
607         IPCObjectStub *target = reinterpret_cast<IPCObjectStub *>(nativeObject.GetRefPtr());
608         return target->GetCallingUid();
609     }
610     return getuid();
611 }
612 
613 /*
614  * Free local Object Holder of RemoteObject.
615  * Class:     ohos.rpc.RemoteObject
616  * Method:    nativeFreeObjectHolder
617  * Signature: (J)V
618  */
Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder(JNIEnv * env,jclass clazz,jlong holder)619 void JNICALL Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder(JNIEnv *env, jclass clazz, jlong holder)
620 {
621     // Delegate sptr to manage memory,
622     // it will automatically release managed memory when the life cycle ends.
623     ZLOGD(LABEL, "Call Free Object Holder");
624     std::unique_ptr<JRemoteObjectHolder> nativeHolder(reinterpret_cast<JRemoteObjectHolder *>(holder));
625 }
626 
627 /*
628  * Free local Object Holder of RemoteObject.
629  * Class:     ohos.rpc.RemoteProxy
630  * Method:    nativeFreeProxyHolder
631  * Signature: (J)V
632  */
Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder(JNIEnv * env,jclass clazz,jlong holder)633 void JNICALL Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder(JNIEnv *env, jclass clazz, jlong holder)
634 {
635     // Delegate sptr to manage memory,
636     // it will automatically release managed memory when the life cycle ends.
637     ZLOGD(LABEL, "Call Free Proxy Holder");
638     std::unique_ptr<JRemoteProxyHolder> nativeHolder(reinterpret_cast<JRemoteProxyHolder *>(holder));
639 }
640 
641 /*
642  * Class:     ohos.rpc.RemoteProxy
643  * Method:    nativeSendRequest
644  * Signature: (ILohos/rpc/MessageParcel;Lohos/rpc/Parcel;Lohos/rpc/MessageOption;)Z
645  */
Java_ohos_rpc_RemoteProxy_nativeSendRequest(JNIEnv * env,jobject object,jint code,jobject data,jobject reply,jobject option)646 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeSendRequest(JNIEnv *env, jobject object, jint code, jobject data,
647     jobject reply, jobject option)
648 {
649     ZLOGD(LABEL, "%s", __func__);
650     MessageParcel *nativeData = JavaOhosRpcMessageParcelGetNative(env, data);
651     if (nativeData == nullptr) {
652         JniHelperThrowNullPointerException(env, "data field is null");
653         return JNI_FALSE;
654     }
655 
656     MessageParcel *nativeReply = JavaOhosRpcMessageParcelGetNative(env, reply);
657     if (nativeReply == nullptr) {
658         ZLOGE(LABEL, "Fail to get native parcel for reply");
659         return JNI_FALSE;
660     }
661 
662     MessageOptionPtr nativeOption = JavaOhosRpcMessageOptionGetNative(env, option);
663     if (nativeOption == nullptr) {
664         ZLOGE(LABEL, "Fail to get native parcel for reply");
665         return JNI_FALSE;
666     }
667 
668     JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
669     if (holder == nullptr) {
670         JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
671         return JNI_FALSE;
672     }
673 
674     sptr<IRemoteObject> target = holder->object_;
675     if (target == nullptr) {
676         ZLOGE(LABEL, "Invalid proxy object");
677         return JNI_FALSE;
678     }
679 
680     int result = target->SendRequest(code, *nativeData, *nativeReply, *nativeOption.get());
681     ZLOGD(LABEL, "nativeSendRequest result %d", result);
682 
683     return (result == ERR_NONE) ? JNI_TRUE : JNI_FALSE;
684 }
685 
686 /*
687  * Class:     ohos.rpc.RemoteProxy
688  * Method:    nativeAddDeathRecipient
689  * Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
690  */
Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient(JNIEnv * env,jobject object,jobject recipient,jint flags)691 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient(JNIEnv *env, jobject object, jobject recipient,
692     jint flags)
693 {
694     if (recipient == nullptr) {
695         JniHelperThrowNullPointerException(env, "the recipient is null");
696         return JNI_FALSE;
697     }
698 
699     JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
700     if (holder == nullptr) {
701         JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
702         return JNI_FALSE;
703     }
704 
705     sptr<IRemoteObject> target = holder->object_;
706     if ((target == nullptr) || !target->IsProxyObject()) {
707         ZLOGE(LABEL, "could not add recipient from invalid target");
708         return JNI_FALSE;
709     }
710 
711     sptr<JDeathRecipient> nativeRecipient = new JDeathRecipient(recipient);
712     if (target->AddDeathRecipient(nativeRecipient)) {
713         JDeathRecipientList *list = holder->list_;
714         return (list->Add(nativeRecipient) ? JNI_TRUE : JNI_FALSE);
715     }
716 
717     return JNI_FALSE;
718 }
719 
720 /*
721  * Class:     ohos.rpc.RemoteProxy
722  * Method:    nativeRemoveDeathRecipient
723  * Signature: (Lohos/rpc/IRemoteObject$DeathRecipient;I)Z
724  */
Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient(JNIEnv * env,jobject object,jobject recipient,jint flags)725 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient(JNIEnv *env, jobject object, jobject recipient,
726     jint flags)
727 {
728     if (recipient == nullptr) {
729         JniHelperThrowNullPointerException(env, "the recipient is null");
730         return JNI_FALSE;
731     }
732 
733     JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
734     if (holder == nullptr) {
735         JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
736         return JNI_FALSE;
737     }
738 
739     sptr<IRemoteObject> target = holder->object_;
740     if ((target == nullptr) || !target->IsProxyObject()) {
741         ZLOGE(LABEL, "could not remove recipient from invalid target");
742         return JNI_FALSE;
743     }
744 
745     // list should not be null here, it should be alloc at create proxy object.
746     sptr<JDeathRecipientList> list = holder->list_;
747     sptr<JDeathRecipient> nativeRecipient = list->Find(recipient);
748     if (nativeRecipient == nullptr) {
749         ZLOGE(LABEL, "recipient not found");
750         return JNI_FALSE;
751     }
752 
753     target->RemoveDeathRecipient(nativeRecipient);
754     return (list->Remove(nativeRecipient) ? JNI_TRUE : JNI_FALSE);
755 }
756 
757 /*
758  * Class:     ohos.rpc.RemoteProxy
759  * Method:    nativeGetInterfaceDescriptor
760  * Signature: ()Ljava/lang/String;
761  */
Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor(JNIEnv * env,jobject object)762 jstring JNICALL Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor(JNIEnv *env, jobject object)
763 {
764     JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
765     if (holder == nullptr) {
766         JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
767         return env->NewStringUTF("");
768     }
769 
770     IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
771     if (target == nullptr) {
772         ZLOGE(LABEL, "Invalid proxy object");
773         return env->NewStringUTF("");
774     }
775     std::u16string remoteDescriptor = target->GetInterfaceDescriptor();
776 
777     return env->NewStringUTF(Str16ToStr8(remoteDescriptor).c_str());
778 }
779 
780 /*
781  * Class:     ohos.rpc.RemoteProxy
782  * Method:    nativeIsObjectDead
783  * Signature: ()Z
784  */
Java_ohos_rpc_RemoteProxy_nativeIsObjectDead(JNIEnv * env,jobject object)785 jboolean JNICALL Java_ohos_rpc_RemoteProxy_nativeIsObjectDead(JNIEnv *env, jobject object)
786 {
787     JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
788     if (holder == nullptr) {
789         JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
790         return JNI_TRUE;
791     }
792 
793     IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
794     if (target == nullptr) {
795         ZLOGE(LABEL, "Invalid proxy object");
796         return JNI_TRUE;
797     }
798 
799     return (target->IsObjectDead() == true) ? JNI_TRUE : JNI_FALSE;
800 }
801 
802 /*
803  * Class:     ohos.rpc.RemoteProxy
804  * Method:    nativeGetHandle
805  * Signature: ()J
806  */
Java_ohos_rpc_RemoteProxy_nativeGetHandle(JNIEnv * env,jobject object)807 jlong JNICALL Java_ohos_rpc_RemoteProxy_nativeGetHandle(JNIEnv *env, jobject object)
808 {
809     JRemoteProxyHolder *holder = Java_ohos_rpc_getRemoteProxyHolder(env, object);
810     if (holder == nullptr) {
811         JniHelperThrowIllegalStateException(env, "Proxy has been finalized!");
812         return 0;
813     }
814 
815     IPCObjectProxy *target = reinterpret_cast<IPCObjectProxy *>(holder->object_.GetRefPtr());
816     if (target == nullptr) {
817         ZLOGE(LABEL, "Invalid proxy object");
818         return 0;
819     }
820 
821     return (jlong)target->GetHandle();
822 }
823 
824 static const JNINativeMethod sMethods[] = {
825     /* Name, Signature, FunctionPointer */
826     { "nativeGetContextObject", "()Lohos/rpc/IRemoteObject;",
827       (void *)Java_ohos_rpc_IPCSkeleton_nativeGetContextObject },
828     { "nativeGetCallingPid", "()I", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingPid },
829     { "nativeGetCallingUid", "()I", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingUid },
830     { "nativeGetCallingDeviceID", "()Ljava/lang/String;", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetCallingDeviceID },
831     { "nativeGetLocalDeviceID", "()Ljava/lang/String;", (void *)Java_ohos_rpc_IPCSkeleton_nativeGetLocalDeviceID },
832     { "nativeIsLocalCalling", "()Z", (void *)Java_ohos_rpc_IPCSkeleton_nativeIsLocalCalling },
833     { "nativeFlushCommands", "(Lohos/rpc/IRemoteObject;)I", (void *)Java_ohos_rpc_IPCSkeleton_nativeFlushCommands },
834     { "nativeResetCallingIdentity", "()Ljava/lang/String;",
835       (void *)Java_ohos_rpc_IPCSkeleton_nativeResetCallingIdentity },
836     { "nativeSetCallingIdentity", "(Ljava/lang/String;I)Z",
837       (void *)Java_ohos_rpc_IPCSkeleton_nativeSetCallingIdentity },
838 };
839 
840 static const JNINativeMethod sObjectMethods[] = {
841     /* Name, Signature, FunctionPointer */
842     { "nativeGetObjectHolder", "(Ljava/lang/String;I)J", (void *)Java_ohos_rpc_RemoteObject_nativeGetObjectHolder },
843     { "nativeFreeObjectHolder", "(J)V", (void *)Java_ohos_rpc_RemoteObject_nativeFreeObjectHolder },
844     { "nativeGetCallingPid", "()I", (void *)Java_ohos_rpc_RemoteObject_nativeGetCallingPid },
845     { "nativeGetCallingUid", "()I", (void *)Java_ohos_rpc_RemoteObject_nativeGetCallingUid },
846 };
847 
848 static const JNINativeMethod sProxyMethods[] = {
849     /* Name, Signature, FunctionPointer */
850     { "nativeFreeProxyHolder", "(J)V", (void *)Java_ohos_rpc_RemoteProxy_nativeFreeProxyHolder },
851     { "nativeGetInterfaceDescriptor", "()Ljava/lang/String;",
852       (void *)Java_ohos_rpc_RemoteProxy_nativeGetInterfaceDescriptor },
853     { "nativeSendRequest", "(ILohos/rpc/MessageParcel;Lohos/rpc/MessageParcel;Lohos/rpc/MessageOption;)Z",
854       (void *)Java_ohos_rpc_RemoteProxy_nativeSendRequest },
855     { "nativeAddDeathRecipient", "(Lohos/rpc/IRemoteObject$DeathRecipient;I)Z",
856       (void *)Java_ohos_rpc_RemoteProxy_nativeAddDeathRecipient },
857     { "nativeRemoveDeathRecipient", "(Lohos/rpc/IRemoteObject$DeathRecipient;I)Z",
858       (void *)Java_ohos_rpc_RemoteProxy_nativeRemoveDeathRecipient },
859     { "nativeIsObjectDead", "()Z", (void *)Java_ohos_rpc_RemoteProxy_nativeIsObjectDead },
860     { "nativeGetHandle", "()J", (void *)Java_ohos_rpc_RemoteProxy_nativeGetHandle }
861 };
862 
JavaOhosRpcIpcSkeletonRegisterNativeMethods(JNIEnv * env)863 int JavaOhosRpcIpcSkeletonRegisterNativeMethods(JNIEnv *env)
864 {
865     return JkitRegisterNativeMethods(env, "ohos/rpc/IPCSkeleton", sMethods, NUM_METHODS(sMethods));
866 }
867 
JavaOhosRpcRemoteObjectRegisterNativeMethods(JNIEnv * env)868 int JavaOhosRpcRemoteObjectRegisterNativeMethods(JNIEnv *env)
869 {
870     jclass clazz = env->FindClass("ohos/rpc/RemoteObject");
871     if (clazz == nullptr) {
872         ZLOGE(LABEL, "Could not find class:RemoteObject");
873         return -1;
874     }
875 
876     g_jRemoteStub.klass = (jclass)env->NewGlobalRef(clazz);
877     if (g_jRemoteStub.klass == nullptr) {
878         ZLOGE(LABEL, "JRemoteObject NewGlobalRef failed");
879         env->DeleteLocalRef(clazz);
880         return -1;
881     }
882 
883     g_jRemoteStub.methodDispatchRequest = env->GetMethodID(clazz, "dispatchRequest", "(IJJLohos/rpc/MessageOption;)Z");
884     if (g_jRemoteStub.methodDispatchRequest == nullptr) {
885         ZLOGE(LABEL, "JRemoteObject get method execTransact failed");
886         env->DeleteGlobalRef(g_jRemoteStub.klass);
887         env->DeleteLocalRef(clazz);
888         return -1;
889     }
890 
891     g_jRemoteStub.methodDispatchDump = env->GetMethodID(clazz, "dispatchDump", "(IJJLohos/rpc/MessageOption;)Z");
892     if (g_jRemoteStub.methodDispatchDump == nullptr) {
893         ZLOGE(LABEL, "JRemoteObject get method execTransact failed");
894         env->DeleteGlobalRef(g_jRemoteStub.klass);
895         env->DeleteLocalRef(clazz);
896         return -1;
897     }
898 
899     g_jRemoteStub.fieldNativeHolder = env->GetFieldID(clazz, "mNativeHolder", "J");
900     if (g_jRemoteStub.fieldNativeHolder == nullptr) {
901         ZLOGE(LABEL, "JRemoteObject get field mNativeHolder failed");
902         env->DeleteGlobalRef(g_jRemoteStub.klass);
903         env->DeleteLocalRef(clazz);
904         return -1;
905     }
906 
907     return JkitRegisterNativeMethods(env, "ohos/rpc/RemoteObject", sObjectMethods, NUM_METHODS(sObjectMethods));
908 }
909 
JavaOhosRpcRemoteProxyRegisterNativeMethods(JNIEnv * env)910 int JavaOhosRpcRemoteProxyRegisterNativeMethods(JNIEnv *env)
911 {
912     jclass clazz = env->FindClass("ohos/rpc/RemoteProxy");
913     if (clazz == nullptr) {
914         ZLOGE(LABEL, "Could not find class:RemoteProxy");
915         return -1;
916     }
917 
918     g_jRemoteProxy.klass = (jclass)env->NewGlobalRef(clazz);
919     g_jRemoteProxy.methodGetInstance = env->GetStaticMethodID(clazz, "getInstance", "(J)Lohos/rpc/RemoteProxy;");
920     if (g_jRemoteProxy.methodGetInstance == nullptr) {
921         ZLOGE(LABEL, "JRemoteProxy get method getInstance failed");
922         env->DeleteGlobalRef(g_jRemoteProxy.klass);
923         env->DeleteLocalRef(clazz);
924         return -1;
925     }
926 
927     g_jRemoteProxy.methodSendObituary =
928         env->GetStaticMethodID(clazz, "sendObituary", "(Lohos/rpc/IRemoteObject$DeathRecipient;)V");
929     if (g_jRemoteProxy.methodSendObituary == nullptr) {
930         env->DeleteGlobalRef(g_jRemoteProxy.klass);
931         env->DeleteLocalRef(clazz);
932         ZLOGE(LABEL, "JRemoteProxy get method sendObituary failed");
933         return -1;
934     }
935 
936     g_jRemoteProxy.fieldNativeData = env->GetFieldID(clazz, "mNativeData", "J");
937     if (g_jRemoteProxy.fieldNativeData == nullptr) {
938         env->DeleteGlobalRef(g_jRemoteProxy.klass);
939         env->DeleteLocalRef(clazz);
940         ZLOGE(LABEL, "JRemoteProxy get field mNativeData failed");
941         return -1;
942     }
943 
944     return JkitRegisterNativeMethods(env, "ohos/rpc/RemoteProxy", sProxyMethods, NUM_METHODS(sProxyMethods));
945 }
946 
RegisterJavaRpcNativeMethods(JNIEnv * env)947 int RegisterJavaRpcNativeMethods(JNIEnv *env)
948 {
949     if (JniHelperRegisterNativeMethods(env) < 0) {
950         ZLOGE(LABEL, "Register JniHelper Native Methods failed");
951         return -1;
952     }
953 
954     if (JavaOhosRpcMessageOptionRegisterNativeMethods(env) < 0) {
955         ZLOGE(LABEL, "Register MessageOption Native Methods failed");
956         return -1;
957     }
958 
959     if (JavaOhosRpcMessageParcelRegisterNativeMethods(env) < 0) {
960         ZLOGE(LABEL, "Register MessageParcel Native Methods failed");
961         return -1;
962     }
963 
964     if (JavaOhosRpcIpcSkeletonRegisterNativeMethods(env) < 0) {
965         ZLOGE(LABEL, "Register IPCSkeleton Native Methods failed");
966         return -1;
967     }
968 
969     if (JavaOhosRpcRemoteObjectRegisterNativeMethods(env) < 0) {
970         ZLOGE(LABEL, "Register JRemoteObject Native Methods failed");
971         return -1;
972     }
973 
974     if (JavaOhosRpcRemoteProxyRegisterNativeMethods(env) < 0) {
975         ZLOGE(LABEL, "Register JRemoteProxy Native Methods failed");
976         return -1;
977     }
978 
979     if (Java_ohos_utils_Parcel_registerNativeMethods(env) < 0) {
980         ZLOGE(LABEL, "Register JParcel Native Methods failed");
981         return -1;
982     }
983 
984     return 0;
985 }
986 
JNI_OnLoad(JavaVM * vm,void * reserved)987 jint JNI_OnLoad(JavaVM *vm, void *reserved)
988 {
989     if (vm == nullptr) {
990         return -1;
991     }
992     if (!g_ipcNativeMethodsLoaded) {
993         JNIEnv *env = NULL;
994         if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) {
995             return -1;
996         }
997 
998         if (RegisterJavaRpcNativeMethods(env) < 0) {
999             return -1;
1000         }
1001 
1002         JNIEnvHelper::nativeInit(vm);
1003         g_ipcNativeMethodsLoaded = true;
1004     }
1005     return JNI_VERSION_1_4;
1006 }
1007