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