blob: 4d9cacb80d53c73ac55e53cfba3a41a619fe04e4 [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
Dan Stoza6dd325b2017-04-07 14:31:51 -070031#include <utils/LightRefBase.h>
Dan Stoza2537db72017-04-07 16:32:38 -070032#include <utils/NativeHandle.h>
33
34#include <cutils/native_handle.h>
Dan Stoza6dd325b2017-04-07 14:31:51 -070035
Dan Stozad630e522016-12-01 15:16:31 -080036#include <optional>
37
Dan Stoza2537db72017-04-07 16:32:38 -070038#include <sys/eventfd.h>
39
Dan Stozad630e522016-12-01 15:16:31 -080040using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
41
42namespace android {
43namespace tests {
44
Dan Stoza81ea3ef2017-04-07 15:00:18 -070045enum class TestEnum : uint32_t {
46 INVALID = 0,
47 INITIAL = 1,
48 FINAL = 2,
49};
50
Dan Stozad630e522016-12-01 15:16:31 -080051// This class serves two purposes:
52// 1) It ensures that the implementation doesn't require copying or moving the data (for
53// efficiency purposes)
54// 2) It tests that Parcelables can be passed correctly
55class NoCopyNoMove : public Parcelable {
56public:
57 NoCopyNoMove() = default;
58 explicit NoCopyNoMove(int32_t value) : mValue(value) {}
59 ~NoCopyNoMove() override = default;
60
61 // Not copyable
62 NoCopyNoMove(const NoCopyNoMove&) = delete;
63 NoCopyNoMove& operator=(const NoCopyNoMove&) = delete;
64
65 // Not movable
66 NoCopyNoMove(NoCopyNoMove&&) = delete;
67 NoCopyNoMove& operator=(NoCopyNoMove&&) = delete;
68
69 // Parcelable interface
70 status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
71 status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }
72
73 int32_t getValue() const { return mValue; }
74 void setValue(int32_t value) { mValue = value; }
75
76private:
77 int32_t mValue = 0;
78 uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
79};
80
Dan Stozadf614ae2017-03-28 17:02:05 -070081struct TestFlattenable : Flattenable<TestFlattenable> {
82 TestFlattenable() = default;
83 explicit TestFlattenable(int32_t v) : value(v) {}
84
85 // Flattenable protocol
86 size_t getFlattenedSize() const { return sizeof(value); }
87 size_t getFdCount() const { return 0; }
88 status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
89 FlattenableUtils::write(buffer, size, value);
90 return NO_ERROR;
91 }
92 status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
93 FlattenableUtils::read(buffer, size, value);
94 return NO_ERROR;
95 }
96
97 int32_t value = 0;
98};
99
Dan Stozad630e522016-12-01 15:16:31 -0800100struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> {
101 TestLightFlattenable() = default;
102 explicit TestLightFlattenable(int32_t v) : value(v) {}
103 int32_t value = 0;
104};
105
Dan Stoza6dd325b2017-04-07 14:31:51 -0700106// It seems like this should be able to inherit from TestFlattenable (to avoid duplicating code),
107// but the SafeInterface logic can't easily be extended to find an indirect Flattenable<T>
108// base class
109class TestLightRefBaseFlattenable : public Flattenable<TestLightRefBaseFlattenable>,
110 public LightRefBase<TestLightRefBaseFlattenable> {
111public:
112 TestLightRefBaseFlattenable() = default;
113 explicit TestLightRefBaseFlattenable(int32_t v) : value(v) {}
114
115 // Flattenable protocol
116 size_t getFlattenedSize() const { return sizeof(value); }
117 size_t getFdCount() const { return 0; }
118 status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
119 FlattenableUtils::write(buffer, size, value);
120 return NO_ERROR;
121 }
122 status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
123 FlattenableUtils::read(buffer, size, value);
124 return NO_ERROR;
125 }
126
127 int32_t value = 0;
128};
129
Dan Stozad630e522016-12-01 15:16:31 -0800130class ExitOnDeath : public IBinder::DeathRecipient {
131public:
132 ~ExitOnDeath() override = default;
133
134 void binderDied(const wp<IBinder>& /*who*/) override {
135 ALOG(LOG_INFO, "ExitOnDeath", "Exiting");
136 exit(0);
137 }
138};
139
140// This callback class is used to test both one-way transactions and that sp<IInterface> can be
141// passed correctly
142class ICallback : public IInterface {
143public:
144 DECLARE_META_INTERFACE(Callback)
145
146 enum class Tag : uint32_t {
147 OnCallback = IBinder::FIRST_CALL_TRANSACTION,
148 Last,
149 };
150
151 virtual void onCallback(int32_t aPlusOne) = 0;
152};
153
154class BpCallback : public SafeBpInterface<ICallback> {
155public:
156 explicit BpCallback(const sp<IBinder>& impl) : SafeBpInterface<ICallback>(impl, getLogTag()) {}
157
158 void onCallback(int32_t aPlusOne) override {
159 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
160 return callRemoteAsync<decltype(&ICallback::onCallback)>(Tag::OnCallback, aPlusOne);
161 }
162
163private:
164 static constexpr const char* getLogTag() { return "BpCallback"; }
165};
166
167#pragma clang diagnostic push
168#pragma clang diagnostic ignored "-Wexit-time-destructors"
169IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback");
170#pragma clang diagnostic pop
171
172class BnCallback : public SafeBnInterface<ICallback> {
173public:
174 BnCallback() : SafeBnInterface("BnCallback") {}
175
176 status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
177 uint32_t /*flags*/) override {
178 EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
179 EXPECT_LT(code, static_cast<uint32_t>(ICallback::Tag::Last));
180 ICallback::Tag tag = static_cast<ICallback::Tag>(code);
181 switch (tag) {
182 case ICallback::Tag::OnCallback: {
183 return callLocalAsync(data, reply, &ICallback::onCallback);
184 }
185 case ICallback::Tag::Last:
186 // Should not be possible because of the asserts at the beginning of the method
187 [&]() { FAIL(); }();
188 return UNKNOWN_ERROR;
189 }
190 }
191};
192
193class ISafeInterfaceTest : public IInterface {
194public:
195 DECLARE_META_INTERFACE(SafeInterfaceTest)
196
197 enum class Tag : uint32_t {
198 SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
199 ReturnsNoMemory,
200 LogicalNot,
Dan Stoza81ea3ef2017-04-07 15:00:18 -0700201 ModifyEnum,
Dan Stozadf614ae2017-03-28 17:02:05 -0700202 IncrementFlattenable,
Dan Stozad630e522016-12-01 15:16:31 -0800203 IncrementLightFlattenable,
Dan Stoza6dd325b2017-04-07 14:31:51 -0700204 IncrementLightRefBaseFlattenable,
Dan Stoza2537db72017-04-07 16:32:38 -0700205 IncrementNativeHandle,
Dan Stozad630e522016-12-01 15:16:31 -0800206 IncrementNoCopyNoMove,
207 ToUpper,
208 CallMeBack,
209 IncrementInt32,
210 IncrementUint32,
Dan Stoza662a8992017-04-06 16:18:39 -0700211 IncrementInt64,
212 IncrementUint64,
Dan Stozad630e522016-12-01 15:16:31 -0800213 IncrementTwo,
214 Last,
215 };
216
217 // This is primarily so that the remote service dies when the test does, but it also serves to
218 // test the handling of sp<IBinder> and non-const methods
219 virtual status_t setDeathToken(const sp<IBinder>& token) = 0;
220
221 // This is the most basic test since it doesn't require parceling any arguments
222 virtual status_t returnsNoMemory() const = 0;
223
224 // These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
225 virtual status_t logicalNot(bool a, bool* notA) const = 0;
Dan Stoza81ea3ef2017-04-07 15:00:18 -0700226 virtual status_t modifyEnum(TestEnum a, TestEnum* b) const = 0;
Dan Stozadf614ae2017-03-28 17:02:05 -0700227 virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
Dan Stozad630e522016-12-01 15:16:31 -0800228 virtual status_t increment(const TestLightFlattenable& a,
229 TestLightFlattenable* aPlusOne) const = 0;
Dan Stoza6dd325b2017-04-07 14:31:51 -0700230 virtual status_t increment(const sp<TestLightRefBaseFlattenable>& a,
231 sp<TestLightRefBaseFlattenable>* aPlusOne) const = 0;
Dan Stoza2537db72017-04-07 16:32:38 -0700232 virtual status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const = 0;
Dan Stozad630e522016-12-01 15:16:31 -0800233 virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
234 virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
235 // As mentioned above, sp<IBinder> is already tested by setDeathToken
236 virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
237 virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
238 virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
Dan Stoza662a8992017-04-06 16:18:39 -0700239 virtual status_t increment(int64_t a, int64_t* aPlusOne) const = 0;
240 virtual status_t increment(uint64_t a, uint64_t* aPlusOne) const = 0;
Dan Stozad630e522016-12-01 15:16:31 -0800241
242 // This tests that input/output parameter interleaving works correctly
243 virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
244 int32_t* bPlusOne) const = 0;
245};
246
247class BpSafeInterfaceTest : public SafeBpInterface<ISafeInterfaceTest> {
248public:
249 explicit BpSafeInterfaceTest(const sp<IBinder>& impl)
250 : SafeBpInterface<ISafeInterfaceTest>(impl, getLogTag()) {}
251
252 status_t setDeathToken(const sp<IBinder>& token) override {
253 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
254 return callRemote<decltype(&ISafeInterfaceTest::setDeathToken)>(Tag::SetDeathToken, token);
255 }
256 status_t returnsNoMemory() const override {
257 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
258 return callRemote<decltype(&ISafeInterfaceTest::returnsNoMemory)>(Tag::ReturnsNoMemory);
259 }
260 status_t logicalNot(bool a, bool* notA) const override {
261 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
262 return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
263 }
Dan Stoza81ea3ef2017-04-07 15:00:18 -0700264 status_t modifyEnum(TestEnum a, TestEnum* b) const override {
265 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
266 return callRemote<decltype(&ISafeInterfaceTest::modifyEnum)>(Tag::ModifyEnum, a, b);
267 }
Dan Stozadf614ae2017-03-28 17:02:05 -0700268 status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
269 using Signature =
270 status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
271 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
272 return callRemote<Signature>(Tag::IncrementFlattenable, a, aPlusOne);
273 }
Dan Stozad630e522016-12-01 15:16:31 -0800274 status_t increment(const TestLightFlattenable& a,
275 TestLightFlattenable* aPlusOne) const override {
276 using Signature = status_t (ISafeInterfaceTest::*)(const TestLightFlattenable&,
277 TestLightFlattenable*) const;
278 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
279 return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne);
280 }
Dan Stoza6dd325b2017-04-07 14:31:51 -0700281 status_t increment(const sp<TestLightRefBaseFlattenable>& a,
282 sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
283 using Signature = status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
284 sp<TestLightRefBaseFlattenable>*) const;
285 return callRemote<Signature>(Tag::IncrementLightRefBaseFlattenable, a, aPlusOne);
286 }
Dan Stoza2537db72017-04-07 16:32:38 -0700287 status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
288 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
289 using Signature =
290 status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&, sp<NativeHandle>*) const;
291 return callRemote<Signature>(Tag::IncrementNativeHandle, a, aPlusOne);
292 }
Dan Stozad630e522016-12-01 15:16:31 -0800293 status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
294 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
295 using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
296 NoCopyNoMove* aPlusOne) const;
297 return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
298 }
299 status_t toUpper(const String8& str, String8* upperStr) const override {
300 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
301 return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
302 }
303 void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
304 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
305 return callRemoteAsync<decltype(&ISafeInterfaceTest::callMeBack)>(Tag::CallMeBack, callback,
306 a);
307 }
308 status_t increment(int32_t a, int32_t* aPlusOne) const override {
309 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
310 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
311 return callRemote<Signature>(Tag::IncrementInt32, a, aPlusOne);
312 }
313 status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
314 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
315 using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
316 return callRemote<Signature>(Tag::IncrementUint32, a, aPlusOne);
317 }
Dan Stoza662a8992017-04-06 16:18:39 -0700318 status_t increment(int64_t a, int64_t* aPlusOne) const override {
319 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
320 using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
321 return callRemote<Signature>(Tag::IncrementInt64, a, aPlusOne);
322 }
323 status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
324 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
325 using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
326 return callRemote<Signature>(Tag::IncrementUint64, a, aPlusOne);
327 }
Dan Stozad630e522016-12-01 15:16:31 -0800328 status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
329 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
330 using Signature =
331 status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t, int32_t*) const;
332 return callRemote<Signature>(Tag::IncrementTwo, a, aPlusOne, b, bPlusOne);
333 }
334
335private:
336 static constexpr const char* getLogTag() { return "BpSafeInterfaceTest"; }
337};
338
339#pragma clang diagnostic push
340#pragma clang diagnostic ignored "-Wexit-time-destructors"
341IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest");
342
343static sp<IBinder::DeathRecipient> getDeathRecipient() {
344 static sp<IBinder::DeathRecipient> recipient = new ExitOnDeath;
345 return recipient;
346}
347#pragma clang diagnostic pop
348
349class BnSafeInterfaceTest : public SafeBnInterface<ISafeInterfaceTest> {
350public:
351 BnSafeInterfaceTest() : SafeBnInterface(getLogTag()) {}
352
353 status_t setDeathToken(const sp<IBinder>& token) override {
354 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
355 token->linkToDeath(getDeathRecipient());
356 return NO_ERROR;
357 }
358 status_t returnsNoMemory() const override {
359 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
360 return NO_MEMORY;
361 }
362 status_t logicalNot(bool a, bool* notA) const override {
363 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
364 *notA = !a;
365 return NO_ERROR;
366 }
Dan Stoza81ea3ef2017-04-07 15:00:18 -0700367 status_t modifyEnum(TestEnum a, TestEnum* b) const override {
368 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
369 *b = (a == TestEnum::INITIAL) ? TestEnum::FINAL : TestEnum::INVALID;
370 return NO_ERROR;
371 }
Dan Stozadf614ae2017-03-28 17:02:05 -0700372 status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
373 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
374 aPlusOne->value = a.value + 1;
375 return NO_ERROR;
376 }
Dan Stozad630e522016-12-01 15:16:31 -0800377 status_t increment(const TestLightFlattenable& a,
378 TestLightFlattenable* aPlusOne) const override {
379 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
380 aPlusOne->value = a.value + 1;
381 return NO_ERROR;
382 }
Dan Stoza6dd325b2017-04-07 14:31:51 -0700383 status_t increment(const sp<TestLightRefBaseFlattenable>& a,
384 sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
385 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
386 *aPlusOne = new TestLightRefBaseFlattenable(a->value + 1);
387 return NO_ERROR;
388 }
Dan Stoza2537db72017-04-07 16:32:38 -0700389 status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
390 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
391 native_handle* rawHandle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
392 if (rawHandle == nullptr) return NO_MEMORY;
393
394 // Copy the fd over directly
395 rawHandle->data[0] = dup(a->handle()->data[0]);
396
397 // Increment the int
398 rawHandle->data[1] = a->handle()->data[1] + 1;
399
400 // This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
401 // the native_handle when it goes out of scope
402 *aPlusOne = NativeHandle::create(rawHandle, true);
403 return NO_ERROR;
404 }
Dan Stozad630e522016-12-01 15:16:31 -0800405 status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
406 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
407 aPlusOne->setValue(a.getValue() + 1);
408 return NO_ERROR;
409 }
410 status_t toUpper(const String8& str, String8* upperStr) const override {
411 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
412 *upperStr = str;
413 upperStr->toUpper();
414 return NO_ERROR;
415 }
416 void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
417 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
418 callback->onCallback(a + 1);
419 }
420 status_t increment(int32_t a, int32_t* aPlusOne) const override {
421 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
422 *aPlusOne = a + 1;
423 return NO_ERROR;
424 }
425 status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
426 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
427 *aPlusOne = a + 1;
428 return NO_ERROR;
429 }
Dan Stoza662a8992017-04-06 16:18:39 -0700430 status_t increment(int64_t a, int64_t* aPlusOne) const override {
431 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
432 *aPlusOne = a + 1;
433 return NO_ERROR;
434 }
435 status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
436 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
437 *aPlusOne = a + 1;
438 return NO_ERROR;
439 }
Dan Stozad630e522016-12-01 15:16:31 -0800440 status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
441 ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
442 *aPlusOne = a + 1;
443 *bPlusOne = b + 1;
444 return NO_ERROR;
445 }
446
447 // BnInterface
448 status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
449 uint32_t /*flags*/) override {
450 EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
451 EXPECT_LT(code, static_cast<uint32_t>(Tag::Last));
452 ISafeInterfaceTest::Tag tag = static_cast<ISafeInterfaceTest::Tag>(code);
453 switch (tag) {
454 case ISafeInterfaceTest::Tag::SetDeathToken: {
455 return callLocal(data, reply, &ISafeInterfaceTest::setDeathToken);
456 }
457 case ISafeInterfaceTest::Tag::ReturnsNoMemory: {
458 return callLocal(data, reply, &ISafeInterfaceTest::returnsNoMemory);
459 }
460 case ISafeInterfaceTest::Tag::LogicalNot: {
461 return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
462 }
Dan Stoza81ea3ef2017-04-07 15:00:18 -0700463 case ISafeInterfaceTest::Tag::ModifyEnum: {
464 return callLocal(data, reply, &ISafeInterfaceTest::modifyEnum);
465 }
Dan Stozadf614ae2017-03-28 17:02:05 -0700466 case ISafeInterfaceTest::Tag::IncrementFlattenable: {
467 using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
468 TestFlattenable* aPlusOne) const;
469 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
470 }
Dan Stozad630e522016-12-01 15:16:31 -0800471 case ISafeInterfaceTest::Tag::IncrementLightFlattenable: {
472 using Signature =
473 status_t (ISafeInterfaceTest::*)(const TestLightFlattenable& a,
474 TestLightFlattenable* aPlusOne) const;
475 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
476 }
Dan Stoza6dd325b2017-04-07 14:31:51 -0700477 case ISafeInterfaceTest::Tag::IncrementLightRefBaseFlattenable: {
478 using Signature =
479 status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
480 sp<TestLightRefBaseFlattenable>*) const;
481 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
482 }
Dan Stoza2537db72017-04-07 16:32:38 -0700483 case ISafeInterfaceTest::Tag::IncrementNativeHandle: {
484 using Signature = status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&,
485 sp<NativeHandle>*) const;
486 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
487 }
Dan Stozad630e522016-12-01 15:16:31 -0800488 case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: {
489 using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
490 NoCopyNoMove* aPlusOne) const;
491 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
492 }
493 case ISafeInterfaceTest::Tag::ToUpper: {
494 return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
495 }
496 case ISafeInterfaceTest::Tag::CallMeBack: {
497 return callLocalAsync(data, reply, &ISafeInterfaceTest::callMeBack);
498 }
499 case ISafeInterfaceTest::Tag::IncrementInt32: {
500 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
501 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
502 }
503 case ISafeInterfaceTest::Tag::IncrementUint32: {
504 using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
505 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
506 }
Dan Stoza662a8992017-04-06 16:18:39 -0700507 case ISafeInterfaceTest::Tag::IncrementInt64: {
508 using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
509 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
510 }
511 case ISafeInterfaceTest::Tag::IncrementUint64: {
512 using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
513 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
514 }
Dan Stozad630e522016-12-01 15:16:31 -0800515 case ISafeInterfaceTest::Tag::IncrementTwo: {
516 using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
517 int32_t*) const;
518 return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
519 }
520 case ISafeInterfaceTest::Tag::Last:
521 // Should not be possible because of the asserts at the beginning of the method
522 [&]() { FAIL(); }();
523 return UNKNOWN_ERROR;
524 }
525 }
526
527private:
528 static constexpr const char* getLogTag() { return "BnSafeInterfaceTest"; }
529};
530
531class SafeInterfaceTest : public ::testing::Test {
532public:
533 SafeInterfaceTest() : mSafeInterfaceTest(getRemoteService()) {
534 ProcessState::self()->startThreadPool();
535 }
536 ~SafeInterfaceTest() override = default;
537
538protected:
539 sp<ISafeInterfaceTest> mSafeInterfaceTest;
540
541private:
542 static constexpr const char* getLogTag() { return "SafeInterfaceTest"; }
543
544 sp<ISafeInterfaceTest> getRemoteService() {
545#pragma clang diagnostic push
546#pragma clang diagnostic ignored "-Wexit-time-destructors"
547 static std::mutex sMutex;
548 static sp<ISafeInterfaceTest> sService;
549 static sp<IBinder> sDeathToken = new BBinder;
550#pragma clang diagnostic pop
551
552 std::unique_lock<decltype(sMutex)> lock;
553 if (sService == nullptr) {
554 ALOG(LOG_INFO, getLogTag(), "Forking remote process");
555 pid_t forkPid = fork();
556 EXPECT_NE(forkPid, -1);
557
558 const String16 serviceName("SafeInterfaceTest");
559
560 if (forkPid == 0) {
561 ALOG(LOG_INFO, getLogTag(), "Remote process checking in");
562 sp<ISafeInterfaceTest> nativeService = new BnSafeInterfaceTest;
563 defaultServiceManager()->addService(serviceName,
564 IInterface::asBinder(nativeService));
565 ProcessState::self()->startThreadPool();
566 IPCThreadState::self()->joinThreadPool();
567 // We shouldn't get to this point
568 [&]() { FAIL(); }();
569 }
570
571 sp<IBinder> binder = defaultServiceManager()->getService(serviceName);
572 sService = interface_cast<ISafeInterfaceTest>(binder);
573 EXPECT_TRUE(sService != nullptr);
574
575 sService->setDeathToken(sDeathToken);
576 }
577
578 return sService;
579 }
580};
581
582TEST_F(SafeInterfaceTest, TestReturnsNoMemory) {
583 status_t result = mSafeInterfaceTest->returnsNoMemory();
584 ASSERT_EQ(NO_MEMORY, result);
585}
586
587TEST_F(SafeInterfaceTest, TestLogicalNot) {
588 const bool a = true;
589 bool notA = true;
590 status_t result = mSafeInterfaceTest->logicalNot(a, &notA);
591 ASSERT_EQ(NO_ERROR, result);
592 ASSERT_EQ(!a, notA);
593 // Test both since we don't want to accidentally catch a default false somewhere
594 const bool b = false;
595 bool notB = false;
596 result = mSafeInterfaceTest->logicalNot(b, &notB);
597 ASSERT_EQ(NO_ERROR, result);
598 ASSERT_EQ(!b, notB);
599}
600
Dan Stoza81ea3ef2017-04-07 15:00:18 -0700601TEST_F(SafeInterfaceTest, TestModifyEnum) {
602 const TestEnum a = TestEnum::INITIAL;
603 TestEnum b = TestEnum::INVALID;
604 status_t result = mSafeInterfaceTest->modifyEnum(a, &b);
605 ASSERT_EQ(NO_ERROR, result);
606 ASSERT_EQ(TestEnum::FINAL, b);
607}
608
Dan Stozadf614ae2017-03-28 17:02:05 -0700609TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
610 const TestFlattenable a{1};
611 TestFlattenable aPlusOne{0};
612 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
613 ASSERT_EQ(NO_ERROR, result);
614 ASSERT_EQ(a.value + 1, aPlusOne.value);
615}
616
Dan Stozad630e522016-12-01 15:16:31 -0800617TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) {
618 const TestLightFlattenable a{1};
619 TestLightFlattenable aPlusOne{0};
620 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
621 ASSERT_EQ(NO_ERROR, result);
622 ASSERT_EQ(a.value + 1, aPlusOne.value);
623}
624
Dan Stoza6dd325b2017-04-07 14:31:51 -0700625TEST_F(SafeInterfaceTest, TestIncrementLightRefBaseFlattenable) {
626 sp<TestLightRefBaseFlattenable> a = new TestLightRefBaseFlattenable{1};
627 sp<TestLightRefBaseFlattenable> aPlusOne;
628 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
629 ASSERT_EQ(NO_ERROR, result);
630 ASSERT_NE(nullptr, aPlusOne.get());
631 ASSERT_EQ(a->value + 1, aPlusOne->value);
632}
633
Dan Stoza2537db72017-04-07 16:32:38 -0700634namespace { // Anonymous namespace
635
636bool fdsAreEquivalent(int a, int b) {
637 struct stat statA {};
638 struct stat statB {};
639 if (fstat(a, &statA) != 0) return false;
640 if (fstat(b, &statB) != 0) return false;
641 return (statA.st_dev == statB.st_dev) && (statA.st_ino == statB.st_ino);
642}
643
644} // Anonymous namespace
645
646TEST_F(SafeInterfaceTest, TestIncrementNativeHandle) {
647 // Create an fd we can use to send and receive from the remote process
648 base::unique_fd eventFd{eventfd(0 /*initval*/, 0 /*flags*/)};
649 ASSERT_NE(-1, eventFd);
650
651 // Determine the maximum number of fds this process can have open
652 struct rlimit limit {};
653 ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &limit));
654 uint32_t maxFds = static_cast<uint32_t>(limit.rlim_cur);
655
656 // Perform this test enough times to rule out fd leaks
657 for (uint32_t iter = 0; iter < (2 * maxFds); ++iter) {
658 native_handle* handle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
659 ASSERT_NE(nullptr, handle);
660 handle->data[0] = dup(eventFd.get());
661 handle->data[1] = 1;
662
663 // This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
664 // the native_handle when it goes out of scope
665 sp<NativeHandle> a = NativeHandle::create(handle, true);
666
667 sp<NativeHandle> aPlusOne;
668 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
669 ASSERT_EQ(NO_ERROR, result);
670 ASSERT_TRUE(fdsAreEquivalent(a->handle()->data[0], aPlusOne->handle()->data[0]));
671 ASSERT_EQ(a->handle()->data[1] + 1, aPlusOne->handle()->data[1]);
672 }
673}
674
Dan Stozad630e522016-12-01 15:16:31 -0800675TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
676 const NoCopyNoMove a{1};
677 NoCopyNoMove aPlusOne{0};
678 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
679 ASSERT_EQ(NO_ERROR, result);
680 ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
681}
682
683TEST_F(SafeInterfaceTest, TestToUpper) {
684 const String8 str{"Hello, world!"};
685 String8 upperStr;
686 status_t result = mSafeInterfaceTest->toUpper(str, &upperStr);
687 ASSERT_EQ(NO_ERROR, result);
688 ASSERT_TRUE(upperStr == String8{"HELLO, WORLD!"});
689}
690
691TEST_F(SafeInterfaceTest, TestCallMeBack) {
692 class CallbackReceiver : public BnCallback {
693 public:
694 void onCallback(int32_t aPlusOne) override {
695 ALOG(LOG_INFO, "CallbackReceiver", "%s", __PRETTY_FUNCTION__);
696 std::unique_lock<decltype(mMutex)> lock(mMutex);
697 mValue = aPlusOne;
698 mCondition.notify_one();
699 }
700
701 std::optional<int32_t> waitForCallback() {
702 std::unique_lock<decltype(mMutex)> lock(mMutex);
703 bool success =
704 mCondition.wait_for(lock, 100ms, [&]() { return static_cast<bool>(mValue); });
705 return success ? mValue : std::nullopt;
706 }
707
708 private:
709 std::mutex mMutex;
710 std::condition_variable mCondition;
711 std::optional<int32_t> mValue;
712 };
713
714 sp<CallbackReceiver> receiver = new CallbackReceiver;
715 const int32_t a = 1;
716 mSafeInterfaceTest->callMeBack(receiver, a);
717 auto result = receiver->waitForCallback();
718 ASSERT_TRUE(result);
719 ASSERT_EQ(a + 1, *result);
720}
721
722TEST_F(SafeInterfaceTest, TestIncrementInt32) {
723 const int32_t a = 1;
724 int32_t aPlusOne = 0;
725 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
726 ASSERT_EQ(NO_ERROR, result);
727 ASSERT_EQ(a + 1, aPlusOne);
728}
729
730TEST_F(SafeInterfaceTest, TestIncrementUint32) {
731 const uint32_t a = 1;
732 uint32_t aPlusOne = 0;
733 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
734 ASSERT_EQ(NO_ERROR, result);
735 ASSERT_EQ(a + 1, aPlusOne);
736}
737
Dan Stoza662a8992017-04-06 16:18:39 -0700738TEST_F(SafeInterfaceTest, TestIncrementInt64) {
739 const int64_t a = 1;
740 int64_t aPlusOne = 0;
741 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
742 ASSERT_EQ(NO_ERROR, result);
743 ASSERT_EQ(a + 1, aPlusOne);
744}
745
746TEST_F(SafeInterfaceTest, TestIncrementUint64) {
747 const uint64_t a = 1;
748 uint64_t aPlusOne = 0;
749 status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
750 ASSERT_EQ(NO_ERROR, result);
751 ASSERT_EQ(a + 1, aPlusOne);
752}
753
Dan Stozad630e522016-12-01 15:16:31 -0800754TEST_F(SafeInterfaceTest, TestIncrementTwo) {
755 const int32_t a = 1;
756 int32_t aPlusOne = 0;
757 const int32_t b = 2;
758 int32_t bPlusOne = 0;
759 status_t result = mSafeInterfaceTest->increment(1, &aPlusOne, 2, &bPlusOne);
760 ASSERT_EQ(NO_ERROR, result);
761 ASSERT_EQ(a + 1, aPlusOne);
762 ASSERT_EQ(b + 1, bPlusOne);
763}
764
765} // namespace tests
766} // namespace android