• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "nfc_api.h"
18 #define LOG_TAG "nfc_behavior_changes_test"
19 
20 #include <aidl/Gtest.h>
21 #include <aidl/Vintf.h>
22 #include <aidl/android/hardware/nfc/BnNfc.h>
23 #include <aidl/android/hardware/nfc/INfc.h>
24 #include <android-base/logging.h>
25 #include <android-base/properties.h>
26 #include <android-base/stringprintf.h>
27 #include <android/binder_process.h>
28 #include <gtest/gtest.h>
29 
30 #include <chrono>
31 #include <future>
32 
33 #include "NfcAdaptation.h"
34 #include "SyncEvent.h"
35 #include "nci_defs.h"
36 #include "nfa_api.h"
37 #include "nfa_ee_api.h"
38 
39 using aidl::android::hardware::nfc::INfc;
40 using android::getAidlHalInstanceNames;
41 using android::PrintInstanceNameToString;
42 using android::base::StringPrintf;
43 
44 static SyncEvent sNfaEnableEvent;  // event for NFA_Enable()
45 static SyncEvent sNfaVsCommand;    // event for VS commands
46 static SyncEvent sNfaEnableDisablePollingEvent;
47 static SyncEvent sNfaPowerChangeEvent;
48 static std::vector<uint8_t> sCaps(0);
49 static uint8_t sObserveModeState;
50 static bool sIsNfaEnabled;
51 static tNFA_STATUS sVSCmdStatus;
52 
53 static const int SET_PASSIVE_OBSERVER_TECH_TIMEOUT_MS = 15;
54 
get_vsr_api_level()55 static int get_vsr_api_level() {
56     int api_level =
57             ::android::base::GetIntProperty("ro.vendor.api_level", -1);
58     if (api_level != -1) {
59         return api_level;
60     }
61 
62     api_level =
63             ::android::base::GetIntProperty("ro.board.api_level", -1);
64     if (api_level != -1) {
65         return api_level;
66     }
67 
68     api_level =
69             ::android::base::GetIntProperty("ro.board.first_api_level", -1);
70     EXPECT_NE(api_level, -1) << "Could not find VSR API level.";
71 
72     return api_level;
73 
74 }
75 
nfaDeviceManagementCallback(uint8_t dmEvent,tNFA_DM_CBACK_DATA * eventData)76 static void nfaDeviceManagementCallback(uint8_t dmEvent, tNFA_DM_CBACK_DATA* eventData) {
77     LOG(DEBUG) << StringPrintf("%s: enter; event=0x%X", __func__, dmEvent);
78 
79     switch (dmEvent) {
80         case NFA_DM_ENABLE_EVT: /* Result of NFA_Enable */
81         {
82             SyncEventGuard guard(sNfaEnableEvent);
83             LOG(DEBUG) << StringPrintf("%s: NFA_DM_ENABLE_EVT; status=0x%X", __func__,
84                                        eventData->status);
85             sIsNfaEnabled = eventData->status == NFA_STATUS_OK;
86             sNfaEnableEvent.notifyOne();
87         } break;
88 
89         case NFA_DM_DISABLE_EVT: /* Result of NFA_Disable */
90         {
91             SyncEventGuard guard(sNfaEnableEvent);
92             LOG(DEBUG) << StringPrintf("%s: NFA_DM_DISABLE_EVT; status=0x%X", __func__,
93                                        eventData->status);
94             sIsNfaEnabled = eventData->status == NFA_STATUS_OK;
95             sNfaEnableEvent.notifyOne();
96         } break;
97 
98         case NFA_DM_PWR_MODE_CHANGE_EVT: {
99             SyncEventGuard guard(sNfaPowerChangeEvent);
100             LOG(DEBUG) << StringPrintf(
101                     "%s: NFA_DM_PWR_MODE_CHANGE_EVT: status=0x%X, power_mode=0x%X", __func__,
102                     eventData->status, eventData->power_mode.power_mode);
103 
104             sNfaPowerChangeEvent.notifyOne();
105 
106         } break;
107     }
108 }
109 
nfaConnectionCallback(uint8_t connEvent,tNFA_CONN_EVT_DATA * eventData)110 static void nfaConnectionCallback(uint8_t connEvent, tNFA_CONN_EVT_DATA* eventData) {
111     LOG(DEBUG) << StringPrintf("%s: event= %u", __func__, connEvent);
112 
113     switch (connEvent) {
114         case NFA_LISTEN_DISABLED_EVT: {
115             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
116             sNfaEnableDisablePollingEvent.notifyOne();
117         } break;
118 
119         case NFA_LISTEN_ENABLED_EVT: {
120             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
121             sNfaEnableDisablePollingEvent.notifyOne();
122         } break;
123 
124         case NFA_RF_DISCOVERY_STARTED_EVT:  // RF Discovery started
125         {
126             LOG(DEBUG) << StringPrintf("%s: NFA_RF_DISCOVERY_STARTED_EVT: status = %u", __func__,
127                                        eventData->status);
128 
129             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
130             sNfaEnableDisablePollingEvent.notifyOne();
131         } break;
132 
133         case NFA_RF_DISCOVERY_STOPPED_EVT:  // RF Discovery stopped event
134         {
135             LOG(DEBUG) << StringPrintf("%s: NFA_RF_DISCOVERY_STOPPED_EVT: status = %u", __func__,
136                                        eventData->status);
137 
138             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
139             sNfaEnableDisablePollingEvent.notifyOne();
140         } break;
141     }
142 }
143 
nfaVSCallback(uint8_t event,uint16_t param_len,uint8_t * p_param)144 void static nfaVSCallback(uint8_t event, uint16_t param_len, uint8_t* p_param) {
145     switch (event & NCI_OID_MASK) {
146         case NCI_MSG_PROP_ANDROID: {
147             uint8_t android_sub_opcode = p_param[3];
148             switch (android_sub_opcode) {
149                 case NCI_QUERY_ANDROID_PASSIVE_OBSERVE: {
150                     sObserveModeState = p_param[5];
151                     LOG(INFO) << StringPrintf("Query observe mode state response is %x",
152                                               sObserveModeState);
153                     SyncEventGuard guard(sNfaVsCommand);
154                     sNfaVsCommand.notifyOne();
155                 } break;
156                 case NCI_ANDROID_SET_PASSIVE_OBSERVER_TECH: {
157                     if (param_len == 5) {
158                         if ((p_param[0] & NCI_MT_MASK) == (NCI_MT_RSP << NCI_MT_SHIFT)) {
159                             sVSCmdStatus = p_param[4];
160                             LOG(INFO) << StringPrintf("Observe mode RSP: status: %x", sVSCmdStatus);
161                             SyncEventGuard guard(sNfaVsCommand);
162                             sNfaVsCommand.notifyOne();
163                         } else {
164                             LOG(WARNING) << StringPrintf(
165                                     "Observe Mode RSP has incorrect message type: %x", p_param[0]);
166                         }
167                     } else {
168                         LOG(WARNING) << StringPrintf("Observe Mode RSP has incorrect length: %d",
169                                                      param_len);
170                     }
171                 } break;
172                 case NCI_ANDROID_POLLING_FRAME_NTF: {
173                     // TODO
174                 } break;
175                 case NCI_ANDROID_GET_CAPS: {
176                     sVSCmdStatus = p_param[4];
177                     SyncEventGuard guard(sNfaVsCommand);
178                     sCaps.assign(p_param + 8, p_param + param_len);
179                     sNfaVsCommand.notifyOne();
180                 } break;
181                 default:
182                     LOG(WARNING) << StringPrintf("Unknown Android sub opcode %x",
183                                                  android_sub_opcode);
184             }
185         } break;
186         default:
187             break;
188     }
189 }
190 
191 /*
192  * Get observe mode state.
193  */
nfaQueryObserveModeState()194 tNFA_STATUS static nfaQueryObserveModeState() {
195     tNFA_STATUS status = NFA_STATUS_FAILED;
196 
197     uint8_t cmd[] = {NCI_QUERY_ANDROID_PASSIVE_OBSERVE};
198 
199     status = NFA_SendVsCommand(NCI_MSG_PROP_ANDROID, sizeof(cmd), cmd, nfaVSCallback);
200 
201     if (status == NFA_STATUS_OK) {
202         if (!sNfaVsCommand.wait(1000)) {
203             LOG(WARNING) << "Timeout waiting for query observe mode response";
204             return NFA_STATUS_TIMEOUT;
205         }
206     }
207 
208     return status;
209 }
210 
211 /*
212  * Enable per-technology observe mode.
213  */
nfaSetPassiveObserverTech(uint8_t tech_mask)214 tNFA_STATUS static nfaSetPassiveObserverTech(uint8_t tech_mask) {
215     tNFA_STATUS status = NFA_STATUS_FAILED;
216 
217     uint8_t cmd[] = {NCI_ANDROID_SET_PASSIVE_OBSERVER_TECH, tech_mask};
218 
219     status = NFA_SendVsCommand(NCI_MSG_PROP_ANDROID, sizeof(cmd), cmd, nfaVSCallback);
220 
221     if (status == NFA_STATUS_OK) {
222         if (!sNfaVsCommand.wait(SET_PASSIVE_OBSERVER_TECH_TIMEOUT_MS)) {
223             LOG(WARNING) << "Timeout waiting for set observer tech response";
224             return NFA_STATUS_TIMEOUT;
225         }
226     }
227 
228     return status;
229 }
230 
231 /*
232  * Get chipset capabilities.
233  */
nfaGetCaps()234 tNFA_STATUS static nfaGetCaps() {
235     tNFA_STATUS status = NFA_STATUS_FAILED;
236 
237     uint8_t cmd[] = {NCI_ANDROID_GET_CAPS};
238     status = NFA_SendVsCommand(NCI_MSG_PROP_ANDROID, sizeof(cmd), cmd, nfaVSCallback);
239 
240     if (status == NFA_STATUS_OK) {
241         if (!sNfaVsCommand.wait(1000)) {
242             LOG(WARNING) << "Timeout waiting for GET_CAPS response";
243             return NFA_STATUS_TIMEOUT;
244         }
245     }
246 
247     return status;
248 }
249 
250 /*
251  * Get observe mode capabilities.
252  */
getCapsPassiveObserverModeValue()253 uint8_t static getCapsPassiveObserverModeValue() {
254     return sCaps[2];
255 }
256 
257 class NfcBehaviorChanges : public testing::TestWithParam<std::string> {
258 protected:
SetUp()259     void SetUp() override {
260         tNFA_STATUS status = NFA_STATUS_OK;
261         status = NFA_StartRfDiscovery();
262         ASSERT_EQ(status, NFA_STATUS_OK);
263         ASSERT_TRUE(sNfaEnableDisablePollingEvent.wait(1000)) << "Timeout starting RF discovery";
264     }
265 
SetUpTestSuite()266     static void SetUpTestSuite() {
267         tNFA_STATUS status = NFA_STATUS_OK;
268 
269         sIsNfaEnabled = false;
270         sVSCmdStatus = NFA_STATUS_OK;
271 
272         NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
273         theInstance.Initialize();  // start GKI, NCI task, NFC task
274 
275         {
276             SyncEventGuard guard(sNfaEnableEvent);
277             tHAL_NFC_ENTRY* halFuncEntries = theInstance.GetHalEntryFuncs();
278 
279             NFA_Init(halFuncEntries);
280 
281             status = NFA_Enable(nfaDeviceManagementCallback, nfaConnectionCallback);
282             ASSERT_EQ(status, NFA_STATUS_OK);
283 
284             // wait for NFA command to finish
285             ASSERT_TRUE(sNfaEnableEvent.wait(1000))
286                     << "Timeout waiting for NFA command on NFA_Enable";
287         }
288 
289         ASSERT_TRUE(sIsNfaEnabled) << "Could not initialize NFC controller";
290     }
291 };
292 
293 /*
294  * SetPassiveObserverTech_getCaps:
295  * Verifies GET_CAPS returns get correct value for observe mode capabilities.
296  */
TEST_P(NfcBehaviorChanges,SetPassiveObserverTech_getCaps)297 TEST_P(NfcBehaviorChanges, SetPassiveObserverTech_getCaps) {
298     if (get_vsr_api_level() < 202504) {
299         GTEST_SKIP() << "Skipping test for board API level < 202504";
300     }
301 
302     tNFC_STATUS status = nfaGetCaps();
303 
304     ASSERT_EQ(status, NFC_STATUS_OK);
305     ASSERT_EQ(getCapsPassiveObserverModeValue(), 0x2);
306 }
307 
308 /*
309  * SetPassiveObserverTech_allExceptF:
310  * Verifies observe mode can be enabled for NFC-A, NFC-B, NFC-V, and disable for NFC-F.
311  *
312  * @VsrTest = GMS-VSR-3.2.8-002
313  */
TEST_P(NfcBehaviorChanges,SetPassiveObserverTech_allExceptF)314 TEST_P(NfcBehaviorChanges, SetPassiveObserverTech_allExceptF) {
315     if (get_vsr_api_level() < 202504) {
316         GTEST_SKIP() << "Skipping test for board API level < 202504";
317     }
318 
319     tNFC_STATUS status = nfaSetPassiveObserverTech(NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_A |
320                                        NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_B |
321                                        NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_V);
322     ASSERT_EQ(status, NFA_STATUS_OK);
323     status = nfaQueryObserveModeState();
324     ASSERT_EQ(status, NFA_STATUS_OK);
325     ASSERT_EQ(sObserveModeState, NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_A |
326                         NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_B |
327                         NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE_V);
328 }
329 
330 /*
331  * SetPassiveObserverTech_allOnAndOff:
332  * Verifies observe mode can be enabled and disabled for all technologies.
333  *
334  * @VsrTest = GMS-VSR-3.2.8-002
335  */
TEST_P(NfcBehaviorChanges,SetPassiveObserverTech_allOnAndOff)336 TEST_P(NfcBehaviorChanges, SetPassiveObserverTech_allOnAndOff) {
337     if (get_vsr_api_level() < 202504) {
338         GTEST_SKIP() << "Skipping test for board API level < 202504";
339     }
340 
341     tNFC_STATUS status = nfaSetPassiveObserverTech(0x0F);
342     ASSERT_EQ(status, NFA_STATUS_OK);
343     status = nfaQueryObserveModeState();
344     ASSERT_EQ(status, NFA_STATUS_OK);
345     ASSERT_EQ(sObserveModeState, 0x0F);
346 
347     status = nfaSetPassiveObserverTech(0x00);
348     ASSERT_EQ(status, NFA_STATUS_OK);
349     status = nfaQueryObserveModeState();
350     ASSERT_EQ(status, NFA_STATUS_OK);
351     ASSERT_EQ(sObserveModeState, 0x00);
352 }
353 
354 /*
355  * SetPassiveObserverTech_testThroughput:
356  * Verifies observe mode can be enabled and disabled repeatedly without timing out or erroring.
357  *
358  * @VsrTest = GMS-VSR-3.2.8-002
359  */
TEST_P(NfcBehaviorChanges,SetPassiveObserverTech_testThroughput)360 TEST_P(NfcBehaviorChanges, SetPassiveObserverTech_testThroughput) {
361     if (get_vsr_api_level() < 202504) {
362         GTEST_SKIP() << "Skipping test for board API level < 202504";
363     }
364 
365     for (int i = 0; i < 100; ++i) {
366         tNFC_STATUS status = nfaSetPassiveObserverTech(0x0F);
367         ASSERT_EQ(status, NFA_STATUS_OK);
368 
369         status = nfaSetPassiveObserverTech(0x00);
370         ASSERT_EQ(status, NFA_STATUS_OK);
371     }
372 }
373 
374 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcBehaviorChanges);
375 INSTANTIATE_TEST_SUITE_P(Nfc, NfcBehaviorChanges,
376         testing::ValuesIn(::android::getAidlHalInstanceNames(INfc::descriptor)),
377         ::android::PrintInstanceNameToString
378 );
379 
main(int argc,char ** argv)380 int main(int argc, char **argv) {
381     testing::InitGoogleTest(&argc, argv);
382     ABinderProcess_startThreadPool();
383     std::system("/system/bin/svc nfc disable"); /* Turn off NFC service */
384     sleep(5);
385     int status = RUN_ALL_TESTS();
386     LOG(INFO) << "Test result = " << status;
387     std::system("/system/bin/svc nfc enable"); /* Turn on NFC service */
388     sleep(5);
389     return status;
390 }
391