1 /*
2  * Copyright (C) 2012 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 /*
18  *  Tag-reading, tag-writing operations.
19  */
20 #include "NfcTag.h"
21 
22 #include <android-base/logging.h>
23 #include <android-base/stringprintf.h>
24 #include <log/log.h>
25 #include <nativehelper/ScopedLocalRef.h>
26 #include <nativehelper/ScopedPrimitiveArray.h>
27 #include <statslog_nfc.h>
28 
29 #include "JavaClassConstants.h"
30 #include "nfc_brcm_defs.h"
31 #include "nfc_config.h"
32 #include "rw_int.h"
33 
34 using android::base::StringPrintf;
35 
36 static void deleteglobaldata(JNIEnv* e);
37 static jobjectArray sTechPollBytes;
38 static jobjectArray gtechActBytes;
39 static int sLastSelectedTagId = 0;
40 
41 /*******************************************************************************
42 **
43 ** Function:        NfcTag
44 **
45 ** Description:     Initialize member variables.
46 **
47 ** Returns:         None
48 **
49 *******************************************************************************/
NfcTag()50 NfcTag::NfcTag()
51     : mNumTechList(0),
52       mNumRfDiscId(0),
53       mIsReselecting(false),
54       mTechnologyTimeoutsTable(MAX_NUM_TECHNOLOGY),
55       mNativeData(NULL),
56       mIsActivated(false),
57       mActivationState(Idle),
58       mProtocol(NFC_PROTOCOL_UNKNOWN),
59       mtT1tMaxMessageSize(0),
60       mReadCompletedStatus(NFA_STATUS_OK),
61       mLastKovioUidLen(0),
62       mNdefDetectionTimedOut(false),
63       mIsDynamicTagId(false),
64       mPresenceCheckAlgorithm(NFA_RW_PRES_CHK_DEFAULT),
65       mIsFelicaLite(false),
66       mNumDiscNtf(0),
67       mNumDiscTechList(0),
68       mTechListTail(0),
69       mIsMultiProtocolTag(false) {
70   memset(mTechList, 0, sizeof(mTechList));
71   memset(mTechHandles, 0, sizeof(mTechHandles));
72   memset(mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes));
73   memset(mTechParams, 0, sizeof(mTechParams));
74   memset(mLastKovioUid, 0, NFC_KOVIO_MAX_LEN);
75   memset(&mLastKovioTime, 0, sizeof(timespec));
76   mNfcStatsUtil = new NfcStatsUtil();
77 }
78 
79 /*******************************************************************************
80 **
81 ** Function:        getInstance
82 **
83 ** Description:     Get a reference to the singleton NfcTag object.
84 **
85 ** Returns:         Reference to NfcTag object.
86 **
87 *******************************************************************************/
getInstance()88 NfcTag& NfcTag::getInstance() {
89   static NfcTag tag;
90   return tag;
91 }
92 
93 /*******************************************************************************
94 **
95 ** Function:        initialize
96 **
97 ** Description:     Reset member variables.
98 **                  native: Native data.
99 **
100 ** Returns:         None
101 **
102 *******************************************************************************/
initialize(nfc_jni_native_data * native)103 void NfcTag::initialize(nfc_jni_native_data* native) {
104   mNativeData = native;
105   mIsActivated = false;
106   mActivationState = Idle;
107   mProtocol = NFC_PROTOCOL_UNKNOWN;
108   mNumRfDiscId = 0;
109   mtT1tMaxMessageSize = 0;
110   mReadCompletedStatus = NFA_STATUS_OK;
111   resetTechnologies();
112   if (NfcConfig::hasKey(NAME_PRESENCE_CHECK_ALGORITHM))
113     mPresenceCheckAlgorithm =
114         NfcConfig::getUnsigned(NAME_PRESENCE_CHECK_ALGORITHM);
115 }
116 
117 /*******************************************************************************
118 **
119 ** Function:        abort
120 **
121 ** Description:     Unblock all operations.
122 **
123 ** Returns:         None
124 **
125 *******************************************************************************/
abort()126 void NfcTag::abort() {
127   SyncEventGuard g(mReadCompleteEvent);
128   mReadCompleteEvent.notifyOne();
129 }
130 
131 /*******************************************************************************
132 **
133 ** Function:        getActivationState
134 **
135 ** Description:     What is the current state: Idle, Sleep, or Activated.
136 **
137 ** Returns:         Idle, Sleep, or Activated.
138 **
139 *******************************************************************************/
getActivationState()140 NfcTag::ActivationState NfcTag::getActivationState() {
141   return mActivationState;
142 }
143 
144 /*******************************************************************************
145 **
146 ** Function:        setDeactivationState
147 **
148 ** Description:     Set the current state: Idle or Sleep.
149 **                  deactivated: state of deactivation.
150 **
151 ** Returns:         None.
152 **
153 *******************************************************************************/
setDeactivationState(tNFA_DEACTIVATED & deactivated)154 void NfcTag::setDeactivationState(tNFA_DEACTIVATED& deactivated) {
155   static const char fn[] = "NfcTag::setDeactivationState";
156   mActivationState = Idle;
157   mNdefDetectionTimedOut = false;
158   if (deactivated.type == NFA_DEACTIVATE_TYPE_SLEEP) mActivationState = Sleep;
159   LOG(DEBUG) << StringPrintf("%s: state=%u", fn, mActivationState);
160 }
161 
162 /*******************************************************************************
163 **
164 ** Function:        setActivationState
165 **
166 ** Description:     Set the current state to Active.
167 **
168 ** Returns:         None.
169 **
170 *******************************************************************************/
setActivationState()171 void NfcTag::setActivationState() {
172   static const char fn[] = "NfcTag::setActivationState";
173   mNdefDetectionTimedOut = false;
174   mActivationState = Active;
175   LOG(DEBUG) << StringPrintf("%s: state=%u", fn, mActivationState);
176 }
177 
178 /*******************************************************************************
179 **
180 ** Function:        isActivated
181 **
182 ** Description:     Is tag activated?
183 **
184 ** Returns:         True if tag is activated.
185 **
186 *******************************************************************************/
isActivated()187 bool NfcTag::isActivated() { return mIsActivated; }
188 
189 /*******************************************************************************
190 **
191 ** Function:        getProtocol
192 **
193 ** Description:     Get the protocol of the current tag.
194 **
195 ** Returns:         Protocol number.
196 **
197 *******************************************************************************/
getProtocol()198 tNFC_PROTOCOL NfcTag::getProtocol() { return mProtocol; }
199 
200 /*******************************************************************************
201 **
202 ** Function         TimeDiff
203 **
204 ** Description      Computes time difference in milliseconds.
205 **
206 ** Returns          Time difference in milliseconds
207 **
208 *******************************************************************************/
TimeDiff(timespec start,timespec end)209 uint32_t TimeDiff(timespec start, timespec end) {
210   timespec temp;
211   if ((end.tv_nsec - start.tv_nsec) < 0) {
212     temp.tv_sec = end.tv_sec - start.tv_sec - 1;
213     temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
214   } else {
215     temp.tv_sec = end.tv_sec - start.tv_sec;
216     temp.tv_nsec = end.tv_nsec - start.tv_nsec;
217   }
218 
219   return (temp.tv_sec * 1000) + (temp.tv_nsec / 1000000);
220 }
221 
222 /*******************************************************************************
223 **
224 ** Function:        IsSameKovio
225 **
226 ** Description:     Checks if tag activate is the same (UID) Kovio tag
227 *previously
228 **                  activated.  This is needed due to a problem with some Kovio
229 **                  tags re-activating multiple times.
230 **                  activationData: data from activation.
231 **
232 ** Returns:         true if the activation is from the same tag previously
233 **                  activated, false otherwise
234 **
235 *******************************************************************************/
IsSameKovio(tNFA_ACTIVATED & activationData)236 bool NfcTag::IsSameKovio(tNFA_ACTIVATED& activationData) {
237   static const char fn[] = "NfcTag::IsSameKovio";
238   LOG(DEBUG) << StringPrintf("%s: enter", fn);
239   tNFC_ACTIVATE_DEVT& rfDetail = activationData.activate_ntf;
240 
241   if (rfDetail.protocol != NFC_PROTOCOL_KOVIO) return false;
242 
243   memcpy(&(mTechParams[0]), &(rfDetail.rf_tech_param),
244          sizeof(rfDetail.rf_tech_param));
245   if (mTechParams[0].mode != NFC_DISCOVERY_TYPE_POLL_KOVIO) return false;
246 
247   struct timespec now;
248   clock_gettime(CLOCK_REALTIME, &now);
249 
250   bool rVal = false;
251   if (mTechParams[0].param.pk.uid_len == mLastKovioUidLen) {
252     if (memcmp(mLastKovioUid, &mTechParams[0].param.pk.uid,
253                mTechParams[0].param.pk.uid_len) == 0) {
254       // same tag
255       if (TimeDiff(mLastKovioTime, now) < 500) {
256         // same tag within 500 ms, ignore activation
257         rVal = true;
258       }
259     }
260   }
261 
262   // save Kovio tag info
263   if (!rVal) {
264     if ((mLastKovioUidLen = mTechParams[0].param.pk.uid_len) >
265         NFC_KOVIO_MAX_LEN)
266       mLastKovioUidLen = NFC_KOVIO_MAX_LEN;
267     memcpy(mLastKovioUid, mTechParams[0].param.pk.uid, mLastKovioUidLen);
268   }
269   mLastKovioTime = now;
270   LOG(DEBUG) << StringPrintf("%s: exit, is same Kovio=%d", fn, rVal);
271   return rVal;
272 }
273 
274 /*******************************************************************************
275 **
276 ** Function:        discoverTechnologies
277 **
278 ** Description:     Discover the technologies that NFC service needs by
279 *interpreting
280 **                  the data structures from the stack.
281 **                  activationData: data from activation.
282 **
283 ** Returns:         None
284 **
285 *******************************************************************************/
discoverTechnologies(tNFA_ACTIVATED & activationData)286 void NfcTag::discoverTechnologies(tNFA_ACTIVATED& activationData) {
287   static const char fn[] = "NfcTag::discoverTechnologies (activation)";
288   LOG(DEBUG) << StringPrintf("%s: enter", fn);
289   tNFC_ACTIVATE_DEVT& rfDetail = activationData.activate_ntf;
290 
291   if (mTechListTail < (MAX_NUM_TECHNOLOGY - 1)) {
292     mNumTechList = mTechListTail;
293   } else {
294     LOG(ERROR) << StringPrintf("%s: exceed max=%d", fn, MAX_NUM_TECHNOLOGY);
295     android_errorWriteLog(0x534e4554, "189942532");
296     goto TheEnd;
297   }
298   mTechHandles[mNumTechList] = rfDetail.rf_disc_id;
299   mTechLibNfcTypes[mNumTechList] = rfDetail.protocol;
300 
301   // save the stack's data structure for interpretation later
302   memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param),
303          sizeof(rfDetail.rf_tech_param));
304 
305   if (NFC_PROTOCOL_T1T == rfDetail.protocol) {
306     mTechList[mNumTechList] =
307         TARGET_TYPE_ISO14443_3A;  // is TagTechnology.NFC_A by Java API
308   } else if (NFC_PROTOCOL_T2T == rfDetail.protocol) {
309     mTechList[mNumTechList] =
310         TARGET_TYPE_ISO14443_3A;  // is TagTechnology.NFC_A by Java API
311     // could be MifFare UL or Classic or Kovio
312     {
313       // need to look at first byte of uid to find Manufacture Byte
314       tNFC_RF_TECH_PARAMS tech_params;
315       memcpy(&tech_params, &(rfDetail.rf_tech_param),
316              sizeof(rfDetail.rf_tech_param));
317 
318       if ((tech_params.param.pa.nfcid1[0] == 0x04 &&
319            rfDetail.rf_tech_param.param.pa.sel_rsp == 0) ||
320           rfDetail.rf_tech_param.param.pa.sel_rsp == 0x18 ||
321           rfDetail.rf_tech_param.param.pa.sel_rsp == 0x08) {
322         if (rfDetail.rf_tech_param.param.pa.sel_rsp == 0) {
323           mNumTechList++;
324           mTechHandles[mNumTechList] = rfDetail.rf_disc_id;
325           mTechLibNfcTypes[mNumTechList] = rfDetail.protocol;
326           // save the stack's data structure for interpretation later
327           memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param),
328                  sizeof(rfDetail.rf_tech_param));
329           mTechList[mNumTechList] =
330               TARGET_TYPE_MIFARE_UL;  // is TagTechnology.MIFARE_ULTRALIGHT by
331                                       // Java API
332         }
333       }
334     }
335   } else if (NFC_PROTOCOL_T3T == rfDetail.protocol) {
336     uint8_t xx = 0;
337 
338     mTechList[mNumTechList] = TARGET_TYPE_FELICA;
339 
340     // see if it is Felica Lite.
341     while (xx < activationData.params.t3t.num_system_codes) {
342       if (activationData.params.t3t.p_system_codes[xx++] ==
343           T3T_SYSTEM_CODE_FELICA_LITE) {
344         mIsFelicaLite = true;
345         break;
346       }
347     }
348   } else if (NFC_PROTOCOL_ISO_DEP == rfDetail.protocol) {
349     // type-4 tag uses technology ISO-DEP and technology A or B
350     mTechList[mNumTechList] =
351         TARGET_TYPE_ISO14443_4;  // is TagTechnology.ISO_DEP by Java API
352     uint8_t fwi = 0;
353     if (NFC_DISCOVERY_TYPE_POLL_A == rfDetail.rf_tech_param.mode) {
354       fwi = rfDetail.intf_param.intf_param.pa_iso.fwi;
355     } else {
356       fwi = rfDetail.rf_tech_param.param.pb.fwi;
357     }
358     if (fwi >= MIN_FWI && fwi <= MAX_FWI) {
359       // 2^MIN_FWI * 256 * 16 * 1000 / 13560000 is approximately 618
360       int fwt = (1 << (fwi - MIN_FWI)) * 618;
361       LOG(DEBUG) << StringPrintf(
362           "%s; Setting the transceive timeout = %d(x2), fwi = %0#x", fn, fwt,
363           fwi);
364       setTransceiveTimeout(mTechList[mNumTechList], fwt * 2);
365     }
366 
367     if ((rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_A) ||
368         (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_A)) {
369       mNumTechList++;
370       mTechHandles[mNumTechList] = rfDetail.rf_disc_id;
371       mTechLibNfcTypes[mNumTechList] = rfDetail.protocol;
372       mTechList[mNumTechList] =
373           TARGET_TYPE_ISO14443_3A;  // is TagTechnology.NFC_A by Java API
374       // save the stack's data structure for interpretation later
375       memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param),
376              sizeof(rfDetail.rf_tech_param));
377     } else if ((rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_B) ||
378                (rfDetail.rf_tech_param.mode ==
379                 NFC_DISCOVERY_TYPE_POLL_B_PRIME) ||
380                (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_LISTEN_B) ||
381                (rfDetail.rf_tech_param.mode ==
382                 NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)) {
383       mNumTechList++;
384       mTechHandles[mNumTechList] = rfDetail.rf_disc_id;
385       mTechLibNfcTypes[mNumTechList] = rfDetail.protocol;
386       mTechList[mNumTechList] =
387           TARGET_TYPE_ISO14443_3B;  // is TagTechnology.NFC_B by Java API
388       // save the stack's data structure for interpretation later
389       memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param),
390              sizeof(rfDetail.rf_tech_param));
391     }
392   } else if (NFC_PROTOCOL_T5T == rfDetail.protocol) {
393     // is TagTechnology.NFC_V by Java API
394     mTechList[mNumTechList] = TARGET_TYPE_V;
395   } else if (NFC_PROTOCOL_KOVIO == rfDetail.protocol) {
396     LOG(DEBUG) << StringPrintf("%s: Kovio", fn);
397     mTechList[mNumTechList] = TARGET_TYPE_KOVIO_BARCODE;
398   } else if (NFC_PROTOCOL_MIFARE == rfDetail.protocol) {
399     LOG(DEBUG) << StringPrintf("%s: Mifare Classic", fn);
400     mTechList[mNumTechList] =
401         TARGET_TYPE_MIFARE_CLASSIC;  // is TagTechnology.MIFARE_CLASSIC by Java
402                                      // API
403     mNumTechList++;
404     mTechHandles[mNumTechList] = rfDetail.rf_disc_id;
405     mTechLibNfcTypes[mNumTechList] = rfDetail.protocol;
406     // save the stack's data structure for interpretation later
407     memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param),
408            sizeof(rfDetail.rf_tech_param));
409     mTechList[mNumTechList] =
410         TARGET_TYPE_ISO14443_3A;  // is TagTechnology.NFC_A by Java API
411   } else {
412     if ((NCI_PROTOCOL_UNKNOWN == rfDetail.protocol) &&
413         (rfDetail.rf_tech_param.mode == NFC_DISCOVERY_TYPE_POLL_B)) {
414       mTechHandles[mNumTechList] = rfDetail.rf_disc_id;
415       mTechLibNfcTypes[mNumTechList] = rfDetail.protocol;
416       LOG(DEBUG) << StringPrintf("%s; Tech type B, unknown ", fn);
417       mTechList[mNumTechList] =
418           TARGET_TYPE_ISO14443_3B;  // is TagTechnology.NFC_B by Java API
419       // save the stack's data structure for interpretation later
420       memcpy(&(mTechParams[mNumTechList]), &(rfDetail.rf_tech_param),
421              sizeof(rfDetail.rf_tech_param));
422     } else {
423       LOG(ERROR) << StringPrintf("%s; unknown protocol ????", fn);
424       mTechList[mNumTechList] = TARGET_TYPE_UNKNOWN;
425     }
426   }
427 
428   mNumTechList++;
429   for (int i = 0; i < mNumTechList; i++) {
430     LOG(DEBUG) << StringPrintf(
431         "%s: index=%d; tech=0x%x; handle=%d; nfc type=0x%x", fn, i,
432         mTechList[i], mTechHandles[i], mTechLibNfcTypes[i]);
433   }
434   mNfcStatsUtil->logNfcTagType(mTechLibNfcTypes[mTechListTail],
435                                mTechParams[mTechListTail].mode);
436 TheEnd:
437   LOG(DEBUG) << StringPrintf("%s: exit", fn);
438 }
439 
440 /*******************************************************************************
441 **
442 ** Function:        discoverTechnologies
443 **
444 ** Description:     Discover the technologies that NFC service needs by
445 *interpreting
446 **                  the data structures from the stack.
447 **                  discoveryData: data from discovery events(s).
448 **
449 ** Returns:         None
450 **
451 *******************************************************************************/
discoverTechnologies(tNFA_DISC_RESULT & discoveryData)452 void NfcTag::discoverTechnologies(tNFA_DISC_RESULT& discoveryData) {
453   static const char fn[] = "NfcTag::discoverTechnologies (discovery)";
454   tNFC_RESULT_DEVT& discovery_ntf = discoveryData.discovery_ntf;
455   uint8_t index = mNumDiscNtf;
456 
457   LOG(DEBUG) << StringPrintf(
458       "%s: enter: rf disc. id=%u; protocol=0x%x, mNumTechList=%u", fn,
459       discovery_ntf.rf_disc_id, discovery_ntf.protocol, mNumTechList);
460   if (index >= MAX_NUM_TECHNOLOGY) {
461     LOG(ERROR) << StringPrintf("%s: exceed max=%d", fn, MAX_NUM_TECHNOLOGY);
462     goto TheEnd;
463   }
464   mTechHandlesDiscData[index] = discovery_ntf.rf_disc_id;
465   mTechLibNfcTypesDiscData[index] = discovery_ntf.protocol;
466   if (mNumDiscTechList < MAX_NUM_TECHNOLOGY) {
467     mNumDiscTechList++;
468   }
469   if (discovery_ntf.more != NCI_DISCOVER_NTF_MORE) {
470     for (int i = 0; i < mNumDiscTechList; i++) {
471       LOG(DEBUG) << StringPrintf("%s: index=%d; handle=%d; nfc type=0x%x", fn,
472                                  i, mTechHandlesDiscData[i],
473                                  mTechLibNfcTypesDiscData[i]);
474     }
475   }
476   LOG(DEBUG) << StringPrintf("%s; mNumDiscTechList=%x", fn, mNumDiscTechList);
477   mNumRfDiscId = discovery_ntf.rf_disc_id;
478 TheEnd:
479   LOG(DEBUG) << StringPrintf("%s: exit", fn);
480 }
481 
482 /*******************************************************************************
483 **
484 ** Function:        createNativeNfcTag
485 **
486 ** Description:     Create a brand new Java NativeNfcTag object;
487 **                  fill the objects's member variables with data;
488 **                  notify NFC service;
489 **                  activationData: data from activation.
490 **
491 ** Returns:         None
492 **
493 *******************************************************************************/
createNativeNfcTag(tNFA_ACTIVATED & activationData)494 void NfcTag::createNativeNfcTag(tNFA_ACTIVATED& activationData) {
495   static const char fn[] = "NfcTag::createNativeNfcTag";
496   LOG(DEBUG) << StringPrintf("%s: enter", fn);
497 
498   if (mNativeData == NULL) {
499     LOG(ERROR) << StringPrintf("%s: mNativeData is null", fn);
500     return;
501   }
502 
503   JNIEnv* e = NULL;
504   ScopedAttach attach(mNativeData->vm, &e);
505   if (e == NULL) {
506     LOG(ERROR) << StringPrintf("%s: jni env is null", fn);
507     return;
508   }
509 
510   ScopedLocalRef<jclass> tag_cls(e,
511                                  e->GetObjectClass(mNativeData->cached_NfcTag));
512   if (e->ExceptionCheck()) {
513     e->ExceptionClear();
514     LOG(ERROR) << StringPrintf("%s: failed to get class", fn);
515     return;
516   }
517 
518   // create a new Java NativeNfcTag object
519   jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V");
520   ScopedLocalRef<jobject> tag(e, e->NewObject(tag_cls.get(), ctor));
521 
522   // fill NativeNfcTag's mProtocols, mTechList, mTechHandles, mTechLibNfcTypes
523   fillNativeNfcTagMembers1(e, tag_cls.get(), tag.get());
524 
525   // fill NativeNfcTag's members: mHandle, mConnectedTechnology
526   fillNativeNfcTagMembers2(e, tag_cls.get(), tag.get(), activationData);
527 
528   // fill NativeNfcTag's members: mTechPollBytes
529   fillNativeNfcTagMembers3(e, tag_cls.get(), tag.get(), activationData);
530 
531   // fill NativeNfcTag's members: mTechActBytes
532   fillNativeNfcTagMembers4(e, tag_cls.get(), tag.get(), activationData);
533 
534   // fill NativeNfcTag's members: mUid
535   fillNativeNfcTagMembers5(e, tag_cls.get(), tag.get(), activationData);
536 
537   if (mNativeData->tag != NULL) {
538     e->DeleteGlobalRef(mNativeData->tag);
539   }
540   mNativeData->tag = e->NewGlobalRef(tag.get());
541 
542   LOG(DEBUG) << StringPrintf("%s; mNumDiscNtf=%x", fn, mNumDiscNtf);
543 
544   if (!mNumDiscNtf) {
545     // notify NFC service about this new tag
546     LOG(DEBUG) << StringPrintf("%s: try notify nfc service", fn);
547     e->CallVoidMethod(mNativeData->manager,
548                       android::gCachedNfcManagerNotifyNdefMessageListeners,
549                       tag.get());
550     if (e->ExceptionCheck()) {
551       e->ExceptionClear();
552       LOG(ERROR) << StringPrintf("%s: fail notify nfc service", fn);
553     }
554     deleteglobaldata(e);
555   } else {
556     LOG(DEBUG) << StringPrintf("%s: Selecting next tag", fn);
557   }
558 
559   LOG(DEBUG) << StringPrintf("%s: exit", fn);
560 }
561 
562 /*******************************************************************************
563 **
564 ** Function:        deleteglobaldata
565 **
566 ** Description:     Deletes the global data reference after notifying to service
567 **                  e: JVM environment.
568 **
569 ** Returns:         None
570 **
571 *******************************************************************************/
deleteglobaldata(JNIEnv * e)572 static void deleteglobaldata(JNIEnv* e) {
573   static const char fn[] = "deleteglobaldata";
574   LOG(DEBUG) << StringPrintf("%s: enter", fn);
575   if (sTechPollBytes != NULL) {
576     e->DeleteGlobalRef(sTechPollBytes);
577   }
578   if (gtechActBytes != NULL) {
579     e->DeleteGlobalRef(gtechActBytes);
580   }
581   LOG(DEBUG) << StringPrintf("%s: exit", fn);
582 }
583 
584 /*******************************************************************************
585 **
586 ** Function:        fillNativeNfcTagMembers1
587 **
588 ** Description:     Fill NativeNfcTag's members: mProtocols, mTechList,
589 *mTechHandles, mTechLibNfcTypes.
590 **                  e: JVM environment.
591 **                  tag_cls: Java NativeNfcTag class.
592 **                  tag: Java NativeNfcTag object.
593 **
594 ** Returns:         None
595 **
596 *******************************************************************************/
fillNativeNfcTagMembers1(JNIEnv * e,jclass tag_cls,jobject tag)597 void NfcTag::fillNativeNfcTagMembers1(JNIEnv* e, jclass tag_cls, jobject tag) {
598   static const char fn[] = "NfcTag::fillNativeNfcTagMembers1";
599   LOG(DEBUG) << StringPrintf("%s", fn);
600 
601   // create objects that represent NativeNfcTag's member variables
602   ScopedLocalRef<jintArray> techList(e, e->NewIntArray(mNumTechList));
603   ScopedLocalRef<jintArray> handleList(e, e->NewIntArray(mNumTechList));
604   ScopedLocalRef<jintArray> typeList(e, e->NewIntArray(mNumTechList));
605 
606   {
607     ScopedIntArrayRW technologies(e, techList.get());
608     ScopedIntArrayRW handles(e, handleList.get());
609     ScopedIntArrayRW types(e, typeList.get());
610     for (int i = 0; i < mNumTechList; i++) {
611       mNativeData->tProtocols[i] = mTechLibNfcTypes[i];
612       mNativeData->handles[i] = mTechHandles[i];
613       technologies[i] = mTechList[i];
614       handles[i] = mTechHandles[i];
615       types[i] = mTechLibNfcTypes[i];
616     }
617   }
618 
619   jfieldID f = NULL;
620 
621   f = e->GetFieldID(tag_cls, "mTechList", "[I");
622   e->SetObjectField(tag, f, techList.get());
623 
624   f = e->GetFieldID(tag_cls, "mTechHandles", "[I");
625   e->SetObjectField(tag, f, handleList.get());
626 
627   f = e->GetFieldID(tag_cls, "mTechLibNfcTypes", "[I");
628   e->SetObjectField(tag, f, typeList.get());
629 }
630 
631 /*******************************************************************************
632 **
633 ** Function:        fillNativeNfcTagMembers2
634 **
635 ** Description:     Fill NativeNfcTag's members: mConnectedTechIndex or
636 *mConnectedTechnology.
637 **                  The original Google's implementation is in
638 *set_target_pollBytes(
639 **                  in com_android_nfc_NativeNfcTag.cpp;
640 **                  e: JVM environment.
641 **                  tag_cls: Java NativeNfcTag class.
642 **                  tag: Java NativeNfcTag object.
643 **                  activationData: data from activation.
644 **
645 ** Returns:         None
646 **
647 *******************************************************************************/
fillNativeNfcTagMembers2(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED &)648 void NfcTag::fillNativeNfcTagMembers2(JNIEnv* e, jclass tag_cls, jobject tag,
649                                       tNFA_ACTIVATED& /*activationData*/) {
650   static const char fn[] = "NfcTag::fillNativeNfcTagMembers2";
651   LOG(DEBUG) << StringPrintf("%s", fn);
652   jfieldID f = e->GetFieldID(tag_cls, "mConnectedTechIndex", "I");
653   e->SetIntField(tag, f, (jint)0);
654 }
655 
656 /*******************************************************************************
657 **
658 ** Function:        fillNativeNfcTagMembers3
659 **
660 ** Description:     Fill NativeNfcTag's members: mTechPollBytes.
661 **                  The original Google's implementation is in
662 *set_target_pollBytes(
663 **                  in com_android_nfc_NativeNfcTag.cpp;
664 **                  e: JVM environment.
665 **                  tag_cls: Java NativeNfcTag class.
666 **                  tag: Java NativeNfcTag object.
667 **                  activationData: data from activation.
668 **
669 ** Returns:         None
670 **
671 *******************************************************************************/
fillNativeNfcTagMembers3(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED & activationData)672 void NfcTag::fillNativeNfcTagMembers3(JNIEnv* e, jclass tag_cls, jobject tag,
673                                       tNFA_ACTIVATED& activationData) {
674   static const char fn[] = "NfcTag::fillNativeNfcTagMembers3";
675   ScopedLocalRef<jbyteArray> pollBytes(e, e->NewByteArray(0));
676   ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(pollBytes.get()));
677   ScopedLocalRef<jobjectArray> techPollBytes(
678       e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0));
679   int len = 0;
680   if (mTechListTail == 0) {
681     sTechPollBytes =
682         reinterpret_cast<jobjectArray>(e->NewGlobalRef(techPollBytes.get()));
683   } else {
684     if (sTechPollBytes == NULL) {
685       sTechPollBytes =
686           reinterpret_cast<jobjectArray>(e->NewGlobalRef(techPollBytes.get()));
687     }
688     /* Add previously activated tag's tech poll bytes also in the
689     list for multiprotocol tag*/
690     jobject techPollBytesObject;
691     for (int j = 0; j < mTechListTail; j++) {
692       techPollBytesObject = e->GetObjectArrayElement(sTechPollBytes, j);
693       e->SetObjectArrayElement(techPollBytes.get(), j, techPollBytesObject);
694     }
695   }
696 
697   for (int i = mTechListTail; i < mNumTechList; i++) {
698     LOG(DEBUG) << StringPrintf("%s: index=%d; rf tech params mode=%u", fn, i,
699                                mTechParams[i].mode);
700     if (NFC_DISCOVERY_TYPE_POLL_A == mTechParams[i].mode ||
701         NFC_DISCOVERY_TYPE_LISTEN_A == mTechParams[i].mode) {
702       LOG(DEBUG) << StringPrintf("%s: tech A", fn);
703       pollBytes.reset(e->NewByteArray(2));
704       e->SetByteArrayRegion(pollBytes.get(), 0, 2,
705                             (jbyte*)mTechParams[i].param.pa.sens_res);
706     } else if (NFC_DISCOVERY_TYPE_POLL_B == mTechParams[i].mode ||
707                NFC_DISCOVERY_TYPE_POLL_B_PRIME == mTechParams[i].mode ||
708                NFC_DISCOVERY_TYPE_LISTEN_B == mTechParams[i].mode ||
709                NFC_DISCOVERY_TYPE_LISTEN_B_PRIME == mTechParams[i].mode) {
710       if (mTechList[i] ==
711           TARGET_TYPE_ISO14443_3B)  // is TagTechnology.NFC_B by Java API
712       {
713         /*****************
714         see NFC Forum Digital Protocol specification; section 5.6.2;
715         in SENSB_RES response, byte 6 through 9 is Application Data, byte 10-12
716         or 13 is Protocol Info; used by public API: NfcB.getApplicationData(),
717         NfcB.getProtocolInfo();
718         *****************/
719         LOG(DEBUG) << StringPrintf("%s: tech B; TARGET_TYPE_ISO14443_3B", fn);
720         len = mTechParams[i].param.pb.sensb_res_len;
721         if (len >= NFC_NFCID0_MAX_LEN) {
722           // subtract 4 bytes for NFCID0 at byte 2 through 5
723           len = len - NFC_NFCID0_MAX_LEN;
724         } else {
725           android_errorWriteLog(0x534e4554, "124940143");
726           LOG(ERROR) << StringPrintf("%s: sensb_res_len error", fn);
727           len = 0;
728         }
729         pollBytes.reset(e->NewByteArray(len));
730         e->SetByteArrayRegion(pollBytes.get(), 0, len,
731                               (jbyte*)(mTechParams[i].param.pb.sensb_res + 4));
732       } else {
733         pollBytes.reset(e->NewByteArray(0));
734       }
735     } else if (NFC_DISCOVERY_TYPE_POLL_F == mTechParams[i].mode ||
736                NFC_DISCOVERY_TYPE_LISTEN_F == mTechParams[i].mode) {
737       /****************
738       see NFC Forum Type 3 Tag Operation Specification; sections 2.3.2, 2.3.1.2;
739       see NFC Forum Digital Protocol Specification; sections 6.6.2;
740       PMm: manufacture parameter; 8 bytes;
741       System Code: 2 bytes;
742       ****************/
743       LOG(DEBUG) << StringPrintf("%s: tech F", fn);
744       uint8_t result[10];  // return result to NFC service
745       memset(result, 0, sizeof(result));
746       len = 10;
747 
748       /****
749       for (int ii = 0; ii < mTechParams [i].param.pf.sensf_res_len; ii++)
750       {
751           LOG(DEBUG) << StringPrintf("%s: tech F,
752       sendf_res[%d]=%d (0x%x)", fn, ii, mTechParams
753       [i].param.pf.sensf_res[ii],mTechParams [i].param.pf.sensf_res[ii]);
754       }
755       ***/
756       memcpy(result, mTechParams[i].param.pf.sensf_res + 8, 8);  // copy PMm
757       if (activationData.params.t3t.num_system_codes >
758           0)  // copy the first System Code
759       {
760         uint16_t systemCode = *(activationData.params.t3t.p_system_codes);
761         result[8] = (uint8_t)(systemCode >> 8);
762         result[9] = (uint8_t)systemCode;
763         LOG(DEBUG) << StringPrintf("%s: tech F; sys code=0x%X 0x%X", fn,
764                                    result[8], result[9]);
765       }
766       pollBytes.reset(e->NewByteArray(len));
767       e->SetByteArrayRegion(pollBytes.get(), 0, len, (jbyte*)result);
768     } else if (NFC_DISCOVERY_TYPE_POLL_V == mTechParams[i].mode ||
769                NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams[i].mode) {
770       LOG(DEBUG) << StringPrintf("%s: tech iso 15693", fn);
771       // iso 15693 response flags: 1 octet
772       // iso 15693 Data Structure Format Identifier (DSF ID): 1 octet
773       // used by public API: NfcV.getDsfId(), NfcV.getResponseFlags();
774       uint8_t data[2] = {activationData.params.i93.afi,
775                          activationData.params.i93.dsfid};
776       pollBytes.reset(e->NewByteArray(2));
777       e->SetByteArrayRegion(pollBytes.get(), 0, 2, (jbyte*)data);
778     } else {
779       LOG(ERROR) << StringPrintf("%s: tech unknown ????", fn);
780       pollBytes.reset(e->NewByteArray(0));
781     }  // switch: every type of technology
782     e->SetObjectArrayElement(techPollBytes.get(), i, pollBytes.get());
783   }  // for: every technology in the array
784   if (sTechPollBytes != NULL && mTechListTail != 0) {
785     /* Save tech poll bytes of all activated tags of a multiprotocol tag in
786      * sTechPollBytes*/
787     e->DeleteGlobalRef(sTechPollBytes);
788     sTechPollBytes =
789         reinterpret_cast<jobjectArray>(e->NewGlobalRef(techPollBytes.get()));
790   }
791   jfieldID f = e->GetFieldID(tag_cls, "mTechPollBytes", "[[B");
792   e->SetObjectField(tag, f, techPollBytes.get());
793 }
794 
795 /*******************************************************************************
796 **
797 ** Function:        fillNativeNfcTagMembers4
798 **
799 ** Description:     Fill NativeNfcTag's members: mTechActBytes.
800 **                  The original Google's implementation is in
801 *set_target_activationBytes()
802 **                  in com_android_nfc_NativeNfcTag.cpp;
803 **                  e: JVM environment.
804 **                  tag_cls: Java NativeNfcTag class.
805 **                  tag: Java NativeNfcTag object.
806 **                  activationData: data from activation.
807 **
808 ** Returns:         None
809 **
810 *******************************************************************************/
fillNativeNfcTagMembers4(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED & activationData)811 void NfcTag::fillNativeNfcTagMembers4(JNIEnv* e, jclass tag_cls, jobject tag,
812                                       tNFA_ACTIVATED& activationData) {
813   static const char fn[] = "NfcTag::fillNativeNfcTagMembers4";
814   ScopedLocalRef<jbyteArray> actBytes(e, e->NewByteArray(0));
815   ScopedLocalRef<jclass> byteArrayClass(e, e->GetObjectClass(actBytes.get()));
816   ScopedLocalRef<jobjectArray> techActBytes(
817       e, e->NewObjectArray(mNumTechList, byteArrayClass.get(), 0));
818   jobject gtechActBytesObject;
819   // Restore previously selected tag information from the gtechActBytes to
820   // techActBytes.
821   for (int j = 0; j < mTechListTail; j++) {
822     gtechActBytesObject = e->GetObjectArrayElement(gtechActBytes, j);
823     e->SetObjectArrayElement(techActBytes.get(), j, gtechActBytesObject);
824   }
825 
826   // merging sak for combi tag
827   if (activationData.activate_ntf.protocol &
828       (NFC_PROTOCOL_T1T | NFC_PROTOCOL_T2T | NFC_PROTOCOL_MIFARE |
829        NFC_PROTOCOL_ISO_DEP)) {
830     uint8_t merge_sak = 0;
831     for (int i = 0; i < mNumTechList; i++) {
832       merge_sak = (merge_sak | mTechParams[i].param.pa.sel_rsp);
833     }
834     for (int i = 0; i < mNumTechList; i++) {
835       if (TARGET_TYPE_ISO14443_3A == mTechList[i]) {
836         mTechParams[i].param.pa.sel_rsp = merge_sak;
837         actBytes.reset(e->NewByteArray(1));
838         e->SetByteArrayRegion(actBytes.get(), 0, 1,
839                               (jbyte*)&mTechParams[i].param.pa.sel_rsp);
840         e->SetObjectArrayElement(techActBytes.get(), i, actBytes.get());
841       }
842     }
843   }
844 
845   if (mTechListTail == 0) {
846     // Keep the backup of the selected tag information to restore back with
847     // multi selection.
848     gtechActBytes =
849         reinterpret_cast<jobjectArray>(e->NewGlobalRef(techActBytes.get()));
850   } else {
851     for (int j = 0; j < mTechListTail; j++) {
852       if (gtechActBytes == NULL) {
853         gtechActBytes =
854             reinterpret_cast<jobjectArray>(e->NewGlobalRef(techActBytes.get()));
855       }
856       gtechActBytesObject = e->GetObjectArrayElement(gtechActBytes, j);
857       e->SetObjectArrayElement(techActBytes.get(), j, gtechActBytesObject);
858     }
859   }
860 
861   for (int i = mTechListTail; i < mNumTechList; i++) {
862     LOG(DEBUG) << StringPrintf("%s: index=%d", fn, i);
863     if (NFC_PROTOCOL_T1T == mTechLibNfcTypes[i] ||
864         NFC_PROTOCOL_T2T == mTechLibNfcTypes[i]) {
865       if (mTechLibNfcTypes[i] == NFC_PROTOCOL_T1T)
866         LOG(DEBUG) << StringPrintf("%s: T1T; tech A", fn);
867       else if (mTechLibNfcTypes[i] == NFC_PROTOCOL_T2T)
868         LOG(DEBUG) << StringPrintf("%s: T2T; tech A", fn);
869       actBytes.reset(e->NewByteArray(1));
870       e->SetByteArrayRegion(actBytes.get(), 0, 1,
871                             (jbyte*)&mTechParams[i].param.pa.sel_rsp);
872     } else if (NFC_PROTOCOL_T3T == mTechLibNfcTypes[i]) {
873       // felica
874       LOG(DEBUG) << StringPrintf("%s: T3T; felica; tech F", fn);
875       // really, there is no data
876       actBytes.reset(e->NewByteArray(0));
877     } else if (NFC_PROTOCOL_MIFARE == mTechLibNfcTypes[i]) {
878       LOG(DEBUG) << StringPrintf("%s: Mifare Classic; tech A", fn);
879       actBytes.reset(e->NewByteArray(1));
880       e->SetByteArrayRegion(actBytes.get(), 0, 1,
881                             (jbyte*)&mTechParams[i].param.pa.sel_rsp);
882     } else if (NFC_PROTOCOL_ISO_DEP == mTechLibNfcTypes[i]) {
883       // t4t
884       if (mTechList[i] ==
885           TARGET_TYPE_ISO14443_4)  // is TagTechnology.ISO_DEP by Java API
886       {
887         if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) ||
888             (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A)) {
889           // see NFC Forum Digital Protocol specification, section 11.6.2, "RATS
890           // Response"; search for "historical bytes";  copy historical bytes
891           // into Java object;  the public API, IsoDep.getHistoricalBytes(),
892           // returns this data;
893           if (activationData.activate_ntf.intf_param.type ==
894               NFC_INTERFACE_ISO_DEP) {
895             tNFC_INTF_PA_ISO_DEP& pa_iso =
896                 activationData.activate_ntf.intf_param.intf_param.pa_iso;
897             LOG(DEBUG) << StringPrintf(
898                 "%s: T4T; ISO_DEP for tech A; copy historical bytes; len=%u",
899                 fn, pa_iso.his_byte_len);
900             actBytes.reset(e->NewByteArray(pa_iso.his_byte_len));
901             if (pa_iso.his_byte_len > 0)
902               e->SetByteArrayRegion(actBytes.get(), 0, pa_iso.his_byte_len,
903                                     (jbyte*)(pa_iso.his_byte));
904           } else {
905             LOG(ERROR) << StringPrintf(
906                 "%s: T4T; ISO_DEP for tech A; wrong interface=%u", fn,
907                 activationData.activate_ntf.intf_param.type);
908             actBytes.reset(e->NewByteArray(0));
909           }
910         } else if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B) ||
911                    (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B_PRIME) ||
912                    (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_B) ||
913                    (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_B_PRIME)) {
914           // see NFC Forum Digital Protocol specification, section 12.6.2,
915           // "ATTRIB Response";  copy higher-layer response bytes into Java
916           // object;  the public API, IsoDep.getHiLayerResponse(), returns this
917           // data;
918           if (activationData.activate_ntf.intf_param.type ==
919               NFC_INTERFACE_ISO_DEP) {
920             tNFC_INTF_PB_ISO_DEP& pb_iso =
921                 activationData.activate_ntf.intf_param.intf_param.pb_iso;
922             LOG(DEBUG) << StringPrintf(
923                 "%s: T4T; ISO_DEP for tech B; copy response bytes; len=%u", fn,
924                 pb_iso.hi_info_len);
925             actBytes.reset(e->NewByteArray(pb_iso.hi_info_len));
926             if (pb_iso.hi_info_len > 0)
927               e->SetByteArrayRegion(actBytes.get(), 0, pb_iso.hi_info_len,
928                                     (jbyte*)(pb_iso.hi_info));
929           } else {
930             LOG(ERROR) << StringPrintf(
931                 "%s: T4T; ISO_DEP for tech B; wrong interface=%u", fn,
932                 activationData.activate_ntf.intf_param.type);
933             actBytes.reset(e->NewByteArray(0));
934           }
935         }
936       } else if (mTechList[i] ==
937                  TARGET_TYPE_ISO14443_3A)  // is TagTechnology.NFC_A by Java API
938       {
939         LOG(DEBUG) << StringPrintf("%s: T4T; tech A", fn);
940         actBytes.reset(e->NewByteArray(1));
941         e->SetByteArrayRegion(actBytes.get(), 0, 1,
942                               (jbyte*)&mTechParams[i].param.pa.sel_rsp);
943       } else {
944         actBytes.reset(e->NewByteArray(0));
945       }
946     }  // case NFC_PROTOCOL_ISO_DEP: //t4t
947     else if (NFC_PROTOCOL_T5T == mTechLibNfcTypes[i]) {
948       LOG(DEBUG) << StringPrintf("%s: tech iso 15693", fn);
949       // iso 15693 response flags: 1 octet
950       // iso 15693 Data Structure Format Identifier (DSF ID): 1 octet
951       // used by public API: NfcV.getDsfId(), NfcV.getResponseFlags();
952       uint8_t data[2] = {activationData.params.i93.afi,
953                          activationData.params.i93.dsfid};
954       actBytes.reset(e->NewByteArray(2));
955       e->SetByteArrayRegion(actBytes.get(), 0, 2, (jbyte*)data);
956     } else {
957       if ((NCI_PROTOCOL_UNKNOWN == mTechLibNfcTypes[i]) &&
958           (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_B)) {
959         LOG(DEBUG) << StringPrintf("%s; Chinese Id Card - MBI = %02X", fn,
960                                    activationData.params.ci.mbi);
961         actBytes.reset(e->NewByteArray(1));
962         e->SetByteArrayRegion(actBytes.get(), 0, 1,
963                               (jbyte*)&activationData.params.ci.mbi);
964       } else {
965         LOG(DEBUG) << StringPrintf("%s: tech unknown ????", fn);
966         actBytes.reset(e->NewByteArray(0));
967       }
968     }
969     e->SetObjectArrayElement(techActBytes.get(), i, actBytes.get());
970   }  // for: every technology in the array of current selected tag
971   if (gtechActBytes != NULL && mTechListTail != 0) {
972     e->DeleteGlobalRef(gtechActBytes);
973     gtechActBytes =
974         reinterpret_cast<jobjectArray>(e->NewGlobalRef(techActBytes.get()));
975   }
976   jfieldID f = e->GetFieldID(tag_cls, "mTechActBytes", "[[B");
977   e->SetObjectField(tag, f, techActBytes.get());
978 }
979 
980 /*******************************************************************************
981 **
982 ** Function:        fillNativeNfcTagMembers5
983 **
984 ** Description:     Fill NativeNfcTag's members: mUid.
985 **                  The original Google's implementation is in
986 *nfc_jni_Discovery_notification_callback()
987 **                  in com_android_nfc_NativeNfcManager.cpp;
988 **                  e: JVM environment.
989 **                  tag_cls: Java NativeNfcTag class.
990 **                  tag: Java NativeNfcTag object.
991 **                  activationData: data from activation.
992 **
993 ** Returns:         None
994 **
995 *******************************************************************************/
fillNativeNfcTagMembers5(JNIEnv * e,jclass tag_cls,jobject tag,tNFA_ACTIVATED & activationData)996 void NfcTag::fillNativeNfcTagMembers5(JNIEnv* e, jclass tag_cls, jobject tag,
997                                       tNFA_ACTIVATED& activationData) {
998   static const char fn[] = "NfcTag::fillNativeNfcTagMembers5";
999   int len = 0;
1000   ScopedLocalRef<jbyteArray> uid(e, NULL);
1001 
1002   if (NFC_DISCOVERY_TYPE_POLL_KOVIO == mTechParams[0].mode) {
1003     LOG(DEBUG) << StringPrintf("%s: Kovio", fn);
1004     len = mTechParams[0].param.pk.uid_len;
1005     uid.reset(e->NewByteArray(len));
1006     e->SetByteArrayRegion(uid.get(), 0, len,
1007                           (jbyte*)&mTechParams[0].param.pk.uid);
1008   } else if (NFC_DISCOVERY_TYPE_POLL_A == mTechParams[0].mode ||
1009              NFC_DISCOVERY_TYPE_LISTEN_A == mTechParams[0].mode) {
1010     LOG(DEBUG) << StringPrintf("%s: tech A", fn);
1011     len = mTechParams[0].param.pa.nfcid1_len;
1012     uid.reset(e->NewByteArray(len));
1013     e->SetByteArrayRegion(uid.get(), 0, len,
1014                           (jbyte*)&mTechParams[0].param.pa.nfcid1);
1015     // a tag's NFCID1 can change dynamically at each activation;
1016     // only the first byte (0x08) is constant; a dynamic NFCID1's length
1017     // must be 4 bytes (see NFC Digitial Protocol,
1018     // section 4.7.2 SDD_RES Response, Requirements 20).
1019     mIsDynamicTagId = (mTechParams[0].param.pa.nfcid1_len == 4) &&
1020                       (mTechParams[0].param.pa.nfcid1[0] == 0x08);
1021   } else if (NFC_DISCOVERY_TYPE_POLL_B == mTechParams[0].mode ||
1022              NFC_DISCOVERY_TYPE_POLL_B_PRIME == mTechParams[0].mode ||
1023              NFC_DISCOVERY_TYPE_LISTEN_B == mTechParams[0].mode ||
1024              NFC_DISCOVERY_TYPE_LISTEN_B_PRIME == mTechParams[0].mode) {
1025     LOG(DEBUG) << StringPrintf("%s: tech B", fn);
1026     uid.reset(e->NewByteArray(NFC_NFCID0_MAX_LEN));
1027     e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID0_MAX_LEN,
1028                           (jbyte*)&mTechParams[0].param.pb.nfcid0);
1029   } else if (NFC_DISCOVERY_TYPE_POLL_F == mTechParams[0].mode ||
1030              NFC_DISCOVERY_TYPE_LISTEN_F == mTechParams[0].mode) {
1031     uid.reset(e->NewByteArray(NFC_NFCID2_LEN));
1032     e->SetByteArrayRegion(uid.get(), 0, NFC_NFCID2_LEN,
1033                           (jbyte*)&mTechParams[0].param.pf.nfcid2);
1034     LOG(DEBUG) << StringPrintf("%s: tech F", fn);
1035   } else if (NFC_DISCOVERY_TYPE_POLL_V == mTechParams[0].mode ||
1036              NFC_DISCOVERY_TYPE_LISTEN_ISO15693 == mTechParams[0].mode) {
1037     LOG(DEBUG) << StringPrintf("%s: tech iso 15693", fn);
1038     jbyte data[I93_UID_BYTE_LEN];               // 8 bytes
1039     for (int i = 0; i < I93_UID_BYTE_LEN; ++i)  // reverse the ID
1040       data[i] = activationData.params.i93.uid[I93_UID_BYTE_LEN - i - 1];
1041     uid.reset(e->NewByteArray(I93_UID_BYTE_LEN));
1042     e->SetByteArrayRegion(uid.get(), 0, I93_UID_BYTE_LEN, data);
1043   } else {
1044     LOG(ERROR) << StringPrintf("%s: tech unknown ????", fn);
1045     uid.reset(e->NewByteArray(0));
1046   }
1047   jfieldID f = e->GetFieldID(tag_cls, "mUid", "[B");
1048   e->SetObjectField(tag, f, uid.get());
1049   mTechListTail = mNumTechList;
1050   if (mNumDiscNtf == 0) mTechListTail = 0;
1051   LOG(DEBUG) << StringPrintf("%s;mTechListTail=%x", fn, mTechListTail);
1052 }
1053 
1054 /*******************************************************************************
1055 **
1056 ** Function:        resetTechnologies
1057 **
1058 ** Description:     Clear all data related to the technology, protocol of the
1059 *tag.
1060 **
1061 ** Returns:         None
1062 **
1063 *******************************************************************************/
resetTechnologies()1064 void NfcTag::resetTechnologies() {
1065   static const char fn[] = "NfcTag::resetTechnologies";
1066   LOG(DEBUG) << StringPrintf("%s", fn);
1067   mNumTechList = 0;
1068   mNumDiscNtf = 0;
1069   mNumDiscTechList = 0;
1070   mTechListTail = 0;
1071   mIsMultiProtocolTag = false;
1072   memset(mTechList, 0, sizeof(mTechList));
1073   memset(mTechHandles, 0, sizeof(mTechHandles));
1074   memset(mTechLibNfcTypes, 0, sizeof(mTechLibNfcTypes));
1075   memset(mTechParams, 0, sizeof(mTechParams));
1076   mIsDynamicTagId = false;
1077   mIsFelicaLite = false;
1078   resetAllTransceiveTimeouts();
1079 }
1080 
1081 /*******************************************************************************
1082 **
1083 ** Function:        selectFirstTag
1084 **
1085 ** Description:     When multiple tags are discovered, just select the first one
1086 *to activate.
1087 **
1088 ** Returns:         None
1089 **
1090 *******************************************************************************/
selectFirstTag()1091 void NfcTag::selectFirstTag() {
1092   static const char fn[] = "NfcTag::selectFirstTag";
1093   int foundIdx = -1;
1094   tNFA_INTF_TYPE rf_intf = NFA_INTERFACE_FRAME;
1095 
1096   for (int i = 0; i < mNumDiscTechList; i++) {
1097     LOG(DEBUG) << StringPrintf("%s: nfa target idx=%d h=0x%X; protocol=0x%X",
1098                                fn, i, mTechHandlesDiscData[i],
1099                                mTechLibNfcTypesDiscData[i]);
1100     if (mTechLibNfcTypesDiscData[i] != NFA_PROTOCOL_NFC_DEP) {
1101       sLastSelectedTagId = i;
1102       foundIdx = i;
1103       break;
1104     }
1105   }
1106 
1107   if (foundIdx != -1) {
1108     if (mTechLibNfcTypesDiscData[foundIdx] == NFA_PROTOCOL_ISO_DEP) {
1109       rf_intf = NFA_INTERFACE_ISO_DEP;
1110     } else if (mTechLibNfcTypesDiscData[foundIdx] == NFC_PROTOCOL_MIFARE) {
1111       rf_intf = NFA_INTERFACE_MIFARE;
1112     } else
1113       rf_intf = NFA_INTERFACE_FRAME;
1114 
1115     tNFA_STATUS stat = NFA_Select(mTechHandlesDiscData[foundIdx],
1116                                   mTechLibNfcTypesDiscData[foundIdx], rf_intf);
1117     if (stat != NFA_STATUS_OK)
1118       LOG(ERROR) << StringPrintf("%s: fail select; error=0x%X", fn, stat);
1119   } else
1120     LOG(ERROR) << StringPrintf("%s: only found NFC-DEP technology.", fn);
1121 }
1122 
1123 /*******************************************************************************
1124 **
1125 ** Function:        selectNextTagIfExists
1126 **
1127 ** Description:     When multiple tags are discovered, selects the next tag to
1128 **                  activate.
1129 **
1130 ** Returns:         None
1131 **
1132 *******************************************************************************/
selectNextTagIfExists()1133 void NfcTag::selectNextTagIfExists() {
1134   static const char fn[] = "NfcTag::selectNextTagIfExists";
1135   int foundIdx = -1;
1136   tNFA_INTF_TYPE rf_intf = NFA_INTERFACE_FRAME;
1137   tNFA_STATUS stat = NFA_STATUS_FAILED;
1138 
1139   if (mNumDiscNtf == 0) {
1140     return;
1141   }
1142   mNumDiscNtf--;
1143   LOG(DEBUG) << StringPrintf("%s: enter, mNumDiscTechList=%x", fn,
1144                              mNumDiscTechList);
1145   for (int i = 0; i < mNumDiscTechList; i++) {
1146     LOG(DEBUG) << StringPrintf("%s: nfa target idx=%d h=0x%X; protocol=0x%X",
1147                                fn, i, mTechHandlesDiscData[i],
1148                                mTechLibNfcTypesDiscData[i]);
1149     if (((mTechHandlesDiscData[sLastSelectedTagId] !=
1150           mTechHandlesDiscData[i]) ||
1151          (mTechLibNfcTypesDiscData[sLastSelectedTagId] !=
1152           mTechLibNfcTypesDiscData[i])) &&
1153         (mTechLibNfcTypesDiscData[i] != NFA_PROTOCOL_NFC_DEP)) {
1154       sLastSelectedTagId = i;
1155       foundIdx = i;
1156       break;
1157     }
1158   }
1159 
1160   if (foundIdx != -1) {
1161     if (mTechLibNfcTypesDiscData[foundIdx] == NFA_PROTOCOL_ISO_DEP) {
1162       rf_intf = NFA_INTERFACE_ISO_DEP;
1163     } else if (mTechLibNfcTypesDiscData[foundIdx] == NFC_PROTOCOL_MIFARE) {
1164       rf_intf = NFA_INTERFACE_MIFARE;
1165     } else {
1166       rf_intf = NFA_INTERFACE_FRAME;
1167     }
1168 
1169     stat = NFA_Select(mTechHandlesDiscData[foundIdx],
1170                       mTechLibNfcTypesDiscData[foundIdx], rf_intf);
1171     if (stat == NFA_STATUS_OK) {
1172       LOG(ERROR) << StringPrintf("%s: Select Success, wait for activated ntf",
1173                                  fn);
1174     } else {
1175       LOG(ERROR) << StringPrintf("%s: fail select; error=0x%X", fn, stat);
1176     }
1177   } else {
1178     LOG(ERROR) << StringPrintf("%s: only found NFC-DEP technology.", fn);
1179   }
1180 }
1181 
1182 /*******************************************************************************
1183 **
1184 ** Function:        getT1tMaxMessageSize
1185 **
1186 ** Description:     Get the maximum size (octet) that a T1T can store.
1187 **
1188 ** Returns:         Maximum size in octets.
1189 **
1190 *******************************************************************************/
getT1tMaxMessageSize()1191 int NfcTag::getT1tMaxMessageSize() {
1192   static const char fn[] = "NfcTag::getT1tMaxMessageSize";
1193 
1194   if (mProtocol != NFC_PROTOCOL_T1T) {
1195     LOG(ERROR) << StringPrintf("%s: wrong protocol %u", fn, mProtocol);
1196     return 0;
1197   }
1198   return mtT1tMaxMessageSize;
1199 }
1200 
1201 /*******************************************************************************
1202 **
1203 ** Function:        calculateT1tMaxMessageSize
1204 **
1205 ** Description:     Calculate type-1 tag's max message size based on header ROM
1206 *bytes.
1207 **                  activate: reference to activation data.
1208 **
1209 ** Returns:         None
1210 **
1211 *******************************************************************************/
calculateT1tMaxMessageSize(tNFA_ACTIVATED & activate)1212 void NfcTag::calculateT1tMaxMessageSize(tNFA_ACTIVATED& activate) {
1213   static const char fn[] = "NfcTag::calculateT1tMaxMessageSize";
1214 
1215   // make sure the tag is type-1
1216   if (activate.activate_ntf.protocol != NFC_PROTOCOL_T1T) {
1217     mtT1tMaxMessageSize = 0;
1218     return;
1219   }
1220 
1221   // examine the first byte of header ROM bytes
1222   switch (activate.params.t1t.hr[0]) {
1223     case RW_T1T_IS_TOPAZ96:
1224       mtT1tMaxMessageSize = 90;
1225       break;
1226     case RW_T1T_IS_TOPAZ512:
1227       mtT1tMaxMessageSize = 462;
1228       break;
1229     default:
1230       LOG(ERROR) << StringPrintf("%s: unknown T1T HR0=%u", fn,
1231                                  activate.params.t1t.hr[0]);
1232       mtT1tMaxMessageSize = 0;
1233       break;
1234   }
1235 }
1236 
1237 /*******************************************************************************
1238 **
1239 ** Function:        isNfcForumT2T
1240 **
1241 ** Description:     Whether tag is Nfc-Forum based and uses read command for
1242 **                  presence check.
1243 **
1244 ** Returns:         True if tag is isNfcForumT2T.
1245 **
1246 *******************************************************************************/
isNfcForumT2T()1247 bool NfcTag::isNfcForumT2T() {
1248   static const char fn[] = "NfcTag::isNfcForumT2T";
1249   bool retval = false;
1250 
1251   for (int i = 0; i < mNumTechList; i++) {
1252     if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) {
1253       if (mTechParams[i].param.pa.sel_rsp == 0) retval = true;
1254 
1255       break;
1256     }
1257   }
1258   LOG(DEBUG) << StringPrintf("%s: return=%u", fn, retval);
1259   return retval;
1260 }
1261 
1262 /*******************************************************************************
1263 **
1264 ** Function:        isMifareUltralight
1265 **
1266 ** Description:     Whether the currently activated tag is Mifare Ultralight.
1267 **
1268 ** Returns:         True if tag is Mifare Ultralight.
1269 **
1270 *******************************************************************************/
isMifareUltralight()1271 bool NfcTag::isMifareUltralight() {
1272   static const char fn[] = "NfcTag::isMifareUltralight";
1273   bool retval = false;
1274 
1275   for (int i = 0; i < mNumTechList; i++) {
1276     if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) {
1277       // see NFC Digital Protocol, section 4.6.3 (SENS_RES); section 4.8.2
1278       // (SEL_RES).  see "MF0ICU1 Functional specification MIFARE Ultralight",
1279       // Rev. 3.4 - 4 February 2008,  section 6.7.
1280       if ((mTechParams[i].param.pa.sens_res[0] == 0x44) &&
1281           (mTechParams[i].param.pa.sens_res[1] == 0) &&
1282           ((mTechParams[i].param.pa.sel_rsp == 0) ||
1283            (mTechParams[i].param.pa.sel_rsp == 0x04)) &&
1284           (mTechParams[i].param.pa.nfcid1[0] == 0x04)) {
1285         retval = true;
1286       }
1287       break;
1288     }
1289   }
1290   LOG(DEBUG) << StringPrintf("%s: return=%u", fn, retval);
1291   return retval;
1292 }
1293 
1294 /*******************************************************************************
1295 **
1296 ** Function:        isMifareDESFire
1297 **
1298 ** Description:     Whether the currently activated tag is Mifare DESFire.
1299 **
1300 ** Returns:         True if tag is Mifare DESFire.
1301 **
1302 *******************************************************************************/
isMifareDESFire()1303 bool NfcTag::isMifareDESFire() {
1304   static const char fn[] = "NfcTag::isMifareDESFire";
1305   bool retval = false;
1306 
1307   for (int i = 0; i < mNumTechList; i++) {
1308     if ((mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) ||
1309         (mTechParams[i].mode == NFC_DISCOVERY_TYPE_LISTEN_A)) {
1310       /* DESfire has one sak byte and 2 ATQA bytes */
1311       if ((mTechParams[i].param.pa.sens_res[0] == 0x44) &&
1312           (mTechParams[i].param.pa.sens_res[1] == 0x03) &&
1313           (mTechParams[i].param.pa.sel_rsp == 0x20)) {
1314         retval = true;
1315       }
1316       break;
1317     }
1318   }
1319 
1320   LOG(DEBUG) << StringPrintf("%s: return=%u", fn, retval);
1321   return retval;
1322 }
1323 
1324 /*******************************************************************************
1325 **
1326 ** Function:        isFelicaLite
1327 **
1328 ** Description:     Whether the currently activated tag is Felica Lite.
1329 **
1330 ** Returns:         True if tag is Felica Lite.
1331 **
1332 *******************************************************************************/
1333 
isFelicaLite()1334 bool NfcTag::isFelicaLite() { return mIsFelicaLite; }
1335 
1336 /*******************************************************************************
1337 **
1338 ** Function:        isT2tNackResponse
1339 **
1340 ** Description:     Whether the response is a T2T NACK response.
1341 **                  See NFC Digital Protocol Technical Specification
1342 *(2010-11-17).
1343 **                  Chapter 9 (Type 2 Tag Platform), section 9.6 (READ).
1344 **                  response: buffer contains T2T response.
1345 **                  responseLen: length of the response.
1346 **
1347 ** Returns:         True if the response is NACK
1348 **
1349 *******************************************************************************/
isT2tNackResponse(const uint8_t * response,uint32_t responseLen)1350 bool NfcTag::isT2tNackResponse(const uint8_t* response, uint32_t responseLen) {
1351   static const char fn[] = "NfcTag::isT2tNackResponse";
1352   bool isNack = false;
1353 
1354   if (responseLen == 1) {
1355     if (response[0] == 0xA)
1356       isNack = false;  // an ACK response, so definitely not a NACK
1357     else
1358       isNack = true;  // assume every value is a NACK
1359   }
1360   LOG(DEBUG) << StringPrintf("%s: return %u", fn, isNack);
1361   return isNack;
1362 }
1363 
1364 /*******************************************************************************
1365 **
1366 ** Function:        isNdefDetectionTimedOut
1367 **
1368 ** Description:     Whether NDEF-detection algorithm timed out.
1369 **
1370 ** Returns:         True if NDEF-detection algorithm timed out.
1371 **
1372 *******************************************************************************/
isNdefDetectionTimedOut()1373 bool NfcTag::isNdefDetectionTimedOut() { return mNdefDetectionTimedOut; }
1374 
1375 /*******************************************************************************
1376 **
1377 ** Function:        notifyTagDiscovered
1378 **
1379 ** Description:     Notify NFC service about tag discovery.
1380 **                  discovered: true if tag is discovered, false if tag is lost.
1381 **
1382 ** Returns:         None
1383 **
1384 *******************************************************************************/
notifyTagDiscovered(bool discovered)1385 void NfcTag::notifyTagDiscovered(bool discovered) {
1386   JNIEnv* e = NULL;
1387   ScopedAttach attach(mNativeData->vm, &e);
1388   if (e == NULL) {
1389     LOG(ERROR) << "jni env is null";
1390     return;
1391   }
1392   LOG(DEBUG) << StringPrintf("%s: %d", __func__, discovered);
1393   e->CallVoidMethod(mNativeData->manager,
1394                     android::gCachedNfcManagerNotifyTagDiscovered,
1395                     discovered);
1396   if (e->ExceptionCheck()) {
1397     e->ExceptionClear();
1398     LOG(ERROR) << StringPrintf("fail notify");
1399   }
1400 }
1401 
1402 /*******************************************************************************
1403 **
1404 ** Function:        connectionEventHandler
1405 **
1406 ** Description:     Handle connection-related events.
1407 **                  event: event code.
1408 **                  data: pointer to event data.
1409 **
1410 ** Returns:         None
1411 **
1412 *******************************************************************************/
connectionEventHandler(uint8_t event,tNFA_CONN_EVT_DATA * data)1413 void NfcTag::connectionEventHandler(uint8_t event, tNFA_CONN_EVT_DATA* data) {
1414   static const char fn[] = "NfcTag::connectionEventHandler";
1415 
1416   switch (event) {
1417     case NFA_DISC_RESULT_EVT: {
1418       tNFA_DISC_RESULT& disc_result = data->disc_result;
1419       if ((disc_result.status == NFA_STATUS_OK) && !mIsReselecting) {
1420         notifyTagDiscovered(true);
1421         discoverTechnologies(disc_result);
1422       }
1423     } break;
1424 
1425     case NFA_ACTIVATED_EVT:
1426       // Only do tag detection if we are polling and it is not 'EE Direct RF'
1427       // activation (which may happen when we are activated as a tag).
1428       if (data->activated.activate_ntf.rf_tech_param.mode <
1429               NCI_DISCOVERY_TYPE_LISTEN_A &&
1430           data->activated.activate_ntf.intf_param.type !=
1431               NFC_INTERFACE_EE_DIRECT_RF) {
1432         notifyTagDiscovered(true);
1433         tNFA_ACTIVATED& activated = data->activated;
1434         if (IsSameKovio(activated)) break;
1435         mIsActivated = true;
1436         mProtocol = activated.activate_ntf.protocol;
1437         calculateT1tMaxMessageSize(activated);
1438         if (!mIsReselecting) {
1439           discoverTechnologies(activated);
1440         }
1441         createNativeNfcTag(activated);
1442       }
1443       break;
1444 
1445     case NFA_DEACTIVATED_EVT:
1446       mIsActivated = false;
1447       mProtocol = NFC_PROTOCOL_UNKNOWN;
1448       if (!mIsReselecting) {
1449         resetTechnologies();
1450       }
1451       notifyTagDiscovered(false);
1452       break;
1453 
1454     case NFA_READ_CPLT_EVT: {
1455       SyncEventGuard g(mReadCompleteEvent);
1456       mReadCompletedStatus = data->status;
1457       mNdefDetectionTimedOut = data->status != NFA_STATUS_OK;
1458       if (mNdefDetectionTimedOut)
1459         LOG(ERROR) << StringPrintf("%s: NDEF detection timed out", fn);
1460       mReadCompleteEvent.notifyOne();
1461     } break;
1462 
1463     case NFA_NDEF_DETECT_EVT: {
1464       tNFA_NDEF_DETECT& ndef_detect = data->ndef_detect;
1465       mNdefDetectionTimedOut = ndef_detect.status == NFA_STATUS_TIMEOUT;
1466       if (mNdefDetectionTimedOut)
1467         LOG(ERROR) << StringPrintf("%s: NDEF detection timed out", fn);
1468     }
1469   }
1470 }
1471 
1472 /*******************************************************************************
1473 **
1474 ** Function         setActive
1475 **
1476 ** Description      Sets the active state for the object
1477 **
1478 ** Returns          None.
1479 **
1480 *******************************************************************************/
setActive(bool active)1481 void NfcTag::setActive(bool active) { mIsActivated = active; }
1482 
1483 /*******************************************************************************
1484 **
1485 ** Function:        isDynamicTagId
1486 **
1487 ** Description:     Whether a tag has a dynamic tag ID.
1488 **
1489 ** Returns:         True if ID is dynamic.
1490 **
1491 *******************************************************************************/
isDynamicTagId()1492 bool NfcTag::isDynamicTagId() {
1493   return mIsDynamicTagId &&
1494          (mTechList[0] == TARGET_TYPE_ISO14443_4) &&  // type-4 tag
1495          (mTechList[1] == TARGET_TYPE_ISO14443_3A);   // tech A
1496 }
1497 
1498 /*******************************************************************************
1499 **
1500 ** Function:        resetAllTransceiveTimeouts
1501 **
1502 ** Description:     Reset all timeouts for all technologies to default values.
1503 **
1504 ** Returns:         none
1505 **
1506 *******************************************************************************/
resetAllTransceiveTimeouts()1507 void NfcTag::resetAllTransceiveTimeouts() {
1508   mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_3A] = 618;   // NfcA
1509   mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_3B] = 1000;  // NfcB
1510   mTechnologyTimeoutsTable[TARGET_TYPE_ISO14443_4] = 618;    // ISO-DEP
1511   mTechnologyTimeoutsTable[TARGET_TYPE_FELICA] = 255;        // Felica
1512   mTechnologyTimeoutsTable[TARGET_TYPE_V] = 1000;            // NfcV
1513   mTechnologyTimeoutsTable[TARGET_TYPE_NDEF] = 1000;
1514   mTechnologyTimeoutsTable[TARGET_TYPE_NDEF_FORMATABLE] = 1000;
1515   mTechnologyTimeoutsTable[TARGET_TYPE_MIFARE_CLASSIC] = 618;  // MifareClassic
1516   mTechnologyTimeoutsTable[TARGET_TYPE_MIFARE_UL] = 618;  // MifareUltralight
1517   mTechnologyTimeoutsTable[TARGET_TYPE_KOVIO_BARCODE] = 1000;  // NfcBarcode
1518 }
1519 
1520 /*******************************************************************************
1521 **
1522 ** Function:        getTransceiveTimeout
1523 **
1524 ** Description:     Get the timeout value for one technology.
1525 **                  techId: one of the values in TARGET_TYPE_* defined in
1526 *NfcJniUtil.h
1527 **
1528 ** Returns:         Timeout value in millisecond.
1529 **
1530 *******************************************************************************/
getTransceiveTimeout(int techId)1531 int NfcTag::getTransceiveTimeout(int techId) {
1532   static const char fn[] = "NfcTag::getTransceiveTimeout";
1533   int retval = 1000;
1534   if ((techId > 0) && (techId < (int)mTechnologyTimeoutsTable.size()))
1535     retval = mTechnologyTimeoutsTable[techId];
1536   else
1537     LOG(ERROR) << StringPrintf("%s: invalid tech=%d", fn, techId);
1538   return retval;
1539 }
1540 
1541 /*******************************************************************************
1542 **
1543 ** Function:        setTransceiveTimeout
1544 **
1545 ** Description:     Set the timeout value for one technology.
1546 **                  techId: one of the values in TARGET_TYPE_* defined in
1547 *NfcJniUtil.h
1548 **                  timeout: timeout value in millisecond.
1549 **
1550 ** Returns:         Timeout value.
1551 **
1552 *******************************************************************************/
setTransceiveTimeout(int techId,int timeout)1553 void NfcTag::setTransceiveTimeout(int techId, int timeout) {
1554   static const char fn[] = "NfcTag::setTransceiveTimeout";
1555   if ((techId >= 0) && (techId < (int)mTechnologyTimeoutsTable.size()))
1556     mTechnologyTimeoutsTable[techId] = timeout;
1557   else
1558     LOG(ERROR) << StringPrintf("%s: invalid tech=%d", fn, techId);
1559 }
1560 
1561 /*******************************************************************************
1562 **
1563 ** Function:        getPresenceCheckAlgorithm
1564 **
1565 ** Description:     Get presence-check algorithm from .conf file.
1566 **
1567 ** Returns:         Presence-check algorithm.
1568 **
1569 *******************************************************************************/
getPresenceCheckAlgorithm()1570 tNFA_RW_PRES_CHK_OPTION NfcTag::getPresenceCheckAlgorithm() {
1571   return mPresenceCheckAlgorithm;
1572 }
1573 
1574 /*******************************************************************************
1575 **
1576 ** Function:        isInfineonMyDMove
1577 **
1578 ** Description:     Whether the currently activated tag is Infineon My-D Move.
1579 **
1580 ** Returns:         True if tag is Infineon My-D Move.
1581 **
1582 *******************************************************************************/
isInfineonMyDMove()1583 bool NfcTag::isInfineonMyDMove() {
1584   static const char fn[] = "NfcTag::isInfineonMyDMove";
1585   bool retval = false;
1586 
1587   for (int i = 0; i < mNumTechList; i++) {
1588     if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) {
1589       // see Infineon my-d move, my-d move NFC, SLE 66R01P, SLE 66R01PN,
1590       // Short Product Information, 2011-11-24, section 3.5
1591       if (mTechParams[i].param.pa.nfcid1[0] == 0x05) {
1592         uint8_t highNibble = mTechParams[i].param.pa.nfcid1[1] & 0xF0;
1593         if (highNibble == 0x30) retval = true;
1594       }
1595       break;
1596     }
1597   }
1598   LOG(DEBUG) << StringPrintf("%s: return=%u", fn, retval);
1599   return retval;
1600 }
1601 
1602 /*******************************************************************************
1603 **
1604 ** Function:        isKovioType2Tag
1605 **
1606 ** Description:     Whether the currently activated tag is Kovio Type-2 tag.
1607 **
1608 ** Returns:         True if tag is Kovio Type-2 tag.
1609 **
1610 *******************************************************************************/
isKovioType2Tag()1611 bool NfcTag::isKovioType2Tag() {
1612   static const char fn[] = "NfcTag::isKovioType2Tag";
1613   bool retval = false;
1614 
1615   for (int i = 0; i < mNumTechList; i++) {
1616     if (mTechParams[i].mode == NFC_DISCOVERY_TYPE_POLL_A) {
1617       // Kovio 2Kb RFID Tag, Functional Specification,
1618       // March 2, 2012, v2.0, section 8.3.
1619       if (mTechParams[i].param.pa.nfcid1[0] == 0x37) retval = true;
1620       break;
1621     }
1622   }
1623   LOG(DEBUG) << StringPrintf("%s: return=%u", fn, retval);
1624   return retval;
1625 }
1626 
1627 /*******************************************************************************
1628 **
1629 ** Function:        setMultiProtocolTagSupport
1630 **
1631 ** Description:     Update mIsMultiProtocolTag
1632 **
1633 ** Returns:         None
1634 **
1635 *******************************************************************************/
1636 
setMultiProtocolTagSupport(bool isMultiProtocolSupported)1637 void NfcTag::setMultiProtocolTagSupport(bool isMultiProtocolSupported) {
1638   mIsMultiProtocolTag = isMultiProtocolSupported;
1639 }
1640 
1641 /*******************************************************************************
1642 **
1643 ** Function:        setNumDiscNtf
1644 **
1645 ** Description:     Update number of Discovery NTF received
1646 **
1647 ** Returns:         None
1648 **
1649 *******************************************************************************/
setNumDiscNtf(int numDiscNtfValue)1650 void NfcTag::setNumDiscNtf(int numDiscNtfValue) {
1651   if (numDiscNtfValue < MAX_NUM_TECHNOLOGY) {
1652     mNumDiscNtf = numDiscNtfValue;
1653   }
1654 }
1655 
1656 /*******************************************************************************
1657 **
1658 ** Function:        getNumDiscNtf
1659 **
1660 ** Description:     number of discovery notifications received from NFCC after
1661 **                  last RF DISCOVERY state
1662 **
1663 ** Returns:         number of discovery notifications received from NFCC
1664 **
1665 *******************************************************************************/
getNumDiscNtf()1666 int NfcTag::getNumDiscNtf() { return mNumDiscNtf; }
1667 
1668 /*******************************************************************************
1669 **
1670 ** Function:        isReselecting
1671 **
1672 ** Description:     used to check if a reSelect() procedure is ongoing
1673 **
1674 ** Returns:         value of mIsReselecting variable
1675 **
1676 *******************************************************************************/
isReselecting()1677 bool NfcTag::isReselecting() { return mIsReselecting; }
1678 
1679 /*******************************************************************************
1680 **
1681 ** Function:        setReselect
1682 **
1683 ** Description:     Called by JNI to indicate status of reSelect() procedure
1684 **
1685 ** Returns:
1686 **
1687 *******************************************************************************/
setReselect(bool isReselecting)1688 void NfcTag::setReselect(bool isReselecting) { mIsReselecting = isReselecting; }
1689