1 /*
2  * Copyright (C) 2023 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/aidl/test/trunk/BnTrunkStableTest.h>
18 #include <android/aidl/test/trunk/ITrunkStableTest.h>
19 #include <binder/IServiceManager.h>
20 #include <binder/ProcessState.h>
21 #include <gtest/gtest.h>
22 #include <utils/String16.h>
23 
24 #include "aidl_test_client.h"
25 
26 #ifdef AIDL_USE_UNFROZEN
27 constexpr bool kUseUnfrozen = true;
28 #else
29 constexpr bool kUseUnfrozen = false;
30 #endif
31 
32 using android::OK;
33 using android::sp;
34 using android::String16;
35 using android::aidl::test::trunk::ITrunkStableTest;
36 using android::binder::Status;
37 using MyParcelable = android::aidl::test::trunk::ITrunkStableTest::MyParcelable;
38 #ifdef AIDL_USE_V2_INTERFACE
39 using MyOtherParcelable = android::aidl::test::trunk::ITrunkStableTest::MyOtherParcelable;
40 #endif  // AIDL_USE_V2_INTERFACE
41 using MyEnum = android::aidl::test::trunk::ITrunkStableTest::MyEnum;
42 using MyUnion = android::aidl::test::trunk::ITrunkStableTest::MyUnion;
43 
44 class TrunkInterfaceTest : public AidlTest {
45  public:
SetUp()46   void SetUp() override {
47     android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
48     android::ProcessState::self()->startThreadPool();
49     service = android::waitForService<ITrunkStableTest>(ITrunkStableTest::descriptor);
50     ASSERT_NE(nullptr, service);
51 
52     AidlTest::SetUp();
53   }
54 
55   sp<ITrunkStableTest> service;
56 };
57 
TEST_F(TrunkInterfaceTest,getInterfaceVersion)58 TEST_F(TrunkInterfaceTest, getInterfaceVersion) {
59   // TODO(b/292539129) this should be done with an annotation instead of ifdefs
60   // We have to match on a single char with #if, even though it is
61   // really "enabled"/"disabled"
62   if (kUseUnfrozen) {
63     EXPECT_EQ(2, service->getInterfaceVersion());
64     // Check the local version as well
65 #ifdef AIDL_USE_V2_INTERFACE
66     EXPECT_EQ(2, ITrunkStableTest::VERSION);
67 #else
68     // linked against V1 explicitly
69     EXPECT_EQ(1, ITrunkStableTest::VERSION);
70 #endif
71   } else {
72     EXPECT_EQ(1, service->getInterfaceVersion());
73     // Check the local version as well
74     EXPECT_EQ(1, ITrunkStableTest::VERSION);
75   }
76 }
77 
TEST_F(TrunkInterfaceTest,getInterfaceHash)78 TEST_F(TrunkInterfaceTest, getInterfaceHash) {
79   if (kUseUnfrozen) {
80     EXPECT_EQ("notfrozen", service->getInterfaceHash());
81     // Check the local hash as well
82 #ifdef AIDL_USE_V2_INTERFACE
83     EXPECT_EQ("notfrozen", ITrunkStableTest::HASH);
84 #else
85     // linked against V1 explicitly
86     EXPECT_EQ("88311b9118fb6fe9eff4a2ca19121de0587f6d5f", ITrunkStableTest::HASH);
87 #endif
88   } else {
89     EXPECT_EQ("88311b9118fb6fe9eff4a2ca19121de0587f6d5f", service->getInterfaceHash());
90     // Check the local hash as well
91     EXPECT_EQ("88311b9118fb6fe9eff4a2ca19121de0587f6d5f", ITrunkStableTest::HASH);
92   }
93 }
94 
95 // `c` is a new field that isn't read from the reply parcel
TEST_F(TrunkInterfaceTest,repeatParcelable)96 TEST_F(TrunkInterfaceTest, repeatParcelable) {
97   MyParcelable in, out;
98   in.a = 14;
99   in.b = 15;
100 #ifdef AIDL_USE_V2_INTERFACE
101   in.c = 16;
102 #endif  // AIDL_USE_V2_INTERFACE
103   auto status = service->repeatParcelable(in, &out);
104   ASSERT_TRUE(status.isOk()) << status;
105   if (kUseUnfrozen) {
106     EXPECT_EQ(in.a, out.a);
107     EXPECT_EQ(in.b, out.b);
108 #ifdef AIDL_USE_V2_INTERFACE
109     EXPECT_EQ(in.c, out.c);
110 #endif  // AIDL_USE_V2_INTERFACE
111   } else {
112     EXPECT_EQ(in.a, out.a);
113     EXPECT_EQ(in.b, out.b);
114 #ifdef AIDL_USE_V2_INTERFACE
115     EXPECT_NE(in.c, out.c);
116     EXPECT_EQ(0, out.c);
117 #endif  // AIDL_USE_V2_INTERFACE
118   }
119 }
120 
121 #ifdef AIDL_USE_V2_INTERFACE
122 // repeatOtherParcelable is a new API that isn't implemented
TEST_F(TrunkInterfaceTest,repeatOtherParcelable)123 TEST_F(TrunkInterfaceTest, repeatOtherParcelable) {
124   MyOtherParcelable in, out;
125   in.a = 14;
126   in.b = 15;
127 
128   auto status = service->repeatOtherParcelable(in, &out);
129   if (kUseUnfrozen) {
130     ASSERT_TRUE(status.isOk()) << status;
131     EXPECT_EQ(in.a, out.a);
132     EXPECT_EQ(in.b, out.b);
133   } else {
134     EXPECT_FALSE(status.isOk()) << status;
135     EXPECT_EQ(::android::UNKNOWN_TRANSACTION, status.transactionError()) << status;
136   }
137 }
138 #endif  // AIDL_USE_V2_INTERFACE
139 
140 // enums aren't handled differently.
TEST_F(TrunkInterfaceTest,repeatEnum)141 TEST_F(TrunkInterfaceTest, repeatEnum) {
142   MyEnum in = MyEnum::TWO;
143   MyEnum out = MyEnum::ZERO;
144 
145   auto status = service->repeatEnum(in, &out);
146   ASSERT_TRUE(status.isOk()) << status;
147   EXPECT_EQ(in, out);
148 }
149 
150 // `c` is a new field that causes a failure if used
151 // `b` is from V1 and will cause no failure
TEST_F(TrunkInterfaceTest,repeatUnion)152 TEST_F(TrunkInterfaceTest, repeatUnion) {
153   MyUnion in_ok = MyUnion::make<MyUnion::b>(13);
154   ;
155 #ifdef AIDL_USE_V2_INTERFACE
156   MyUnion in_test = MyUnion::make<MyUnion::c>(12);
157   ;
158 #endif  // AIDL_USE_V2_INTERFACE
159   MyUnion out;
160 
161   auto status = service->repeatUnion(in_ok, &out);
162   ASSERT_TRUE(status.isOk()) << status;
163   EXPECT_EQ(in_ok, out);
164 
165 #ifdef AIDL_USE_V2_INTERFACE
166   status = service->repeatUnion(in_test, &out);
167   if (kUseUnfrozen) {
168     ASSERT_TRUE(status.isOk()) << status;
169     EXPECT_EQ(in_test, out);
170   } else {
171     ASSERT_FALSE(status.isOk()) << status;
172     EXPECT_NE(in_test, out);
173   }
174 #endif  // AIDL_USE_V2_INTERFACE
175 }
176 
177 class MyCallback : public ITrunkStableTest::BnMyCallback {
178  public:
MyCallback()179   MyCallback() {}
180   virtual ~MyCallback() = default;
181 
repeatParcelable(const MyParcelable & input,MyParcelable * _aidl_return)182   Status repeatParcelable(const MyParcelable& input, MyParcelable* _aidl_return) override {
183     *_aidl_return = input;
184     repeatParcelableCalled = true;
185     return Status::ok();
186   }
repeatEnum(MyEnum input,MyEnum * _aidl_return)187   Status repeatEnum(MyEnum input, MyEnum* _aidl_return) override {
188     *_aidl_return = input;
189     repeatEnumCalled = true;
190     return Status::ok();
191   }
repeatUnion(const MyUnion & input,MyUnion * _aidl_return)192   Status repeatUnion(const MyUnion& input, MyUnion* _aidl_return) override {
193     *_aidl_return = input;
194     repeatUnionCalled = true;
195     return Status::ok();
196   }
197 #ifdef AIDL_USE_V2_INTERFACE
repeatOtherParcelable(const MyOtherParcelable & input,MyOtherParcelable * _aidl_return)198   Status repeatOtherParcelable(const MyOtherParcelable& input,
199                                MyOtherParcelable* _aidl_return) override {
200     *_aidl_return = input;
201     repeatOtherParcelableCalled = true;
202     return Status::ok();
203   }
204 #endif  // AIDL_USE_V2_INTERFACE
205   bool repeatParcelableCalled = false;
206   bool repeatEnumCalled = false;
207   bool repeatUnionCalled = false;
208 #ifdef AIDL_USE_V2_INTERFACE
209   bool repeatOtherParcelableCalled = false;
210 #endif  // AIDL_USE_V2_INTERFACE
211 };
212 
213 // repeatOtherParcelable is new in V2, so it won't be called
TEST_F(TrunkInterfaceTest,callMyCallback)214 TEST_F(TrunkInterfaceTest, callMyCallback) {
215   sp<MyCallback> cb = sp<MyCallback>::make();
216 
217   auto status = service->callMyCallback(cb);
218   ASSERT_TRUE(status.isOk()) << status;
219   if (kUseUnfrozen) {
220     EXPECT_TRUE(cb->repeatParcelableCalled);
221     EXPECT_TRUE(cb->repeatEnumCalled);
222     EXPECT_TRUE(cb->repeatUnionCalled);
223 #ifdef AIDL_USE_V2_INTERFACE
224     EXPECT_TRUE(cb->repeatOtherParcelableCalled);
225 #endif  // AIDL_USE_V2_INTERFACE
226   } else {
227     EXPECT_TRUE(cb->repeatParcelableCalled);
228     EXPECT_TRUE(cb->repeatEnumCalled);
229     EXPECT_TRUE(cb->repeatUnionCalled);
230 #ifdef AIDL_USE_V2_INTERFACE
231     EXPECT_FALSE(cb->repeatOtherParcelableCalled);
232 #endif  // AIDL_USE_V2_INTERFACE
233   }
234 }
235