binder_android.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 
17 #ifndef GRPC_NO_BINDER
18 
19 #ifdef GPR_SUPPORT_BINDER_TRANSPORT
20 
21 #include <map>
22 
23 #include "absl/memory/memory.h"
24 #include "absl/strings/str_cat.h"
25 
26 #include <grpc/support/log.h>
27 
30 
31 namespace grpc_binder {
32 namespace {
33 
34 struct BinderUserData {
35  explicit BinderUserData(grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
37  : wire_reader_ref(wire_reader_ref), callback(callback) {}
40 };
41 
42 struct OnCreateArgs {
45 };
46 
47 void* f_onCreate_userdata(void* data) {
48  auto* args = static_cast<OnCreateArgs*>(data);
49  return new BinderUserData(args->wire_reader_ref, args->callback);
50 }
51 
52 void f_onDestroy_delete(void* data) {
53  auto* user_data = static_cast<BinderUserData*>(data);
54  delete user_data;
55 }
56 
57 void* f_onCreate_noop(void* /*args*/) { return nullptr; }
58 void f_onDestroy_noop(void* /*userData*/) {}
59 
60 // TODO(mingcl): Consider if thread safety is a requirement here
61 ndk_util::binder_status_t f_onTransact(ndk_util::AIBinder* binder,
63  const ndk_util::AParcel* in,
64  ndk_util::AParcel* /*out*/) {
65  gpr_log(GPR_INFO, __func__);
66  gpr_log(GPR_INFO, "tx code = %u", code);
67 
68  auto* user_data =
69  static_cast<BinderUserData*>(ndk_util::AIBinder_getUserData(binder));
70  TransactionReceiver::OnTransactCb* callback = user_data->callback;
71  // Wrap the parcel in a ReadableParcel.
72  std::unique_ptr<ReadableParcel> output =
73  absl::make_unique<ReadableParcelAndroid>(in);
74  // The lock should be released "after" the callback finishes.
76  (*callback)(code, output.get(), ndk_util::AIBinder_getCallingUid());
77  if (status.ok()) {
78  return ndk_util::STATUS_OK;
79  } else {
80  gpr_log(GPR_ERROR, "Callback failed: %s", status.ToString().c_str());
81  return ndk_util::STATUS_UNKNOWN_ERROR;
82  }
83 }
84 
85 // StdStringAllocator, ReadString, StdVectorAllocator, and ReadVector's
86 // implementations are copied from android/binder_parcel_utils.h
87 // We cannot include the header because it does not compile in C++11
88 
89 bool StdStringAllocator(void* stringData, int32_t length, char** buffer) {
90  if (length <= 0) return false;
91 
92  std::string* str = static_cast<std::string*>(stringData);
93  str->resize(static_cast<size_t>(length) - 1);
94  *buffer = &(*str)[0];
95  return true;
96 }
97 
98 ndk_util::binder_status_t AParcelReadString(const ndk_util::AParcel* parcel,
99  std::string* str) {
100  void* stringData = static_cast<void*>(str);
101  return ndk_util::AParcel_readString(parcel, stringData, StdStringAllocator);
102 }
103 
104 template <typename T>
105 bool StdVectorAllocator(void* vectorData, int32_t length, T** outBuffer) {
106  if (length < 0) return false;
107 
108  std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
109  if (static_cast<size_t>(length) > vec->max_size()) return false;
110 
111  vec->resize(static_cast<size_t>(length));
112  *outBuffer = vec->data();
113  return true;
114 }
115 
116 ndk_util::binder_status_t AParcelReadVector(const ndk_util::AParcel* parcel,
117  std::vector<uint8_t>* vec) {
118  void* vectorData = static_cast<void*>(vec);
119  return ndk_util::AParcel_readByteArray(parcel, vectorData,
120  StdVectorAllocator<int8_t>);
121 }
122 
123 } // namespace
124 
125 ndk_util::SpAIBinder FromJavaBinder(JNIEnv* jni_env, jobject binder) {
126  return ndk_util::SpAIBinder(
127  ndk_util::AIBinder_fromJavaBinder(jni_env, binder));
128 }
129 
130 TransactionReceiverAndroid::TransactionReceiverAndroid(
131  grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
132  OnTransactCb transact_cb)
133  : transact_cb_(transact_cb) {
134  // TODO(mingcl): For now interface descriptor is always empty, figure out if
135  // we want it to be something more meaningful (we can probably manually change
136  // interface descriptor by modifying Java code's reply to
137  // os.IBinder.INTERFACE_TRANSACTION)
138  ndk_util::AIBinder_Class* aibinder_class = ndk_util::AIBinder_Class_define(
139  /*interfaceDescriptor=*/"", f_onCreate_userdata, f_onDestroy_delete,
140  f_onTransact);
141 
142  ndk_util::AIBinder_Class_disableInterfaceTokenHeader(aibinder_class);
143 
144  // Pass the on-transact callback to the on-create function of the binder. The
145  // on-create function equips the callback with a mutex and gives it to the
146  // user data stored in the binder which can be retrieved later.
147  // Also Ref() (called implicitly by the copy constructor of RefCountedPtr) the
148  // wire reader so that it would not be destructed during the callback
149  // invocation.
150  OnCreateArgs args;
151  args.wire_reader_ref = wire_reader_ref;
152  args.callback = &transact_cb_;
153  binder_ = ndk_util::AIBinder_new(aibinder_class, &args);
154  GPR_ASSERT(binder_);
155  gpr_log(GPR_INFO, "ndk_util::AIBinder_associateClass = %d",
156  static_cast<int>(
157  ndk_util::AIBinder_associateClass(binder_, aibinder_class)));
158 }
159 
160 TransactionReceiverAndroid::~TransactionReceiverAndroid() {
161  // Release the binder.
162  ndk_util::AIBinder_decStrong(binder_);
163 }
164 
165 namespace {
166 
167 ndk_util::binder_status_t f_onTransact_noop(ndk_util::AIBinder* /*binder*/,
168  transaction_code_t /*code*/,
169  const ndk_util::AParcel* /*in*/,
170  ndk_util::AParcel* /*out*/) {
171  return {};
172 }
173 
174 void AssociateWithNoopClass(ndk_util::AIBinder* binder) {
175  // Need to associate class before using it
176  ndk_util::AIBinder_Class* aibinder_class = ndk_util::AIBinder_Class_define(
177  "", f_onCreate_noop, f_onDestroy_noop, f_onTransact_noop);
178 
179  ndk_util::AIBinder_Class_disableInterfaceTokenHeader(aibinder_class);
180 
181  gpr_log(GPR_INFO, "ndk_util::AIBinder_associateClass = %d",
182  static_cast<int>(
183  ndk_util::AIBinder_associateClass(binder, aibinder_class)));
184 }
185 
186 } // namespace
187 
189  ndk_util::AIBinder* binder = binder_.get();
190  AssociateWithNoopClass(binder);
191 }
192 
193 absl::Status BinderAndroid::PrepareTransaction() {
194  ndk_util::AIBinder* binder = binder_.get();
195  return ndk_util::AIBinder_prepareTransaction(
196  binder, &input_parcel_->parcel_) == ndk_util::STATUS_OK
197  ? absl::OkStatus()
198  : absl::InternalError(
199  "ndk_util::AIBinder_prepareTransaction failed");
200 }
201 
202 absl::Status BinderAndroid::Transact(BinderTransportTxCode tx_code) {
203  ndk_util::AIBinder* binder = binder_.get();
204  // We only do one-way transaction and thus the output parcel is never used.
205  ndk_util::AParcel* unused_output_parcel;
207  (ndk_util::AIBinder_transact(
208  binder, static_cast<transaction_code_t>(tx_code),
209  &input_parcel_->parcel_, &unused_output_parcel,
210  ndk_util::FLAG_ONEWAY) == ndk_util::STATUS_OK)
211  ? absl::OkStatus()
212  : absl::InternalError("ndk_util::AIBinder_transact failed");
213  ndk_util::AParcel_delete(unused_output_parcel);
214  return result;
215 }
216 
217 std::unique_ptr<TransactionReceiver> BinderAndroid::ConstructTxReceiver(
218  grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
219  TransactionReceiver::OnTransactCb transact_cb) const {
220  return absl::make_unique<TransactionReceiverAndroid>(wire_reader_ref,
221  transact_cb);
222 }
223 
224 int32_t WritableParcelAndroid::GetDataSize() const {
225  return ndk_util::AParcel_getDataSize(parcel_);
226 }
227 
228 absl::Status WritableParcelAndroid::WriteInt32(int32_t data) {
229  return ndk_util::AParcel_writeInt32(parcel_, data) == ndk_util::STATUS_OK
230  ? absl::OkStatus()
231  : absl::InternalError("AParcel_writeInt32 failed");
232 }
233 
234 absl::Status WritableParcelAndroid::WriteInt64(int64_t data) {
235  return ndk_util::AParcel_writeInt64(parcel_, data) == ndk_util::STATUS_OK
236  ? absl::OkStatus()
237  : absl::InternalError("AParcel_writeInt64 failed");
238 }
239 
240 absl::Status WritableParcelAndroid::WriteBinder(HasRawBinder* binder) {
241  return ndk_util::AParcel_writeStrongBinder(
242  parcel_, reinterpret_cast<ndk_util::AIBinder*>(
243  binder->GetRawBinder())) == ndk_util::STATUS_OK
244  ? absl::OkStatus()
245  : absl::InternalError("AParcel_writeStrongBinder failed");
246 }
247 
248 absl::Status WritableParcelAndroid::WriteString(absl::string_view s) {
249  return ndk_util::AParcel_writeString(parcel_, s.data(), s.length()) ==
250  ndk_util::STATUS_OK
251  ? absl::OkStatus()
252  : absl::InternalError("AParcel_writeString failed");
253 }
254 
255 absl::Status WritableParcelAndroid::WriteByteArray(const int8_t* buffer,
256  int32_t length) {
257  return ndk_util::AParcel_writeByteArray(parcel_, buffer, length) ==
258  ndk_util::STATUS_OK
259  ? absl::OkStatus()
260  : absl::InternalError("AParcel_writeByteArray failed");
261 }
262 
263 int32_t ReadableParcelAndroid::GetDataSize() const {
264  return ndk_util::AParcel_getDataSize(parcel_);
265 }
266 
267 absl::Status ReadableParcelAndroid::ReadInt32(int32_t* data) {
268  return ndk_util::AParcel_readInt32(parcel_, data) == ndk_util::STATUS_OK
269  ? absl::OkStatus()
270  : absl::InternalError("AParcel_readInt32 failed");
271 }
272 
273 absl::Status ReadableParcelAndroid::ReadInt64(int64_t* data) {
274  return ndk_util::AParcel_readInt64(parcel_, data) == ndk_util::STATUS_OK
275  ? absl::OkStatus()
276  : absl::InternalError("AParcel_readInt64 failed");
277 }
278 
279 absl::Status ReadableParcelAndroid::ReadBinder(std::unique_ptr<Binder>* data) {
280  ndk_util::AIBinder* binder;
281  if (AParcel_readStrongBinder(parcel_, &binder) != ndk_util::STATUS_OK) {
282  *data = nullptr;
283  return absl::InternalError("AParcel_readStrongBinder failed");
284  }
285  *data = absl::make_unique<BinderAndroid>(ndk_util::SpAIBinder(binder));
286  return absl::OkStatus();
287 }
288 
289 absl::Status ReadableParcelAndroid::ReadByteArray(std::string* data) {
290  std::vector<uint8_t> vec;
291  if (AParcelReadVector(parcel_, &vec) == ndk_util::STATUS_OK) {
292  data->resize(vec.size());
293  if (!vec.empty()) {
294  memcpy(&((*data)[0]), vec.data(), vec.size());
295  }
296  return absl::OkStatus();
297  }
298  return absl::InternalError("AParcel_readByteArray failed");
299 }
300 
301 absl::Status ReadableParcelAndroid::ReadString(std::string* str) {
302  return AParcelReadString(parcel_, str) == ndk_util::STATUS_OK
303  ? absl::OkStatus()
304  : absl::InternalError("AParcel_readString failed");
305 }
306 
307 } // namespace grpc_binder
308 
309 #endif // GPR_SUPPORT_BINDER_TRANSPORT
310 #endif
xds_interop_client.str
str
Definition: xds_interop_client.py:487
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
GPR_INFO
#define GPR_INFO
Definition: include/grpc/impl/codegen/log.h:56
log.h
absl::Status::ToString
std::string ToString(StatusToStringMode mode=StatusToStringMode::kDefault) const
Definition: third_party/abseil-cpp/absl/status/status.h:821
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
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
transaction_code_t
uint32_t transaction_code_t
Definition: binder_constants.h:24
absl::OkStatus
Status OkStatus()
Definition: third_party/abseil-cpp/absl/status/status.h:882
status
absl::Status status
Definition: rls.cc:251
absl::FormatConversionChar::s
@ s
absl::InternalError
Status InternalError(absl::string_view message)
Definition: third_party/abseil-cpp/absl/status/status.cc:347
tx_code
int tx_code
Definition: fake_binder_test.cc:241
T
#define T(upbtypeconst, upbtype, ctype, default_value)
grpc_status._async.code
code
Definition: grpcio_status/grpc_status/_async.py:34
grpc_binder::BinderTransportTxCode
BinderTransportTxCode
Definition: binder_constants.h:31
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
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
binder_android.h
grpc_core::RefCountedPtr
Definition: ref_counted_ptr.h:35
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
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
gpr_log
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, const char *format,...) GPR_PRINT_FORMAT_CHECK(4
benchmark::Initialize
void Initialize(int *argc, char **argv)
Definition: benchmark/src/benchmark.cc:602
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
callback
static void callback(void *arg, int status, int timeouts, struct hostent *host)
Definition: acountry.c:224
buffer
char buffer[1024]
Definition: libuv/docs/code/idle-compute/main.c:8
GPR_ERROR
#define GPR_ERROR
Definition: include/grpc/impl/codegen/log.h:57
grpc_binder::TransactionReceiver::OnTransactCb
std::function< absl::Status(transaction_code_t, ReadableParcel *, int uid)> OnTransactCb
Definition: binder.h:80
absl::Status
Definition: third_party/abseil-cpp/absl/status/status.h:424
absl::Status::ok
ABSL_MUST_USE_RESULT bool ok() const
Definition: third_party/abseil-cpp/absl/status/status.h:802
absl
Definition: abseil-cpp/absl/algorithm/algorithm.h:31
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 Thu Mar 13 2025 02:58:38