• 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 #include "base/android/binder_box.h"
6 
7 #include <android/binder_ibinder.h>
8 #include <jni.h>
9 
10 #include <cstddef>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/android/binder.h"
15 #include "base/android/scoped_java_ref.h"
16 #include "base/types/expected_macros.h"
17 
18 namespace base::android {
19 
20 namespace {
21 
22 DEFINE_BINDER_CLASS(BinderBoxInterface);
23 
24 // Binder transaction support for PackBinderBox() and UnpackBinderBox().
25 class BinderBox : public SupportsBinder<BinderBoxInterface> {
26   static constexpr transaction_code_t kUnpack = 1;
27 
28  public:
BinderBox(std::vector<BinderRef> binders)29   explicit BinderBox(std::vector<BinderRef> binders)
30       : binders_(std::move(binders)) {}
31 
GetJavaBinder(JNIEnv * env)32   ScopedJavaLocalRef<jobject> GetJavaBinder(JNIEnv* env) {
33     return GetBinder().ToJavaBinder(env);
34   }
35 
Unpack(JNIEnv * env,const JavaRef<jobject> & box)36   static BinderStatusOr<std::vector<BinderRef>> Unpack(
37       JNIEnv* env,
38       const JavaRef<jobject>& box) {
39     auto proxy = TypedBinderRef<BinderBoxInterface>::Adopt(
40         BinderRef::FromJavaBinder(env, box.obj()));
41     if (!proxy) {
42       return unexpected(STATUS_BAD_TYPE);
43     }
44     ASSIGN_OR_RETURN(auto parcel, proxy.PrepareTransaction());
45     ASSIGN_OR_RETURN(const auto reply,
46                      proxy.Transact(kUnpack, std::move(parcel)));
47     ASSIGN_OR_RETURN(const size_t num_binders, reply.reader().ReadUint32());
48     std::vector<BinderRef> binders(num_binders);
49     for (size_t i = 0; i < num_binders; ++i) {
50       ASSIGN_OR_RETURN(binders[i], reply.reader().ReadBinder());
51     }
52     return binders;
53   }
54 
55  private:
56   ~BinderBox() override = default;
57 
58   // SupportsBinder<BinderBoxInterface>:
OnBinderTransaction(transaction_code_t code,const ParcelReader & in,const ParcelWriter & out)59   BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
60                                            const ParcelReader& in,
61                                            const ParcelWriter& out) override {
62     if (code != kUnpack) {
63       return unexpected(STATUS_UNKNOWN_TRANSACTION);
64     }
65     const uint32_t num_binders = checked_cast<uint32_t>(binders_.size());
66     RETURN_IF_ERROR(out.WriteUint32(num_binders));
67     for (uint32_t i = 0; i < num_binders; ++i) {
68       RETURN_IF_ERROR(out.WriteBinder(binders_[i]));
69     }
70     binders_.clear();
71     return ok();
72   }
73 
74   std::vector<BinderRef> binders_;
75 };
76 
77 }  // namespace
78 
PackBinderBox(JNIEnv * env,std::vector<BinderRef> binders)79 ScopedJavaLocalRef<jobject> PackBinderBox(JNIEnv* env,
80                                           std::vector<BinderRef> binders) {
81   if (binders.empty()) {
82     return nullptr;
83   }
84   return MakeRefCounted<BinderBox>(std::move(binders))->GetJavaBinder(env);
85 }
86 
UnpackBinderBox(JNIEnv * env,const JavaRef<jobject> & box)87 BinderStatusOr<std::vector<BinderRef>> UnpackBinderBox(
88     JNIEnv* env,
89     const JavaRef<jobject>& box) {
90   return BinderBox::Unpack(env, box);
91 }
92 
93 }  // namespace base::android
94