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