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 #define LOG_TAG "nfc_aidl_hal_test"
18
19 #include <aidl/Gtest.h>
20 #include <aidl/Vintf.h>
21 #include <aidl/android/hardware/nfc/BnNfc.h>
22 #include <aidl/android/hardware/nfc/BnNfcClientCallback.h>
23 #include <aidl/android/hardware/nfc/INfc.h>
24 #include <android-base/logging.h>
25 #include <android-base/stringprintf.h>
26 #include <android/binder_auto_utils.h>
27 #include <android/binder_enums.h>
28 #include <android/binder_interface_utils.h>
29 #include <android/binder_manager.h>
30 #include <android/binder_process.h>
31
32 #include <chrono>
33 #include <future>
34
35 using aidl::android::hardware::nfc::INfc;
36 using aidl::android::hardware::nfc::INfcClientCallback;
37 using aidl::android::hardware::nfc::NfcCloseType;
38 using aidl::android::hardware::nfc::NfcConfig;
39 using aidl::android::hardware::nfc::NfcEvent;
40 using aidl::android::hardware::nfc::NfcStatus;
41 using aidl::android::hardware::nfc::PresenceCheckAlgorithm;
42
43 using android::getAidlHalInstanceNames;
44 using android::PrintInstanceNameToString;
45 using android::base::StringPrintf;
46 using ndk::enum_range;
47 using ndk::ScopedAStatus;
48 using ndk::SharedRefBase;
49 using ndk::SpAIBinder;
50
51 constexpr static int kCallbackTimeoutMs = 10000;
52
53 // 261 bytes is the default and minimum transceive length
54 constexpr unsigned int MIN_ISO_DEP_TRANSCEIVE_LENGTH = 261;
55
56 // Range of valid off host route ids
57 constexpr uint8_t MIN_OFFHOST_ROUTE_ID = 0x01;
58 constexpr uint8_t MAX_OFFHOST_ROUTE_ID = 0xFE;
59
60 class NfcClientCallback : public aidl::android::hardware::nfc::BnNfcClientCallback {
61 public:
NfcClientCallback(const std::function<void (NfcEvent,NfcStatus)> & on_hal_event_cb,const std::function<void (const std::vector<uint8_t> &)> & on_nci_data_cb)62 NfcClientCallback(const std::function<void(NfcEvent, NfcStatus)>& on_hal_event_cb,
63 const std::function<void(const std::vector<uint8_t>&)>& on_nci_data_cb)
64 : on_nci_data_cb_(on_nci_data_cb), on_hal_event_cb_(on_hal_event_cb) {}
65 virtual ~NfcClientCallback() = default;
66
sendEvent(NfcEvent event,NfcStatus event_status)67 ::ndk::ScopedAStatus sendEvent(NfcEvent event, NfcStatus event_status) override {
68 on_hal_event_cb_(event, event_status);
69 return ::ndk::ScopedAStatus::ok();
70 };
sendData(const std::vector<uint8_t> & data)71 ::ndk::ScopedAStatus sendData(const std::vector<uint8_t>& data) override {
72 on_nci_data_cb_(data);
73 return ::ndk::ScopedAStatus::ok();
74 };
75
76 private:
77 std::function<void(const std::vector<uint8_t>&)> on_nci_data_cb_;
78 std::function<void(NfcEvent, NfcStatus)> on_hal_event_cb_;
79 };
80
81 class NfcAidl : public testing::TestWithParam<std::string> {
82 public:
SetUp()83 void SetUp() override {
84 SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
85 infc_ = INfc::fromBinder(binder);
86 ASSERT_NE(infc_, nullptr);
87 }
88 std::shared_ptr<INfc> infc_;
89 };
90
91 /*
92 * OpenAndCloseForDisable:
93 * Makes an open call, waits for NfcEvent::OPEN_CPLT
94 * Immediately calls close(NfcCloseType::DISABLE) and
95 * waits for NfcEvent::CLOSE_CPLT
96 *
97 */
TEST_P(NfcAidl,OpenAndCloseForDisable)98 TEST_P(NfcAidl, OpenAndCloseForDisable) {
99 std::promise<void> open_cb_promise;
100 std::promise<void> close_cb_promise;
101 auto open_cb_future = open_cb_promise.get_future();
102 auto close_cb_future = close_cb_promise.get_future();
103 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
104 [&open_cb_promise, &close_cb_promise](auto event, auto status) {
105 EXPECT_EQ(status, NfcStatus::OK);
106 LOG(INFO) << StringPrintf("%s,%d ", __func__, event);
107 if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
108 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
109 },
110 [](auto) {});
111 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
112 // Open and wait for OPEN_CPLT
113 LOG(INFO) << "open";
114 EXPECT_TRUE(infc_->open(mCallback).isOk());
115 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
116 // Close and wait for CLOSE_CPLT
117 LOG(INFO) << "close DISABLE";
118 EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
119 LOG(INFO) << "wait for close";
120 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
121 }
122
123 /*
124 * OpenAndCloseForHostSwitchedOff:
125 * Makes an open call, waits for NfcEvent::OPEN_CPLT
126 * Immediately calls close(NfcCloseType::HOST_SWITCHED_OFF) and
127 * waits for NfcEvent::CLOSE_CPLT
128 *
129 */
TEST_P(NfcAidl,OpenAndCloseForHostSwitchedOff)130 TEST_P(NfcAidl, OpenAndCloseForHostSwitchedOff) {
131 std::promise<void> open_cb_promise;
132 std::promise<void> close_cb_promise;
133 auto open_cb_future = open_cb_promise.get_future();
134 auto close_cb_future = close_cb_promise.get_future();
135 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
136 [&open_cb_promise, &close_cb_promise](auto event, auto status) {
137 EXPECT_EQ(status, NfcStatus::OK);
138 if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
139 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
140 },
141 [](auto) {});
142 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
143 // Open and wait for OPEN_CPLT
144 LOG(INFO) << "open";
145 EXPECT_TRUE(infc_->open(mCallback).isOk());
146 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
147
148 // Close and wait for CLOSE_CPLT
149 LOG(INFO) << "close HOST_SWITCHED_OFF";
150 EXPECT_TRUE(infc_->close(NfcCloseType::HOST_SWITCHED_OFF).isOk());
151 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
152 }
153
154 /*
155 * OpenAfterOpen:
156 * Calls open() multiple times
157 * Checks status
158 */
TEST_P(NfcAidl,OpenAfterOpen)159 TEST_P(NfcAidl, OpenAfterOpen) {
160 int open_count = 0;
161 std::promise<void> open_cb_promise;
162 std::promise<void> open2_cb_promise;
163 auto open_cb_future = open_cb_promise.get_future();
164 auto open2_cb_future = open2_cb_promise.get_future();
165 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
166 [&open_cb_promise, &open2_cb_promise, &open_count](auto event, auto status) {
167 EXPECT_EQ(status, NfcStatus::OK);
168 if (event == NfcEvent::OPEN_CPLT) {
169 open_count == 0 ? open_cb_promise.set_value() : open2_cb_promise.set_value();
170 open_count++;
171 }
172 },
173 [](auto) {});
174
175 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
176 // Open and wait for OPEN_CPLT
177 LOG(INFO) << "open";
178 EXPECT_TRUE(infc_->open(mCallback).isOk());
179 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
180
181 // Open again and wait for OPEN_CPLT
182 LOG(INFO) << "open again";
183 EXPECT_TRUE(infc_->open(mCallback).isOk());
184 EXPECT_EQ(open2_cb_future.wait_for(timeout), std::future_status::ready);
185 }
186
187 /*
188 * CloseAfterClose:
189 * Calls close() multiple times
190 * Checks status
191 */
TEST_P(NfcAidl,CloseAfterClose)192 TEST_P(NfcAidl, CloseAfterClose) {
193 std::promise<void> open_cb_promise;
194 std::promise<void> close_cb_promise;
195 auto open_cb_future = open_cb_promise.get_future();
196 auto close_cb_future = close_cb_promise.get_future();
197 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
198 [&open_cb_promise, &close_cb_promise](auto event, auto status) {
199 EXPECT_EQ(status, NfcStatus::OK);
200 if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
201 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
202 },
203 [](auto) {});
204 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
205 // Open and wait for OPEN_CPLT
206 LOG(INFO) << "open";
207 EXPECT_TRUE(infc_->open(mCallback).isOk());
208 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
209
210 // Close and wait for CLOSE_CPLT
211 LOG(INFO) << "close";
212 EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
213 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
214 // Close again should fail.
215 LOG(INFO) << "close again";
216 EXPECT_TRUE(!(infc_->close(NfcCloseType::DISABLE).isOk()));
217 }
218
219 /*
220 * PowerCycleAfterOpen:
221 * Calls powerCycle() after open
222 * Waits for NfcEvent.OPEN_CPLT
223 * Checks status
224 */
TEST_P(NfcAidl,PowerCycleAfterOpen)225 TEST_P(NfcAidl, PowerCycleAfterOpen) {
226 int open_cplt_count = 0;
227 std::promise<void> open_cb_promise;
228 std::promise<void> power_cycle_cb_promise;
229 std::promise<void> close_cb_promise;
230 auto open_cb_future = open_cb_promise.get_future();
231 auto power_cycle_cb_future = power_cycle_cb_promise.get_future();
232 auto close_cb_future = close_cb_promise.get_future();
233 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
234 [&open_cb_promise, &close_cb_promise, &power_cycle_cb_promise, &open_cplt_count](
235 auto event, auto status) {
236 EXPECT_EQ(status, NfcStatus::OK);
237 if (event == NfcEvent::OPEN_CPLT) {
238 if (open_cplt_count == 0) {
239 open_cplt_count++;
240 open_cb_promise.set_value();
241 } else {
242 power_cycle_cb_promise.set_value();
243 }
244 }
245 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
246 },
247 [](auto) {});
248 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
249 // Open and wait for OPEN_CPLT
250 LOG(INFO) << "open";
251 EXPECT_TRUE(infc_->open(mCallback).isOk());
252 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
253
254 // PowerCycle and wait for OPEN_CPLT
255 LOG(INFO) << "PowerCycle";
256 EXPECT_TRUE(infc_->powerCycle().isOk());
257 EXPECT_EQ(power_cycle_cb_future.wait_for(timeout), std::future_status::ready);
258
259 // Close and wait for CLOSE_CPLT
260 LOG(INFO) << "close";
261 EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
262 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
263 }
264
265 /*
266 * PowerCycleAfterClose:
267 * Calls powerCycle() after close
268 * PowerCycle should fail immediately
269 */
TEST_P(NfcAidl,PowerCycleAfterClose)270 TEST_P(NfcAidl, PowerCycleAfterClose) {
271 std::promise<void> open_cb_promise;
272 std::promise<void> close_cb_promise;
273 auto open_cb_future = open_cb_promise.get_future();
274 auto close_cb_future = close_cb_promise.get_future();
275 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
276 [&open_cb_promise, &close_cb_promise](auto event, auto status) {
277 EXPECT_EQ(status, NfcStatus::OK);
278 if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
279 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
280 },
281 [](auto) {});
282 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
283 // Open and wait for OPEN_CPLT
284 LOG(INFO) << "open";
285 EXPECT_TRUE(infc_->open(mCallback).isOk());
286 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
287
288 // Close and wait for CLOSE_CPLT
289 LOG(INFO) << "close";
290 EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
291 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
292
293 // PowerCycle should fail
294 LOG(INFO) << "PowerCycle";
295 EXPECT_TRUE(!(infc_->powerCycle().isOk()));
296 }
297
298 /*
299 * CoreInitializedAfterOpen:
300 * Calls coreInitialized() after open
301 * Waits for NfcEvent.POST_INIT_CPLT
302 */
TEST_P(NfcAidl,CoreInitializedAfterOpen)303 TEST_P(NfcAidl, CoreInitializedAfterOpen) {
304 std::promise<void> open_cb_promise;
305 std::promise<void> core_init_cb_promise;
306 std::promise<void> close_cb_promise;
307 auto open_cb_future = open_cb_promise.get_future();
308 auto core_init_cb_future = core_init_cb_promise.get_future();
309 auto close_cb_future = close_cb_promise.get_future();
310 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
311 [&open_cb_promise, &close_cb_promise, &core_init_cb_promise](auto event, auto status) {
312 EXPECT_EQ(status, NfcStatus::OK);
313 if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
314 if (event == NfcEvent::POST_INIT_CPLT) core_init_cb_promise.set_value();
315 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
316 },
317 [](auto) {});
318 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
319 // Open and wait for OPEN_CPLT
320 LOG(INFO) << "open";
321 EXPECT_TRUE(infc_->open(mCallback).isOk());
322 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
323
324 // CoreInitialized and wait for POST_INIT_CPLT
325 LOG(INFO) << "coreInitialized";
326 EXPECT_TRUE(infc_->coreInitialized().isOk());
327 EXPECT_EQ(core_init_cb_future.wait_for(timeout), std::future_status::ready);
328
329 // Close and wait for CLOSE_CPLT
330 LOG(INFO) << "close";
331 EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
332 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
333 }
334
335 /*
336 * CoreInitializedAfterClose:
337 * Calls coreInitialized() after close
338 * coreInitialized() should fail immediately
339 */
TEST_P(NfcAidl,CoreInitializedAfterClose)340 TEST_P(NfcAidl, CoreInitializedAfterClose) {
341 std::promise<void> open_cb_promise;
342 std::promise<void> close_cb_promise;
343 auto open_cb_future = open_cb_promise.get_future();
344 auto close_cb_future = close_cb_promise.get_future();
345 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
346 [&open_cb_promise, &close_cb_promise](auto event, auto status) {
347 EXPECT_EQ(status, NfcStatus::OK);
348 if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
349 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
350 },
351 [](auto) {});
352 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
353 // Open and wait for OPEN_CPLT
354 LOG(INFO) << "open";
355 EXPECT_TRUE(infc_->open(mCallback).isOk());
356 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
357
358 // Close and wait for CLOSE_CPLT
359 LOG(INFO) << "close";
360 EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
361 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
362
363 // coreInitialized should fail
364 LOG(INFO) << "CoreInitialized";
365 EXPECT_TRUE(!(infc_->coreInitialized().isOk()));
366 }
367
368 /*
369 * PreDiscoverAfterClose:
370 * Call preDiscover() after close
371 * preDiscover() should fail immediately
372 */
TEST_P(NfcAidl,PreDiscoverAfterClose)373 TEST_P(NfcAidl, PreDiscoverAfterClose) {
374 std::promise<void> open_cb_promise;
375 std::promise<void> close_cb_promise;
376 auto open_cb_future = open_cb_promise.get_future();
377 auto close_cb_future = close_cb_promise.get_future();
378 std::shared_ptr<INfcClientCallback> mCallback = ::ndk::SharedRefBase::make<NfcClientCallback>(
379 [&open_cb_promise, &close_cb_promise](auto event, auto status) {
380 EXPECT_EQ(status, NfcStatus::OK);
381 if (event == NfcEvent::OPEN_CPLT) open_cb_promise.set_value();
382 if (event == NfcEvent::CLOSE_CPLT) close_cb_promise.set_value();
383 },
384 [](auto) {});
385 std::chrono::milliseconds timeout{kCallbackTimeoutMs};
386 // Open and wait for OPEN_CPLT
387 LOG(INFO) << "open";
388 EXPECT_TRUE(infc_->open(mCallback).isOk());
389 EXPECT_EQ(open_cb_future.wait_for(timeout), std::future_status::ready);
390
391 // Close and wait for CLOSE_CPLT
392 LOG(INFO) << "close";
393 EXPECT_TRUE(infc_->close(NfcCloseType::DISABLE).isOk());
394 EXPECT_EQ(close_cb_future.wait_for(timeout), std::future_status::ready);
395
396 // preDiscover should fail
397 LOG(INFO) << "preDiscover";
398 EXPECT_TRUE(!(infc_->preDiscover().isOk()));
399 }
400
401 /*
402 * checkGetConfigValues:
403 * Calls getConfig()
404 * checks if fields in NfcConfig are populated correctly
405 */
TEST_P(NfcAidl,CheckGetConfigValues)406 TEST_P(NfcAidl, CheckGetConfigValues) {
407 NfcConfig configValue;
408 EXPECT_TRUE(infc_->getConfig(&configValue).isOk());
409 EXPECT_GE(configValue.maxIsoDepTransceiveLength, MIN_ISO_DEP_TRANSCEIVE_LENGTH);
410 LOG(INFO) << StringPrintf("configValue.maxIsoDepTransceiveLength = %x",
411 configValue.maxIsoDepTransceiveLength);
412 for (auto uicc : configValue.offHostRouteUicc) {
413 LOG(INFO) << StringPrintf("offHostRouteUicc = %x", uicc);
414 EXPECT_GE(uicc, MIN_OFFHOST_ROUTE_ID);
415 EXPECT_LE(uicc, MAX_OFFHOST_ROUTE_ID);
416 }
417 for (auto ese : configValue.offHostRouteEse) {
418 LOG(INFO) << StringPrintf("offHostRouteEse = %x", ese);
419 EXPECT_GE(ese, MIN_OFFHOST_ROUTE_ID);
420 EXPECT_LE(ese, MAX_OFFHOST_ROUTE_ID);
421 }
422 if (configValue.defaultIsoDepRoute != 0) {
423 EXPECT_GE((uint8_t)configValue.defaultIsoDepRoute, MIN_OFFHOST_ROUTE_ID);
424 EXPECT_LE((uint8_t)configValue.defaultIsoDepRoute, MAX_OFFHOST_ROUTE_ID);
425 }
426 }
427
428 /*
429 * CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging:
430 * Calls setEnableVerboseLogging()
431 * checks the return value of isVerboseLoggingEnabled
432 */
TEST_P(NfcAidl,CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging)433 TEST_P(NfcAidl, CheckisVerboseLoggingEnabledAfterSetEnableVerboseLogging) {
434 bool enabled = false;
435 EXPECT_TRUE(infc_->setEnableVerboseLogging(true).isOk());
436 EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
437 EXPECT_TRUE(enabled);
438 EXPECT_TRUE(infc_->setEnableVerboseLogging(false).isOk());
439 EXPECT_TRUE(infc_->isVerboseLoggingEnabled(&enabled).isOk());
440 EXPECT_TRUE(!enabled);
441 }
442
443 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcAidl);
444 INSTANTIATE_TEST_SUITE_P(Nfc, NfcAidl,
445 testing::ValuesIn(::android::getAidlHalInstanceNames(INfc::descriptor)),
446 ::android::PrintInstanceNameToString);
447
main(int argc,char ** argv)448 int main(int argc, char** argv) {
449 ::testing::InitGoogleTest(&argc, argv);
450 ABinderProcess_startThreadPool();
451 std::system("/system/bin/svc nfc disable"); /* Turn off NFC */
452 sleep(5);
453 int status = RUN_ALL_TESTS();
454 LOG(INFO) << "Test result = " << status;
455 std::system("/system/bin/svc nfc enable"); /* Turn on NFC */
456 sleep(5);
457 return status;
458 }
459