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