xref: /aosp_15_r20/external/grpc-grpc/test/core/transport/binder/end2end/fake_binder.h (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
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 // A collection of fake objects that offers in-memory simulation of data
16 // transmission from one binder to another.
17 //
18 // Once the implementation of Binder is changed from BinderAndroid to
19 // FakeBinder, we'll be able to test and fuzz our end-to-end binder transport in
20 // a non-Android environment.
21 //
22 // The following diagram shows the high-level overview of how the in-memory
23 // simulation works (FakeReceiver means FakeTransactionReceiver).
24 //
25 //                                        thread boundary
26 //                                                |
27 //                                                |
28 // ----------------           ----------------    |  receive
29 // |  FakeBinder  |           | FakeReceiver | <--|----------------
30 // ----------------           ----------------    |               |
31 //        |                           ^           |   ------------------------
32 //        | endpoint            owner |           |   | TransactionProcessor |
33 //        |                           |           |   ------------------------
34 //        v                           |           |               ^
35 // ----------------           ----------------    |               |
36 // | FakeEndpoint | --------> | FakeEndpoint | ---|----------------
37 // ---------------- other_end ----------------    |  enqueue
38 //       | ^                         ^ |          |
39 //       | |           recv_endpoint | |          |
40 //       | |                         | |
41 //       | | send_endpoint           | |
42 //       v |                         | v
43 // -------------------------------------------
44 // |             FakeBinderTunnel            |
45 // -------------------------------------------
46 
47 #ifndef GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H
48 #define GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H
49 
50 #include <atomic>
51 #include <forward_list>
52 #include <memory>
53 #include <queue>
54 #include <string>
55 #include <thread>
56 #include <tuple>
57 #include <utility>
58 #include <vector>
59 
60 #include "absl/memory/memory.h"
61 #include "absl/random/random.h"
62 #include "absl/strings/str_format.h"
63 #include "absl/strings/string_view.h"
64 #include "absl/time/time.h"
65 #include "absl/types/variant.h"
66 
67 #include "src/core/ext/transport/binder/wire_format/binder.h"
68 #include "src/core/ext/transport/binder/wire_format/wire_reader.h"
69 #include "src/core/lib/gprpp/sync.h"
70 #include "src/core/lib/gprpp/thd.h"
71 
72 namespace grpc_binder {
73 namespace end2end_testing {
74 
75 using FakeData = std::vector<
76     absl::variant<int32_t, int64_t, void*, std::string, std::vector<int8_t>>>;
77 
78 // A fake writable parcel.
79 //
80 // It simulates the functionalities of a real writable parcel and stores all
81 // written data in memory. The data can then be transferred by calling
82 // MoveData().
83 class FakeWritableParcel final : public WritableParcel {
84  public:
85   int32_t GetDataSize() const override;
86   absl::Status WriteInt32(int32_t data) override;
87   absl::Status WriteInt64(int64_t data) override;
88   absl::Status WriteBinder(HasRawBinder* binder) override;
89   absl::Status WriteString(absl::string_view s) override;
90   absl::Status WriteByteArray(const int8_t* buffer, int32_t length) override;
91 
MoveData()92   FakeData MoveData() { return std::move(data_); }
93 
94  private:
95   FakeData data_;
96   int32_t data_size_ = 0;
97 };
98 
99 // A fake readable parcel.
100 //
101 // It takes in the data transferred from a FakeWritableParcel and provides
102 // methods to retrieve those data in the receiving end.
103 class FakeReadableParcel final : public ReadableParcel {
104  public:
FakeReadableParcel(FakeData data)105   explicit FakeReadableParcel(FakeData data) : data_(std::move(data)) {
106     for (auto& d : data_) {
107       if (absl::holds_alternative<int32_t>(d)) {
108         data_size_ += sizeof(int32_t);
109       } else if (absl::holds_alternative<int64_t>(d)) {
110         data_size_ += sizeof(int64_t);
111       } else if (absl::holds_alternative<void*>(d)) {
112         data_size_ += sizeof(void*);
113       } else if (absl::holds_alternative<std::string>(d)) {
114         data_size_ += absl::get<std::string>(d).size();
115       } else {
116         data_size_ += absl::get<std::vector<int8_t>>(d).size();
117       }
118     }
119   }
120 
121   int32_t GetDataSize() const override;
122   absl::Status ReadInt32(int32_t* data) override;
123   absl::Status ReadInt64(int64_t* data) override;
124   absl::Status ReadBinder(std::unique_ptr<Binder>* data) override;
125   absl::Status ReadByteArray(std::string* data) override;
126   absl::Status ReadString(std::string* str) override;
127 
128  private:
129   const FakeData data_;
130   size_t data_position_ = 0;
131   int32_t data_size_ = 0;
132 };
133 
134 class FakeBinder;
135 class FakeBinderTunnel;
136 
137 // FakeEndpoint is a simple struct that holds the pointer to the other end, a
138 // pointer to the tunnel and a pointer to its owner. This tells the owner where
139 // the data should be sent.
140 struct FakeEndpoint {
FakeEndpointFakeEndpoint141   explicit FakeEndpoint(FakeBinderTunnel* tunnel) : tunnel(tunnel) {}
142 
143   FakeEndpoint* other_end;
144   FakeBinderTunnel* tunnel;
145   // The owner is either a FakeBinder (the sending part) or a
146   // FakeTransactionReceiver (the receiving part). Both parts hold an endpoint
147   // with |owner| pointing back to them and |other_end| pointing to each other.
148   void* owner;
149 };
150 
151 class PersistentFakeTransactionReceiver;
152 
153 // A fake transaction receiver.
154 //
155 // This is the receiving part of a pair of binders. When constructed, a binder
156 // tunnle is created, and the sending part can be retrieved by calling
157 // GetSender().
158 //
159 // It also provides a Receive() function to simulate the on-transaction
160 // callback of a real Android binder.
161 class FakeTransactionReceiver : public TransactionReceiver {
162  public:
163   FakeTransactionReceiver(grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
164                           TransactionReceiver::OnTransactCb cb);
165 
166   void* GetRawBinder() override;
167 
168   std::unique_ptr<Binder> GetSender() const;
169 
170  private:
171   PersistentFakeTransactionReceiver* persistent_tx_receiver_;
172 };
173 
174 // A "persistent" version of the FakeTransactionReceiver. That is, its lifetime
175 // is managed by the processor and it outlives the wire reader and
176 // grpc_binder_transport, so we can safely dereference a pointer to it in
177 // ProcessLoop().
178 class PersistentFakeTransactionReceiver {
179  public:
180   PersistentFakeTransactionReceiver(
181       grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
182       TransactionReceiver::OnTransactCb cb,
183       std::unique_ptr<FakeBinderTunnel> tunnel);
184 
Receive(BinderTransportTxCode tx_code,ReadableParcel * parcel)185   absl::Status Receive(BinderTransportTxCode tx_code, ReadableParcel* parcel) {
186     return callback_(static_cast<transaction_code_t>(tx_code), parcel,
187                      /*uid=*/0);
188   }
189 
190  private:
191   grpc_core::RefCountedPtr<WireReader> wire_reader_ref_;
192   TransactionReceiver::OnTransactCb callback_;
193   std::unique_ptr<FakeBinderTunnel> tunnel_;
194 
195   friend class FakeTransactionReceiver;
196 };
197 
198 // The sending part of a binders pair. It provides a FakeWritableParcel to the
199 // user, and when Transact() is called, it transfers the written data to the
200 // other end of the tunnel by following the information in its endpoint.
201 class FakeBinder final : public Binder {
202  public:
FakeBinder(FakeEndpoint * endpoint)203   explicit FakeBinder(FakeEndpoint* endpoint) : endpoint_(endpoint) {}
204 
Initialize()205   void Initialize() override {}
PrepareTransaction()206   absl::Status PrepareTransaction() override {
207     input_ = std::make_unique<FakeWritableParcel>();
208     return absl::OkStatus();
209   }
210 
211   absl::Status Transact(BinderTransportTxCode tx_code) override;
212 
GetWritableParcel()213   WritableParcel* GetWritableParcel() const override { return input_.get(); }
214 
215   std::unique_ptr<TransactionReceiver> ConstructTxReceiver(
216       grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
217       TransactionReceiver::OnTransactCb transact_cb) const override;
218 
GetRawBinder()219   void* GetRawBinder() override { return endpoint_->other_end; }
220 
221  private:
222   FakeEndpoint* endpoint_;
223   std::unique_ptr<FakeWritableParcel> input_;
224 };
225 
226 // A transaction processor.
227 //
228 // Once constructed, it'll create a another thread that deliver in-coming
229 // transactions to their destinations.
230 class TransactionProcessor {
231  public:
232   explicit TransactionProcessor(absl::Duration delay = absl::ZeroDuration());
~TransactionProcessor()233   ~TransactionProcessor() { Terminate(); }
234 
235   void SetDelay(absl::Duration delay);
236 
237   void Terminate();
238   void ProcessLoop();
239   void Flush();
240 
241   // Issue a transaction with |target| pointing to the target endpoint. The
242   // transactions will be delivered in the same order they're issued, possibly
243   // with random delay to simulate real-world situation.
244   void EnQueueTransaction(FakeEndpoint* target, BinderTransportTxCode tx_code,
245                           FakeData data);
246 
NewPersistentTxReceiver(grpc_core::RefCountedPtr<WireReader> wire_reader_ref,TransactionReceiver::OnTransactCb cb,std::unique_ptr<FakeBinderTunnel> tunnel)247   PersistentFakeTransactionReceiver& NewPersistentTxReceiver(
248       grpc_core::RefCountedPtr<WireReader> wire_reader_ref,
249       TransactionReceiver::OnTransactCb cb,
250       std::unique_ptr<FakeBinderTunnel> tunnel) {
251     grpc_core::MutexLock lock(&tx_receiver_mu_);
252     storage_.emplace_front(wire_reader_ref, cb, std::move(tunnel));
253     return storage_.front();
254   }
255 
256  private:
257   absl::Duration GetRandomDelay();
258   void WaitForNextTransaction() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_);
259 
260   grpc_core::Mutex mu_;
261   std::queue<std::tuple<FakeEndpoint*, BinderTransportTxCode, FakeData>>
262       tx_queue_ ABSL_GUARDED_BY(mu_);
263   absl::Time deliver_time_ ABSL_GUARDED_BY(mu_);
264   int64_t delay_nsec_;
265   absl::BitGen bit_gen_;
266   grpc_core::Thread tx_thread_;
267   std::atomic<bool> terminated_;
268 
269   grpc_core::Mutex tx_receiver_mu_;
270   // Use forward_list to avoid invalid pointers resulted by reallocation in
271   // containers such as std::vector.
272   std::forward_list<PersistentFakeTransactionReceiver> storage_
273       ABSL_GUARDED_BY(tx_receiver_mu_);
274 };
275 
276 // The global (shared) processor. Test suite should be responsible of
277 // creating/deleting it.
278 extern TransactionProcessor* g_transaction_processor;
279 
280 // A binder tunnel.
281 //
282 // It is a simple helper that creates and links two endpoints.
283 class FakeBinderTunnel {
284  public:
285   FakeBinderTunnel();
286 
EnQueueTransaction(FakeEndpoint * target,BinderTransportTxCode tx_code,FakeData data)287   void EnQueueTransaction(FakeEndpoint* target, BinderTransportTxCode tx_code,
288                           FakeData data) {
289     g_transaction_processor->EnQueueTransaction(target, tx_code,
290                                                 std::move(data));
291   }
292 
GetSendEndpoint()293   FakeEndpoint* GetSendEndpoint() const { return send_endpoint_.get(); }
GetRecvEndpoint()294   FakeEndpoint* GetRecvEndpoint() const { return recv_endpoint_.get(); }
295 
296  private:
297   std::unique_ptr<FakeEndpoint> send_endpoint_;
298   std::unique_ptr<FakeEndpoint> recv_endpoint_;
299 };
300 
301 // A helper function for constructing a pair of connected binders.
302 std::pair<std::unique_ptr<Binder>, std::unique_ptr<TransactionReceiver>>
303 NewBinderPair(TransactionReceiver::OnTransactCb transact_cb);
304 
305 }  // namespace end2end_testing
306 }  // namespace grpc_binder
307 
308 #endif  // GRPC_TEST_CORE_TRANSPORT_BINDER_END2END_FAKE_BINDER_H
309