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