blob: d1f63a728b2a76ebb457a44f23103e8189e112b6 [file] [log] [blame]
Dan Stozad630e522016-12-01 15:16:31 -08001/*
2 * Copyright 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <binder/SafeInterface.h>
18
19#include <binder/IInterface.h>
20#include <binder/IPCThreadState.h>
21#include <binder/IServiceManager.h>
22#include <binder/Parcel.h>
23#include <binder/Parcelable.h>
24#include <binder/ProcessState.h>
25
26#pragma clang diagnostic push
27#pragma clang diagnostic ignored "-Weverything"
28#include <gtest/gtest.h>
29#pragma clang diagnostic pop
30
31#include <optional>
32
33using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
34
35namespace android {
36namespace tests {
37
38// This class serves two purposes:
39// 1) It ensures that the implementation doesn't require copying or moving the data (for
40// efficiency purposes)
41// 2) It tests that Parcelables can be passed correctly
42class NoCopyNoMove : public Parcelable {
43public:
44 NoCopyNoMove() = default;
45 explicit NoCopyNoMove(int32_t value) : mValue(value) {}
46 ~NoCopyNoMove() override = default;
47
48 // Not copyable
49 NoCopyNoMove(const NoCopyNoMove&) = delete;
50 NoCopyNoMove& operator=(const NoCopyNoMove&) = delete;
51
52 // Not movable
53 NoCopyNoMove(NoCopyNoMove&&) = delete;
54 NoCopyNoMove& operator=(NoCopyNoMove&&) = delete;
55
56 // Parcelable interface
57 status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
58 status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }
59
60 int32_t getValue() const { return mValue; }
61 void setValue(int32_t value) { mValue = value; }
62
63private:
64 int32_t mValue = 0;
65 uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
66};
67
Dan Stozadf614ae2017-03-28 17:02:05 -070068struct TestFlattenable : Flattenable<TestFlattenable> {
69 TestFlattenable() = default;
70 explicit TestFlattenable(int32_t v) : value(v) {}
71
72 // Flattenable protocol
73 size_t getFlattenedSize() const { return sizeof(value); }
74 size_t getFdCount() const { return 0; }
75 status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
76 FlattenableUtils::write(buffer, size, value);
77 return NO_ERROR;
78 }
79 status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
80 FlattenableUtils::read(buffer, size, value);
81 return NO_ERROR;
82 }
83
84 int32_t value = 0;
85};
86
Dan Stozad630e522016-12-01 15:16:31 -080087struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> {
88 TestLightFlattenable() = default;
89 explicit TestLightFlattenable(int32_t v) : value(v) {}
90 int32_t value = 0;
91};
92
93class ExitOnDeath : public IBinder::DeathRecipient {
94public:
95 ~ExitOnDeath() override = default;
96
97 void binderDied(const wp<IBinder>& /*who*/) override {
98 ALOG(LOG_INFO, "ExitOnDeath", "Exiting");
99 exit(0);
100 }
101};
102
103// This callback class is used to test both one-way transactions and that sp<IInterface> can be
104// passed correctly
105class ICallback : public IInterface {
106public:
107 DECLARE_META_INTERFACE(Callback)
108
109 enum class Tag : uint32_t {
110 OnCallback = IBinder::FIRST_CALL_TRANSACTION,
111 Last,
112 };
113
114 virtual void onCallback(int32_t aPlusOne) = 0;
115};
116
117class BpCallback : public SafeBpInterface<ICallback> {
118public:
119 explicit BpCallback(const sp<IBinder>& impl) : SafeBpInterface<ICallback>(impl, getLogTag()) {}
120
121 void onCallback(int32_t aPlusOne) override {
122 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
123 return callRemoteAsync<decltype(&ICallback::onCallback)>(Tag::OnCallback, aPlusOne);
124 }
125
126private:
127 static constexpr const char* getLogTag() { return "BpCallback"; }
128};
129
130#pragma clang diagnostic push
131#pragma clang diagnostic ignored "-Wexit-time-destructors"
132IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback");
133#pragma clang diagnostic pop
134
135class BnCallback : public SafeBnInterface<ICallback> {
136public:
137 BnCallback() : SafeBnInterface("BnCallback") {}
138
139 status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
140 uint32_t /*flags*/) override {
141 EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
142 EXPECT_LT(code, static_cast<uint32_t>(ICallback::Tag::Last));
143 ICallback::Tag tag = static_cast<ICallback::Tag>(code);
144 switch (tag) {
145 case ICallback::Tag::OnCallback: {
146 return callLocalAsync(data, reply, &ICallback::onCallback);
147 }
148 case ICallback::Tag::Last:
149 // Should not be possible because of the asserts at the beginning of the method
150 [&]() { FAIL(); }();
151 return UNKNOWN_ERROR;
152 }
153 }
154};
155
156class ISafeInterfaceTest : public IInterface {
157public:
158 DECLARE_META_INTERFACE(SafeInterfaceTest)
159
160 enum class Tag : uint32_t {
161 SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
162 ReturnsNoMemory,
163 LogicalNot,
Dan Stozadf614ae2017-03-28 17:02:05 -0700164 IncrementFlattenable,
Dan Stozad630e522016-12-01 15:16:31 -0800165 IncrementLightFlattenable,
166 IncrementNoCopyNoMove,
167 ToUpper,
168 CallMeBack,
169 IncrementInt32,
170 IncrementUint32,
171 IncrementTwo,
172 Last,
173 };
174
175 // This is primarily so that the remote service dies when the test does, but it also serves to
176 // test the handling of sp<IBinder> and non-const methods
177 virtual status_t setDeathToken(const sp<IBinder>& token) = 0;
178
179 // This is the most basic test since it doesn't require parceling any arguments
180 virtual status_t returnsNoMemory() const = 0;
181
182 // These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
183 virtual status_t logicalNot(bool a, bool* notA) const = 0;
Dan Stozadf614ae2017-03-28 17:02:05 -0700184 virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
Dan Stozad630e522016-12-01 15:16:31 -0800185 virtual status_t increment(const TestLightFlattenable& a,
186 TestLightFlattenable* aPlusOne) const = 0;
187 virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
188 virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
189 // As mentioned above, sp<IBinder> is already tested by setDeathToken
190 virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
191 virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
192 virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
193
194 // This tests that input/output parameter interleaving works correctly
195 virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
196 int32_t* bPlusOne) const = 0;
197};
198
199class BpSafeInterfaceTest : public SafeBpInterface<ISafeInterfaceTest> {
200public:
201 explicit BpSafeInterfaceTest(const sp<IBinder>& impl)
202 : SafeBpInterface<ISafeInterfaceTest>(impl, getLogTag()) {}
203
204 status_t setDeathToken(const sp<IBinder>& token) override {
205 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
206 return callRemote<decltype(&ISafeInterfaceTest::setDeathToken)>(Tag::SetDeathToken, token);
207 }
208 status_t returnsNoMemory() const override {
209 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
210 return callRemote<decltype(&ISafeInterfaceTest::returnsNoMemory)>(Tag::ReturnsNoMemory);
211 }
212 status_t logicalNot(bool a, bool* notA) const override {
213 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
214 return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
215 }
Dan Stozadf614ae2017-03-28 17:02:05 -0700216 status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
217 using Signature =
218 status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
219 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
220 return callRemote<Signature>(Tag::IncrementFlattenable, a, aPlusOne);
221 }
Dan Stozad630e522016-12-01 15:16:31 -0800222 status_t increment(const TestLightFlattenable& a,
223 TestLightFlattenable* aPlusOne) const override {
224 using Signature = status_t (ISafeInterfaceTest::*)(const TestLightFlattenable&,
225 TestLightFlattenable*) const;
226 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
227 return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne);
228 }
229 status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
230 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
231 using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
232 NoCopyNoMove* aPlusOne) const;
233 return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
234 }
235 status_t toUpper(const String8& str, String8* upperStr) const override {
236 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
237 return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
238 }
239 void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
240 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
241 return callRemoteAsync<decltype(&ISafeInterfaceTest::callMeBack)>(Tag::CallMeBack, callback,
242 a);
243 }
244 status_t increment(int32_t a, int32_t* aPlusOne) const override {
245 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
246 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
247 return callRemote<Signature>(Tag::IncrementInt32, a, aPlusOne);
248 }
249 status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
250 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
251 using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
252 return callRemote<Signature>(Tag::IncrementUint32, a, aPlusOne);
253 }
254 status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
255 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
256 using Signature =
257 status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t, int32_t*) const;
258 return callRemote<Signature>(Tag::IncrementTwo, a, aPlusOne, b, bPlusOne);
259 }
260
261private:
262 static constexpr const char* getLogTag() { return "BpSafeInterfaceTest"; }
263};
264
265#pragma clang diagnostic push
266#pragma clang diagnostic ignored "-Wexit-time-destructors"
267IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest");
268
269static sp<IBinder::DeathRecipient> getDeathRecipient() {
270 static sp<IBinder::DeathRecipient> recipient = new ExitOnDeath;
271 return recipient;
272}
273#pragma clang diagnostic pop
274
275class BnSafeInterfaceTest : public SafeBnInterface<ISafeInterfaceTest> {
276public:
277 BnSafeInterfaceTest() : SafeBnInterface(getLogTag()) {}
278
279 status_t setDeathToken(const sp<IBinder>& token) override {
280 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
281 token->linkToDeath(getDeathRecipient());
282 return NO_ERROR;
283 }
284 status_t returnsNoMemory() const override {
285 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
286 return NO_MEMORY;
287 }
288 status_t logicalNot(bool a, bool* notA) const override {
289 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
290 *notA = !a;
291 return NO_ERROR;
292 }
Dan Stozadf614ae2017-03-28 17:02:05 -0700293 status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
294 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
295 aPlusOne->value = a.value + 1;
296 return NO_ERROR;
297 }
Dan Stozad630e522016-12-01 15:16:31 -0800298 status_t increment(const TestLightFlattenable& a,
299 TestLightFlattenable* aPlusOne) const override {
300 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
301 aPlusOne->value = a.value + 1;
302 return NO_ERROR;
303 }
304 status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
305 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
306 aPlusOne->setValue(a.getValue() + 1);
307 return NO_ERROR;
308 }
309 status_t toUpper(const String8& str, String8* upperStr) const override {
310 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
311 *upperStr = str;
312 upperStr->toUpper();
313 return NO_ERROR;
314 }
315 void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
316 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
317 callback->onCallback(a + 1);
318 }
319 status_t increment(int32_t a, int32_t* aPlusOne) const override {
320 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
321 *aPlusOne = a + 1;
322 return NO_ERROR;
323 }
324 status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
325 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
326 *aPlusOne = a + 1;
327 return NO_ERROR;
328 }
329 status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
330 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
331 *aPlusOne = a + 1;
332 *bPlusOne = b + 1;
333 return NO_ERROR;
334 }
335
336 // BnInterface
337 status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
338 uint32_t /*flags*/) override {
339 EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
340 EXPECT_LT(code, static_cast<uint32_t>(Tag::Last));
341 ISafeInterfaceTest::Tag tag = static_cast<ISafeInterfaceTest::Tag>(code);
342 switch (tag) {
343 case ISafeInterfaceTest::Tag::SetDeathToken: {
344 return callLocal(data, reply, &ISafeInterfaceTest::setDeathToken);
345 }
346 case ISafeInterfaceTest::Tag::ReturnsNoMemory: {
347 return callLocal(data, reply, &ISafeInterfaceTest::returnsNoMemory);
348 }
349 case ISafeInterfaceTest::Tag::LogicalNot: {
350 return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
351 }
Dan Stozadf614ae2017-03-28 17:02:05 -0700352 case ISafeInterfaceTest::Tag::IncrementFlattenable: {
353 using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
354 TestFlattenable* aPlusOne) const;
355 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
356 }
Dan Stozad630e522016-12-01 15:16:31 -0800357 case ISafeInterfaceTest::Tag::IncrementLightFlattenable: {
358 using Signature =
359 status_t (ISafeInterfaceTest::*)(const TestLightFlattenable& a,
360 TestLightFlattenable* aPlusOne) const;
361 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
362 }
363 case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: {
364 using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
365 NoCopyNoMove* aPlusOne) const;
366 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
367 }
368 case ISafeInterfaceTest::Tag::ToUpper: {
369 return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
370 }
371 case ISafeInterfaceTest::Tag::CallMeBack: {
372 return callLocalAsync(data, reply, &ISafeInterfaceTest::callMeBack);
373 }
374 case ISafeInterfaceTest::Tag::IncrementInt32: {
375 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
376 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
377 }
378 case ISafeInterfaceTest::Tag::IncrementUint32: {
379 using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
380 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
381 }
382 case ISafeInterfaceTest::Tag::IncrementTwo: {
383 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
384 int32_t*) const;
385 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
386 }
387 case ISafeInterfaceTest::Tag::Last:
388 // Should not be possible because of the asserts at the beginning of the method
389 [&]() { FAIL(); }();
390 return UNKNOWN_ERROR;
391 }
392 }
393
394private:
395 static constexpr const char* getLogTag() { return "BnSafeInterfaceTest"; }
396};
397
398class SafeInterfaceTest : public ::testing::Test {
399public:
400 SafeInterfaceTest() : mSafeInterfaceTest(getRemoteService()) {
401 ProcessState::self()->startThreadPool();
402 }
403 ~SafeInterfaceTest() override = default;
404
405protected:
406 sp<ISafeInterfaceTest> mSafeInterfaceTest;
407
408private:
409 static constexpr const char* getLogTag() { return "SafeInterfaceTest"; }
410
411 sp<ISafeInterfaceTest> getRemoteService() {
412#pragma clang diagnostic push
413#pragma clang diagnostic ignored "-Wexit-time-destructors"
414 static std::mutex sMutex;
415 static sp<ISafeInterfaceTest> sService;
416 static sp<IBinder> sDeathToken = new BBinder;
417#pragma clang diagnostic pop
418
419 std::unique_lock<decltype(sMutex)> lock;
420 if (sService == nullptr) {
421 ALOG(LOG_INFO, getLogTag(), "Forking remote process");
422 pid_t forkPid = fork();
423 EXPECT_NE(forkPid, -1);
424
425 const String16 serviceName("SafeInterfaceTest");
426
427 if (forkPid == 0) {
428 ALOG(LOG_INFO, getLogTag(), "Remote process checking in");
429 sp<ISafeInterfaceTest> nativeService = new BnSafeInterfaceTest;
430 defaultServiceManager()->addService(serviceName,
431 IInterface::asBinder(nativeService));
432 ProcessState::self()->startThreadPool();
433 IPCThreadState::self()->joinThreadPool();
434 // We shouldn't get to this point
435 [&]() { FAIL(); }();
436 }
437
438 sp<IBinder> binder = defaultServiceManager()->getService(serviceName);
439 sService = interface_cast<ISafeInterfaceTest>(binder);
440 EXPECT_TRUE(sService != nullptr);
441
442 sService->setDeathToken(sDeathToken);
443 }
444
445 return sService;
446 }
447};
448
449TEST_F(SafeInterfaceTest, TestReturnsNoMemory) {
450 status_t result = mSafeInterfaceTest->returnsNoMemory();
451 ASSERT_EQ(NO_MEMORY, result);
452}
453
454TEST_F(SafeInterfaceTest, TestLogicalNot) {
455 const bool a = true;
456 bool notA = true;
457 status_t result = mSafeInterfaceTest->logicalNot(a, &notA);
458 ASSERT_EQ(NO_ERROR, result);
459 ASSERT_EQ(!a, notA);
460 // Test both since we don't want to accidentally catch a default false somewhere
461 const bool b = false;
462 bool notB = false;
463 result = mSafeInterfaceTest->logicalNot(b, &notB);
464 ASSERT_EQ(NO_ERROR, result);
465 ASSERT_EQ(!b, notB);
466}
467
Dan Stozadf614ae2017-03-28 17:02:05 -0700468TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
469 const TestFlattenable a{1};
470 TestFlattenable aPlusOne{0};
471 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
472 ASSERT_EQ(NO_ERROR, result);
473 ASSERT_EQ(a.value + 1, aPlusOne.value);
474}
475
Dan Stozad630e522016-12-01 15:16:31 -0800476TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) {
477 const TestLightFlattenable a{1};
478 TestLightFlattenable aPlusOne{0};
479 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
480 ASSERT_EQ(NO_ERROR, result);
481 ASSERT_EQ(a.value + 1, aPlusOne.value);
482}
483
484TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
485 const NoCopyNoMove a{1};
486 NoCopyNoMove aPlusOne{0};
487 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
488 ASSERT_EQ(NO_ERROR, result);
489 ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
490}
491
492TEST_F(SafeInterfaceTest, TestToUpper) {
493 const String8 str{"Hello, world!"};
494 String8 upperStr;
495 status_t result = mSafeInterfaceTest->toUpper(str, &upperStr);
496 ASSERT_EQ(NO_ERROR, result);
497 ASSERT_TRUE(upperStr == String8{"HELLO, WORLD!"});
498}
499
500TEST_F(SafeInterfaceTest, TestCallMeBack) {
501 class CallbackReceiver : public BnCallback {
502 public:
503 void onCallback(int32_t aPlusOne) override {
504 ALOG(LOG_INFO, "CallbackReceiver", "%s", __PRETTY_FUNCTION__);
505 std::unique_lock<decltype(mMutex)> lock(mMutex);
506 mValue = aPlusOne;
507 mCondition.notify_one();
508 }
509
510 std::optional<int32_t> waitForCallback() {
511 std::unique_lock<decltype(mMutex)> lock(mMutex);
512 bool success =
513 mCondition.wait_for(lock, 100ms, [&]() { return static_cast<bool>(mValue); });
514 return success ? mValue : std::nullopt;
515 }
516
517 private:
518 std::mutex mMutex;
519 std::condition_variable mCondition;
520 std::optional<int32_t> mValue;
521 };
522
523 sp<CallbackReceiver> receiver = new CallbackReceiver;
524 const int32_t a = 1;
525 mSafeInterfaceTest->callMeBack(receiver, a);
526 auto result = receiver->waitForCallback();
527 ASSERT_TRUE(result);
528 ASSERT_EQ(a + 1, *result);
529}
530
531TEST_F(SafeInterfaceTest, TestIncrementInt32) {
532 const int32_t a = 1;
533 int32_t aPlusOne = 0;
534 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
535 ASSERT_EQ(NO_ERROR, result);
536 ASSERT_EQ(a + 1, aPlusOne);
537}
538
539TEST_F(SafeInterfaceTest, TestIncrementUint32) {
540 const uint32_t a = 1;
541 uint32_t aPlusOne = 0;
542 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
543 ASSERT_EQ(NO_ERROR, result);
544 ASSERT_EQ(a + 1, aPlusOne);
545}
546
547TEST_F(SafeInterfaceTest, TestIncrementTwo) {
548 const int32_t a = 1;
549 int32_t aPlusOne = 0;
550 const int32_t b = 2;
551 int32_t bPlusOne = 0;
552 status_t result = mSafeInterfaceTest->increment(1, &aPlusOne, 2, &bPlusOne);
553 ASSERT_EQ(NO_ERROR, result);
554 ASSERT_EQ(a + 1, aPlusOne);
555 ASSERT_EQ(b + 1, bPlusOne);
556}
557
558} // namespace tests
559} // namespace android