ndk_binder.cc
Go to the documentation of this file.
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 
16 
18 
19 #ifndef GRPC_NO_BINDER
20 
21 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
22 
23 #include <dlfcn.h>
24 
25 #include <grpc/support/log.h>
26 
27 #include "src/core/lib/gpr/tls.h"
29 
30 namespace {
31 void* GetNdkBinderHandle() {
32  // TODO(mingcl): Consider using RTLD_NOLOAD to check if it is already loaded
33  // first
34  static void* handle = dlopen("libbinder_ndk.so", RTLD_LAZY);
35  if (handle == nullptr) {
36  gpr_log(
37  GPR_ERROR,
38  "Cannot open libbinder_ndk.so. Does this device support API level 29?");
39  GPR_ASSERT(0);
40  }
41  return handle;
42 }
43 
44 JavaVM* g_jvm = nullptr;
45 grpc_core::Mutex g_jvm_mu;
46 
47 // Whether the thread has already attached to JVM (this is to prevent
48 // repeated attachment in `AttachJvm()`)
49 GPR_THREAD_LOCAL(bool) g_is_jvm_attached = false;
50 
51 void SetJvm(JNIEnv* env) {
52  // OK to lock here since this function will only be called once for each
53  // connection.
54  grpc_core::MutexLock lock(&g_jvm_mu);
55  if (g_jvm != nullptr) {
56  return;
57  }
58  JavaVM* jvm = nullptr;
59  jint error = env->GetJavaVM(&jvm);
60  if (error != JNI_OK) {
61  gpr_log(GPR_ERROR, "Failed to get JVM");
62  }
63  g_jvm = jvm;
64  gpr_log(GPR_INFO, "JVM cached");
65 }
66 
67 // `SetJvm` need to be called in the process before `AttachJvm`. This is always
68 // the case because one of `AIBinder_fromJavaBinder`/`AIBinder_toJavaBinder`
69 // will be called before we actually uses the binder. Return `false` if not able
70 // to attach to JVM. Return `true` if JVM is attached (or already attached).
71 bool AttachJvm() {
72  if (g_is_jvm_attached) {
73  return true;
74  }
75  // Note: The following code would be run at most once per thread.
76  grpc_core::MutexLock lock(&g_jvm_mu);
77  if (g_jvm == nullptr) {
78  gpr_log(GPR_ERROR, "JVM not cached yet");
79  return false;
80  }
81  JNIEnv* env_unused;
82  // Note that attach a thread that is already attached is a no-op, so it is
83  // fine to call this again if the thread has already been attached by other.
84  g_jvm->AttachCurrentThread(&env_unused, /* thr_args= */ nullptr);
85  gpr_log(GPR_INFO, "JVM attached successfully");
86  g_is_jvm_attached = true;
87  return true;
88 }
89 
90 } // namespace
91 
92 namespace grpc_binder {
93 namespace ndk_util {
94 
95 // Helper macro to obtain the function pointer corresponding to the name
96 #define FORWARD(name) \
97  typedef decltype(&name) func_type; \
98  static func_type ptr = \
99  reinterpret_cast<func_type>(dlsym(GetNdkBinderHandle(), #name)); \
100  if (ptr == nullptr) { \
101  gpr_log(GPR_ERROR, \
102  "dlsym failed. Cannot find %s in libbinder_ndk.so. " \
103  "BinderTransport requires API level >= 33", \
104  #name); \
105  GPR_ASSERT(0); \
106  } \
107  return ptr
108 
109 void AIBinder_Class_disableInterfaceTokenHeader(AIBinder_Class* clazz) {
110  FORWARD(AIBinder_Class_disableInterfaceTokenHeader)(clazz);
111 }
112 
113 void* AIBinder_getUserData(AIBinder* binder) {
114  FORWARD(AIBinder_getUserData)(binder);
115 }
116 
117 uid_t AIBinder_getCallingUid() { FORWARD(AIBinder_getCallingUid)(); }
118 
119 AIBinder* AIBinder_fromJavaBinder(JNIEnv* env, jobject binder) {
120  SetJvm(env);
121  FORWARD(AIBinder_fromJavaBinder)(env, binder);
122 }
123 
124 AIBinder_Class* AIBinder_Class_define(const char* interfaceDescriptor,
125  AIBinder_Class_onCreate onCreate,
126  AIBinder_Class_onDestroy onDestroy,
127  AIBinder_Class_onTransact onTransact) {
128  FORWARD(AIBinder_Class_define)
129  (interfaceDescriptor, onCreate, onDestroy, onTransact);
130 }
131 
132 AIBinder* AIBinder_new(const AIBinder_Class* clazz, void* args) {
133  FORWARD(AIBinder_new)(clazz, args);
134 }
135 
136 bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
137  FORWARD(AIBinder_associateClass)(binder, clazz);
138 }
139 
140 void AIBinder_incStrong(AIBinder* binder) {
141  FORWARD(AIBinder_incStrong)(binder);
142 }
143 
144 void AIBinder_decStrong(AIBinder* binder) {
145  FORWARD(AIBinder_decStrong)(binder);
146 }
147 
148 binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code,
149  AParcel** in, AParcel** out,
150  binder_flags_t flags) {
151  if (!AttachJvm()) {
152  gpr_log(GPR_ERROR, "failed to attach JVM. AIBinder_transact might fail.");
153  }
154  FORWARD(AIBinder_transact)(binder, code, in, out, flags);
155 }
156 
157 binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
158  AParcel_byteArrayAllocator allocator) {
159  FORWARD(AParcel_readByteArray)(parcel, arrayData, allocator);
160 }
161 
162 void AParcel_delete(AParcel* parcel) { FORWARD(AParcel_delete)(parcel); }
163 int32_t AParcel_getDataSize(const AParcel* parcel) {
164  FORWARD(AParcel_getDataSize)(parcel);
165 }
166 
167 binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
168  FORWARD(AParcel_writeInt32)(parcel, value);
169 }
170 
171 binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
172  FORWARD(AParcel_writeInt64)(parcel, value);
173 }
174 
175 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
176  FORWARD(AParcel_writeStrongBinder)(parcel, binder);
177 }
178 
179 binder_status_t AParcel_writeString(AParcel* parcel, const char* string,
180  int32_t length) {
181  FORWARD(AParcel_writeString)(parcel, string, length);
182 }
183 
184 binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
185  FORWARD(AParcel_readInt32)(parcel, value);
186 }
187 
188 binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
189  FORWARD(AParcel_readInt64)(parcel, value);
190 }
191 
192 binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
193  AParcel_stringAllocator allocator) {
194  FORWARD(AParcel_readString)(parcel, stringData, allocator);
195 }
196 
197 binder_status_t AParcel_readStrongBinder(const AParcel* parcel,
198  AIBinder** binder) {
199  FORWARD(AParcel_readStrongBinder)(parcel, binder);
200 }
201 
202 binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData,
203  int32_t length) {
204  FORWARD(AParcel_writeByteArray)(parcel, arrayData, length);
205 }
206 
207 binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in) {
208  FORWARD(AIBinder_prepareTransaction)(binder, in);
209 }
210 
211 jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder) {
212  SetJvm(env);
213  FORWARD(AIBinder_toJavaBinder)(env, binder);
214 }
215 
216 } // namespace ndk_util
217 } // namespace grpc_binder
218 
219 #endif
220 #endif
ndk_binder.h
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
log.h
generate.env
env
Definition: generate.py:37
grpc_core::MutexLock
Definition: src/core/lib/gprpp/sync.h:88
grpc_binder
Definition: connection_id_generator.cc:45
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
error
grpc_error_handle error
Definition: retry_filter.cc:499
transaction_code_t
uint32_t transaction_code_t
Definition: binder_constants.h:24
grpc_status._async.code
code
Definition: grpcio_status/grpc_status/_async.py:34
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
asyncio_get_stats.args
args
Definition: asyncio_get_stats.py:40
GPR_ASSERT
#define GPR_ASSERT(x)
Definition: include/grpc/impl/codegen/log.h:94
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
GPR_THREAD_LOCAL
#define GPR_THREAD_LOCAL(type)
Definition: tls.h:151
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
value
const char * value
Definition: hpack_parser_table.cc:165
grpc_core::Mutex
Definition: src/core/lib/gprpp/sync.h:61
absl::flags_internal
Definition: abseil-cpp/absl/flags/commandlineflag.h:40
env
Definition: env.py:1
tls.h
handle
static csh handle
Definition: test_arm_regression.c:16
flags
uint32_t flags
Definition: retry_filter.cc:632
int8_t
signed char int8_t
Definition: stdint-msvc2008.h:75
code
Definition: bloaty/third_party/zlib/contrib/infback9/inftree9.h:24
length
std::size_t length
Definition: abseil-cpp/absl/time/internal/test_util.cc:57
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
sync.h
port_platform.h


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:31