1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290
  291
  292
  293
  294
  295
  296
  297
  298
  299
  300
  301
  302
  303
  304
  305
  306
  307
  308
  309
  310
  311
  312
  313
  314
  315
  316
  317
  318
  319
  320
  321
  322
  323
  324
  325
  326
  327
  328
  329
  330
  331
  332
  333
  334
  335
  336
  337
  338
  339
  340
  341
  342
  343
  344
  345
  346
  347
  348
  349
  350
  351
  352
  353
  354
  355
  356
  357
  358
  359
  360
  361
  362
  363
  364
  365
  366
  367
  368
  369
  370
  371
  372
  373
  374
  375
  376
  377
  378
  379
  380
  381
  382
  383
  384
  385
  386
  387
  388
  389
  390
  391
  392
  393
  394
  395
  396
  397
  398
  399
  400
  401
  402
  403
  404
  405
  406
  407
  408

base / android / binder.h [blame]

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_ANDROID_BINDER_H_
#define BASE_ANDROID_BINDER_H_

#include <android/binder_ibinder.h>
#include <android/binder_parcel.h>
#include <android/binder_status.h>
#include <jni.h>

#include <cstdint>
#include <type_traits>
#include <utility>
#include <vector>

#include "base/android/scoped_java_ref.h"
#include "base/base_export.h"
#include "base/check.h"
#include "base/containers/span.h"
#include "base/files/scoped_file.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/numerics/safe_conversions.h"
#include "base/synchronization/lock.h"
#include "base/types/expected.h"
#include "base/types/expected_macros.h"

// DEFINE_BINDER_CLASS() generates a definition for a unique binder class.
// Binder classes are used by the binder implementation to enforce a kind of
// type safety, requiring client IBinders to be associated with the same class
// as the remote object's original IBinder.
//
// Objects implementing SupportsBinder<T> must specify such a class as the T;
// and clients wishing to perform transactions against such objects must use a
// TypedBinderRef<T> to do so.
//
// See usage comments on SupportsBinder<T> below.
#define _BINDER_CLASS_LINE(line) _BINDER_CLASS_LINE2(line)
#define _BINDER_CLASS_LINE2(line) #line
#define DEFINE_BINDER_CLASS(name)                                           \
  struct name : public base::android::internal::BinderClassBase {           \
    using BinderRef = base::android::TypedBinderRef<name>;                  \
    static inline AIBinder_Class* GetBinderClass() {                        \
      static AIBinder_Class* const clazz = RegisterBinderClass(             \
          #name ":" __FILE__ ":" _BINDER_CLASS_LINE(__LINE__));             \
      return clazz;                                                         \
    }                                                                       \
    static inline base::android::TypedBinderRef<name> AdoptBinderRef(       \
        base::android::BinderRef binder) {                                  \
      return base::android::TypedBinderRef<name>::Adopt(std::move(binder)); \
    }                                                                       \
  }

namespace base::android {

class BinderRef;
class Parcel;

template <typename T>
using BinderStatusOr = expected<T, binder_status_t>;

// Provides a read-only view into a AParcel. Does not retain ownership of the
// AParcel, which must outlive this object.
class BASE_EXPORT ParcelReader {
 public:
  explicit ParcelReader(const AParcel* parcel);
  explicit ParcelReader(const Parcel& parcel);
  ParcelReader(const ParcelReader&);
  ParcelReader& operator=(const ParcelReader&);
  ~ParcelReader();

  // A subset of the NDK functions defined for reading from an AParcel. Others
  // may be exposed here as needed.
  BinderStatusOr<BinderRef> ReadBinder() const;
  BinderStatusOr<int32_t> ReadInt32() const;
  BinderStatusOr<uint32_t> ReadUint32() const;
  BinderStatusOr<uint64_t> ReadUint64() const;
  BinderStatusOr<ScopedFD> ReadFileDescriptor() const;

  // Reads a byte array from the parcel. `allocator` is called with a single
  // size_t argument for the number of bytes in the array and must return a
  // pointer to at least that much memory, into which ReadByteArray() will copy
  // the array data before returning. If the parcel contains an empty or null
  // byte array, `allocator` is not invoked. If `allocator` is invoked and
  // returns null, ReadByteArray() returns an error.
  template <typename Allocator>
  BinderStatusOr<void> ReadByteArray(Allocator allocator) const {
    auto c_allocator = [](void* context, int32_t length, int8_t** out) {
      const auto& allocator = *static_cast<Allocator*>(context);
      const auto size = saturated_cast<size_t>(length);
      if (!size) {
        *out = nullptr;
        return true;
      }

      // Binder API wants int8_t for bytes, but we generally use uint8_t.
      uint8_t* const data = allocator(size);
      *out = reinterpret_cast<int8_t*>(data);
      return !!data;
    };
    return ReadByteArrayImpl(c_allocator, &allocator);
  }

 private:
  BinderStatusOr<void> ReadByteArrayImpl(AParcel_byteArrayAllocator allocator,
                                         void* context) const;

  raw_ptr<const AParcel> parcel_;
};

// Provides a writable view into a AParcel. Does not retain ownership of the
// AParcel, which must outlive this object.
class BASE_EXPORT ParcelWriter {
 public:
  explicit ParcelWriter(AParcel* parcel);
  explicit ParcelWriter(Parcel& parcel);
  ParcelWriter(const ParcelWriter&);
  ParcelWriter& operator=(const ParcelWriter&);
  ~ParcelWriter();

  // A subset of the NDK functions defined for writing to an AParcel. Others may
  // be exposed here as needed.
  BinderStatusOr<void> WriteBinder(BinderRef binder) const;
  BinderStatusOr<void> WriteInt32(int32_t value) const;
  BinderStatusOr<void> WriteUint32(uint32_t value) const;
  BinderStatusOr<void> WriteUint64(uint64_t value) const;
  BinderStatusOr<void> WriteByteArray(span<const uint8_t> bytes) const;
  BinderStatusOr<void> WriteFileDescriptor(ScopedFD fd) const;

 private:
  raw_ptr<AParcel> parcel_;
};

// Wraps unique ownership of an AParcel. This is similar to the NDK's
// ScopedAParcel, but it uses our internal BinderApi to invoke NDK functions.
class BASE_EXPORT Parcel {
 public:
  Parcel();
  explicit Parcel(AParcel* parcel);
  Parcel(Parcel&& other);
  Parcel& operator=(Parcel&& other);
  ~Parcel();

  explicit operator bool() const { return parcel_ != nullptr; }

  const AParcel* get() const { return parcel_; }
  AParcel* get() { return parcel_; }
  [[nodiscard]] AParcel* release() { return std::exchange(parcel_, nullptr); }

  void reset();

  ParcelReader reader() const { return ParcelReader(*this); }
  ParcelWriter writer() { return ParcelWriter(*this); }

 private:
  raw_ptr<AParcel> parcel_ = nullptr;
};

// A BinderRef owns a strong ref-count on an AIBinder. This is like the NDK's
// SpAIBinder, but it uses our internal BinderApi to invoke NDK functions.
class BASE_EXPORT BinderRef {
 public:
  BinderRef();
  explicit BinderRef(AIBinder* binder);
  BinderRef(const BinderRef& other);
  BinderRef& operator=(const BinderRef& other);
  BinderRef(BinderRef&& other);
  BinderRef& operator=(BinderRef&& other);
  ~BinderRef();

  explicit operator bool() const { return binder_ != nullptr; }

  AIBinder* get() const { return binder_; }
  [[nodiscard]] AIBinder* release() { return std::exchange(binder_, nullptr); }

  void reset();

  // Returns a new strong reference to this binder as a local Java object
  // reference.
  ScopedJavaLocalRef<jobject> ToJavaBinder(JNIEnv* env) const;

  // Returns a new strong reference to an existing Java binder as a BinderRef.
  static BinderRef FromJavaBinder(JNIEnv* env, jobject java_binder);

  // Attempts to associate this binder with `binder_class`. Generally should be
  // used via TypedBinderRef<T>::Adopt() or the equivalent T::AdoptBinderRef()
  // for some binder class T.
  bool AssociateWithClass(AIBinder_Class* binder_class);

 protected:
  // Protected to force usage through a strongly typed subclass, ensuring that
  // transaction clients have an associated binder class. See documentation on
  // TypedBinderRef<T> below.
  BinderStatusOr<Parcel> PrepareTransaction();
  BinderStatusOr<Parcel> TransactImpl(transaction_code_t code,
                                      Parcel parcel,
                                      binder_flags_t flags);

 protected:
  raw_ptr<AIBinder> binder_ = nullptr;
};

namespace internal {

// Base class for classes generated by DEFINE_BINDER_CLASS().
class BASE_EXPORT BinderClassBase {
 public:
  static AIBinder_Class* RegisterBinderClass(const char* descriptor);
};

// Common implementation for SupportsBinder<T> below. Instances of this base
// class handle IBinder callbacks and forward events for destruction and
// incoming transactions to a templated subclass.
class BASE_EXPORT SupportsBinderBase
    : public RefCountedThreadSafe<SupportsBinderBase> {
 public:
  explicit SupportsBinderBase(AIBinder_Class* binder_class);

  // Called for every incoming transaction on the underlying IBinder. Note that
  // this is called from the binder thread pool so implementations must be
  // thread-safe.
  virtual BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
                                                   const ParcelReader& in,
                                                   const ParcelWriter& out) = 0;

  // Called any time the underlying IBinder is destroyed. Note that this may be
  // invoked multiple times, as the underlying IBinder exists only as long as
  // there are living BinderRefs referencing this object. If BinderRefs are
  // created and then all destroyed, this will be invoked once. If subsequent
  // BinderRefs are created and then all destroyed, this will be invoked again.
  //
  // Similar to OnBinderTransaction, this is invoked from the binder thread pool
  // and implementations must be thread-safe.
  virtual void OnBinderDestroyed();

 protected:
  friend class RefCountedThreadSafe<SupportsBinderBase>;
  friend class BinderClassBase;

  virtual ~SupportsBinderBase();

  // Creates a strong reference to the underlying IBinder, allocating a new
  // IBinder if one did not already exist for this object.
  BinderRef GetBinder();

 private:
  void OnBinderDestroyedBase();

  // Binder class callbacks.
  static void* OnIBinderCreate(void* self);
  static void OnIBinderDestroy(void* self);
  static binder_status_t OnIBinderTransact(AIBinder* binder,
                                           transaction_code_t code,
                                           const AParcel* in,
                                           AParcel* out);

  const raw_ptr<AIBinder_Class> binder_class_;

  Lock lock_;

  // A weak reference to the underlying IBinder, if one exists.
  raw_ptr<AIBinder_Weak> weak_binder_ GUARDED_BY(lock_) = nullptr;

  // As long as any IBinder is alive for this object, we retain an extra ref
  // count on `this` to ensure that transactions can be handled safely.
  scoped_refptr<SupportsBinderBase> self_for_binder_ GUARDED_BY(lock_);
};

}  // namespace internal

// A BinderRef which has been associated with a specific binder class.
template <typename T>
class TypedBinderRef : public BinderRef {
 public:
  static_assert(std::is_base_of_v<android::internal::BinderClassBase, T>,
                "Invalid binder class type");
  TypedBinderRef() = default;

  // Asserts that the binder can be associated with class T. This is safe to
  // call when it's known that the binder hasn't been associated with any other
  // class in the calling process yet.
  explicit TypedBinderRef(BinderRef binder) {
    CHECK(!binder || binder.AssociateWithClass(T::GetBinderClass()));
    binder_ = binder.release();
  }

  TypedBinderRef(const TypedBinderRef&) = default;
  TypedBinderRef& operator=(const TypedBinderRef&) = default;
  TypedBinderRef(TypedBinderRef&&) = default;
  TypedBinderRef& operator=(TypedBinderRef&&) = default;
  ~TypedBinderRef() = default;

  // Adopts a BinderRef that is not already associated with another binder
  // class, associating it with T. If `binder` is already associated with T this
  // is a no-op which only narrows the ref type.
  //
  // If `binder` was already associated with a binder class other than T, the
  // reference is dropped and this returns null.
  //
  // For convenience clients may instead prefer to call this method via
  // T::AdoptBinderRef() as defined by DEFINE_BINDER_CLASS(T).
  static TypedBinderRef<T> Adopt(BinderRef binder) {
    TypedBinderRef<T> typed_binder;
    if (binder.AssociateWithClass(T::GetBinderClass())) {
      typed_binder.binder_ = binder.release();
    }
    return typed_binder;
  }

  // Prepares a new transaction on this binder, returning a Parcel that can be
  // populated and then sent via Transact() or TransactOneWay() below.
  BinderStatusOr<Parcel> PrepareTransaction() {
    return BinderRef::PrepareTransaction();
  }

  // Transact with a `parcel` created by a call to PrepareTransaction() on the
  // same binder. Returns the output parcel from the transaction. `code` is
  // an arbitrary value with interface-specific meaning.
  BinderStatusOr<Parcel> Transact(transaction_code_t code, Parcel parcel) {
    return TransactImpl(code, std::move(parcel), /*flags=*/0);
  }

  // Like Transact(), but this internally prepares a transacation and passes the
  // allocated Parcel into `fn`. After `fn` returns the Parcel is transacted.
  template <typename Fn>
  BinderStatusOr<Parcel> Transact(transaction_code_t code, Fn fn) {
    ASSIGN_OR_RETURN(auto parcel, PrepareTransaction());
    RETURN_IF_ERROR(fn(ParcelWriter(parcel.get())));
    return Transact(code, std::move(parcel));
  }

  // Like Transact() but asynchronous. Discards the empty response parcel.
  BinderStatusOr<void> TransactOneWay(transaction_code_t code, Parcel parcel) {
    RETURN_IF_ERROR(TransactImpl(code, std::move(parcel), FLAG_ONEWAY));
    return ok();
  }

  // Like TransactOneWay(), but this internally prepares a transaction
  // passes the allocated Parcel into `fn`. After `fn` returns the Parcel is
  // transacted.
  template <typename Fn>
  BinderStatusOr<void> TransactOneWay(transaction_code_t code, Fn fn) {
    ASSIGN_OR_RETURN(auto parcel, PrepareTransaction());
    RETURN_IF_ERROR(fn(ParcelWriter(parcel.get())));
    return TransactOneWay(code, std::move(parcel));
  }
};

// Base class for objects which support native binder transactions. Example
// usage:
//
//   // In some common header.
//   DEFINE_BINDER_CLASS(ThingyInterface);
//
//   // The interface implementation.
//   class Thingy : public base::android::SupportsBinder<ThingyInterface> {
//    public:
//     ... (normal class stuff, plus overrides of SupportsBinder methods)
//   };
//
//   // The client. `ref` generally comes from the parent process untyped,
//   // specifically from some SupportsBinder<T> subclass calling GetBinder().
//   void UseThingy(BinderRef ref) {
//     auto thingy = ThingyInterface::AdoptBinderRef(std::move(ref));
//     ... (do transactions with `thingy`)
//   }
template <typename T>
class BASE_EXPORT SupportsBinder : public internal::SupportsBinderBase {
 public:
  static_assert(std::is_base_of_v<android::internal::BinderClassBase, T>,
                "Invalid binder class type");

  SupportsBinder() : SupportsBinderBase(T::GetBinderClass()) {}

  // Creates a strong reference to the underlying IBinder, allocating a new
  // IBinder if one did not already exist for this object.
  TypedBinderRef<T> GetBinder() {
    return TypedBinderRef<T>(SupportsBinderBase::GetBinder());
  }

 protected:
  ~SupportsBinder() override = default;
};

// Indicates whether Binder NDK functionality is generally available to the
// caller. If this returns false, BinderRefs will always be null and
// SupportsBinder<T> implementations will never receive binder transactions; but
// definitions within this header are otherwise still safe to reference and use.
BASE_EXPORT bool IsNativeBinderAvailable();

// Stashes a global collection of BinderRefs for later retrieval by
// TakeBinderFromParent(). This is intended for use by generic multiprocess
// support code to retain interfaces from the parent process so application-
// specific logic in the child process can retrieve them later. It should be
// called at most once per process, and as early as possible.
BASE_EXPORT void SetBindersFromParent(std::vector<BinderRef> binders);

// Retrieves (by index) a BinderRef which was stashed earlier by
// SetBindersFromParent(). If there is no binder for the given index, the
// returned BinderRef is null. This consumes the binder for that index, so
// subsequent calls for the same index will always return null.
BASE_EXPORT BinderRef TakeBinderFromParent(size_t index);

}  // namespace base::android

#endif  // BASE_ANDROID_BINDER_H_