• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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