1 // Copyright 2021 gRPC authors.
2 //
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 #include <grpc/support/port_platform.h>
16
17 #include "src/core/ext/transport/binder/client/endpoint_binder_pool.h"
18
19 #ifndef GRPC_NO_BINDER
20
21 #include "src/core/ext/transport/binder/client/jni_utils.h"
22
23 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
24
25 #include <jni.h>
26
27 #include "src/core/ext/transport/binder/wire_format/binder_android.h"
28
29 extern "C" {
30 // Adds endpoint binder to binder pool when Java notify us that the endpoint
31 // binder is ready. This is called from GrpcBinderConnection.java
32 JNIEXPORT void JNICALL
Java_io_grpc_binder_cpp_GrpcBinderConnection_notifyConnected__Ljava_lang_String_2Landroid_os_IBinder_2(JNIEnv * jni_env,jobject,jstring conn_id_jstring,jobject ibinder)33 Java_io_grpc_binder_cpp_GrpcBinderConnection_notifyConnected__Ljava_lang_String_2Landroid_os_IBinder_2(
34 JNIEnv* jni_env, jobject, jstring conn_id_jstring, jobject ibinder) {
35 jboolean isCopy;
36 const char* conn_id = jni_env->GetStringUTFChars(conn_id_jstring, &isCopy);
37 gpr_log(GPR_INFO, "%s invoked with conn_id = %s", __func__, conn_id);
38 GPR_ASSERT(ibinder != nullptr);
39 grpc_binder::ndk_util::SpAIBinder aibinder =
40 grpc_binder::FromJavaBinder(jni_env, ibinder);
41 gpr_log(GPR_INFO, "%s got aibinder = %p", __func__, aibinder.get());
42 auto b = std::make_unique<grpc_binder::BinderAndroid>(aibinder);
43 GPR_ASSERT(b != nullptr);
44 grpc_binder::GetEndpointBinderPool()->AddEndpointBinder(conn_id,
45 std::move(b));
46 if (isCopy == JNI_TRUE) {
47 jni_env->ReleaseStringUTFChars(conn_id_jstring, conn_id);
48 }
49 }
50 }
51
52 #endif // GPR_SUPPORT_BINDER_TRANSPORT
53
54 namespace grpc_binder {
55
GetEndpointBinder(std::string conn_id,std::function<void (std::unique_ptr<grpc_binder::Binder>)> cb)56 void EndpointBinderPool::GetEndpointBinder(
57 std::string conn_id,
58 std::function<void(std::unique_ptr<grpc_binder::Binder>)> cb) {
59 gpr_log(GPR_INFO, "EndpointBinder requested. conn_id = %s", conn_id.c_str());
60 std::unique_ptr<grpc_binder::Binder> b;
61 {
62 grpc_core::MutexLock l(&m_);
63 if (binder_map_.count(conn_id)) {
64 b = std::move(binder_map_[conn_id]);
65 binder_map_.erase(conn_id);
66 GPR_ASSERT(b != nullptr);
67 } else {
68 if (pending_requests_.count(conn_id) != 0) {
69 gpr_log(GPR_ERROR,
70 "Duplicate GetEndpointBinder requested. conn_id = %s",
71 conn_id.c_str());
72 return;
73 }
74 pending_requests_[conn_id] = std::move(cb);
75 return;
76 }
77 }
78 GPR_ASSERT(b != nullptr);
79 cb(std::move(b));
80 }
81
AddEndpointBinder(std::string conn_id,std::unique_ptr<grpc_binder::Binder> b)82 void EndpointBinderPool::AddEndpointBinder(
83 std::string conn_id, std::unique_ptr<grpc_binder::Binder> b) {
84 gpr_log(GPR_INFO, "EndpointBinder added. conn_id = %s", conn_id.c_str());
85 GPR_ASSERT(b != nullptr);
86 // cb will be set in the following block if there is a pending callback
87 std::function<void(std::unique_ptr<grpc_binder::Binder>)> cb = nullptr;
88 {
89 grpc_core::MutexLock l(&m_);
90 if (binder_map_.count(conn_id) != 0) {
91 gpr_log(GPR_ERROR, "EndpointBinder already in the pool. conn_id = %s",
92 conn_id.c_str());
93 return;
94 }
95 if (pending_requests_.count(conn_id)) {
96 cb = std::move(pending_requests_[conn_id]);
97 pending_requests_.erase(conn_id);
98 } else {
99 binder_map_[conn_id] = std::move(b);
100 b = nullptr;
101 }
102 }
103 if (cb != nullptr) {
104 cb(std::move(b));
105 }
106 }
107
GetEndpointBinderPool()108 EndpointBinderPool* GetEndpointBinderPool() {
109 static EndpointBinderPool* p = new EndpointBinderPool();
110 return p;
111 }
112 } // namespace grpc_binder
113 #endif
114