1 /*
2 * Copyright (C) 2021 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 <android/binder_auto_utils.h>
18 #include <android/binder_manager.h>
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 #include <aidl/android/aidl/tests/ITestService.h>
23
24 using aidl::android::aidl::tests::BackendType;
25 using aidl::android::aidl::tests::INamedCallback;
26 using aidl::android::aidl::tests::ITestService;
27 using testing::Eq;
28
29 struct AidlTest : testing::Test {
30 template <typename T>
getServiceAidlTest31 std::shared_ptr<T> getService() {
32 ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
33 return T::fromBinder(binder);
34 }
SetUpAidlTest35 void SetUp() override {
36 service = getService<ITestService>();
37 auto status = service->getBackendType(&backend);
38 ASSERT_TRUE(status.isOk()) << status.getDescription();
39 }
40 std::shared_ptr<ITestService> service;
41 BackendType backend;
42
43 template <typename T>
DoTestAidlTest44 void DoTest(ndk::ScopedAStatus (ITestService::*func)(const std::optional<T>&, std::optional<T>*),
45 std::optional<T> input) {
46 std::optional<T> output;
47 auto status = (*service.*func)(input, &output);
48 ASSERT_TRUE(status.isOk());
49 ASSERT_TRUE(output.has_value());
50 ASSERT_THAT(*output, Eq(*input));
51
52 input.reset();
53 status = (*service.*func)(input, &output);
54 ASSERT_TRUE(status.isOk());
55 ASSERT_FALSE(output.has_value());
56 }
57 };
58
TEST_F(AidlTest,parcelableArray)59 TEST_F(AidlTest, parcelableArray) {
60 std::vector<std::optional<ITestService::Empty>> input;
61 input.push_back(ITestService::Empty());
62 input.push_back(std::nullopt);
63 DoTest(&ITestService::RepeatNullableParcelableArray, std::make_optional(input));
64 }
65
TEST_F(AidlTest,parcelableList)66 TEST_F(AidlTest, parcelableList) {
67 std::vector<std::optional<ITestService::Empty>> input;
68 input.push_back(ITestService::Empty());
69 input.push_back(std::nullopt);
70 DoTest(&ITestService::RepeatNullableParcelableList, std::make_optional(input));
71 }
72
TEST_F(AidlTest,nullBinder)73 TEST_F(AidlTest, nullBinder) {
74 auto status = service->TakesAnIBinder(nullptr);
75 ASSERT_THAT(status.getStatus(), Eq(STATUS_UNEXPECTED_NULL)) << status.getDescription();
76 // Note that NDK backend checks null before transaction while C++ backends doesn't.
77 }
78
TEST_F(AidlTest,binderListWithNull)79 TEST_F(AidlTest, binderListWithNull) {
80 std::vector<ndk::SpAIBinder> input{service->asBinder(), nullptr};
81 auto status = service->TakesAnIBinderList(input);
82 ASSERT_THAT(status.getStatus(), Eq(STATUS_UNEXPECTED_NULL));
83 // Note that NDK backend checks null before transaction while C++ backends doesn't.
84 }
85
TEST_F(AidlTest,nonNullBinder)86 TEST_F(AidlTest, nonNullBinder) {
87 auto status = service->TakesAnIBinder(service->asBinder());
88 ASSERT_TRUE(status.isOk());
89 }
90
TEST_F(AidlTest,binderListWithoutNull)91 TEST_F(AidlTest, binderListWithoutNull) {
92 std::vector<ndk::SpAIBinder> input{service->asBinder()};
93 auto status = service->TakesAnIBinderList(input);
94 ASSERT_TRUE(status.isOk());
95 }
96
TEST_F(AidlTest,nullBinderToAnnotatedMethod)97 TEST_F(AidlTest, nullBinderToAnnotatedMethod) {
98 auto status = service->TakesANullableIBinder(nullptr);
99 ASSERT_TRUE(status.isOk());
100 }
101
TEST_F(AidlTest,binderListWithNullToAnnotatedMethod)102 TEST_F(AidlTest, binderListWithNullToAnnotatedMethod) {
103 std::vector<ndk::SpAIBinder> input{service->asBinder(), nullptr};
104 auto status = service->TakesANullableIBinderList(input);
105 ASSERT_TRUE(status.isOk());
106 }
107
TEST_F(AidlTest,binderArray)108 TEST_F(AidlTest, binderArray) {
109 std::vector<ndk::SpAIBinder> repeated;
110 if (backend == BackendType::JAVA) {
111 // Java can only modify out-argument arrays in-place
112 repeated.resize(2);
113 }
114 // get INamedCallback for "SpAIBinder" object
115 std::shared_ptr<INamedCallback> callback;
116 auto status = service->GetCallback(false, &callback);
117 ASSERT_TRUE(status.isOk()) << status.getDescription();
118
119 std::vector<ndk::SpAIBinder> reversed;
120 std::vector<ndk::SpAIBinder> input{service->asBinder(), callback->asBinder()};
121 status = service->ReverseIBinderArray(input, &repeated, &reversed);
122 ASSERT_TRUE(status.isOk()) << status.getDescription();
123
124 EXPECT_THAT(input, Eq(repeated));
125 std::reverse(std::begin(reversed), std::end(reversed));
126 EXPECT_THAT(input, Eq(reversed));
127 }
128
TEST_F(AidlTest,nullableBinderArray)129 TEST_F(AidlTest, nullableBinderArray) {
130 std::optional<std::vector<ndk::SpAIBinder>> repeated;
131 if (backend == BackendType::JAVA) {
132 // Java can only modify out-argument arrays in-place
133 repeated = std::vector<ndk::SpAIBinder>(2);
134 }
135
136 std::optional<std::vector<ndk::SpAIBinder>> reversed;
137 std::optional<std::vector<ndk::SpAIBinder>> input =
138 std::vector<ndk::SpAIBinder>{service->asBinder(), service->asBinder()};
139 auto status = service->ReverseNullableIBinderArray(input, &repeated, &reversed);
140 ASSERT_TRUE(status.isOk()) << status.getDescription();
141
142 EXPECT_THAT(input, Eq(repeated));
143 ASSERT_TRUE(reversed);
144 std::reverse(std::begin(*reversed), std::end(*reversed));
145 EXPECT_THAT(input, Eq(reversed));
146 }