• 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.h"
6 
7 #include <android/binder_status.h>
8 
9 #include <algorithm>
10 #include <atomic>
11 #include <limits>
12 #include <utility>
13 
14 #include "base/command_line.h"
15 #include "base/files/file.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/functional/callback.h"
18 #include "base/memory/raw_ref.h"
19 #include "base/notreached.h"
20 #include "base/process/launch.h"
21 #include "base/process/process.h"
22 #include "base/synchronization/waitable_event.h"
23 #include "base/test/bind.h"
24 #include "base/test/multiprocess_test.h"
25 #include "base/test/test_timeouts.h"
26 #include "base/types/expected_macros.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 #include "testing/multiprocess_func_list.h"
29 
30 namespace base::android {
31 namespace {
32 
33 class BinderTest : public testing::Test {
34  public:
SetUp()35   void SetUp() override {
36     if (!IsNativeBinderAvailable()) {
37       GTEST_SKIP() << "This test is only meaningful when run on Android Q+ "
38                    << "with the binder NDK library available.";
39     }
40   }
41 };
42 
43 DEFINE_BINDER_CLASS(ReflectorClass);
44 
45 class Reflector : public SupportsBinder<ReflectorClass> {
46  public:
47   using ReflectCallback = OnceCallback<void(const ParcelReader&)>;
48 
49   template <typename WriteFn, typename ReadFn>
Reflect(WriteFn writer,ReadFn reader)50   void Reflect(WriteFn writer, ReadFn reader) {
51     auto binder = GetBinder();
52     auto parcel = *binder.PrepareTransaction();
53     writer(parcel.writer());
54     reflected_.Reset();
55     reflect_ = BindLambdaForTesting(reader);
56     EXPECT_TRUE(binder.TransactOneWay(1, std::move(parcel)).has_value());
57     reflected_.Wait();
58   }
59 
60  private:
61   ~Reflector() override = default;
62 
63   // SupportsBinder<ReflectorClass>:
OnBinderTransaction(transaction_code_t code,const ParcelReader & reader,const ParcelWriter & out)64   BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
65                                            const ParcelReader& reader,
66                                            const ParcelWriter& out) override {
67     std::move(reflect_).Run(reader);
68     reflected_.Signal();
69     return ok();
70   }
71 
72   ReflectCallback reflect_;
73   WaitableEvent reflected_;
74 };
75 
TEST_F(BinderTest,ReadWriteInt32)76 TEST_F(BinderTest, ReadWriteInt32) {
77   auto reflector = MakeRefCounted<Reflector>();
78   reflector->Reflect(
79       [](const ParcelWriter& writer) {
80         EXPECT_TRUE(writer.WriteInt32(42).has_value());
81         EXPECT_TRUE(writer.WriteInt32(-42).has_value());
82         EXPECT_TRUE(
83             writer.WriteInt32(std::numeric_limits<int32_t>::min()).has_value());
84         EXPECT_TRUE(
85             writer.WriteInt32(std::numeric_limits<int32_t>::max()).has_value());
86       },
87       [](const ParcelReader& reader) {
88         EXPECT_EQ(42, *reader.ReadInt32());
89         EXPECT_EQ(-42, *reader.ReadInt32());
90         EXPECT_EQ(std::numeric_limits<int32_t>::min(), *reader.ReadInt32());
91         EXPECT_EQ(std::numeric_limits<int32_t>::max(), *reader.ReadInt32());
92       });
93 }
94 
TEST_F(BinderTest,ReadWriteUint32)95 TEST_F(BinderTest, ReadWriteUint32) {
96   auto reflector = MakeRefCounted<Reflector>();
97   reflector->Reflect(
98       [](const ParcelWriter& writer) {
99         EXPECT_TRUE(writer.WriteUint32(42).has_value());
100         EXPECT_TRUE(writer.WriteUint32(std::numeric_limits<uint32_t>::min())
101                         .has_value());
102         EXPECT_TRUE(writer.WriteUint32(std::numeric_limits<uint32_t>::max())
103                         .has_value());
104       },
105       [](const ParcelReader& reader) {
106         EXPECT_EQ(42u, *reader.ReadUint32());
107         EXPECT_EQ(std::numeric_limits<uint32_t>::min(), *reader.ReadUint32());
108         EXPECT_EQ(std::numeric_limits<uint32_t>::max(), *reader.ReadUint32());
109       });
110 }
111 
TEST_F(BinderTest,ReadWriteUint64)112 TEST_F(BinderTest, ReadWriteUint64) {
113   auto reflector = MakeRefCounted<Reflector>();
114   reflector->Reflect(
115       [](const ParcelWriter& writer) {
116         EXPECT_TRUE(writer.WriteUint64(42).has_value());
117         EXPECT_TRUE(writer.WriteUint64(std::numeric_limits<uint64_t>::min())
118                         .has_value());
119         EXPECT_TRUE(writer.WriteUint64(std::numeric_limits<uint64_t>::max())
120                         .has_value());
121       },
122       [](const ParcelReader& reader) {
123         EXPECT_EQ(42u, *reader.ReadUint64());
124         EXPECT_EQ(std::numeric_limits<uint64_t>::min(), *reader.ReadUint64());
125         EXPECT_EQ(std::numeric_limits<uint64_t>::max(), *reader.ReadUint64());
126       });
127 }
128 
TEST_F(BinderTest,ReadWriteByteArray)129 TEST_F(BinderTest, ReadWriteByteArray) {
130   auto reflector = MakeRefCounted<Reflector>();
131   const uint8_t kPrimeData[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
132   reflector->Reflect(
133       [&](const ParcelWriter& writer) {
134         EXPECT_TRUE(writer.WriteByteArray(kPrimeData).has_value());
135       },
136       [&](const ParcelReader& reader) {
137         std::vector<uint8_t> buffer;
138         EXPECT_TRUE(reader
139                         .ReadByteArray([&](size_t size) {
140                           buffer.resize(size);
141                           return buffer.data();
142                         })
143                         .has_value());
144         EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(),
145                                std::begin(kPrimeData), std::end(kPrimeData)));
146       });
147 }
148 
TEST_F(BinderTest,ReadWriteEmptyByteArray)149 TEST_F(BinderTest, ReadWriteEmptyByteArray) {
150   auto reflector = MakeRefCounted<Reflector>();
151   reflector->Reflect(
152       [&](const ParcelWriter& writer) {
153         EXPECT_TRUE(writer.WriteByteArray({}).has_value());
154       },
155       [](const ParcelReader& reader) {
156         EXPECT_TRUE(reader
157                         .ReadByteArray([](size_t size) -> uint8_t* {
158                           // We don't call the allocator for empty arrays.
159                           NOTREACHED();
160                         })
161                         .has_value());
162       });
163 }
164 
TEST_F(BinderTest,ReadWriteFileDescriptor)165 TEST_F(BinderTest, ReadWriteFileDescriptor) {
166   ScopedTempDir temp_dir;
167   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
168   File file(temp_dir.GetPath().AppendASCII("test_file"),
169             File::Flags::FLAG_CREATE | File::Flags::FLAG_WRITE);
170   auto reflector = MakeRefCounted<Reflector>();
171   reflector->Reflect(
172       [&](const ParcelWriter& writer) {
173         EXPECT_TRUE(
174             writer.WriteFileDescriptor(ScopedFD(file.TakePlatformFile()))
175                 .has_value());
176       },
177       [](const ParcelReader& reader) {
178         ScopedFD fd = *reader.ReadFileDescriptor();
179         EXPECT_TRUE(fd.is_valid());
180       });
181 }
182 
183 class AddInterface {
184  public:
185   DEFINE_BINDER_CLASS(Class);
186 
187   static constexpr transaction_code_t kAdd = 1234;
188 
189   class Proxy : public Class::BinderRef {
190    public:
Proxy(BinderRef binder)191     explicit Proxy(BinderRef binder) : Class::BinderRef(std::move(binder)) {}
192 
Add(int32_t n)193     int32_t Add(int32_t n) {
194       const Parcel sum =
195           *Transact(kAdd, [n](const auto& p) { return p.WriteInt32(n); });
196       return *sum.reader().ReadInt32();
197     }
198   };
199 };
200 
201 // Test service which adds a fixed offset to any transacted values;
202 class AddService : public SupportsBinder<AddInterface::Class> {
203  public:
AddService(int32_t offset)204   explicit AddService(int32_t offset) : offset_(offset) {}
205 
set_destruction_callback(base::OnceClosure callback)206   void set_destruction_callback(base::OnceClosure callback) {
207     destruction_callback_ = std::move(callback);
208   }
209 
set_binder_destruction_callback(base::RepeatingClosure callback)210   void set_binder_destruction_callback(base::RepeatingClosure callback) {
211     binder_destruction_callback_ = std::move(callback);
212   }
213 
214   // SupportsBinder<AddInterface::Class>:
OnBinderTransaction(transaction_code_t code,const ParcelReader & in,const ParcelWriter & out)215   BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
216                                            const ParcelReader& in,
217                                            const ParcelWriter& out) override {
218     EXPECT_EQ(AddInterface::kAdd, code);
219     return out.WriteInt32(*in.ReadInt32() + offset_);
220   }
221 
OnBinderDestroyed()222   void OnBinderDestroyed() override {
223     if (binder_destruction_callback_) {
224       binder_destruction_callback_.Run();
225     }
226   }
227 
228  private:
~AddService()229   ~AddService() override {
230     if (destruction_callback_) {
231       std::move(destruction_callback_).Run();
232     }
233   }
234 
235   const int32_t offset_;
236 
237   base::OnceClosure destruction_callback_;
238   base::RepeatingClosure binder_destruction_callback_;
239 };
240 
TEST_F(BinderTest,NullBinderRef)241 TEST_F(BinderTest, NullBinderRef) {
242   BinderRef ref;
243   EXPECT_FALSE(ref);
244 
245   TypedBinderRef<AddInterface::Class> typed_ref(std::move(ref));
246   EXPECT_FALSE(typed_ref);
247 }
248 
TEST_F(BinderTest,BasicTransaction)249 TEST_F(BinderTest, BasicTransaction) {
250   auto add42_service = base::MakeRefCounted<AddService>(42);
251   AddInterface::Proxy add42(add42_service->GetBinder());
252   EXPECT_EQ(47, add42.Add(5));
253 }
254 
TEST_F(BinderTest,Lifecycle)255 TEST_F(BinderTest, Lifecycle) {
256   auto add42_service = base::MakeRefCounted<AddService>(42);
257   AddInterface::Proxy add42(add42_service->GetBinder());
258 
259   bool is_destroyed = false;
260   base::WaitableEvent destruction;
261   add42_service->set_destruction_callback(base::BindLambdaForTesting([&] {
262     is_destroyed = true;
263     destruction.Signal();
264   }));
265   add42_service.reset();
266 
267   EXPECT_FALSE(is_destroyed);
268 
269   EXPECT_EQ(47, add42.Add(5));
270   add42.reset();
271   destruction.Wait();
272 
273   EXPECT_TRUE(is_destroyed);
274 }
275 
TEST_F(BinderTest,OnBinderDestroyed)276 TEST_F(BinderTest, OnBinderDestroyed) {
277   auto add5_service = base::MakeRefCounted<AddService>(5);
278 
279   bool has_binder = true;
280   base::WaitableEvent binder_destruction;
281   add5_service->set_binder_destruction_callback(base::BindLambdaForTesting([&] {
282     has_binder = false;
283     binder_destruction.Signal();
284   }));
285 
286   AddInterface::Proxy add5(add5_service->GetBinder());
287   EXPECT_TRUE(has_binder);
288   EXPECT_EQ(12, add5.Add(7));
289   add5.reset();
290   binder_destruction.Wait();
291   EXPECT_FALSE(has_binder);
292 
293   binder_destruction.Reset();
294   has_binder = true;
295 
296   AddInterface::Proxy add5_1(add5_service->GetBinder());
297   AddInterface::Proxy add5_2(add5_service->GetBinder());
298   EXPECT_EQ(6, add5_1.Add(1));
299   EXPECT_EQ(7, add5_2.Add(2));
300 
301   add5_1.reset();
302   EXPECT_TRUE(has_binder);
303   add5_2.reset();
304   binder_destruction.Wait();
305   EXPECT_FALSE(has_binder);
306 }
307 
308 class MultiplyInterface {
309  public:
310   DEFINE_BINDER_CLASS(Class);
311 
312   static constexpr transaction_code_t kMultiply = 5678;
313 
314   class Proxy : public Class::BinderRef {
315    public:
Proxy(BinderRef binder)316     explicit Proxy(BinderRef binder) : Class::BinderRef(std::move(binder)) {}
317 
Multiply(int32_t n)318     int32_t Multiply(int32_t n) {
319       const Parcel product =
320           *Transact(kMultiply, [n](const auto& p) { return p.WriteInt32(n); });
321       return *product.reader().ReadInt32();
322     }
323   };
324 };
325 
326 // Test service which multiplies transacted values by a fixed scale.
327 class MultiplyService : public SupportsBinder<MultiplyInterface::Class> {
328  public:
MultiplyService(int32_t scale)329   explicit MultiplyService(int32_t scale) : scale_(scale) {}
330 
set_destruction_callback(base::OnceClosure callback)331   void set_destruction_callback(base::OnceClosure callback) {
332     destruction_callback_ = std::move(callback);
333   }
334 
335   // SupportsBinder<MultiplyInterface::Class>:
OnBinderTransaction(transaction_code_t code,const ParcelReader & in,const ParcelWriter & out)336   BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
337                                            const ParcelReader& in,
338                                            const ParcelWriter& out) override {
339     EXPECT_EQ(MultiplyInterface::kMultiply, code);
340     return out.WriteInt32(*in.ReadInt32() * scale_);
341   }
342 
343  private:
~MultiplyService()344   ~MultiplyService() override {
345     if (destruction_callback_) {
346       std::move(destruction_callback_).Run();
347     }
348   }
349 
350   const int32_t scale_;
351 
352   base::OnceClosure destruction_callback_;
353 };
354 
TEST_F(BinderTest,MultipleInstances)355 TEST_F(BinderTest, MultipleInstances) {
356   auto add100_service = base::MakeRefCounted<AddService>(100);
357   auto add200_service = base::MakeRefCounted<AddService>(200);
358   AddInterface::Proxy add100(add100_service->GetBinder());
359   AddInterface::Proxy add200(add200_service->GetBinder());
360   EXPECT_EQ(105, add100.Add(5));
361   EXPECT_EQ(207, add200.Add(7));
362 }
363 
TEST_F(BinderTest,MultipleClasses)364 TEST_F(BinderTest, MultipleClasses) {
365   auto add100_service = base::MakeRefCounted<AddService>(100);
366   auto multiply7_service = base::MakeRefCounted<MultiplyService>(7);
367   AddInterface::Proxy add100(add100_service->GetBinder());
368   MultiplyInterface::Proxy multiply7(multiply7_service->GetBinder());
369   EXPECT_EQ(105, add100.Add(5));
370   EXPECT_EQ(63, multiply7.Multiply(9));
371 }
372 
373 class MathInterface {
374  public:
375   DEFINE_BINDER_CLASS(Class);
376 
377   static constexpr transaction_code_t kGetAdd = 1;
378   static constexpr transaction_code_t kGetMultiply = 2;
379 
380   class Proxy : public Class::BinderRef {
381    public:
Proxy(BinderRef binder)382     explicit Proxy(BinderRef binder) : Class::BinderRef(std::move(binder)) {}
383 
GetAdd(int32_t offset)384     AddInterface::Proxy GetAdd(int32_t offset) {
385       auto reply = *Transact(
386           kGetAdd, [offset](const auto& p) { return p.WriteInt32(offset); });
387       return AddInterface::Proxy(*reply.reader().ReadBinder());
388     }
389 
GetMultiply(int32_t scale)390     MultiplyInterface::Proxy GetMultiply(int32_t scale) {
391       auto reply = *Transact(
392           kGetMultiply, [scale](const auto& p) { return p.WriteInt32(scale); });
393       return MultiplyInterface::Proxy(*reply.reader().ReadBinder());
394     }
395   };
396 };
397 
398 // A service which expects transactions requesting new AddInterface or
399 // MultiplyInterface binders with a respective offset or scale. Each request
400 // returns a binder for a bespoke service instance configured accordingly.
401 class MathService : public SupportsBinder<MathInterface::Class> {
402  public:
403   // SupportsBinder<MathInterface::Class>:
OnBinderTransaction(transaction_code_t code,const ParcelReader & in,const ParcelWriter & out)404   BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
405                                            const ParcelReader& in,
406                                            const ParcelWriter& out) override {
407     ASSIGN_OR_RETURN(const int32_t value, in.ReadInt32());
408     switch (code) {
409       case MathInterface::kGetAdd: {
410         auto service = base::MakeRefCounted<AddService>(value);
411         RETURN_IF_ERROR(out.WriteBinder(service->GetBinder()));
412         service->set_destruction_callback(MakeNewServiceDestructionCallback());
413         break;
414       }
415 
416       case MathInterface::kGetMultiply: {
417         auto service = base::MakeRefCounted<MultiplyService>(value);
418         RETURN_IF_ERROR(out.WriteBinder(service->GetBinder()));
419         service->set_destruction_callback(MakeNewServiceDestructionCallback());
420         break;
421       }
422 
423       default:
424         NOTREACHED();
425     }
426     return base::ok();
427   }
428 
WaitForAllServicesToBeDestroyed()429   void WaitForAllServicesToBeDestroyed() { all_services_destroyed_.Wait(); }
430 
431  private:
MakeNewServiceDestructionCallback()432   base::OnceClosure MakeNewServiceDestructionCallback() {
433     num_service_instances_.fetch_add(1, std::memory_order_relaxed);
434     return base::BindLambdaForTesting([this] {
435       if (num_service_instances_.fetch_sub(1, std::memory_order_relaxed) == 1) {
436         all_services_destroyed_.Signal();
437       }
438     });
439   }
440 
441   ~MathService() override = default;
442 
443   std::atomic_int num_service_instances_{0};
444   base::WaitableEvent all_services_destroyed_;
445 };
446 
TEST_F(BinderTest,BindersInTransactions)447 TEST_F(BinderTest, BindersInTransactions) {
448   auto math_service = base::MakeRefCounted<MathService>();
449   MathInterface::Proxy math(math_service->GetBinder());
450 
451   auto add2 = math.GetAdd(2);
452   auto multiply3 = math.GetMultiply(3);
453   EXPECT_EQ(8002, add2.Add(8000));
454   EXPECT_EQ(27000, multiply3.Multiply(9000));
455   add2.reset();
456   multiply3.reset();
457 
458   math_service->WaitForAllServicesToBeDestroyed();
459 }
460 
461 class BinderMultiprocessTest : public BinderTest {
462  public:
463   template <typename... Binders>
LaunchChild(const char * name,Binders &&...binders)464   Process LaunchChild(const char* name, Binders&&... binders) {
465     CommandLine cmd = GetMultiProcessTestChildBaseCommandLine();
466     LaunchOptions options;
467     options.binders =
468         std::vector<BinderRef>({std::forward<Binders>(binders)...});
469     return SpawnMultiProcessTestChild(name, cmd, options);
470   }
471 
JoinChild(const Process & child)472   bool JoinChild(const Process& child) {
473     int child_exit_code = -1;
474     WaitForMultiprocessTestChildExit(child, TestTimeouts::action_timeout(),
475                                      &child_exit_code);
476     return child_exit_code == 0;
477   }
478 };
479 
480 // Helper to define child process logic such that EXPECT* macro failures will
481 // impact the process exit code and thereby percolate up to the parent test
482 // process when joining the child.
483 #define BINDER_TEST_CHILD_MAIN(name)              \
484   class name##_Child {                            \
485    public:                                        \
486     void Run();                                   \
487   };                                              \
488   MULTIPROCESS_TEST_MAIN(name) {                  \
489     name##_Child().Run();                         \
490     return ::testing::Test::HasFailure() ? 1 : 0; \
491   }                                               \
492   void name##_Child::Run()
493 
TEST_F(BinderMultiprocessTest,PassBinder)494 TEST_F(BinderMultiprocessTest, PassBinder) {
495   auto add42 = base::MakeRefCounted<AddService>(42);
496   Process child = LaunchChild("PassBinder_Child", add42->GetBinder());
497   EXPECT_TRUE(JoinChild(child));
498 }
499 
BINDER_TEST_CHILD_MAIN(PassBinder_Child)500 BINDER_TEST_CHILD_MAIN(PassBinder_Child) {
501   AddInterface::Proxy add42(TakeBinderFromParent(0));
502   EXPECT_EQ(47, add42.Add(5));
503 }
504 
TEST_F(BinderMultiprocessTest,PassMultipleBinders)505 TEST_F(BinderMultiprocessTest, PassMultipleBinders) {
506   auto add100 = base::MakeRefCounted<AddService>(100);
507   auto multiply7 = base::MakeRefCounted<MultiplyService>(7);
508   Process child = LaunchChild("PassMultipleBinders_Child", add100->GetBinder(),
509                               multiply7->GetBinder());
510   EXPECT_TRUE(JoinChild(child));
511 }
512 
BINDER_TEST_CHILD_MAIN(PassMultipleBinders_Child)513 BINDER_TEST_CHILD_MAIN(PassMultipleBinders_Child) {
514   AddInterface::Proxy add100(TakeBinderFromParent(0));
515   MultiplyInterface::Proxy multiply7(TakeBinderFromParent(1));
516   EXPECT_EQ(105, add100.Add(5));
517   EXPECT_EQ(63, multiply7.Multiply(9));
518 }
519 
TEST_F(BinderMultiprocessTest,BindersInTransactions)520 TEST_F(BinderMultiprocessTest, BindersInTransactions) {
521   auto math = base::MakeRefCounted<MathService>();
522   Process child = LaunchChild("BindersInTransactions_Child", math->GetBinder());
523   math->WaitForAllServicesToBeDestroyed();
524   EXPECT_TRUE(JoinChild(child));
525 }
526 
BINDER_TEST_CHILD_MAIN(BindersInTransactions_Child)527 BINDER_TEST_CHILD_MAIN(BindersInTransactions_Child) {
528   MathInterface::Proxy math(TakeBinderFromParent(0));
529   auto add2 = math.GetAdd(2);
530   auto multiply3 = math.GetMultiply(3);
531   EXPECT_EQ(8002, add2.Add(8000));
532   EXPECT_EQ(27000, multiply3.Multiply(9000));
533 }
534 
TEST_F(BinderMultiprocessTest,PassedBinderLifetime)535 TEST_F(BinderMultiprocessTest, PassedBinderLifetime) {
536   auto service = base::MakeRefCounted<AddService>(15);
537   bool is_destroyed = false;
538   base::WaitableEvent destruction;
539   service->set_destruction_callback(base::BindLambdaForTesting([&] {
540     is_destroyed = true;
541     destruction.Signal();
542   }));
543 
544   auto binder = service->GetBinder();
545   service.reset();
546 
547   EXPECT_FALSE(is_destroyed);
548   Process child = LaunchChild("PassedBinderLifetime_Child", std::move(binder));
549   EXPECT_TRUE(JoinChild(child));
550   destruction.Wait();
551   EXPECT_TRUE(is_destroyed);
552 }
553 
BINDER_TEST_CHILD_MAIN(PassedBinderLifetime_Child)554 BINDER_TEST_CHILD_MAIN(PassedBinderLifetime_Child) {
555   AddInterface::Proxy add15(TakeBinderFromParent(0));
556   EXPECT_EQ(18, add15.Add(3));
557 }
558 
559 DEFINE_BINDER_CLASS(BinderSinkClass);
560 
561 class BinderSink : public SupportsBinder<BinderSinkClass> {
562  public:
563   using Callback = RepeatingCallback<void(BinderRef)>;
564 
BinderSink(BinderMultiprocessTest & test)565   explicit BinderSink(BinderMultiprocessTest& test) : test_(test) {}
566 
567   template <typename Fn>
LaunchChildAndWaitForBinder(const char * child_name,Fn fn)568   Process LaunchChildAndWaitForBinder(const char* child_name, Fn fn) {
569     callback_ = BindLambdaForTesting(fn);
570     Process process = test_->LaunchChild(child_name, GetBinder());
571     called_.Wait();
572     return process;
573   }
574 
WaitForDisconnect()575   void WaitForDisconnect() { disconnected_.Wait(); }
576 
577   // SupportsBinder<BinderSinkClass>:
OnBinderTransaction(transaction_code_t code,const ParcelReader & reader,const ParcelWriter & out)578   BinderStatusOr<void> OnBinderTransaction(transaction_code_t code,
579                                            const ParcelReader& reader,
580                                            const ParcelWriter& out) override {
581     ASSIGN_OR_RETURN(auto binder, reader.ReadBinder());
582     callback_.Run(std::move(binder));
583     called_.Signal();
584     return base::ok();
585   }
586 
OnBinderDestroyed()587   void OnBinderDestroyed() override { disconnected_.Signal(); }
588 
589  private:
590   ~BinderSink() override = default;
591 
592   raw_ref<BinderMultiprocessTest> test_;
593   BinderRef child_binder_;
594   Callback callback_;
595   WaitableEvent called_;
596   WaitableEvent disconnected_;
597 };
598 
TEST_F(BinderMultiprocessTest,AssociateValid)599 TEST_F(BinderMultiprocessTest, AssociateValid) {
600   auto sink = base::MakeRefCounted<BinderSink>(*this);
601   Process child = sink->LaunchChildAndWaitForBinder(
602       "Associate_Child", [](BinderRef binder) {
603         EXPECT_TRUE(
604             binder.AssociateWithClass(AddInterface::Class::GetBinderClass()));
605       });
606   EXPECT_TRUE(JoinChild(child));
607 }
608 
609 // (crbug.com/365998251): Builder failing this unittest.
TEST_F(BinderMultiprocessTest,DISABLED_AssociateInvalid)610 TEST_F(BinderMultiprocessTest, DISABLED_AssociateInvalid) {
611   auto sink = base::MakeRefCounted<BinderSink>(*this);
612   Process child = sink->LaunchChildAndWaitForBinder(
613       "Associate_Child", [](BinderRef binder) {
614         EXPECT_FALSE(binder.AssociateWithClass(
615             MultiplyInterface::Class::GetBinderClass()));
616       });
617   EXPECT_TRUE(JoinChild(child));
618 }
619 
BINDER_TEST_CHILD_MAIN(Associate_Child)620 BINDER_TEST_CHILD_MAIN(Associate_Child) {
621   auto sink = BinderSinkClass::AdoptBinderRef(TakeBinderFromParent(0));
622   auto service = base::MakeRefCounted<AddService>(15);
623   std::ignore = sink.Transact(42, [&service](ParcelWriter in) {
624     return in.WriteBinder(service->GetBinder());
625   });
626 }
627 
TEST_F(BinderMultiprocessTest,AssociateDestroyed)628 TEST_F(BinderMultiprocessTest, AssociateDestroyed) {
629   auto sink = base::MakeRefCounted<BinderSink>(*this);
630   BinderRef child_binder;
631   Process child = sink->LaunchChildAndWaitForBinder(
632       "AssociateDestroyed_Child",
633       [&](BinderRef binder) { child_binder = std::move(binder); });
634   sink->WaitForDisconnect();
635 
636   // Though the class would be correct, association should fail because the
637   // child process is already dead and the class descriptor can't be validated.
638   EXPECT_FALSE(
639       child_binder.AssociateWithClass(AddInterface::Class::GetBinderClass()));
640 }
641 
BINDER_TEST_CHILD_MAIN(AssociateDestroyed_Child)642 BINDER_TEST_CHILD_MAIN(AssociateDestroyed_Child) {
643   auto sink = BinderSinkClass::AdoptBinderRef(TakeBinderFromParent(0));
644   auto service = base::MakeRefCounted<AddService>(15);
645   std::ignore = sink.Transact(42, [&](ParcelWriter in) {
646     return in.WriteBinder(service->GetBinder());
647   });
648   Process::TerminateCurrentProcessImmediately(0);
649 }
650 
651 }  // namespace
652 }  // namespace base::android
653