1 /*
2 * Copyright (C) 2015 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 "aidl_test_client_nullables.h"
18
19 #include <utils/String16.h>
20
21 #include <iostream>
22 #include <memory>
23 #include <string>
24 #include <vector>
25
26 // libutils:
27 using android::sp;
28 using android::String16;
29
30 // libbinder:
31 using android::binder::Status;
32
33 // generated
34 using android::aidl::tests::ITestService;
35 using android::aidl::tests::SimpleParcelable;
36
37 using std::string;
38 using std::unique_ptr;
39 using std::vector;
40 using std::cout;
41 using std::cerr;
42 using std::endl;
43
44 namespace android {
45 namespace aidl {
46 namespace tests {
47 namespace client {
48
49 namespace {
50 template<typename T>
ValuesEqual(const unique_ptr<T> & in,const unique_ptr<T> & out)51 bool ValuesEqual(const unique_ptr<T>& in, const unique_ptr<T>& out) {
52 return *in == *out;
53 }
54
55 template<>
ValuesEqual(const unique_ptr<vector<unique_ptr<String16>>> & in,const unique_ptr<vector<unique_ptr<String16>>> & out)56 bool ValuesEqual<vector<unique_ptr<String16>>>(
57 const unique_ptr<vector<unique_ptr<String16>>>& in,
58 const unique_ptr<vector<unique_ptr<String16>>>& out) {
59 if (!in) {
60 return !out;
61 }
62
63 if (!out) {
64 return false;
65 }
66
67 if (in->size() != out->size()) {
68 return false;
69 }
70
71 for (size_t i = 0; i < in->size(); i++) {
72 const unique_ptr<String16>& a = (*in)[i];
73 const unique_ptr<String16>& b = (*out)[i];
74
75 if (!(a || b)) {
76 continue;
77 }
78
79 if (!(a && b)) {
80 return false;
81 }
82
83 if (*a != *b) {
84 return false;
85 }
86 }
87
88 return true;
89 }
90
91 template<typename T>
ConfirmNullableType(const sp<ITestService> & s,const string & type_name,unique_ptr<T> in,Status (ITestService::* func)(const unique_ptr<T> &,unique_ptr<T> *))92 bool ConfirmNullableType(const sp<ITestService>& s, const string& type_name,
93 unique_ptr<T> in,
94 Status(ITestService::*func)(const unique_ptr<T>&,
95 unique_ptr<T>*)) {
96 cout << "... Confirming nullables for " << type_name << " ..." << endl;
97 Status status;
98 unique_ptr<T> out;
99
100 status = (*s.*func)(in, &out);
101
102 if (!status.isOk()) {
103 cerr << "Could not repeat nullable " << type_name << "." << endl;
104 return false;
105 }
106
107 if (!out) {
108 cerr << "Got back null when repeating " << type_name << "." << endl;
109 return false;
110 }
111
112 if (!ValuesEqual(in, out)) {
113 cerr << "Got back a non-matching value when repeating " << type_name
114 << "." << endl;
115 return false;
116 }
117
118 in.reset();
119 status = (*s.*func)(in, &out);
120
121 if (!status.isOk()) {
122 cerr << "Could not repeat null as " << type_name << "." << endl;
123 return false;
124 }
125
126 if (out) {
127 cerr << "Got back a value when sent null for " << type_name << "."
128 << endl;
129 return false;
130 }
131
132 return true;
133 }
134
CheckAppropriateIBinderHandling(const sp<ITestService> & s)135 bool CheckAppropriateIBinderHandling(const sp<ITestService>& s) {
136
137 Status status;
138 sp<IBinder> binder = new BBinder();
139 sp<IBinder> null_binder = nullptr;
140 unique_ptr<vector<sp<IBinder>>> list_with_nulls(
141 new vector<sp<IBinder>>{binder, null_binder});
142 unique_ptr<vector<sp<IBinder>>> list_without_nulls(
143 new vector<sp<IBinder>>{binder, binder});
144
145 // Methods without @nullable throw up when given null binders
146 if (s->TakesAnIBinder(null_binder).exceptionCode() !=
147 binder::Status::EX_NULL_POINTER) {
148 cerr << "Did not receive expected null exception on line: "
149 << __LINE__ << endl;
150 return false;
151 }
152 if (s->TakesAnIBinderList(*list_with_nulls).exceptionCode() !=
153 binder::Status::EX_NULL_POINTER) {
154 cerr << "Did not receive expected null exception on line: "
155 << __LINE__ << endl;
156 return false;
157 }
158
159 // But those same methods are fine with valid binders
160 if (!s->TakesAnIBinder(binder).isOk()) {
161 cerr << "Received unexpected exception on line "
162 << __LINE__ << endl;
163 return false;
164 }
165 if (!s->TakesAnIBinderList(*list_without_nulls).isOk()) {
166 cerr << "Received unexpected exception on line "
167 << __LINE__ << endl;
168 return false;
169 }
170
171 // And methods with @nullable don't care.
172 if (!s->TakesANullableIBinder(null_binder).isOk()) {
173 cerr << "Received unexpected exception on line "
174 << __LINE__ << endl;
175 return false;
176 }
177 if (!s->TakesANullableIBinder(binder).isOk()) {
178 cerr << "Received unexpected exception on line "
179 << __LINE__ << endl;
180 return false;
181 }
182 if (!s->TakesANullableIBinderList(list_with_nulls).isOk()) {
183 cerr << "Received unexpected exception on line "
184 << __LINE__ << endl;
185 return false;
186 }
187 if (!s->TakesANullableIBinderList(list_without_nulls).isOk()) {
188 cerr << "Received unexpected exception on line "
189 << __LINE__ << endl;
190 return false;
191 }
192
193 return true;
194 }
195
CheckAppropriateIInterfaceHandling(const sp<ITestService> & s)196 bool CheckAppropriateIInterfaceHandling(const sp<ITestService>& s) {
197
198 sp<INamedCallback> callback;
199 if (!s->GetCallback(false, &callback).isOk()) {
200 cerr << "Received unexpected exception on line "
201 << __LINE__ << endl;
202 return false;
203 }
204 if (callback.get() == nullptr) {
205 cerr << "Expected to receive a non-null binder on line: "
206 << __LINE__ << endl;
207 return false;
208 }
209 if (!s->GetCallback(true, &callback).isOk()) {
210 cerr << "Received unexpected exception on line "
211 << __LINE__ << endl;
212 return false;
213 }
214 if (callback.get() != nullptr) {
215 cerr << "Expected to receive a null binder on line: "
216 << __LINE__ << endl;
217 return false;
218 }
219 return true;
220 }
221
222 } // namespace
223
ConfirmNullables(const sp<ITestService> & s)224 bool ConfirmNullables(const sp<ITestService>& s) {
225 Status status;
226 cout << "Confirming passing and returning nullable values works." << endl;
227
228 if (!ConfirmNullableType(s, "integer array",
229 unique_ptr<vector<int32_t>>(
230 new vector<int32_t>({1,2,3})),
231 &ITestService::RepeatNullableIntArray)) {
232 return false;
233 }
234
235 if (!ConfirmNullableType(s, "string",
236 unique_ptr<String16>(new String16("Blooob")),
237 &ITestService::RepeatNullableString)) {
238 return false;
239 }
240
241 unique_ptr<vector<unique_ptr<String16>>> test_string_array(
242 new vector<unique_ptr<String16>>());
243 test_string_array->push_back(unique_ptr<String16>(new String16("Wat")));
244 test_string_array->push_back(unique_ptr<String16>(
245 new String16("Blooob")));
246 test_string_array->push_back(unique_ptr<String16>(new String16("Wat")));
247 test_string_array->push_back(unique_ptr<String16>(nullptr));
248 test_string_array->push_back(unique_ptr<String16>(new String16("YEAH")));
249 test_string_array->push_back(unique_ptr<String16>(
250 new String16("OKAAAAY")));
251
252 if (!ConfirmNullableType(s, "string array", std::move(test_string_array),
253 &ITestService::RepeatNullableStringList)) {
254 return false;
255 }
256
257 if (!ConfirmNullableType(s, "parcelable",
258 unique_ptr<SimpleParcelable>(
259 new SimpleParcelable("Booya", 42)),
260 &ITestService::RepeatNullableParcelable)) {
261 return false;
262 }
263
264 if (!CheckAppropriateIBinderHandling(s)) {
265 cerr << "Handled null IBinders poorly." << endl;
266 return false;
267 }
268
269 if (!CheckAppropriateIInterfaceHandling(s)) {
270 cerr << "Handled nullable IInterface instances poorly." << endl;
271 return false;
272 }
273
274 return true;
275 }
276
277 } // namespace client
278 } // namespace tests
279 } // namespace aidl
280 } // namespace android
281