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