• 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 #define LOG_TAG "nfc_behavior_changes_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/INfc.h>
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <android/binder_process.h>
26 #include <gtest/gtest.h>
27 
28 #include <chrono>
29 #include <future>
30 
31 #include "NfcAdaptation.h"
32 #include "SyncEvent.h"
33 #include "nci_defs.h"
34 #include "nfa_api.h"
35 #include "nfa_ee_api.h"
36 
37 using aidl::android::hardware::nfc::INfc;
38 using android::getAidlHalInstanceNames;
39 using android::PrintInstanceNameToString;
40 using android::base::StringPrintf;
41 
42 static SyncEvent sNfaEnableEvent;  // event for NFA_Enable()
43 static SyncEvent sNfaVsCommand;    // event for VS commands
44 static SyncEvent sNfaEnableDisablePollingEvent;
45 static SyncEvent sNfaPowerChangeEvent;
46 static bool sIsNfaEnabled;
47 static tNFA_STATUS sVSCmdStatus;
48 
nfaDeviceManagementCallback(uint8_t dmEvent,tNFA_DM_CBACK_DATA * eventData)49 static void nfaDeviceManagementCallback(uint8_t dmEvent, tNFA_DM_CBACK_DATA* eventData) {
50     LOG(DEBUG) << StringPrintf("%s: enter; event=0x%X", __func__, dmEvent);
51 
52     switch (dmEvent) {
53         case NFA_DM_ENABLE_EVT: /* Result of NFA_Enable */
54         {
55             SyncEventGuard guard(sNfaEnableEvent);
56             LOG(DEBUG) << StringPrintf("%s: NFA_DM_ENABLE_EVT; status=0x%X", __func__,
57                                        eventData->status);
58             sIsNfaEnabled = eventData->status == NFA_STATUS_OK;
59             sNfaEnableEvent.notifyOne();
60         } break;
61 
62         case NFA_DM_DISABLE_EVT: /* Result of NFA_Disable */
63         {
64             SyncEventGuard guard(sNfaEnableEvent);
65             LOG(DEBUG) << StringPrintf("%s: NFA_DM_DISABLE_EVT; status=0x%X", __func__,
66                                        eventData->status);
67             sIsNfaEnabled = eventData->status == NFA_STATUS_OK;
68             sNfaEnableEvent.notifyOne();
69         } break;
70 
71         case NFA_DM_PWR_MODE_CHANGE_EVT: {
72             SyncEventGuard guard(sNfaPowerChangeEvent);
73             LOG(DEBUG) << StringPrintf(
74                     "%s: NFA_DM_PWR_MODE_CHANGE_EVT: status=0x%X, power_mode=0x%X", __func__,
75                     eventData->status, eventData->power_mode.power_mode);
76 
77             sNfaPowerChangeEvent.notifyOne();
78 
79         } break;
80     }
81 }
82 
nfaConnectionCallback(uint8_t connEvent,tNFA_CONN_EVT_DATA * eventData)83 static void nfaConnectionCallback(uint8_t connEvent, tNFA_CONN_EVT_DATA* eventData) {
84     LOG(DEBUG) << StringPrintf("%s: event= %u", __func__, connEvent);
85 
86     switch (connEvent) {
87         case NFA_LISTEN_DISABLED_EVT: {
88             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
89             sNfaEnableDisablePollingEvent.notifyOne();
90         } break;
91 
92         case NFA_LISTEN_ENABLED_EVT: {
93             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
94             sNfaEnableDisablePollingEvent.notifyOne();
95         } break;
96 
97         case NFA_RF_DISCOVERY_STARTED_EVT:  // RF Discovery started
98         {
99             LOG(DEBUG) << StringPrintf("%s: NFA_RF_DISCOVERY_STARTED_EVT: status = %u", __func__,
100                                        eventData->status);
101 
102             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
103             sNfaEnableDisablePollingEvent.notifyOne();
104         } break;
105 
106         case NFA_RF_DISCOVERY_STOPPED_EVT:  // RF Discovery stopped event
107         {
108             LOG(DEBUG) << StringPrintf("%s: NFA_RF_DISCOVERY_STOPPED_EVT: status = %u", __func__,
109                                        eventData->status);
110 
111             SyncEventGuard guard(sNfaEnableDisablePollingEvent);
112             sNfaEnableDisablePollingEvent.notifyOne();
113         } break;
114     }
115 }
116 
nfaVSCallback(uint8_t event,uint16_t,uint8_t * p_param)117 void static nfaVSCallback(uint8_t event, uint16_t /* param_len */, uint8_t* p_param) {
118     switch (event & NCI_OID_MASK) {
119         case NCI_MSG_PROP_ANDROID: {
120             uint8_t android_sub_opcode = p_param[3];
121             switch (android_sub_opcode) {
122                 case NCI_ANDROID_PASSIVE_OBSERVE: {
123                     sVSCmdStatus = p_param[4];
124                     LOG(INFO) << StringPrintf("Observe mode RSP: status: %x", sVSCmdStatus);
125                     SyncEventGuard guard(sNfaVsCommand);
126                     sNfaVsCommand.notifyOne();
127                 } break;
128                 case NCI_ANDROID_POLLING_FRAME_NTF: {
129                     // TODO
130                 } break;
131                 default:
132                     LOG(WARNING) << StringPrintf("Unknown Android sub opcode %x",
133                                                  android_sub_opcode);
134             }
135         } break;
136         default:
137             break;
138     }
139 }
140 
141 /*
142  * Enable passive observe mode.
143  */
nfaObserveModeEnable(bool enable)144 tNFA_STATUS static nfaObserveModeEnable(bool enable) {
145     tNFA_STATUS status = NFA_STATUS_FAILED;
146 
147     status = NFA_StopRfDiscovery();
148     if (status == NFA_STATUS_OK) {
149         if (!sNfaEnableDisablePollingEvent.wait(1000)) {
150             LOG(WARNING) << "Timeout waiting to disable NFC RF discovery";
151             return NFA_STATUS_TIMEOUT;
152         }
153     }
154 
155     uint8_t cmd[] = {(NCI_MT_CMD << NCI_MT_SHIFT) | NCI_GID_PROP, NCI_MSG_PROP_ANDROID,
156                      NCI_ANDROID_PASSIVE_OBSERVE_PARAM_SIZE, NCI_ANDROID_PASSIVE_OBSERVE,
157                      static_cast<uint8_t>(enable ? NCI_ANDROID_PASSIVE_OBSERVE_PARAM_ENABLE
158                                                  : NCI_ANDROID_PASSIVE_OBSERVE_PARAM_DISABLE)};
159 
160     status = NFA_SendRawVsCommand(sizeof(cmd), cmd, nfaVSCallback);
161 
162     if (status == NFA_STATUS_OK) {
163         if (!sNfaVsCommand.wait(1000)) {
164             LOG(WARNING) << "Timeout waiting for NFA VS command response";
165             return NFA_STATUS_TIMEOUT;
166         }
167     }
168 
169     return status;
170 }
171 
172 class NfcBehaviorChanges : public testing::TestWithParam<std::string> {
173   protected:
SetUp()174     void SetUp() override {
175         tNFA_STATUS status = NFA_STATUS_OK;
176 
177         sIsNfaEnabled = false;
178         sVSCmdStatus = NFA_STATUS_OK;
179 
180         NfcAdaptation& theInstance = NfcAdaptation::GetInstance();
181         theInstance.Initialize();  // start GKI, NCI task, NFC task
182 
183         {
184             SyncEventGuard guard(sNfaEnableEvent);
185             tHAL_NFC_ENTRY* halFuncEntries = theInstance.GetHalEntryFuncs();
186 
187             NFA_Init(halFuncEntries);
188 
189             status = NFA_Enable(nfaDeviceManagementCallback, nfaConnectionCallback);
190             ASSERT_EQ(status, NFA_STATUS_OK);
191 
192             // wait for NFA command to finish
193             ASSERT_TRUE(sNfaEnableEvent.wait(1000))
194                     << "Timeout waiting for NFA command on NFA_Enable";
195         }
196 
197         ASSERT_TRUE(sIsNfaEnabled) << "Could not initialize NFC controller";
198 
199         status = NFA_StartRfDiscovery();
200         ASSERT_EQ(status, NFA_STATUS_OK);
201         ASSERT_TRUE(sNfaEnableDisablePollingEvent.wait(1000)) << "Timeout starting RF discovery";
202     }
203 };
204 
205 /*
206  * ObserveModeEnable:
207  * Attempts to enable observe mode. Does not test Observe Mode functionality,
208  * but simply verifies that the enable command responds successfully.
209  *
210  * @VsrTest = GMS-VSR-3.2.8-001
211  */
TEST_P(NfcBehaviorChanges,ObserveModeEnableDisable)212 TEST_P(NfcBehaviorChanges, ObserveModeEnableDisable) {
213     tNFA_STATUS status = nfaObserveModeEnable(true);
214     ASSERT_EQ(status, NFA_STATUS_OK);
215 
216     status = nfaObserveModeEnable(false);
217     ASSERT_EQ(status, NFA_STATUS_OK);
218 }
219 
220 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(NfcBehaviorChanges);
221 INSTANTIATE_TEST_SUITE_P(Nfc, NfcBehaviorChanges,
222                          testing::ValuesIn(::android::getAidlHalInstanceNames(INfc::descriptor)),
223                          ::android::PrintInstanceNameToString);
224 
main(int argc,char ** argv)225 int main(int argc, char** argv) {
226     testing::InitGoogleTest(&argc, argv);
227     ABinderProcess_startThreadPool();
228     std::system("/system/bin/svc nfc disable"); /* Turn off NFC service */
229     sleep(5);
230     int status = RUN_ALL_TESTS();
231     LOG(INFO) << "Test result = " << status;
232     std::system("/system/bin/svc nfc enable"); /* Turn on NFC service */
233     sleep(5);
234     return status;
235 }
236