1 /* 2 * Copyright (C) 2010 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 package com.android.nfc.dhimpl; 18 19 import static com.android.nfc.NfcStatsLog.NFC_PROPRIETARY_CAPABILITIES_REPORTED__PASSIVE_OBSERVE_MODE__MODE_UNKNOWN; 20 import static com.android.nfc.NfcStatsLog.NFC_PROPRIETARY_CAPABILITIES_REPORTED__PASSIVE_OBSERVE_MODE__SUPPORT_WITHOUT_RF_DEACTIVATION; 21 import static com.android.nfc.NfcStatsLog.NFC_PROPRIETARY_CAPABILITIES_REPORTED__PASSIVE_OBSERVE_MODE__SUPPORT_WITH_RF_DEACTIVATION; 22 23 import android.content.Context; 24 import android.nfc.cardemulation.PollingFrame; 25 import android.nfc.tech.Ndef; 26 import android.nfc.tech.TagTechnology; 27 import android.os.Bundle; 28 import android.os.Trace; 29 import android.sysprop.NfcProperties; 30 import android.util.Log; 31 32 import com.android.nfc.DeviceHost; 33 import com.android.nfc.ExitFrame; 34 import com.android.nfc.NfcDiscoveryParameters; 35 import com.android.nfc.NfcProprietaryCaps; 36 import com.android.nfc.NfcService; 37 import com.android.nfc.NfcStatsLog; 38 import com.android.nfc.NfcVendorNciResponse; 39 40 import java.io.FileDescriptor; 41 import java.io.PrintWriter; 42 import java.nio.ByteBuffer; 43 import java.nio.ByteOrder; 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.HashMap; 47 import java.util.HexFormat; 48 import java.util.Iterator; 49 import java.util.Map; 50 51 /** Native interface to the NFC Manager functions */ 52 public class NativeNfcManager implements DeviceHost { 53 private static final String TAG = "NativeNfcManager"; 54 static final String PREF = "NciDeviceHost"; 55 56 static final String DRIVER_NAME = "android-nci"; 57 58 /* Native structure */ 59 private long mNative; 60 61 private int mIsoDepMaxTransceiveLength; 62 private final DeviceHostListener mListener; 63 private final NativeT4tNfceeManager mT4tNfceeMgr; 64 private final Context mContext; 65 66 private final Object mLock = new Object(); 67 private final HashMap<Integer, byte[]> mT3tIdentifiers = new HashMap<Integer, byte[]>(); 68 private NfcProprietaryCaps mProprietaryCaps = null; 69 private static final int MIN_POLLING_FRAME_TLV_SIZE = 5; 70 private static final int TAG_FIELD_CHANGE = 0; 71 private static final int TAG_NFC_A = 1; 72 private static final int TAG_NFC_B = 2; 73 private static final int TAG_NFC_F = 3; 74 private static final int TAG_NFC_UNKNOWN = 7; 75 private static final int NCI_HEADER_MIN_LEN = 3; 76 private static final int NCI_GID_INDEX = 0; 77 private static final int NCI_OID_INDEX = 1; 78 private static final int OP_CODE_INDEX = 3; 79 80 private static final int OBSERVE_MODE_SUSPENDED_FRAME_TYPE_A = 0x00; 81 private static final int OBSERVE_MODE_SUSPENDED_FRAME_TYPE_B = 0x01; 82 loadLibrary()83 private void loadLibrary() { 84 System.loadLibrary("nfc_nci_jni"); 85 } 86 87 private static NativeNfcManager sInstance; 88 getInstance()89 public static NativeNfcManager getInstance() { 90 if (sInstance == null) throw new IllegalStateException("NativeNfcManager instance null"); 91 return sInstance; 92 } 93 NativeNfcManager(Context context, DeviceHostListener listener)94 public NativeNfcManager(Context context, DeviceHostListener listener) { 95 mListener = listener; 96 loadLibrary(); 97 initializeNativeStructure(); 98 mContext = context; 99 mT4tNfceeMgr = new NativeT4tNfceeManager(); 100 sInstance = this; 101 } 102 initializeNativeStructure()103 public native boolean initializeNativeStructure(); 104 doDownload()105 private native boolean doDownload(); 106 107 @Override checkFirmware()108 public boolean checkFirmware() { 109 return doDownload(); 110 } 111 doInitialize()112 private native boolean doInitialize(); 113 getIsoDepMaxTransceiveLength()114 private native int getIsoDepMaxTransceiveLength(); 115 116 @Override initialize()117 public boolean initialize() { 118 boolean ret = doInitialize(); 119 if (ret && isProprietaryGetCapsSupported()) { 120 mProprietaryCaps = NfcProprietaryCaps.createFromByteArray(getProprietaryCaps()); 121 Log.i(TAG, "initialize: mProprietaryCaps: " + mProprietaryCaps); 122 logProprietaryCaps(mProprietaryCaps); 123 } 124 mIsoDepMaxTransceiveLength = getIsoDepMaxTransceiveLength(); 125 return ret; 126 } 127 isObserveModeSupportedWithoutRfDeactivation()128 boolean isObserveModeSupportedWithoutRfDeactivation() { 129 if (!com.android.nfc.flags.Flags.observeModeWithoutRf()) { 130 return false; 131 } 132 return mProprietaryCaps != null && 133 mProprietaryCaps.getPassiveObserveMode() == 134 NfcProprietaryCaps.PassiveObserveMode.SUPPORT_WITHOUT_RF_DEACTIVATION; 135 } 136 doSetPartialInitMode(int mode)137 private native void doSetPartialInitMode(int mode); 138 139 @Override setPartialInitMode(int mode)140 public void setPartialInitMode(int mode) { 141 doSetPartialInitMode(mode); 142 } 143 doEnableDtaMode()144 private native void doEnableDtaMode(); 145 146 @Override enableDtaMode()147 public void enableDtaMode() { 148 doEnableDtaMode(); 149 } 150 doDisableDtaMode()151 private native void doDisableDtaMode(); 152 153 @Override disableDtaMode()154 public void disableDtaMode() { 155 Log.d(TAG, "disableDtaMode:"); 156 doDisableDtaMode(); 157 } 158 doFactoryReset()159 private native void doFactoryReset(); 160 161 @Override factoryReset()162 public void factoryReset() { 163 doFactoryReset(); 164 } 165 doSetPowerSavingMode(boolean flag)166 private native boolean doSetPowerSavingMode(boolean flag); 167 168 @Override setPowerSavingMode(boolean flag)169 public boolean setPowerSavingMode(boolean flag) { 170 return doSetPowerSavingMode(flag); 171 } 172 doShutdown()173 private native void doShutdown(); 174 175 @Override shutdown()176 public void shutdown() { 177 doShutdown(); 178 } 179 doDeinitialize()180 private native boolean doDeinitialize(); 181 182 @Override deinitialize()183 public boolean deinitialize() { 184 return doDeinitialize(); 185 } 186 187 @Override getName()188 public String getName() { 189 return DRIVER_NAME; 190 } 191 192 @Override sendRawFrame(byte[] data)193 public native boolean sendRawFrame(byte[] data); 194 195 @Override routeAid(byte[] aid, int route, int aidInfo, int power)196 public native boolean routeAid(byte[] aid, int route, int aidInfo, int power); 197 198 @Override unrouteAid(byte[] aid)199 public native boolean unrouteAid(byte[] aid); 200 201 @Override commitRouting()202 public native int commitRouting(); 203 doRegisterT3tIdentifier(byte[] t3tIdentifier)204 public native int doRegisterT3tIdentifier(byte[] t3tIdentifier); 205 206 /** 207 * Injects a NTF to the HAL. 208 * 209 * This is only used for testing. 210 */ injectNtf(byte[] data)211 public native void injectNtf(byte[] data); 212 isProprietaryGetCapsSupported()213 public boolean isProprietaryGetCapsSupported() { 214 return mContext.getResources() 215 .getBoolean(com.android.nfc.R.bool.nfc_proprietary_getcaps_supported) 216 && NfcProperties.get_caps_supported().orElse(true); 217 } 218 219 @Override isObserveModeSupported()220 public boolean isObserveModeSupported() { 221 // Check if the device overlay and HAL capabilities indicate that observe 222 // mode is supported. 223 if (!mContext.getResources().getBoolean( 224 com.android.nfc.R.bool.nfc_observe_mode_supported)) { 225 return false; 226 } 227 if (!NfcProperties.observe_mode_supported().orElse(true)) { 228 return false; 229 } 230 if (com.android.nfc.flags.Flags.observeModeWithoutRf()) { 231 if (isProprietaryGetCapsSupported()) { 232 return isObserveModeSupportedWithoutRfDeactivation(); 233 } 234 return false; 235 } else { 236 if (isProprietaryGetCapsSupported()) { 237 return isObserveModeSupportedCaps(mProprietaryCaps); 238 } 239 return true; 240 } 241 } 242 243 @Override isFirmwareExitFramesSupported()244 public boolean isFirmwareExitFramesSupported() { 245 if (!com.android.nfc.flags.Flags.exitFrames()) { 246 return false; 247 } 248 if (isProprietaryGetCapsSupported()) { 249 return mProprietaryCaps != null 250 && mProprietaryCaps.isAutotransactPollingLoopFilterSupported() 251 && mProprietaryCaps.getNumberOfExitFramesSupported() > 0; 252 } 253 return false; 254 } 255 256 @Override setObserveMode(boolean enabled)257 public native boolean setObserveMode(boolean enabled); 258 259 @Override isObserveModeEnabled()260 public native boolean isObserveModeEnabled(); 261 262 @Override getNumberOfFirmwareExitFramesSupported()263 public int getNumberOfFirmwareExitFramesSupported() { 264 return mProprietaryCaps != null ? mProprietaryCaps.getNumberOfExitFramesSupported() : -1; 265 } 266 267 @Override setFirmwareExitFrameTable(ExitFrame[] exitFrames, byte[] timeoutMs)268 public native boolean setFirmwareExitFrameTable(ExitFrame[] exitFrames, byte[] timeoutMs); 269 270 @Override getT4TNfceePowerState()271 public int getT4TNfceePowerState() { 272 return mT4tNfceeMgr.getT4TNfceePowerState(); 273 } 274 275 @Override getNdefNfceeRouteId()276 public int getNdefNfceeRouteId() { 277 return mT4tNfceeMgr.getNdefNfceeRouteId(); 278 } 279 280 @Override isNdefNfceefeatureEnabled()281 public boolean isNdefNfceefeatureEnabled() { 282 return mT4tNfceeMgr.isNdefNfceefeatureEnabled(); 283 } 284 285 @Override doWriteData(byte[] fileId, byte[] data)286 public int doWriteData(byte[] fileId, byte[] data) { 287 return mT4tNfceeMgr.doWriteData(fileId, data); 288 } 289 290 @Override doReadData(byte[] fileId)291 public byte[] doReadData(byte[] fileId) { 292 return mT4tNfceeMgr.doReadData(fileId); 293 } 294 295 @Override doClearNdefData()296 public boolean doClearNdefData() { 297 return mT4tNfceeMgr.doClearNdefData(); 298 } 299 300 @Override isNdefOperationOngoing()301 public boolean isNdefOperationOngoing() { 302 return mT4tNfceeMgr.isNdefOperationOngoing(); 303 } 304 305 @Override isNdefNfceeEmulationSupported()306 public boolean isNdefNfceeEmulationSupported() { 307 return mT4tNfceeMgr.isNdefNfceeEmulationSupported(); 308 } 309 310 @Override registerT3tIdentifier(byte[] t3tIdentifier)311 public void registerT3tIdentifier(byte[] t3tIdentifier) { 312 synchronized (mLock) { 313 int handle = doRegisterT3tIdentifier(t3tIdentifier); 314 if (handle != 0xffff) { 315 mT3tIdentifiers.put(Integer.valueOf(handle), t3tIdentifier); 316 } 317 } 318 } 319 doDeregisterT3tIdentifier(int handle)320 public native void doDeregisterT3tIdentifier(int handle); 321 322 @Override deregisterT3tIdentifier(byte[] t3tIdentifier)323 public void deregisterT3tIdentifier(byte[] t3tIdentifier) { 324 synchronized (mLock) { 325 Iterator<Integer> it = mT3tIdentifiers.keySet().iterator(); 326 while (it.hasNext()) { 327 int handle = it.next().intValue(); 328 byte[] value = mT3tIdentifiers.get(handle); 329 if (Arrays.equals(value, t3tIdentifier)) { 330 doDeregisterT3tIdentifier(handle); 331 mT3tIdentifiers.remove(handle); 332 break; 333 } 334 } 335 } 336 } 337 338 @Override clearT3tIdentifiersCache()339 public void clearT3tIdentifiersCache() { 340 synchronized (mLock) { 341 mT3tIdentifiers.clear(); 342 } 343 } 344 345 @Override getLfT3tMax()346 public native int getLfT3tMax(); 347 348 @Override doSetScreenState(int screen_state_mask, boolean alwaysPoll)349 public native void doSetScreenState(int screen_state_mask, boolean alwaysPoll); 350 351 @Override getNciVersion()352 public native int getNciVersion(); 353 doEnableDiscovery( int techMask, boolean enableLowPowerPolling, boolean enableReaderMode, boolean enableHostRouting, byte[] techAPollingLoopAnnotation, boolean restart)354 private native void doEnableDiscovery( 355 int techMask, 356 boolean enableLowPowerPolling, 357 boolean enableReaderMode, 358 boolean enableHostRouting, 359 byte[] techAPollingLoopAnnotation, 360 boolean restart); 361 362 363 @Override enableDiscovery(NfcDiscoveryParameters params, boolean restart)364 public void enableDiscovery(NfcDiscoveryParameters params, boolean restart) { 365 doEnableDiscovery( 366 params.getTechMask(), 367 params.shouldEnableLowPowerDiscovery(), 368 params.shouldEnableReaderMode(), 369 params.shouldEnableHostRouting(), 370 params.techAPollingLoopAnnotation(), 371 restart); 372 } 373 374 @Override disableDiscovery()375 public native void disableDiscovery(); 376 doResetTimeouts()377 private native void doResetTimeouts(); 378 379 @Override resetTimeouts()380 public void resetTimeouts() { 381 doResetTimeouts(); 382 } 383 384 @Override doAbort(String msg)385 public native void doAbort(String msg); 386 doSetTimeout(int tech, int timeout)387 private native boolean doSetTimeout(int tech, int timeout); 388 389 @Override setTimeout(int tech, int timeout)390 public boolean setTimeout(int tech, int timeout) { 391 return doSetTimeout(tech, timeout); 392 } 393 doGetTimeout(int tech)394 private native int doGetTimeout(int tech); 395 396 @Override getTimeout(int tech)397 public int getTimeout(int tech) { 398 return doGetTimeout(tech); 399 } 400 401 @Override canMakeReadOnly(int ndefType)402 public boolean canMakeReadOnly(int ndefType) { 403 return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2); 404 } 405 406 @Override getMaxTransceiveLength(int technology)407 public int getMaxTransceiveLength(int technology) { 408 switch (technology) { 409 case (TagTechnology.NFC_A): 410 case (TagTechnology.MIFARE_CLASSIC): 411 case (TagTechnology.MIFARE_ULTRALIGHT): 412 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 413 case (TagTechnology.NFC_B): 414 ///////////////////////////////////////////////////////////////// 415 // Broadcom: Since BCM2079x supports this, set NfcB max size. 416 // return 0; // PN544 does not support transceive of raw NfcB 417 return 253; // PN544 does not support transceive of raw NfcB 418 case (TagTechnology.NFC_V): 419 return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC 420 case (TagTechnology.ISO_DEP): 421 return mIsoDepMaxTransceiveLength; 422 case (TagTechnology.NFC_F): 423 return 255; 424 default: 425 return 0; 426 } 427 } 428 getAidTableSize()429 public native int getAidTableSize(); 430 431 @Override getExtendedLengthApdusSupported()432 public boolean getExtendedLengthApdusSupported() { 433 /* 261 is the default size if extended length frames aren't supported */ 434 if (getMaxTransceiveLength(TagTechnology.ISO_DEP) > 261) return true; 435 return false; 436 } 437 doDump(FileDescriptor fd)438 private native void doDump(FileDescriptor fd); 439 440 @Override dump(PrintWriter pw, FileDescriptor fd)441 public void dump(PrintWriter pw, FileDescriptor fd) { 442 pw.println("Native Proprietary Caps=" + mProprietaryCaps); 443 doDump(fd); 444 } 445 doRestartRfDiscovery()446 private native void doRestartRfDiscovery(); 447 448 @Override restartRfDiscovery()449 public void restartRfDiscovery() { 450 doRestartRfDiscovery(); 451 } 452 doSetNfcSecure(boolean enable)453 private native boolean doSetNfcSecure(boolean enable); 454 455 @Override setNfcSecure(boolean enable)456 public boolean setNfcSecure(boolean enable) { 457 return doSetNfcSecure(enable); 458 } 459 doStartStopPolling(boolean start)460 private native void doStartStopPolling(boolean start); 461 462 @Override startStopPolling(boolean start)463 public void startStopPolling(boolean start) { 464 doStartStopPolling(start); 465 } 466 doSetNfceePowerAndLinkCtrl(boolean enable)467 private native void doSetNfceePowerAndLinkCtrl(boolean enable); 468 469 @Override setNfceePowerAndLinkCtrl(boolean enable)470 public void setNfceePowerAndLinkCtrl(boolean enable) { 471 doSetNfceePowerAndLinkCtrl(enable); 472 } 473 474 @Override getRoutingTable()475 public native byte[] getRoutingTable(); 476 477 @Override getMaxRoutingTableSize()478 public native int getMaxRoutingTableSize(); 479 isMultiTag()480 public native boolean isMultiTag(); 481 482 @Override dofetchActiveNfceeList()483 public native Map<String, Integer> dofetchActiveNfceeList(); 484 nativeSendRawVendorCmd( int mt, int gid, int oid, byte[] payload)485 private native NfcVendorNciResponse nativeSendRawVendorCmd( 486 int mt, int gid, int oid, byte[] payload); 487 488 @Override sendRawVendorCmd(int mt, int gid, int oid, byte[] payload)489 public NfcVendorNciResponse sendRawVendorCmd(int mt, int gid, int oid, byte[] payload) { 490 NfcVendorNciResponse res= nativeSendRawVendorCmd(mt, gid, oid, payload); 491 return res; 492 } 493 494 /** Notifies Ndef Message (TODO: rename into notifyTargetDiscovered) */ notifyNdefMessageListeners(NativeNfcTag tag)495 private void notifyNdefMessageListeners(NativeNfcTag tag) { 496 mListener.onRemoteEndpointDiscovered(tag); 497 } 498 notifyHostEmuActivated(int technology)499 private void notifyHostEmuActivated(int technology) { 500 mListener.onHostCardEmulationActivated(technology); 501 } 502 notifyHostEmuData(int technology, byte[] data)503 private void notifyHostEmuData(int technology, byte[] data) { 504 mListener.onHostCardEmulationData(technology, data); 505 } 506 notifyHostEmuDeactivated(int technology)507 private void notifyHostEmuDeactivated(int technology) { 508 mListener.onHostCardEmulationDeactivated(technology); 509 } 510 notifyRfFieldActivated()511 private void notifyRfFieldActivated() { 512 mListener.onRemoteFieldActivated(); 513 } 514 notifyRfFieldDeactivated()515 private void notifyRfFieldDeactivated() { 516 mListener.onRemoteFieldDeactivated(); 517 } 518 notifyTransactionListeners(byte[] aid, byte[] data, String evtSrc)519 private void notifyTransactionListeners(byte[] aid, byte[] data, String evtSrc) { 520 mListener.onNfcTransactionEvent(aid, data, evtSrc); 521 } 522 notifyEeUpdated()523 private void notifyEeUpdated() { 524 mListener.onEeUpdated(); 525 } 526 notifyHwErrorReported()527 private void notifyHwErrorReported() { 528 mListener.onHwErrorReported(); 529 } 530 notifyEeAidSelected(byte[] aid, String eventSrc)531 private void notifyEeAidSelected(byte[] aid, String eventSrc) { 532 Log.i(TAG, "notifyEeAidSelected: AID= " + HexFormat.of().formatHex(aid) + " selected by " 533 + eventSrc); 534 if (com.android.nfc.flags.Flags.eeAidSelect()) { 535 mListener.onSeSelected(NfcService.SE_SELECTED_AID); 536 } 537 } 538 notifyEeProtocolSelected(int protocol, String eventSrc)539 private void notifyEeProtocolSelected(int protocol, String eventSrc) { 540 Log.i(TAG, "notifyEeProtocolSelected: Protocol: " + protocol + " selected by " + eventSrc); 541 if (com.android.nfc.flags.Flags.eeAidSelect()) { 542 mListener.onSeSelected(NfcService.SE_SELECTED_PROTOCOL); 543 } 544 } 545 notifyEeTechSelected(int tech, String eventSrc)546 private void notifyEeTechSelected(int tech, String eventSrc) { 547 Log.i(TAG, "notifyEeTechSelected: Tech: " + tech + " selected by " + eventSrc); 548 if (com.android.nfc.flags.Flags.eeAidSelect()) { 549 mListener.onSeSelected(NfcService.SE_SELECTED_TECH); 550 } 551 } 552 notifyPollingLoopFrame(int data_len, byte[] p_data)553 public void notifyPollingLoopFrame(int data_len, byte[] p_data) { 554 if (data_len < MIN_POLLING_FRAME_TLV_SIZE) { 555 return; 556 } 557 Trace.beginSection("notifyPollingLoopFrame"); 558 final int header_len = 4; 559 int pos = header_len; 560 final int TLV_header_len = 3; 561 final int TLV_type_offset = 0; 562 final int TLV_len_offset = 2; 563 final int TLV_timestamp_offset = 3; 564 final int TLV_gain_offset = 7; 565 final int TLV_data_offset = 8; 566 ArrayList<PollingFrame> frames = new ArrayList<PollingFrame>(); 567 if (data_len >= TLV_header_len) { 568 int tlv_len = Byte.toUnsignedInt(p_data[TLV_len_offset]) + TLV_header_len; 569 if (tlv_len < data_len) { 570 data_len = tlv_len; 571 } 572 } 573 while (pos + TLV_len_offset < data_len) { 574 @PollingFrame.PollingFrameType int frameType; 575 Bundle frame = new Bundle(); 576 int type = p_data[pos + TLV_type_offset]; 577 int length = p_data[pos + TLV_len_offset]; 578 if (TLV_len_offset + length < TLV_gain_offset) { 579 Log.e(TAG, "notifyPollingLoopFrame: Length (" + length 580 + ") is less than a polling frame, dropping."); 581 break; 582 } 583 if (pos + TLV_header_len + length > data_len) { 584 // Frame is bigger than buffer. 585 Log.e(TAG, "notifyPollingLoopFrame: Polling frame data (" + pos + ", " + length 586 + ") is longer than buffer data length (" + data_len + ")."); 587 break; 588 } 589 switch (type) { 590 case TAG_FIELD_CHANGE: 591 frameType = p_data[pos + TLV_data_offset] != 0x00 592 ? PollingFrame.POLLING_LOOP_TYPE_ON 593 : PollingFrame.POLLING_LOOP_TYPE_OFF; 594 break; 595 case TAG_NFC_A: 596 frameType = PollingFrame.POLLING_LOOP_TYPE_A; 597 break; 598 case TAG_NFC_B: 599 frameType = PollingFrame.POLLING_LOOP_TYPE_B; 600 break; 601 case TAG_NFC_F: 602 frameType = PollingFrame.POLLING_LOOP_TYPE_F; 603 break; 604 case TAG_NFC_UNKNOWN: 605 frameType = PollingFrame.POLLING_LOOP_TYPE_UNKNOWN; 606 break; 607 default: 608 Log.e(TAG, "notifyPollingLoopFrame: Unknown polling loop tag type."); 609 return; 610 } 611 byte[] frameData = null; 612 if (pos + TLV_header_len + length <= data_len) { 613 frameData = Arrays.copyOfRange(p_data, pos + TLV_data_offset, 614 pos + TLV_header_len + length); 615 } 616 int gain = -1; 617 if (pos + TLV_gain_offset <= data_len) { 618 gain = Byte.toUnsignedInt(p_data[pos + TLV_gain_offset]); 619 if (gain == 0XFF) { 620 gain = -1; 621 } 622 } 623 long timestamp = 0; 624 if (pos + TLV_timestamp_offset + 3 < data_len) { 625 timestamp = Integer.toUnsignedLong(ByteBuffer.wrap(p_data, 626 pos + TLV_timestamp_offset, 4).order(ByteOrder.BIG_ENDIAN).getInt()); 627 } 628 pos += (TLV_header_len + length); 629 frames.add(new PollingFrame(frameType, frameData, gain, timestamp, false)); 630 } 631 mListener.onPollingLoopDetected(frames); 632 Trace.endSection(); 633 } 634 onObserveModeEnabledInFirmware()635 private void onObserveModeEnabledInFirmware() { 636 mListener.onObserveModeEnabledInFirmware(); 637 } 638 onObserveModeDisabledInFirmware(int type, byte[] data)639 private void onObserveModeDisabledInFirmware(int type, byte[] data) { 640 int pollingFrameType = PollingFrame.POLLING_LOOP_TYPE_UNKNOWN; 641 if (type == OBSERVE_MODE_SUSPENDED_FRAME_TYPE_A) { 642 pollingFrameType = PollingFrame.POLLING_LOOP_TYPE_A; 643 } else if (type == OBSERVE_MODE_SUSPENDED_FRAME_TYPE_B) { 644 pollingFrameType = PollingFrame.POLLING_LOOP_TYPE_B; 645 } 646 647 mListener.onObserveModeDisabledInFirmware( 648 new PollingFrame(pollingFrameType, data, -1, -1, true)); 649 } 650 doDetectEpRemoval(int waiting_time_int)651 private native boolean doDetectEpRemoval(int waiting_time_int); 652 653 @Override detectEpRemoval(int waiting_time_int)654 public boolean detectEpRemoval(int waiting_time_int) { 655 return doDetectEpRemoval(waiting_time_int); 656 } 657 notifyWlcStopped(int wpt_end_condition)658 private void notifyWlcStopped(int wpt_end_condition) { 659 mListener.onWlcStopped(wpt_end_condition); 660 } notifyTagDiscovered(boolean discovered)661 private void notifyTagDiscovered(boolean discovered) { 662 mListener.onTagRfDiscovered(discovered); 663 } notifyVendorSpecificEvent(int event, int dataLen, byte[] pData)664 private void notifyVendorSpecificEvent(int event, int dataLen, byte[] pData) { 665 if (pData.length < NCI_HEADER_MIN_LEN || dataLen != pData.length) { 666 Log.e(TAG, "notifyVendorSpecificEvent: Invalid data"); 667 return; 668 } 669 if (android.nfc.Flags.nfcVendorCmd()) { 670 mListener.onVendorSpecificEvent(pData[NCI_GID_INDEX], pData[NCI_OID_INDEX], 671 Arrays.copyOfRange(pData, OP_CODE_INDEX, pData.length)); 672 } 673 } 674 notifyRFDiscoveryEvent(boolean isDiscoveryStarted)675 private void notifyRFDiscoveryEvent(boolean isDiscoveryStarted) { 676 mListener.onRfDiscoveryEvent(isDiscoveryStarted); 677 } 678 notifyEeListenActivated(boolean isActivated)679 private void notifyEeListenActivated(boolean isActivated) { 680 mListener.onEeListenActivated(isActivated); 681 } 682 683 @Override setDiscoveryTech(int pollTech, int listenTech)684 public native void setDiscoveryTech(int pollTech, int listenTech); 685 686 @Override resetDiscoveryTech()687 public native void resetDiscoveryTech(); 688 689 @Override clearRoutingEntry(int clearFlags)690 public native void clearRoutingEntry(int clearFlags); 691 692 @Override setIsoDepProtocolRoute(int route)693 public native void setIsoDepProtocolRoute(int route); 694 695 @Override setTechnologyABFRoute(int route, int felicaRoute)696 public native void setTechnologyABFRoute(int route, int felicaRoute); 697 698 @Override setSystemCodeRoute(int route)699 public native void setSystemCodeRoute(int route); 700 getProprietaryCaps()701 private native byte[] getProprietaryCaps(); 702 703 @Override enableVendorNciNotifications(boolean enabled)704 public native void enableVendorNciNotifications(boolean enabled); 705 notifyCommandTimeout()706 private void notifyCommandTimeout() { 707 if (android.nfc.Flags.nfcEventListener()) { 708 mListener.onCommandTimeout(); 709 } 710 NfcService.getInstance().storeNativeCrashLogs(); 711 } 712 713 /** wrappers for values */ 714 private static final int CAPS_OBSERVE_MODE_UNKNOWN = 715 NFC_PROPRIETARY_CAPABILITIES_REPORTED__PASSIVE_OBSERVE_MODE__MODE_UNKNOWN; 716 private static final int CAPS_OBSERVE_MODE_SUPPORT_WITH_RF_DEACTIVATION = 717 NFC_PROPRIETARY_CAPABILITIES_REPORTED__PASSIVE_OBSERVE_MODE__SUPPORT_WITH_RF_DEACTIVATION; 718 private static final int CAPS_OBSERVE_MODE_SUPPORT_WITHOUT_RF_DEACTIVATION = 719 NFC_PROPRIETARY_CAPABILITIES_REPORTED__PASSIVE_OBSERVE_MODE__SUPPORT_WITHOUT_RF_DEACTIVATION; 720 private static final int CAPS_OBSERVE_MODE_NOT_SUPPORTED = 721 NfcStatsLog.NFC_PROPRIETARY_CAPABILITIES_REPORTED__PASSIVE_OBSERVE_MODE__NOT_SUPPORTED; 722 isObserveModeSupportedCaps(NfcProprietaryCaps proprietaryCaps)723 private static boolean isObserveModeSupportedCaps(NfcProprietaryCaps proprietaryCaps) { 724 return proprietaryCaps.getPassiveObserveMode() 725 != NfcProprietaryCaps.PassiveObserveMode.NOT_SUPPORTED; 726 } 727 isReaderModeAnnotationSupportedCaps()728 private boolean isReaderModeAnnotationSupportedCaps() { 729 return mProprietaryCaps != null && mProprietaryCaps.isReaderModeAnnotationSupported(); 730 } 731 732 @Override isReaderModeAnnotationSupported()733 public boolean isReaderModeAnnotationSupported() { 734 return isReaderModeAnnotationSupportedCaps(); 735 } 736 logProprietaryCaps(NfcProprietaryCaps proprietaryCaps)737 private static void logProprietaryCaps(NfcProprietaryCaps proprietaryCaps) { 738 int observeModeStatsd = CAPS_OBSERVE_MODE_UNKNOWN; 739 740 NfcProprietaryCaps.PassiveObserveMode mode = proprietaryCaps.getPassiveObserveMode(); 741 742 if (mode == NfcProprietaryCaps.PassiveObserveMode.SUPPORT_WITH_RF_DEACTIVATION) { 743 observeModeStatsd = CAPS_OBSERVE_MODE_SUPPORT_WITH_RF_DEACTIVATION; 744 } else if (mode == NfcProprietaryCaps.PassiveObserveMode.SUPPORT_WITHOUT_RF_DEACTIVATION) { 745 observeModeStatsd = CAPS_OBSERVE_MODE_SUPPORT_WITHOUT_RF_DEACTIVATION; 746 } else if (mode == NfcProprietaryCaps.PassiveObserveMode.NOT_SUPPORTED) { 747 observeModeStatsd = CAPS_OBSERVE_MODE_NOT_SUPPORTED; 748 } 749 750 NfcStatsLog.write(NfcStatsLog.NFC_PROPRIETARY_CAPABILITIES_REPORTED, 751 observeModeStatsd, 752 proprietaryCaps.isPollingFrameNotificationSupported(), 753 proprietaryCaps.isPowerSavingModeSupported(), 754 proprietaryCaps.isAutotransactPollingLoopFilterSupported(), 755 proprietaryCaps.getNumberOfExitFramesSupported()); 756 } 757 notifyObserveModeChanged(boolean enabled)758 public void notifyObserveModeChanged(boolean enabled) { 759 mListener.onObserveModeStateChanged(enabled); 760 } 761 /** Notifies remote endpoint removed */ notifyEndpointRemoved(int reason)762 private void notifyEndpointRemoved(int reason) { 763 mListener.onEndpointRemoved(reason); 764 765 } 766 767 @Override isRemovalDetectionInPollModeSupported()768 public native boolean isRemovalDetectionInPollModeSupported(); 769 onRestartRfDiscovery()770 public void onRestartRfDiscovery() { 771 mListener.onRestartRfDiscovery(); 772 } 773 } 774