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> 51 bool ValuesEqual(const unique_ptr<T>& in, const unique_ptr<T>& out) { 52 return *in == *out; 53 } 54 55 template<> 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> 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 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 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 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