1 /*
2 * Copyright (C) 2018 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 #include "HciEventManager.h"
17
18 #include <android-base/logging.h>
19 #include <android-base/stringprintf.h>
20 #include <log/log.h>
21 #include <nativehelper/ScopedLocalRef.h>
22
23 #include "JavaClassConstants.h"
24 #include "NfcJniUtil.h"
25 #include "nfc_config.h"
26
27 const char* APP_NAME = "NfcNci";
28 uint8_t HciEventManager::sEsePipe;
29 std::vector<uint8_t> HciEventManager::sSimPipeIds;
30 static Mutex sSimPipeIdsMutex;
31
32 using android::base::StringPrintf;
33
HciEventManager()34 HciEventManager::HciEventManager() : mNativeData(nullptr) {}
35
getInstance()36 HciEventManager& HciEventManager::getInstance() {
37 static HciEventManager sHciEventManager;
38 return sHciEventManager;
39 }
40
initialize(nfc_jni_native_data * native)41 void HciEventManager::initialize(nfc_jni_native_data* native) {
42 mNativeData = native;
43 tNFA_STATUS nfaStat = NFA_HciRegister(const_cast<char*>(APP_NAME),
44 (tNFA_HCI_CBACK*)&nfaHciCallback, true);
45 if (nfaStat != NFA_STATUS_OK) {
46 LOG(ERROR) << "HCI registration failed; status=" << nfaStat;
47 }
48 sEsePipe = NfcConfig::getUnsigned(NAME_OFF_HOST_ESE_PIPE_ID, 0x16);
49 // Backward compatibility or For vendor supporting only single sim pipe ID
50 sSimPipeIdsMutex.lock();
51 if (!NfcConfig::hasKey(NAME_OFF_HOST_SIM_PIPE_IDS)) {
52 uint8_t simPipeId = NfcConfig::getUnsigned(NAME_OFF_HOST_SIM_PIPE_ID, 0x0A);
53 sSimPipeIds = {simPipeId};
54 } else {
55 sSimPipeIds = NfcConfig::getBytes(NAME_OFF_HOST_SIM_PIPE_IDS);
56 }
57 sSimPipeIdsMutex.unlock();
58 }
59
notifyTransactionListenersOfAid(std::vector<uint8_t> aid,std::vector<uint8_t> data,std::string evtSrc)60 void HciEventManager::notifyTransactionListenersOfAid(std::vector<uint8_t> aid,
61 std::vector<uint8_t> data,
62 std::string evtSrc) {
63 if (aid.empty()) {
64 return;
65 }
66
67 JNIEnv* e = NULL;
68 ScopedAttach attach(mNativeData->vm, &e);
69 CHECK(e);
70
71 ScopedLocalRef<jobject> aidJavaArray(e, e->NewByteArray(aid.size()));
72 CHECK(aidJavaArray.get());
73 e->SetByteArrayRegion((jbyteArray)aidJavaArray.get(), 0, aid.size(),
74 (jbyte*)&aid[0]);
75 CHECK(!e->ExceptionCheck());
76
77 ScopedLocalRef<jobject> srcJavaString(e, e->NewStringUTF(evtSrc.c_str()));
78 CHECK(srcJavaString.get());
79
80 if (data.size() > 0) {
81 ScopedLocalRef<jobject> dataJavaArray(e, e->NewByteArray(data.size()));
82 CHECK(dataJavaArray.get());
83 e->SetByteArrayRegion((jbyteArray)dataJavaArray.get(), 0, data.size(),
84 (jbyte*)&data[0]);
85 CHECK(!e->ExceptionCheck());
86 e->CallVoidMethod(mNativeData->manager,
87 android::gCachedNfcManagerNotifyTransactionListeners,
88 aidJavaArray.get(), dataJavaArray.get(),
89 srcJavaString.get());
90 } else {
91 e->CallVoidMethod(mNativeData->manager,
92 android::gCachedNfcManagerNotifyTransactionListeners,
93 aidJavaArray.get(), NULL, srcJavaString.get());
94 }
95 }
96
97 /**
98 * BerTlv has the following format:
99 *
100 * byte1 byte2 byte3 byte4 byte5 byte6
101 * 00-7F - - - - -
102 * 81 00-FF - - - -
103 * 82 0000-FFFF - - -
104 * 83 000000-FFFFFF - -
105 * 84 00000000-FFFFFFFF -
106 */
getDataFromBerTlv(std::vector<uint8_t> berTlv)107 std::vector<uint8_t> HciEventManager::getDataFromBerTlv(
108 std::vector<uint8_t> berTlv) {
109 if (berTlv.empty()) {
110 return std::vector<uint8_t>();
111 }
112 size_t lengthTag = berTlv[0];
113 LOG(DEBUG) << "decodeBerTlv: berTlv[0]=" << berTlv[0];
114
115 /* As per ISO/IEC 7816, read the first byte to determine the length and
116 * the start index accordingly
117 */
118 if (lengthTag < 0x80 && berTlv.size() == (lengthTag + 1)) {
119 return std::vector<uint8_t>(berTlv.begin() + 1, berTlv.end());
120 } else if (lengthTag == 0x81 && berTlv.size() > 2) {
121 size_t length = berTlv[1];
122 if ((length + 2) == berTlv.size()) {
123 return std::vector<uint8_t>(berTlv.begin() + 2, berTlv.end());
124 }
125 } else if (lengthTag == 0x82 && berTlv.size() > 3) {
126 size_t length = ((berTlv[1] << 8) | berTlv[2]);
127 if ((length + 3) == berTlv.size()) {
128 return std::vector<uint8_t>(berTlv.begin() + 3, berTlv.end());
129 }
130 } else if (lengthTag == 0x83 && berTlv.size() > 4) {
131 size_t length = (berTlv[1] << 16) | (berTlv[2] << 8) | berTlv[3];
132 if ((length + 4) == berTlv.size()) {
133 return std::vector<uint8_t>(berTlv.begin() + 4, berTlv.end());
134 }
135 } else if (lengthTag == 0x84 && berTlv.size() > 5) {
136 size_t length =
137 (berTlv[1] << 24) | (berTlv[2] << 16) | (berTlv[3] << 8) | berTlv[4];
138 if ((length + 5) == berTlv.size()) {
139 return std::vector<uint8_t>(berTlv.begin() + 5, berTlv.end());
140 }
141 }
142 LOG(ERROR) << "Error in TLV length encoding!";
143 return std::vector<uint8_t>();
144 }
145
nfaHciCallback(tNFA_HCI_EVT event,tNFA_HCI_EVT_DATA * eventData)146 void HciEventManager::nfaHciCallback(tNFA_HCI_EVT event,
147 tNFA_HCI_EVT_DATA* eventData) {
148 if (eventData == nullptr) {
149 return;
150 }
151
152 LOG(DEBUG) << StringPrintf(
153 "event=%d code=%d pipe=%d len=%d", event, eventData->rcvd_evt.evt_code,
154 eventData->rcvd_evt.pipe, eventData->rcvd_evt.evt_len);
155
156 std::string evtSrc;
157 if (eventData->rcvd_evt.pipe == sEsePipe) {
158 evtSrc = "eSE1";
159 } else {
160 sSimPipeIdsMutex.lock();
161 bool isSimPipeId = false;
162 for (size_t i = 0; i < (size_t)sSimPipeIds.size(); i++) {
163 if (eventData->rcvd_evt.pipe == sSimPipeIds[i]) {
164 evtSrc = "SIM" + std::to_string(i + 1);
165 isSimPipeId = true;
166 break;
167 }
168 }
169 sSimPipeIdsMutex.unlock();
170
171 if (!isSimPipeId) {
172 LOG(WARNING) << "Incorrect Pipe Id";
173 return;
174 }
175 }
176
177 // Check the event and check if it contains the AID
178 uint8_t* event_buff = eventData->rcvd_evt.p_evt_buf;
179 uint32_t event_buff_len = eventData->rcvd_evt.evt_len;
180 if (event != NFA_HCI_EVENT_RCVD_EVT ||
181 eventData->rcvd_evt.evt_code != NFA_HCI_EVT_TRANSACTION ||
182 event_buff_len <= 3 || event_buff == nullptr || event_buff[0] != 0x81) {
183 LOG(WARNING) << "Invalid event";
184 return;
185 }
186
187 uint32_t aid_len = event_buff[1];
188 if (aid_len >= (event_buff_len - 1)) {
189 android_errorWriteLog(0x534e4554, "181346545");
190 LOG(ERROR) << StringPrintf("error: aidlen(%d) is too big", aid_len);
191 return;
192 }
193
194 std::vector<uint8_t> aid(event_buff + 2, event_buff + aid_len + 2);
195 int32_t berTlvStart = aid_len + 2 + 1;
196 int32_t berTlvLen = event_buff_len - berTlvStart;
197 std::vector<uint8_t> data;
198 if (berTlvLen > 0 && event_buff[2 + aid_len] == 0x82) {
199 std::vector<uint8_t> berTlv(event_buff + berTlvStart,
200 event_buff + event_buff_len);
201 // BERTLV decoding here, to support extended data length for params.
202 data = getInstance().getDataFromBerTlv(berTlv);
203 }
204
205 getInstance().notifyTransactionListenersOfAid(aid, data, evtSrc);
206 }
207
finalize()208 void HciEventManager::finalize() { mNativeData = NULL; }
209