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_