blob: ac2f4d5a5935661c7d7d8b8b11e88bf468a12756 [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
68struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> {
69 TestLightFlattenable() = default;
70 explicit TestLightFlattenable(int32_t v) : value(v) {}
71 int32_t value = 0;
72};
73
74class ExitOnDeath : public IBinder::DeathRecipient {
75public:
76 ~ExitOnDeath() override = default;
77
78 void binderDied(const wp<IBinder>& /*who*/) override {
79 ALOG(LOG_INFO, "ExitOnDeath", "Exiting");
80 exit(0);
81 }
82};
83
84// This callback class is used to test both one-way transactions and that sp<IInterface> can be
85// passed correctly
86class ICallback : public IInterface {
87public:
88 DECLARE_META_INTERFACE(Callback)
89
90 enum class Tag : uint32_t {
91 OnCallback = IBinder::FIRST_CALL_TRANSACTION,
92 Last,
93 };
94
95 virtual void onCallback(int32_t aPlusOne) = 0;
96};
97
98class BpCallback : public SafeBpInterface<ICallback> {
99public:
100 explicit BpCallback(const sp<IBinder>& impl) : SafeBpInterface<ICallback>(impl, getLogTag()) {}
101
102 void onCallback(int32_t aPlusOne) override {
103 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
104 return callRemoteAsync<decltype(&ICallback::onCallback)>(Tag::OnCallback, aPlusOne);
105 }
106
107private:
108 static constexpr const char* getLogTag() { return "BpCallback"; }
109};
110
111#pragma clang diagnostic push
112#pragma clang diagnostic ignored "-Wexit-time-destructors"
113IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback");
114#pragma clang diagnostic pop
115
116class BnCallback : public SafeBnInterface<ICallback> {
117public:
118 BnCallback() : SafeBnInterface("BnCallback") {}
119
120 status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
121 uint32_t /*flags*/) override {
122 EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
123 EXPECT_LT(code, static_cast<uint32_t>(ICallback::Tag::Last));
124 ICallback::Tag tag = static_cast<ICallback::Tag>(code);
125 switch (tag) {
126 case ICallback::Tag::OnCallback: {
127 return callLocalAsync(data, reply, &ICallback::onCallback);
128 }
129 case ICallback::Tag::Last:
130 // Should not be possible because of the asserts at the beginning of the method
131 [&]() { FAIL(); }();
132 return UNKNOWN_ERROR;
133 }
134 }
135};
136
137class ISafeInterfaceTest : public IInterface {
138public:
139 DECLARE_META_INTERFACE(SafeInterfaceTest)
140
141 enum class Tag : uint32_t {
142 SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
143 ReturnsNoMemory,
144 LogicalNot,
145 IncrementLightFlattenable,
146 IncrementNoCopyNoMove,
147 ToUpper,
148 CallMeBack,
149 IncrementInt32,
150 IncrementUint32,
151 IncrementTwo,
152 Last,
153 };
154
155 // This is primarily so that the remote service dies when the test does, but it also serves to
156 // test the handling of sp<IBinder> and non-const methods
157 virtual status_t setDeathToken(const sp<IBinder>& token) = 0;
158
159 // This is the most basic test since it doesn't require parceling any arguments
160 virtual status_t returnsNoMemory() const = 0;
161
162 // These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
163 virtual status_t logicalNot(bool a, bool* notA) const = 0;
164 virtual status_t increment(const TestLightFlattenable& a,
165 TestLightFlattenable* aPlusOne) const = 0;
166 virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
167 virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
168 // As mentioned above, sp<IBinder> is already tested by setDeathToken
169 virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
170 virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
171 virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
172
173 // This tests that input/output parameter interleaving works correctly
174 virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
175 int32_t* bPlusOne) const = 0;
176};
177
178class BpSafeInterfaceTest : public SafeBpInterface<ISafeInterfaceTest> {
179public:
180 explicit BpSafeInterfaceTest(const sp<IBinder>& impl)
181 : SafeBpInterface<ISafeInterfaceTest>(impl, getLogTag()) {}
182
183 status_t setDeathToken(const sp<IBinder>& token) override {
184 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
185 return callRemote<decltype(&ISafeInterfaceTest::setDeathToken)>(Tag::SetDeathToken, token);
186 }
187 status_t returnsNoMemory() const override {
188 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
189 return callRemote<decltype(&ISafeInterfaceTest::returnsNoMemory)>(Tag::ReturnsNoMemory);
190 }
191 status_t logicalNot(bool a, bool* notA) const override {
192 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
193 return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
194 }
195 status_t increment(const TestLightFlattenable& a,
196 TestLightFlattenable* aPlusOne) const override {
197 using Signature = status_t (ISafeInterfaceTest::*)(const TestLightFlattenable&,
198 TestLightFlattenable*) const;
199 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
200 return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne);
201 }
202 status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
203 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
204 using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
205 NoCopyNoMove* aPlusOne) const;
206 return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
207 }
208 status_t toUpper(const String8& str, String8* upperStr) const override {
209 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
210 return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
211 }
212 void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
213 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
214 return callRemoteAsync<decltype(&ISafeInterfaceTest::callMeBack)>(Tag::CallMeBack, callback,
215 a);
216 }
217 status_t increment(int32_t a, int32_t* aPlusOne) const override {
218 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
219 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
220 return callRemote<Signature>(Tag::IncrementInt32, a, aPlusOne);
221 }
222 status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
223 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
224 using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
225 return callRemote<Signature>(Tag::IncrementUint32, a, aPlusOne);
226 }
227 status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
228 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
229 using Signature =
230 status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t, int32_t*) const;
231 return callRemote<Signature>(Tag::IncrementTwo, a, aPlusOne, b, bPlusOne);
232 }
233
234private:
235 static constexpr const char* getLogTag() { return "BpSafeInterfaceTest"; }
236};
237
238#pragma clang diagnostic push
239#pragma clang diagnostic ignored "-Wexit-time-destructors"
240IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest");
241
242static sp<IBinder::DeathRecipient> getDeathRecipient() {
243 static sp<IBinder::DeathRecipient> recipient = new ExitOnDeath;
244 return recipient;
245}
246#pragma clang diagnostic pop
247
248class BnSafeInterfaceTest : public SafeBnInterface<ISafeInterfaceTest> {
249public:
250 BnSafeInterfaceTest() : SafeBnInterface(getLogTag()) {}
251
252 status_t setDeathToken(const sp<IBinder>& token) override {
253 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
254 token->linkToDeath(getDeathRecipient());
255 return NO_ERROR;
256 }
257 status_t returnsNoMemory() const override {
258 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
259 return NO_MEMORY;
260 }
261 status_t logicalNot(bool a, bool* notA) const override {
262 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
263 *notA = !a;
264 return NO_ERROR;
265 }
266 status_t increment(const TestLightFlattenable& a,
267 TestLightFlattenable* aPlusOne) const override {
268 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
269 aPlusOne->value = a.value + 1;
270 return NO_ERROR;
271 }
272 status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
273 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
274 aPlusOne->setValue(a.getValue() + 1);
275 return NO_ERROR;
276 }
277 status_t toUpper(const String8& str, String8* upperStr) const override {
278 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
279 *upperStr = str;
280 upperStr->toUpper();
281 return NO_ERROR;
282 }
283 void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
284 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
285 callback->onCallback(a + 1);
286 }
287 status_t increment(int32_t a, int32_t* aPlusOne) const override {
288 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
289 *aPlusOne = a + 1;
290 return NO_ERROR;
291 }
292 status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
293 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
294 *aPlusOne = a + 1;
295 return NO_ERROR;
296 }
297 status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
298 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
299 *aPlusOne = a + 1;
300 *bPlusOne = b + 1;
301 return NO_ERROR;
302 }
303
304 // BnInterface
305 status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
306 uint32_t /*flags*/) override {
307 EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
308 EXPECT_LT(code, static_cast<uint32_t>(Tag::Last));
309 ISafeInterfaceTest::Tag tag = static_cast<ISafeInterfaceTest::Tag>(code);
310 switch (tag) {
311 case ISafeInterfaceTest::Tag::SetDeathToken: {
312 return callLocal(data, reply, &ISafeInterfaceTest::setDeathToken);
313 }
314 case ISafeInterfaceTest::Tag::ReturnsNoMemory: {
315 return callLocal(data, reply, &ISafeInterfaceTest::returnsNoMemory);
316 }
317 case ISafeInterfaceTest::Tag::LogicalNot: {
318 return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
319 }
320 case ISafeInterfaceTest::Tag::IncrementLightFlattenable: {
321 using Signature =
322 status_t (ISafeInterfaceTest::*)(const TestLightFlattenable& a,
323 TestLightFlattenable* aPlusOne) const;
324 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
325 }
326 case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: {
327 using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
328 NoCopyNoMove* aPlusOne) const;
329 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
330 }
331 case ISafeInterfaceTest::Tag::ToUpper: {
332 return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
333 }
334 case ISafeInterfaceTest::Tag::CallMeBack: {
335 return callLocalAsync(data, reply, &ISafeInterfaceTest::callMeBack);
336 }
337 case ISafeInterfaceTest::Tag::IncrementInt32: {
338 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
339 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
340 }
341 case ISafeInterfaceTest::Tag::IncrementUint32: {
342 using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
343 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
344 }
345 case ISafeInterfaceTest::Tag::IncrementTwo: {
346 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
347 int32_t*) const;
348 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
349 }
350 case ISafeInterfaceTest::Tag::Last:
351 // Should not be possible because of the asserts at the beginning of the method
352 [&]() { FAIL(); }();
353 return UNKNOWN_ERROR;
354 }
355 }
356
357private:
358 static constexpr const char* getLogTag() { return "BnSafeInterfaceTest"; }
359};
360
361class SafeInterfaceTest : public ::testing::Test {
362public:
363 SafeInterfaceTest() : mSafeInterfaceTest(getRemoteService()) {
364 ProcessState::self()->startThreadPool();
365 }
366 ~SafeInterfaceTest() override = default;
367
368protected:
369 sp<ISafeInterfaceTest> mSafeInterfaceTest;
370
371private:
372 static constexpr const char* getLogTag() { return "SafeInterfaceTest"; }
373
374 sp<ISafeInterfaceTest> getRemoteService() {
375#pragma clang diagnostic push
376#pragma clang diagnostic ignored "-Wexit-time-destructors"
377 static std::mutex sMutex;
378 static sp<ISafeInterfaceTest> sService;
379 static sp<IBinder> sDeathToken = new BBinder;
380#pragma clang diagnostic pop
381
382 std::unique_lock<decltype(sMutex)> lock;
383 if (sService == nullptr) {
384 ALOG(LOG_INFO, getLogTag(), "Forking remote process");
385 pid_t forkPid = fork();
386 EXPECT_NE(forkPid, -1);
387
388 const String16 serviceName("SafeInterfaceTest");
389
390 if (forkPid == 0) {
391 ALOG(LOG_INFO, getLogTag(), "Remote process checking in");
392 sp<ISafeInterfaceTest> nativeService = new BnSafeInterfaceTest;
393 defaultServiceManager()->addService(serviceName,
394 IInterface::asBinder(nativeService));
395 ProcessState::self()->startThreadPool();
396 IPCThreadState::self()->joinThreadPool();
397 // We shouldn't get to this point
398 [&]() { FAIL(); }();
399 }
400
401 sp<IBinder> binder = defaultServiceManager()->getService(serviceName);
402 sService = interface_cast<ISafeInterfaceTest>(binder);
403 EXPECT_TRUE(sService != nullptr);
404
405 sService->setDeathToken(sDeathToken);
406 }
407
408 return sService;
409 }
410};
411
412TEST_F(SafeInterfaceTest, TestReturnsNoMemory) {
413 status_t result = mSafeInterfaceTest->returnsNoMemory();
414 ASSERT_EQ(NO_MEMORY, result);
415}
416
417TEST_F(SafeInterfaceTest, TestLogicalNot) {
418 const bool a = true;
419 bool notA = true;
420 status_t result = mSafeInterfaceTest->logicalNot(a, &notA);
421 ASSERT_EQ(NO_ERROR, result);
422 ASSERT_EQ(!a, notA);
423 // Test both since we don't want to accidentally catch a default false somewhere
424 const bool b = false;
425 bool notB = false;
426 result = mSafeInterfaceTest->logicalNot(b, &notB);
427 ASSERT_EQ(NO_ERROR, result);
428 ASSERT_EQ(!b, notB);
429}
430
431TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) {
432 const TestLightFlattenable a{1};
433 TestLightFlattenable aPlusOne{0};
434 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
435 ASSERT_EQ(NO_ERROR, result);
436 ASSERT_EQ(a.value + 1, aPlusOne.value);
437}
438
439TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
440 const NoCopyNoMove a{1};
441 NoCopyNoMove aPlusOne{0};
442 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
443 ASSERT_EQ(NO_ERROR, result);
444 ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
445}
446
447TEST_F(SafeInterfaceTest, TestToUpper) {
448 const String8 str{"Hello, world!"};
449 String8 upperStr;
450 status_t result = mSafeInterfaceTest->toUpper(str, &upperStr);
451 ASSERT_EQ(NO_ERROR, result);
452 ASSERT_TRUE(upperStr == String8{"HELLO, WORLD!"});
453}
454
455TEST_F(SafeInterfaceTest, TestCallMeBack) {
456 class CallbackReceiver : public BnCallback {
457 public:
458 void onCallback(int32_t aPlusOne) override {
459 ALOG(LOG_INFO, "CallbackReceiver", "%s", __PRETTY_FUNCTION__);
460 std::unique_lock<decltype(mMutex)> lock(mMutex);
461 mValue = aPlusOne;
462 mCondition.notify_one();
463 }
464
465 std::optional<int32_t> waitForCallback() {
466 std::unique_lock<decltype(mMutex)> lock(mMutex);
467 bool success =
468 mCondition.wait_for(lock, 100ms, [&]() { return static_cast<bool>(mValue); });
469 return success ? mValue : std::nullopt;
470 }
471
472 private:
473 std::mutex mMutex;
474 std::condition_variable mCondition;
475 std::optional<int32_t> mValue;
476 };
477
478 sp<CallbackReceiver> receiver = new CallbackReceiver;
479 const int32_t a = 1;
480 mSafeInterfaceTest->callMeBack(receiver, a);
481 auto result = receiver->waitForCallback();
482 ASSERT_TRUE(result);
483 ASSERT_EQ(a + 1, *result);
484}
485
486TEST_F(SafeInterfaceTest, TestIncrementInt32) {
487 const int32_t a = 1;
488 int32_t aPlusOne = 0;
489 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
490 ASSERT_EQ(NO_ERROR, result);
491 ASSERT_EQ(a + 1, aPlusOne);
492}
493
494TEST_F(SafeInterfaceTest, TestIncrementUint32) {
495 const uint32_t a = 1;
496 uint32_t aPlusOne = 0;
497 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
498 ASSERT_EQ(NO_ERROR, result);
499 ASSERT_EQ(a + 1, aPlusOne);
500}
501
502TEST_F(SafeInterfaceTest, TestIncrementTwo) {
503 const int32_t a = 1;
504 int32_t aPlusOne = 0;
505 const int32_t b = 2;
506 int32_t bPlusOne = 0;
507 status_t result = mSafeInterfaceTest->increment(1, &aPlusOne, 2, &bPlusOne);
508 ASSERT_EQ(NO_ERROR, result);
509 ASSERT_EQ(a + 1, aPlusOne);
510 ASSERT_EQ(b + 1, bPlusOne);
511}
512
513} // namespace tests
514} // namespace android