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