• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef BASE_ANDROID_BINDER_H_
6 #define BASE_ANDROID_BINDER_H_
7 
8 #include <android/binder_ibinder.h>
9 #include <android/binder_parcel.h>
10 #include <android/binder_status.h>
11 #include <jni.h>
12 
13 #include <cstdint>
14 #include <type_traits>
15 #include <utility>
16 #include <vector>
17 
18 #include "base/android/scoped_java_ref.h"
19 #include "base/base_export.h"
20 #include "base/check.h"
21 #include "base/containers/span.h"
22 #include "base/files/scoped_file.h"
23 #include "base/memory/raw_ptr.h"
24 #include "base/memory/ref_counted.h"
25 #include "base/numerics/safe_conversions.h"
26 #include "base/synchronization/lock.h"
27 #include "base/types/expected.h"
28 #include "base/types/expected_macros.h"
29 
30 // DEFINE_BINDER_CLASS() generates a definition for a unique binder class.
31 // Binder classes are used by the binder implementation to enforce a kind of
32 // type safety, requiring client IBinders to be associated with the same class
33 // as the remote object's original IBinder.
34 //
35 // Objects implementing SupportsBinder<T> must specify such a class as the T;
36 // and clients wishing to perform transactions against such objects must use a
37 // TypedBinderRef<T> to do so.
38 //
39 // See usage comments on SupportsBinder<T> below.
40 #define _BINDER_CLASS_LINE(line) _BINDER_CLASS_LINE2(line)
41 #define _BINDER_CLASS_LINE2(line) #line
42 #define DEFINE_BINDER_CLASS(name)                                           \
43   struct name : public base::android::internal::BinderClassBase {           \
44     using BinderRef = base::android::TypedBinderRef<name>;                  \
45     static inline AIBinder_Class* GetBinderClass() {                        \
46       static AIBinder_Class* const clazz = RegisterBinderClass(             \
47           #name ":" __FILE__ ":" _BINDER_CLASS_LINE(__LINE__));             \
48       return clazz;                                                         \
49     }                                                                       \
50     static inline base::android::TypedBinderRef<name> AdoptBinderRef(       \
51         base::android::BinderRef binder) {                                  \
52       return base::android::TypedBinderRef<name>::Adopt(std::move(binder)); \
53     }                                                                       \
54   }
55 
56 namespace base::android {
57 
58 class BinderRef;
59 class Parcel;
60 
61 template <typename T>
62 using BinderStatusOr = expected<T, binder_status_t>;
63 
64 // Provides a read-only view into a AParcel. Does not retain ownership of the
65 // AParcel, which must outlive this object.
66 class BASE_EXPORT ParcelReader {
67  public:
68   explicit ParcelReader(const AParcel* parcel);
69   explicit ParcelReader(const Parcel& parcel);
70   ParcelReader(const ParcelReader&);
71   ParcelReader& operator=(const ParcelReader&);
72   ~ParcelReader();
73 
74   // A subset of the NDK functions defined for reading from an AParcel. Others
75   // may be exposed here as needed.
76   BinderStatusOr<BinderRef> ReadBinder() const;
77   BinderStatusOr<int32_t> ReadInt32() const;
78   BinderStatusOr<uint32_t> ReadUint32() const;
79   BinderStatusOr<uint64_t> ReadUint64() const;
80   BinderStatusOr<ScopedFD> ReadFileDescriptor() const;
81 
82   // Reads a byte array from the parcel. `allocator` is called with a single
83   // size_t argument for the number of bytes in the array and must return a
84   // pointer to at least that much memory, into which ReadByteArray() will copy
85   // the array data before returning. If the parcel contains an empty or null
86   // byte array, `allocator` is not invoked. If `allocator` is invoked and
87   // returns null, ReadByteArray() returns an error.
88   template <typename Allocator>
ReadByteArray(Allocator allocator)89   BinderStatusOr<void> ReadByteArray(Allocator allocator) const {
90     auto c_allocator = [](void* context, int32_t length, int8_t** out) {
91       const auto& allocator = *static_cast<Allocator*>(context);
92       const auto size = saturated_cast<size_t>(length);
93       if (!size) {
94         *out = nullptr;
95         return true;
96       }
97 
98       // Binder API wants int8_t for bytes, but we generally use uint8_t.
99       uint8_t* const data = allocator(size);
100       *out = reinterpret_cast<int8_t*>(data);
101       return !!data;
102     };
103     return ReadByteArrayImpl(c_allocator, &allocator);
104   }
105 
106  private:
107   BinderStatusOr<void> ReadByteArrayImpl(AParcel_byteArrayAllocator allocator,
108                                          void* context) const;
109 
110   raw_ptr<const AParcel> parcel_;
111 };
112 
113 // Provides a writable view into a AParcel. Does not retain ownership of the
114 // AParcel, which must outlive this object.
115 class BASE_EXPORT ParcelWriter {
116  public:
117   explicit ParcelWriter(AParcel* parcel);
118   explicit ParcelWriter(Parcel& parcel);
119   ParcelWriter(const ParcelWriter&);
120   ParcelWriter& operator=(const ParcelWriter&);
121   ~ParcelWriter();
122 
123   // A subset of the NDK functions defined for writing to an AParcel. Others may
124   // be exposed here as needed.
125   BinderStatusOr<void> WriteBinder(BinderRef binder) const;
126   BinderStatusOr<void> WriteInt32(int32_t value) const;
127   BinderStatusOr<void> WriteUint32(uint32_t value) const;
128   BinderStatusOr<void> WriteUint64(uint64_t value) const;
129   BinderStatusOr<void> WriteByteArray(span<const uint8_t> bytes) const;
130   BinderStatusOr<void> WriteFileDescriptor(ScopedFD fd) const;
131 
132  private:
133   raw_ptr<AParcel> parcel_;
134 };
135 
136 // Wraps unique ownership of an AParcel. This is similar to the NDK's
137 // ScopedAParcel, but it uses our internal BinderApi to invoke NDK functions.
138 class BASE_EXPORT Parcel {
139  public:
140   Parcel();
141   explicit Parcel(AParcel* parcel);
142   Parcel(Parcel&& other);
143   Parcel& operator=(Parcel&& other);
144   ~Parcel();
145 
146   explicit operator bool() const { return parcel_ != nullptr; }
147 
get()148   const AParcel* get() const { return parcel_; }
get()149   AParcel* get() { return parcel_; }
release()150   [[nodiscard]] AParcel* release() { return std::exchange(parcel_, nullptr); }
151 
152   void reset();
153 
reader()154   ParcelReader reader() const { return ParcelReader(*this); }
writer()155   ParcelWriter writer() { return ParcelWriter(*this); }
156 
157  private:
158   raw_ptr<AParcel> parcel_ = nullptr;
159 };
160 
161 // A BinderRef owns a strong ref-count on an AIBinder. This is like the NDK's
162 // SpAIBinder, but it uses our internal BinderApi to invoke NDK functions.
163 class BASE_EXPORT BinderRef {
164  public:
165   BinderRef();
166   explicit BinderRef(AIBinder* binder);
167   BinderRef(const BinderRef& other);
168   BinderRef& operator=(const BinderRef& other);
169   BinderRef(BinderRef&& other);
170   BinderRef& operator=(BinderRef&& other);
171   ~BinderRef();
172 
173   explicit operator bool() const { return binder_ != nullptr; }
174 
get()175   AIBinder* get() const { return binder_; }
release()176   [[nodiscard]] AIBinder* release() { return std::exchange(binder_, nullptr); }
177 
178   void reset();
179 
180   // Returns a new strong reference to this binder as a local Java object
181   // reference.
182   ScopedJavaLocalRef<jobject> ToJavaBinder(JNIEnv* env) const;
183 
184   // Returns a new strong reference to an existing Java binder as a BinderRef.
185   static BinderRef FromJavaBinder(JNIEnv* env, jobject java_binder);
186 
187   // Attempts to associate this binder with `binder_class`. Generally should be
188   // used via TypedBinderRef<T>::Adopt() or the equivalent T::AdoptBinderRef()
189   // for some binder class T.
190   bool AssociateWithClass(AIBinder_Class* binder_class);
191 
192  protected:
193   // Protected to force usage through a strongly typed subclass, ensuring that
194   // transaction clients have an associated binder class. See documentation on
195   // TypedBinderRef<T> below.
196   BinderStatusOr<Parcel> PrepareTransaction();
197   BinderStatusOr<Parcel> TransactImpl(transaction_code_t code,
198                                       Parcel parcel,
199                                       binder_flags_t flags);
200 
201  protected:
202   raw_ptr<AIBinder> binder_ = nullptr;
203 };
204 
205 namespace internal {
206 
207 // Base class for classes generated by DEFINE_BINDER_CLASS().
208 class BASE_EXPORT BinderClassBase {
209  public:
210   static AIBinder_Class* RegisterBinderClass(const char* descriptor);
211 };
212 
213 // Common implementation for SupportsBinder<T> below. Instances of this base
214 // class handle IBinder callbacks and forward events for destruction and
215 // incoming transactions to a templated subclass.
216 class BASE_EXPORT SupportsBinderBase
217     : public RefCountedThreadSafe<SupportsBinderBase> {
218  public:
219   explicit SupportsBinderBase(AIBinder_Class* binder_class);
220 
221   // Called for every incoming transaction on the underlying IBinder. Note that
222   // this is called from the binder thread pool so implementations must be
223   // thread-safe.
224   virtual BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
225                                                    const ParcelReader& in,
226                                                    const ParcelWriter& out) = 0;
227 
228   // Called any time the underlying IBinder is destroyed. Note that this may be
229   // invoked multiple times, as the underlying IBinder exists only as long as
230   // there are living BinderRefs referencing this object. If BinderRefs are
231   // created and then all destroyed, this will be invoked once. If subsequent
232   // BinderRefs are created and then all destroyed, this will be invoked again.
233   //
234   // Similar to OnBinderTransaction, this is invoked from the binder thread pool
235   // and implementations must be thread-safe.
236   virtual void OnBinderDestroyed();
237 
238  protected:
239   friend class RefCountedThreadSafe<SupportsBinderBase>;
240   friend class BinderClassBase;
241 
242   virtual ~SupportsBinderBase();
243 
244   // Creates a strong reference to the underlying IBinder, allocating a new
245   // IBinder if one did not already exist for this object.
246   BinderRef GetBinder();
247 
248  private:
249   void OnBinderDestroyedBase();
250 
251   // Binder class callbacks.
252   static void* OnIBinderCreate(void* self);
253   static void OnIBinderDestroy(void* self);
254   static binder_status_t OnIBinderTransact(AIBinder* binder,
255                                            transaction_code_t code,
256                                            const AParcel* in,
257                                            AParcel* out);
258 
259   const raw_ptr<AIBinder_Class> binder_class_;
260 
261   Lock lock_;
262 
263   // A weak reference to the underlying IBinder, if one exists.
264   raw_ptr<AIBinder_Weak> weak_binder_ GUARDED_BY(lock_) = nullptr;
265 
266   // As long as any IBinder is alive for this object, we retain an extra ref
267   // count on `this` to ensure that transactions can be handled safely.
268   scoped_refptr<SupportsBinderBase> self_for_binder_ GUARDED_BY(lock_);
269 };
270 
271 }  // namespace internal
272 
273 // A BinderRef which has been associated with a specific binder class.
274 template <typename T>
275 class TypedBinderRef : public BinderRef {
276  public:
277   static_assert(std::is_base_of_v<android::internal::BinderClassBase, T>,
278                 "Invalid binder class type");
279   TypedBinderRef() = default;
280 
281   // Asserts that the binder can be associated with class T. This is safe to
282   // call when it's known that the binder hasn't been associated with any other
283   // class in the calling process yet.
TypedBinderRef(BinderRef binder)284   explicit TypedBinderRef(BinderRef binder) {
285     CHECK(!binder || binder.AssociateWithClass(T::GetBinderClass()));
286     binder_ = binder.release();
287   }
288 
289   TypedBinderRef(const TypedBinderRef&) = default;
290   TypedBinderRef& operator=(const TypedBinderRef&) = default;
291   TypedBinderRef(TypedBinderRef&&) = default;
292   TypedBinderRef& operator=(TypedBinderRef&&) = default;
293   ~TypedBinderRef() = default;
294 
295   // Adopts a BinderRef that is not already associated with another binder
296   // class, associating it with T. If `binder` is already associated with T this
297   // is a no-op which only narrows the ref type.
298   //
299   // If `binder` was already associated with a binder class other than T, the
300   // reference is dropped and this returns null.
301   //
302   // For convenience clients may instead prefer to call this method via
303   // T::AdoptBinderRef() as defined by DEFINE_BINDER_CLASS(T).
Adopt(BinderRef binder)304   static TypedBinderRef<T> Adopt(BinderRef binder) {
305     TypedBinderRef<T> typed_binder;
306     if (binder.AssociateWithClass(T::GetBinderClass())) {
307       typed_binder.binder_ = binder.release();
308     }
309     return typed_binder;
310   }
311 
312   // Prepares a new transaction on this binder, returning a Parcel that can be
313   // populated and then sent via Transact() or TransactOneWay() below.
PrepareTransaction()314   BinderStatusOr<Parcel> PrepareTransaction() {
315     return BinderRef::PrepareTransaction();
316   }
317 
318   // Transact with a `parcel` created by a call to PrepareTransaction() on the
319   // same binder. Returns the output parcel from the transaction. `code` is
320   // an arbitrary value with interface-specific meaning.
Transact(transaction_code_t code,Parcel parcel)321   BinderStatusOr<Parcel> Transact(transaction_code_t code, Parcel parcel) {
322     return TransactImpl(code, std::move(parcel), /*flags=*/0);
323   }
324 
325   // Like Transact(), but this internally prepares a transacation and passes the
326   // allocated Parcel into `fn`. After `fn` returns the Parcel is transacted.
327   template <typename Fn>
Transact(transaction_code_t code,Fn fn)328   BinderStatusOr<Parcel> Transact(transaction_code_t code, Fn fn) {
329     ASSIGN_OR_RETURN(auto parcel, PrepareTransaction());
330     RETURN_IF_ERROR(fn(ParcelWriter(parcel.get())));
331     return Transact(code, std::move(parcel));
332   }
333 
334   // Like Transact() but asynchronous. Discards the empty response parcel.
TransactOneWay(transaction_code_t code,Parcel parcel)335   BinderStatusOr<void> TransactOneWay(transaction_code_t code, Parcel parcel) {
336     RETURN_IF_ERROR(TransactImpl(code, std::move(parcel), FLAG_ONEWAY));
337     return ok();
338   }
339 
340   // Like TransactOneWay(), but this internally prepares a transaction
341   // passes the allocated Parcel into `fn`. After `fn` returns the Parcel is
342   // transacted.
343   template <typename Fn>
TransactOneWay(transaction_code_t code,Fn fn)344   BinderStatusOr<void> TransactOneWay(transaction_code_t code, Fn fn) {
345     ASSIGN_OR_RETURN(auto parcel, PrepareTransaction());
346     RETURN_IF_ERROR(fn(ParcelWriter(parcel.get())));
347     return TransactOneWay(code, std::move(parcel));
348   }
349 };
350 
351 // Base class for objects which support native binder transactions. Example
352 // usage:
353 //
354 //   // In some common header.
355 //   DEFINE_BINDER_CLASS(ThingyInterface);
356 //
357 //   // The interface implementation.
358 //   class Thingy : public base::android::SupportsBinder<ThingyInterface> {
359 //    public:
360 //     ... (normal class stuff, plus overrides of SupportsBinder methods)
361 //   };
362 //
363 //   // The client. `ref` generally comes from the parent process untyped,
364 //   // specifically from some SupportsBinder<T> subclass calling GetBinder().
365 //   void UseThingy(BinderRef ref) {
366 //     auto thingy = ThingyInterface::AdoptBinderRef(std::move(ref));
367 //     ... (do transactions with `thingy`)
368 //   }
369 template <typename T>
370 class BASE_EXPORT SupportsBinder : public internal::SupportsBinderBase {
371  public:
372   static_assert(std::is_base_of_v<android::internal::BinderClassBase, T>,
373                 "Invalid binder class type");
374 
SupportsBinder()375   SupportsBinder() : SupportsBinderBase(T::GetBinderClass()) {}
376 
377   // Creates a strong reference to the underlying IBinder, allocating a new
378   // IBinder if one did not already exist for this object.
GetBinder()379   TypedBinderRef<T> GetBinder() {
380     return TypedBinderRef<T>(SupportsBinderBase::GetBinder());
381   }
382 
383  protected:
384   ~SupportsBinder() override = default;
385 };
386 
387 // Indicates whether Binder NDK functionality is generally available to the
388 // caller. If this returns false, BinderRefs will always be null and
389 // SupportsBinder<T> implementations will never receive binder transactions; but
390 // definitions within this header are otherwise still safe to reference and use.
391 BASE_EXPORT bool IsNativeBinderAvailable();
392 
393 // Stashes a global collection of BinderRefs for later retrieval by
394 // TakeBinderFromParent(). This is intended for use by generic multiprocess
395 // support code to retain interfaces from the parent process so application-
396 // specific logic in the child process can retrieve them later. It should be
397 // called at most once per process, and as early as possible.
398 BASE_EXPORT void SetBindersFromParent(std::vector<BinderRef> binders);
399 
400 // Retrieves (by index) a BinderRef which was stashed earlier by
401 // SetBindersFromParent(). If there is no binder for the given index, the
402 // returned BinderRef is null. This consumes the binder for that index, so
403 // subsequent calls for the same index will always return null.
404 BASE_EXPORT BinderRef TakeBinderFromParent(size_t index);
405 
406 }  // namespace base::android
407 
408 #endif  // BASE_ANDROID_BINDER_H_
409