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