NFC源码分析-ZGS
AndroidManifest.xml
<application android:name=".NfcApplication"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.Material.Light"
android:persistent="true"
android:hardwareAccelerated="false"
android:backupAgent="com.android.nfc.NfcBackupAgent"
android:killAfterRestore="false"
android:usesCleartextTraffic="false"
android:supportsRtl="true"
>
public void onCreate() {
super.onCreate();
boolean isMainProcess = false;
......
ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
List processes = am.getRunningAppProcesses();
Iterator i = processes.iterator();
while (i.hasNext()) {
RunningAppProcessInfo appInfo = (RunningAppProcessInfo)(i.next());
if (appInfo.pid == Process.myPid()) {
isMainProcess = (NFC_PROCESS.equals(appInfo.processName));
break;
}
}
if (UserHandle.myUserId() == 0 && isMainProcess) {
mNfcService = new NfcService(this);
ThreadedRenderer.enableForegroundTrimming();
}
}
xp022430@cnbjlx24729:~$ adb shell ps -A | grep nfc
nfc 897 1 22164 3016 binder_thread_read 70db203f18 S vendor.nxp.nxpnfc@1.0-service
nfc 2785 735 2283348 68876 SyS_epoll_wait 7d0f471e28 S com.android.nfc
u0_a114 7005 735 2249568 39120 SyS_epoll_wait 7d0f471e28 S com.sonymobile.nfcextension
import com.android.nfc.DeviceHost.DeviceHostListener;
public class NfcService implements DeviceHostListener { }.
public interface DeviceHost {
//NfcService实现了它的具体功能,里面基本上都是描述的整体nfc的状态的接口.
public interface DeviceHostListener {
//当检测到远端的tag的时候的回调,TagEndpoint:来表示远端的tag
public void onRemoteEndpointDiscovered(TagEndpoint tag);
......
//当卡模拟的Aid被选中的时候
public void onCardEmulationAidSelected(byte[] aid,byte[] data, int evtSrc);
//通知se相关的事件
public void onConnectivityEvent(int evtSrc);
//当P2P链接成功的时候
public void onLlcpLinkActivated(NfcDepEndpoint device);
......
//作为reader检测到remoteFiled(就是远端的card)的时候
public void onRemoteFieldActivated();
......
}
//NativeNfcTag类实现了它的具体功能,用来实现Nfc Tag的一些功能。
public interface TagEndpoint {
//Tag建立起了连接
boolean connect(int technology);
......
//读取Tag中所用到的tech
int[] getTechList();
......
//读取Tag中的ndef消息
byte[] readNdef();
//向Tag中写入Ndef消息
boolean writeNdef(byte[] data);
......
}
//Tag断开链接的回调
public interface TagDisconnectedCallback {
void onTagDisconnected(long handle);
}
......
//NativeP2pDevice类实现它的具体功能,P2P的Initiator发起端的功能实现。
//自己没有跟这里的看起来即可以表示发起端,又可以表示接收端。
public interface NfcDepEndpoint {
/**
* Peer-to-Peer Target
*/
public static final short MODE_P2P_TARGET = 0x00;
/**
* Peer-to-Peer Initiator
*/
public static final short MODE_P2P_INITIATOR = 0x01;
......
public byte[] receive();
public boolean send(byte[] data);
public boolean connect();
public boolean disconnect();
......
}
//NativeLlcpSocket类实现它的具体功能,
//代表了一个llcp链接中的客户端的通信部分.
//那么问题来了P2P的这个连接中谁是客户端?发起方?接收方?还是说并不是P2P才用这个?
//比如read/write模式。这样就比较好定义客户端和服务端了。?这块不太清楚
public interface LlcpSocket {
......
public void connectToService(String serviceName) throws IOException;
public void close() throws IOException;
public void send(byte[] data) throws IOException;
public int receive(byte[] recvBuff) throws IOException;
public int getRemoteMiu();
......
public int getLocalSap();
......
}
//NativeLlcpServiceSocket类实现它的具体功能,表示一个llcp链接中的服务端的通信部分.
public interface LlcpServerSocket {
//监听客户端的链接
public LlcpSocket accept() throws IOException, LlcpException;
//关闭服务
public void close() throws IOException;
}
//NativeLlcpConnectionlessSocket类实现它的具体功能,代表在无连接通信中使用的LLCP对象?不太清楚.
public interface LlcpConnectionlessSocket {
public int getLinkMiu();
public int getSap();
public void send(int sap, byte[] data) throws IOException;
public LlcpPacket receive() throws IOException;
public void close() throws IOException;
}
//以上的接口在内部实现的时候如它们的名字所示,Native...,他们内部基本都有native方法去进一步的
//通过JNI调用到native层实现的地方。
//下面都是管理NFC功能的api,位于NativeNfcManager当中.
public void checkFirmware();
......
public boolean initialize();
public String getName();
public void enableDiscovery(NfcDiscoveryParameters params, boolean restart);
public void doSetScreenState(int mScreenState);
......
public void disableDiscovery();
......
public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
throws LlcpException;
public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
int rw, int linearBufferLength) throws LlcpException;
public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
int linearBufferLength) throws LlcpException;
......
}
public NfcService(Application nfcApplication) {
......
//Nfc Tag相关的一些操作.最终调用到的就是DeviceHost里面的interface的
//实现NativeNfcTag此处就是final class TagService extends INfcTag.Stub {...}
//然后在内部的方法中去调用DeviceHost.TagEndpoint,也就是调用到了NativeNfcTag.
//下面的很多service都是这种实现方式,这样framework层api通过binder调用到native层实现的地方
mNfcTagService = new TagService();
//BluetoothAdapter类似,用于供外部调用NFC功能。个人理解adapter适配,也就是说其实是一个转接口
//它只是提供统一规范,然后在它的内部会再去调用如NativeNfcManager里面真正的native的方法去和NFC打交道
//这样做还有一个好处就是可以一定程度封装代码。结构清晰,代码隐蔽.
//实现方式类似上面的TagService
mNfcAdapter = new NfcAdapterService();
//下面省略了一些NxpNfcAdapterService的初始化,暂时不清楚这些类的功能,可能是HiNXP扩展用.
......
//卡模拟的service,现在直接被注释掉了,可能不用了,直接用对应的manager管理
//mCardEmulationService = new CardEmulationService();
//sService是NfcService
sService = this;
//NFC与屏幕锁定状态相关的类,用来方便屏幕状态的管理
mScreenStateHelper = new ScreenStateHelper(mContext);
//NativeNfcManager里面基本上都是native的方法,用于进一步调用到native层和NFC进行通信.
//private DeviceHost mDeviceHost;可以看到NativeNfcManager就是DeviceHost
mDeviceHost = new NativeNfcManager(mContext, this);
//在进行一些handover等的时候,NFC对屏幕解锁的一些逻辑(某些状态下)。
mNfcUnlockManager = NfcUnlockManager.getInstance();
//使用别的技术如蓝牙进行handover的时候的帮助类,目前为止只有对蓝牙的实现,可以通过此类
//把蓝牙地址、名字等信息封装成对应的标准NDEF Message进行传输.
mHandoverDataParser = new HandoverDataParser();
......//此处省略了在Nfc在setup wizard阶段接受数据的处理
//分发Nfc的不同的EVENT然后根据Android的policy区启动对应的activity处理相应的事件。
mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);
//基于LLCP连接的服务,含NdefPushService/SnepService/P2pEventManager
//就是处理NFC进行P2P的时候的一些逻辑
mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,
mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
//电源管理模块,主要是处理屏幕状态与NFC是否响应的联系
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
......
//注册屏幕亮/灭,用户激活和切换
IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_USER_PRESENT);
filter.addAction(Intent.ACTION_USER_SWITCHED);
mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
filter = new IntentFilter(Intent.ACTION_SHUTDOWN);
mContext.registerReceiver(mOwnerReceiver, filter);
IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(mOwnerReceiver, ownerFilter);
//关注程序安装和卸载
ownerFilter = new IntentFilter();
ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
ownerFilter.addDataScheme("package");
mContext.registerReceiver(mOwnerReceiver, ownerFilter);
......
//gmsa enable Nfc的时候,可能和一些测试case有关
IntentFilter enableNfc = new IntentFilter();
enableNfc.addAction(NxpConstants.ACTION_GSMA_ENABLE_NFC);
mContext.registerReceiverAsUser(mEnableNfc, UserHandle.ALL, enableNfc, null, null);
//Nfc状态变化的时候的广播
IntentFilter lsFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
//mContext.registerReceiver(mAlaReceiver, lsFilter);
mContext.registerReceiverAsUser(mAlaReceiver, UserHandle.ALL, lsFilter, null, null);
......
//把NfcAdapterService添加到ServiceManager当中,别的就可以通过
//INfcAdapter.Stub.asInterface(nfcServiceBinder).
ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
//Nfc和相机的一些交互,如相机启动的时候Nfc能不能工作等
mCameraManager = (CameraManager)mContext.getSystemService(Context.CAMERA_SERVICE);
......
//TASK_BOOT,异步的开始执行NFC的enable.
new EnableDisableTask().execute(TASK_BOOT);
}
final class TagService extends INfcTag.Stub{
@Override
public int connect(int nativeHandle, int technology) throws RemoteException {
//检查权限
NfcPermissions.enforceUserPermissions(mContext);
TagEndpoint tag = null;
//判断NFC是否可用.
if (!isNfcEnabled()) {
return ErrorCodes.ERROR_NOT_INITIALIZED;
}
//final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
//tag在发现时候会调用registerTagObject添加到一个集合当中,
//以:key = tag.getHandle() native的handle就是如在c/c++层的对象的代表,value = tag
tag = (TagEndpoint) findObject(nativeHandle);
......
//判断Tag是否还在范围内
if (!tag.isPresent()) {
return ErrorCodes.ERROR_DISCONNECT;
}
//调用NativeNfcTag的connect方法,传入technology
//technology是Nfc Tag使用技术协议有:
//public static final int NFC_A = 1;
//public static final int NFC_B = 2;
//public static final int ISO_DEP = 3;
//public static final int NDEF = 6;
//.....等等很多
if (tag.connect(technology)) {
return ErrorCodes.SUCCESS;
}
......
}
@Override
public int reconnect(int nativeHandle) throws RemoteException {
......
tag.reconnect())
......
}
@Override
public int[] getTechList(int nativeHandle) throws RemoteException {
......
tag.getTechList();
......
}
@Override
public boolean isPresent(int nativeHandle) throws RemoteException {
......
return tag.isPresent();
}
@Override
public boolean isNdef(int nativeHandle) throws RemoteException {
......
return tag.checkNdef(ndefInfo);
}
@Override
public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
throws RemoteException {
......
/* find the tag in the hmap */
tag = (TagEndpoint) findObject(nativeHandle);
if (tag != null) {
// Check if length is within limits
if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) {
return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null);
}
int[] targetLost = new int[1];
response = tag.transceive(data, raw, targetLost);
int result;
if (response != null) {
result = TransceiveResult.RESULT_SUCCESS;
} else if (targetLost[0] == 1) {
result = TransceiveResult.RESULT_TAGLOST;
} else {
result = TransceiveResult.RESULT_FAILURE;
}
return new TransceiveResult(result, response);
}
return null;
}
@Override
public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
......
return new NdefMessage(buf);
......
}
@Override
public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
......
tag.writeNdef(msg.toByteArray())
......
}
......
@Override
public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
......
tag.formatNdef(key)
......
}
......
}
public class NativeNfcTag implements TagEndpoint {
//通过JNI调用到了native层相应的实现处.
private native int doConnect(int handle);
......
public synchronized boolean connect(int technology) {
return connectWithStatus(technology) == 0;
}
public synchronized int connectWithStatus(int technology) {
......
int status = -1;
for (int i = 0; i < mTechList.length; i++) {
//当要链接的tech包含在支持的Tech的时候
if (mTechList[i] == technology) {
// Get the handle and connect, if not already connected
if (mConnectedHandle != mTechHandles[i]) {
//如果是没有连接过,
if (mConnectedHandle == -1) {
//则直接调用到doConnect()
status = doConnect(i);
} else {
//调用接口再次链接
status = reconnectWithStatus(i);
}
if (status == 0) {
mConnectedHandle = mTechHandles[i];
mConnectedTechIndex = i;
}
} else {
//当我们已经连接过Tag的时候要分情况讨论
// 1) We are connected to a technology which has the same
// handle; we do not support connecting at a different
// level (libnfc auto-activates to the max level on
// any handle).
// 2) We are connecting to the ndef technology - always
// allowed.
if ((technology == TagTechnology.NDEF) ||
(technology == TagTechnology.NDEF_FORMATABLE)) {
// special case for NDEF, this will cause switch to ISO_DEP frame intf
i = 0;
}
status = reconnectWithStatus(i);
......
}
break;
}
}
......
return status;
}
......
native int doHandleReconnect(int handle);
public synchronized int reconnectWithStatus(int handle) {
......
int status = doHandleReconnect(handle);
......
return status;
}
}
/*******************************************************************************
**
** Function: nativeNfcTag_doConnect
**
** Description: Connect to the tag in RF field.
** e: JVM environment.
** o: Java object.
** targetHandle: Handle of the tag.
**
** Returns: Must return NXP status code, which NFC service expects.
**
*******************************************************************************/
static jint nativeNfcTag_doConnect (JNIEnv*, jobject, jint targetHandle)
{
ALOGV("%s: targetHandle = %d", __func__, targetHandle);
int i = targetHandle;
NfcTag& natTag = NfcTag::getInstance ();
int retCode = NFCSTATUS_SUCCESS;
sCurrentConnectedTargetType = natTag.mTechList[i];
sCurrentConnectedTargetProtocol = natTag.mTechLibNfcTypes[i];
......
#if(NXP_EXTNS == TRUE) //可以在mk文件中搜索"DNXP_EXTNS"
sCurrentConnectedHandle = targetHandle;
if(sCurrentConnectedTargetProtocol == NFC_PROTOCOL_T3BT)
{
goto TheEnd;
}
#endif
if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP)
{
ALOGV("%s() Nfc type = %d, do nothing for non ISO_DEP", __func__,
sCurrentConnectedTargetProtocol);
retCode = NFCSTATUS_SUCCESS; //打印Log的时候发现,即使进入到此处也是能打印出来。
goto TheEnd;
}
/* Switching is required for CTS protocol paramter test case.*/
if (sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3A || sCurrentConnectedTargetType ==
TARGET_TYPE_ISO14443_3B)
{
retCode = switchRfInterface(NFA_INTERFACE_FRAME) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
}
else
{
//切换NFC chip的RF interface.这样应该不会连接好像再往下会执行好几次的reconnect.
retCode = switchRfInterface(NFA_INTERFACE_ISO_DEP) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
}
TheEnd:
ALOGV("%s: exit 0x%X", __func__, retCode);
return retCode;
}
/*******************************************************************************
**
** Function: nativeNfcTag_doHandleReconnect
**
** Description: Re-connect to the tag in RF field.
** e: JVM environment.
** o: Java object.
** targetHandle: Handle of the tag.
**
** Returns: Status code.
**
*******************************************************************************/
static jint nativeNfcTag_doHandleReconnect (JNIEnv *e, jobject o, jint targetHandle)
{
ALOGV("%s: targetHandle = %d", __func__, targetHandle);
...
//可以看到又调用到了前面说的nativeNfcTag_doConnect
return nativeNfcTag_doConnect (e, o, targetHandle);
}
/*******************************************************************************
**
** Function: switchRfInterface
**
** Description: Switch controller's RF interface to frame, ISO-DEP, or NFC-DEP.
** rfInterface: Type of RF interface.
**
** Returns: True if ok.
**
*******************************************************************************/
static bool switchRfInterface (tNFA_INTF_TYPE rfInterface)
{
ALOGV("%s: rf intf = %d", __func__, rfInterface);
......
bool rVal = true;
if (rfInterface != sCurrentRfInterface)
{
//有变化的话,调用reSelect
//Deactivates the tag and re-selects it with the specified rf interface.
if (0 == reSelect(rfInterface, true))
{
sCurrentRfInterface = rfInterface;
rVal = true;
}
...
}
return rVal;
}
final class NfcAdapterService extends INfcAdapter.Stub{
@Override
public boolean enable() throws RemoteException {
//检查权限
NfcPermissions.enforceAdminPermissions(mContext);
int val = mDeviceHost.GetDefaultSE();
Log.i(TAG, "getDefaultSE " + val);
//默认的安全模块策略
saveNfcOnSetting(true);
//对比前面的NfcService的构造中的最后一步,会发现enable/disable都是通过这个Task
new EnableDisableTask().execute(TASK_ENABLE);
return true;
}
@Override
public boolean disable(boolean saveState) throws RemoteException {
......
new EnableDisableTask().execute(TASK_DISABLE);
return true;
}
......
@Override
public void resumePolling() {
......
new ApplyRoutingTask().execute();
}
......
@Override
public boolean enableNdefPush() throws RemoteException {
......
mDeviceHost.doEnablep2p(mIsNdefPushEnabled);
mP2pLinkManager.enableDisable(true, true);
......
}
@Override
public boolean disableNdefPush() throws RemoteException {
......
mP2pLinkManager.enableDisable(false, true);
......
}
//在activity中置此函数后,收到的消息会只在前台的APP处理。
//场景是进入一个app如taginfo以后再读取nfc tag
@Override
public void setForegroundDispatch(PendingIntent intent,
IntentFilter[] filters, TechListParcel techListsParcel) {
......
mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
}
......
//得到卡模拟的interface
@Override
public INfcFCardEmulation getNfcFCardEmulationInterface() {
......
return mCardEmulationManager.getNfcFCardEmulationInterface();
......
}
//返回当前Nfc的state: on/off/turning..
@Override
public int getState() throws RemoteException {
synchronized (NfcService.this) {
return mState;
}
}
......
//分发检测到的Tag的信息,尝试去启动相应的activity
@Override
public void dispatch(Tag tag) throws RemoteException {
......
mNfcDispatcher.dispatchTag(tag);
}
@Override
public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException {
NfcPermissions.enforceAdminPermissions(mContext);
mDeviceHost.setP2pInitiatorModes(initiatorModes);
mDeviceHost.setP2pTargetModes(targetModes);
applyRouting(true);
}
//外部第三方app调用,用来做卡模拟的.
@Override
public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras)
throws RemoteException {
......
synchronized (NfcService.this) {
...
if (flags != 0) {
mReaderModeParams = new ReaderModeParams();
mReaderModeParams.callback = callback;
mReaderModeParams.flags = flags;
mReaderModeParams.presenceCheckDelay = extras != null
? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY,
DEFAULT_PRESENCE_CHECK_DELAY))
: DEFAULT_PRESENCE_CHECK_DELAY;
binder.linkToDeath(mReaderModeDeathRecipient, 0);
} else {
......
mReaderModeParams = null;
binder.unlinkToDeath(mReaderModeDeathRecipient, 0);
}
Log.e(TAG, "applyRouting -4");
applyRouting(false);
}
}
......
}
class NfcDispatcher {
......
//使用前台调度系统的时候最终会回调到这里。
public synchronized void setForegroundDispatch(PendingIntent intent,
IntentFilter[] filters, String[][] techLists) {
//为相应的变量进行初始化
mOverrideIntent = intent;
mOverrideFilters = filters;
mOverrideTechLists = techLists;
}
......
//分发Tag,内部分发时候调用具体的如:tryOverrides、tryNdef、tryTech去做进一步的处理.
//整体是按照Android Nfc的分发系统来进行不同优先级的处理的,前台的最高,然后是注册
//ACTION_NDEF_DISCOVERED,再然后是ACTION_TECH_DISCOVERED,最后是ACTION_TAG_DISCOVERD
具体策略可查看官方文档:
//https://developer.android.com/guide/topics/connectivity/nfc/nfc.html
public int dispatchTag(Tag tag) {
PendingIntent overrideIntent;
IntentFilter[] overrideFilters;
String[][] overrideTechLists;
String[] provisioningMimes;
boolean provisioningOnly;
synchronized (this) {
overrideFilters = mOverrideFilters;
overrideIntent = mOverrideIntent;
overrideTechLists = mOverrideTechLists;
provisioningOnly = mProvisioningOnly;
provisioningMimes = mProvisioningMimes;
}
//屏幕解锁相关
boolean screenUnlocked = false;
//如果是处在锁屏(屏幕已经点亮)
if (!provisioningOnly &&
mScreenStateHelper.checkScreenState() ==
ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
//尝试去解锁屏幕
screenUnlocked = handleNfcUnlock(tag);
if (!screenUnlocked) {
return DISPATCH_FAIL;
}
}
......
//当使用前台调度系统的时候会通过它进行覆盖,成功的话就不去执行NFC基本的分发系统了.
if (tryOverrides(dispatch, tag, message, overrideIntent, overrideFilters,
overrideTechLists)) {
return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
}
//尝试去进行Handover.如带Nfc的BT耳机、键盘等等.
if (tryPeripheralHandover(message)) {
if (DBG) Log.i(TAG, "matched BT HANDOVER");
return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
}
//按理说现在Android还没有实现Nfc打开wifi呀?
if (NfcWifiProtectedSetup.tryNfcWifiSetup(ndef, mContext)) {
if (DBG) Log.i(TAG, "matched NFC WPS TOKEN");
return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
}
......
//在进行NDEF Message的判断,判断是否为ACTION_NDEF_DISCOVERD
if (tryNdef(dispatch, message)) {
return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
}
......
//如果前面都没有成功处理消息,判断是否为ACTION_TECH_DISCOVERD.
if (tryTech(dispatch, tag)) {
return DISPATCH_SUCCESS;
}
//最后一种,也是优先级最低的intent为ACTION_TAG_DISCOVERD 。
dispatch.setTagIntent();
//直接尝试查询启动,有多个时候会弹框提示。
if (dispatch.tryStartActivity()) {
if (DBG) Log.i(TAG, "matched TAG");
return DISPATCH_SUCCESS;
}
if (DBG) Log.i(TAG, "no match");
return DISPATCH_FAIL;
}
}
boolean tryStartActivity() {
//查询所有注册了的携带指定action的intent的activities
//注意到这之前就已经为intent配置好了对应的action
List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(intent, 0,
ActivityManager.getCurrentUser());
if (activities.size() > 0) {
context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
NfcIddEvent.NfcTag.dispatchedToApp(tag, activities);
return true;
}
return false;
}
//道理同上
boolean tryStartActivity(Intent intentToStart) {
List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(
intentToStart, 0, ActivityManager.getCurrentUser());
if (activities.size() > 0) {
rootIntent.putExtra(NfcRootActivity.EXTRA_LAUNCH_INTENT, intentToStart);
context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
NfcIddEvent.NfcTag.dispatchedToApp(tag, activities);
return true;
}
return false;
}
interface P2pEventListener {
//user想要通过Nfc去share一些数据,但是远端的设备还没有onRange,对用户进行提示.
public void onP2pNfcTapRequested();
//等待传输超时的回调.
public void onP2pTimeoutWaitingForLink();
//表明P2P的设备in range
public void onP2pInRange();
//当一个NDEF的数据准备发送,并且需要确认的时候调用.
public void onP2pSendConfirmationRequested();
//P2P发送完成
public void onP2pSendComplete();
......
//Called to indicate the remote device does not support connection handover
public void onP2pHandoverNotSupported();
//Called to indicate the device is busy with another handover transfer
public void onP2pHandoverBusy();
//当P2P接受完成的时候
public void onP2pReceiveComplete(boolean playSound);
//Indicates the P2P device went out of range.
public void onP2pOutOfRange();
//Indicates the P2P Beam UI is in idle mode.
public boolean isP2pIdle();
//此处还有两个回调,这两个CallBack是在P2pLinkManager中实现的
public interface Callback {
public void onP2pSendConfirmed();
public void onP2pCanceled();
}
}
class P2pLinkManager implements Handler.Callback, P2pEventListener.Callback {
......
//构造,创建了很多P2P通信需要的server
public P2pLinkManager(Context context, HandoverDataParser handoverDataParser, int
defaultMiu,
int defaultRwSize) {
//用于NdefPushServer:启动NPP Server,等待Client连接
mNdefPushServer = new NdefPushServer(NDEFPUSH_SAP, mNppCallback);
//用于启动SNPP Server,等待Client连接
mDefaultSnepServer = new SnepServer(mDefaultSnepCallback, defaultMiu, defaultRwSize);
//启动Handover Server,等待Client连接
mHandoverServer = new HandoverServer(context, HANDOVER_SAP, handoverDataParser,
mHandoverCallback);
......
//实例化P2pEventManager,用于将底层消息notify到UI或者上层APP
mEventListener = new P2pEventManager(context, this);
mHandler = new Handler(this);
......
}
//处理mHandler中的信息,底层处理完请求后会调用NativeNfcManager中相应回调,然后往外发消息。
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_START_ECHOSERVER:
...
case MSG_STOP_ECHOSERVER:
...
case MSG_WAIT_FOR_LINK_TIMEOUT:
...
case MSG_DEBOUNCE_TIMEOUT:
...
case MSG_RECEIVE_HANDOVER:
...
case MSG_RECEIVE_COMPLETE:
...
case MSG_HANDOVER_NOT_SUPPORTED:
...
case MSG_SEND_COMPLETE:
...
}
return true;
}
}
public void start() {
synchronized (this) {
if (mServerThread == null) {
mServerThread = new ServerThread();
mServerThread.start();
}
}
}
/** Server class, used to listen for incoming connection request */
class ServerThread extends Thread{
boolean mRunning = true;
LlcpServerSocket mServerSocket;
@Override
public void run() {
boolean threadRunning;
synchronized (NdefPushServer.this) {
threadRunning = mRunning;
}
while (threadRunning) {
try {
synchronized (NdefPushServer.this) {
//创建llcp服务端socket,根据所用的协议,填写不同的参数
mServerSocket = mService.createLlcpServerSocket(mSap, SERVICE_NAME,
MIU, 1, 1024);
}
......
synchronized (NdefPushServer.this) {
threadRunning = mRunning;
}
while (threadRunning) {
LlcpServerSocket serverSocket;
synchronized (NdefPushServer.this) {
serverSocket = mServerSocket;
}
......
//阻塞等待客户端连接,一个server端,可以有多个客户端连接
LlcpSocket communicationSocket = serverSocket.accept();
//每次client端连接都会创建新的thread,用于连接服务端.
if (communicationSocket != null) {
new ConnectionThread(communicationSocket).start();
}
synchronized (NdefPushServer.this) {
threadRunning = mRunning;
}
}
if (DBG) Log.d(TAG, "stop running");
} catch (LlcpException e) {
......
} finally {
......
mServerSocket.close();
}
}
}
......
}
/** Connection class, used to handle incoming connections */
private class ConnectionThread extends Thread {
private LlcpSocket mSock;
ConnectionThread(LlcpSocket sock) {
super(TAG);
mSock = sock;
}
@Override
public void run() {
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024);
byte[] partial = new byte[1024];
int size;
boolean connectionBroken = false;
//从远程服务端获取数据.
// Get raw data from remote server
while(!connectionBroken) {
try {
//把收到数据写入buffer
size = mSock.receive(partial);
......
buffer.write(partial, 0, size);
} catch (IOException e) {...}
}
//把接收到的数据转换成NDEF Message
// Build NDEF message set from the stream
NdefPushProtocol msg = new NdefPushProtocol(buffer.toByteArray());
if (DBG) Log.d(TAG, "got message " + msg.toString());
// Send the intent for the fake tag
//通过回调做进一步的对消息的处理.mCallback是最开始实例化的时候传入的mNppCallback
mCallback.onMessageReceived(msg.getImmediate());
} catch (FormatException e) {
.....
} finally {......}
}
}
final NdefPushServer.Callback mNppCallback = new NdefPushServer.Callback() {
@Override
public void onMessageReceived(NdefMessage msg) {
onReceiveComplete(msg);
}
};
void onReceiveComplete(NdefMessage msg) {
// Make callbacks on UI thread
mHandler.obtainMessage(MSG_RECEIVE_COMPLETE, msg).sendToTarget();
NfcIddEvent.Beam.Ndef.receive(msg);
}
//Manages vibration, sound and animation for P2P events.
public class P2pEventManager implements P2pEventListener, SendUi.Callback {
public P2pEventManager(Context context, P2pEventListener.Callback callback) {
mNfcService = NfcService.getInstance();
mContext = context;
mCallback = callback;
//实例化震动管理和通知管理。
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
......
//用于和UI界面交互,SendUi类实现了一些动画。
mSendUi = new SendUi(context, this);
主要函数如下:从名字也能看出大概意思,碰到相关BUG再详细分析.
public void onP2pInRange()
public void onP2pNfcTapRequested()
public void onP2pTimeoutWaitingForLink()
public void onP2pSendConfirmationRequested()
public void onP2pSendComplete()
public void onP2pHandoverNotSupported()
public void onP2pReceiveComplete(boolean playSound)
public void onP2pOutOfRange()
public void onSendConfirmed()
public void onCanceled()
public void onP2pSendDebounce()
public void onP2pResumeSend()
}
static {
System.loadLibrary("nfc_nci_jni");//对应于nci包下的jni的实现
}
//构造:
public native boolean initializeNativeStructure();
public NativeNfcManager(Context context, DeviceHostListener listener) {
mListener = listener;
initializeNativeStructure();//重点,
mContext = context;
mNfcid2ToHandle = new HashMap<String, Integer>();
NfcDiagService.setDeviceHost(this);
}
/*******************************************************************************
**
** Function: nfcManager_initNativeStruc
**
** Description: Initialize variables.就是利用JNI技术把java层的native方法和native层中的函数对应
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_initNativeStruc (JNIEnv* e, jobject o){
ALOGV("%s: enter", __func__);
......
nfc_jni_native_data* nat = (nfc_jni_native_data*)malloc(sizeof(struct nfc_jni_native_data));
......
memset (nat, 0, sizeof(*nat));
e->GetJavaVM(&(nat->vm));
nat->env_version = e->GetVersion();
nat->manager = e->NewGlobalRef(o);
......
/* Initialize native cached references */
//初始化java层方法和native方法对应关系
gCachedNfcManagerNotifyNdefMessageListeners = e->GetMethodID(cls.get(),
"notifyNdefMessageListeners", "(Lcom/android/nfc/dhimpl/NativeNfcTag;)V");
gCachedNfcManagerNotifyTransactionListeners = e->GetMethodID(cls.get(),
"notifyTransactionListeners", "([B[BI)V");
gCachedNfcManagerNotifyConnectivityListeners = e->GetMethodID(cls.get(),
"notifyConnectivityListeners", "(I)V");
gCachedNfcManagerNotifyEmvcoMultiCardDetectedListeners = e->GetMethodID(cls.get(),
"notifyEmvcoMultiCardDetectedListeners", "()V");
gCachedNfcManagerNotifyLlcpLinkActivation = e->GetMethodID(cls.get(),
"notifyLlcpLinkActivation", "(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
gCachedNfcManagerNotifyLlcpLinkDeactivated = e->GetMethodID(cls.get(),
"notifyLlcpLinkDeactivated", "(Lcom/android/nfc/dhimpl/NativeP2pDevice;)V");
......
gCachedNfcManagerNotifySWPReaderRequested = e->GetMethodID (cls.get(),
"notifySWPReaderRequested", "(ZZ)V");
gCachedNfcManagerNotifySWPReaderRequestedFail= e->GetMethodID (cls.get(),
"notifySWPReaderRequestedFail", "(I)V");
gCachedNfcManagerNotifySWPReaderActivated = e->GetMethodID (cls.get(),
"notifySWPReaderActivated", "()V");
gCachedNfcManagerNotifyUiccCardEmulationActivated = e->GetMethodID (cls.get(),
"notifyUiccCardEmulationActivated", "(I)V");
......
if (nfc_jni_cache_object(e, gNativeNfcTagClassName, &(nat->cached_NfcTag)) == -1)
{
ALOGE("%s: fail cache NativeNfcTag", __func__);
return JNI_FALSE;
}
if (nfc_jni_cache_object(e, gNativeP2pDeviceClassName, &(nat->cached_P2pDevice)) == -1)
{
ALOGE("%s: fail cache NativeP2pDevice", __func__);
return JNI_FALSE;
}
gNativeData = getNative(e,o);
ALOGV("%s: exit", __func__);
return JNI_TRUE;
}
/**
* 1)、Manages tasks that involve turning on/off the NFC controller.
* All work that might turn the NFC adapter on or off must be done
* through this task, to keep the handling of mState simple.
*
* 2)、Each task may temporarily transitionmState to STATE_TURNING_OFF
* or STATE_TURNING_ON, but must exit in either STATE_ON or STATE_OFF
*
* 3)、AsyncTask's are also implicitly queued. This is useful for corner
* cases like turning airplane mode on while TASK_ENABLE is in progress.
* The TASK_DISABLE triggered by airplane mode will be correctly executed
* immediately after TASK_ENABLE is complete. This seems like the most sane
* way to deal with these situations.
*
* TASK_ENABLE: enables the NFC adapter, without changing preferences
* TASK_DISABLE: disables the NFC adapter, without changing preferences
* TASK_BOOT: does first boot work and may enable NFC (就是首次开机的时候的初始化
* 根据配置来看是否需要enable)
*/
class EnableDisableTask extends AsyncTask<Integer, Void, Void> {
......
@Override
protected Void doInBackground(Integer... params) {
......
switch (params[0].intValue()) {
case TASK_ENABLE:
enableInternal(); //这个方法是EnableDisableTask内部的
break;
case TASK_DISABLE:
disableInternal();
break
case TASK_BOOT:
Log.d(TAG, "checking on firmware download");
//看看Nfc关机前是on还是off
if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
mIsTaskBoot = true;
enableInternal();
mIsTaskBoot = false;
} else {
mDeviceHost.checkFirmware();
Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
Log.i(TAG, "First Boot");
mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
mPrefsEditor.apply();
}
break;
case TASK_RESTART:
restartInternal();
}
......
}
......
/**
* Enable NFC adapter functions.
* Does not toggle preferences.
*/
boolean enableInternal(){
......
//调用mDeviceHost的initialize去初始化NFC
if (!mDeviceHost.initialize()) {
Log.w(TAG, "Error enabling NFC");
updateState(NfcAdapter.STATE_OFF);
return false;
}
......
checkSecureElementConfuration();
mNfcEnabled = true;
mIsRouteForced = true;
if (mIsHceCapable) {
// Generate the initial card emulation routing table
sAidTableFull = false;
mCardEmulationManager.onNfcEnabled();
}
mIsRouteForced = false;
synchronized (NfcService.this) {
mObjectMap.clear();
mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
updateState(NfcAdapter.STATE_ON);
}
......
//初始化Nfc需要用到的声音?
initSoundPool();
/* Start polling loop */
Log.e(TAG, "applyRouting -3");
//初始屏幕on&lock的状态,会发送相应的2103cmd.
mScreenState = mScreenStateHelper.checkScreenState();
mDeviceHost.doSetScreenOrPowerState(mScreenState);
mIsRoutingTableDirty = true;
if((mScreenState < NFC_POLLING_MODE) && mIsTaskBoot)
{
/*During device boot if screen state is other ON_UNLOCKED,
*first send discovery command with poll and linsten enabled
*for DC/DC pass through mode activation.
*Then send normal discovery according to screen state*/
applyRouting(true);
mIsTaskBoot = false;
}
//调用applyRouting,去更新一些参数,然后执行新的RF Discovery的命令.
applyRouting(true);
return true;
}
}
@Override
public boolean initialize() {
......
if (doInitialize()) {
......
return true;
}
......
}
private native boolean doInitialize();
/*******************************************************************************
**
** Function: nfcManager_doInitialize
**
** Description: Turn on NFC.
** e: JVM environment.
** o: Java object.
**
** Returns: True if ok.
**
*******************************************************************************/
static jboolean nfcManager_doInitialize (JNIEnv* e, jobject o)
{......}
@Override
protected Void doInBackground(Integer... params) {
//当从如下两个状态enable Nfc的时候就会失败.
switch (mState) {
case NfcAdapter.STATE_TURNING_OFF:
case NfcAdapter.STATE_TURNING_ON:
Log.e(TAG, "Processing EnableDisable task " + params[0] + " from bad state " +
mState);
return null;
}
/* AsyncTask sets this thread to THREAD_PRIORITY_BACKGROUND,
* override with the default. THREAD_PRIORITY_BACKGROUND causes
* us to service software I2C too slow for firmware download
* with the NXP PN544.
* TODO: move this to the DAL I2C layer in libnfc-nxp, since this
* problem only occurs on I2C platforms using PN544
*/
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
switch (params[0].intValue()) {
case TASK_ENABLE:
enableInternal();
break;
case TASK_DISABLE:
disableInternal();
break;
case TASK_BOOT:
//首次启动检查NFC默认的开启状态,可以看到根据如下属性设置的.
//NFC_ON_DEFAULT = SystemProperties.getBoolean("ro.nfc.on.default", false);
//当你在Settings中保存成关闭的时候此处会被设置为false.
if (mPrefs.getBoolean(PREF_NFC_ON, NFC_ON_DEFAULT)) {
Log.d(TAG, "NFC is on. Doing normal stuff");
mIsTaskBoot = true;
//手气enable,此处mIsTaskBoot = true。
enableInternal();
mIsTaskBoot = false;
} else {
//看起来是只有Nfc关闭的时候才回去检查是否需要更新Firmware.
//firmware可以理解为用来驱动NFC 芯片的代码.
Log.d(TAG, "NFC is off. Checking firmware version");
mDeviceHost.checkFirmware(); //mDeviceHost的实现前面也说过。
//发送NFC关闭的广播
Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, NfcAdapter.STATE_OFF);
mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
if (mPrefs.getBoolean(PREF_FIRST_BOOT, true)) {
Log.i(TAG, "First Boot");
mPrefsEditor.putBoolean(PREF_FIRST_BOOT, false);
mPrefsEditor.apply();
}
break;
case TASK_RESTART:
restartInternal();
}
// Restore default AsyncTask priority
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return null;
}
private native boolean doDownload();
@Override
public void checkFirmware() {
//此处省略了很多原生的注释,
// Perform download without condition(无条件的)
if (doDownload()) {
if (DBG) Log.d(TAG, "Download Succeeded");
sendChipReadyIfNeeded();
} else {
Log.e(TAG, "Download Failed");
}
}
NFC源码分析-ZGS相关推荐
- NFC源码分析之R/W工作模式
文章整理总结java层,NFC读取和写入Tag的流程. 整体的时序图: 1.读取Tag的流程 NfcService启动完成后,会通过NfcService中的applyRouting方法设置对应的Dis ...
- NFC源码分析之Handover
此处的代码为Android O的代码,本也有有一些patch的添加和修改,不过这些都不影响整个流程的理解.Handover相关的 大致可分为两种情况:直接读取带NFC的特殊设备如:带Nfc的蓝牙耳机. ...
- [转载]NFC源码分析之R/W工作模式
https://blog.csdn.net/zy00000000001/article/details/71183262 文章整理总结java层,NFC读取和写入Tag的流程. 整体的时序图: 1.读 ...
- NFC源码分析之初始化流程
Nfc的app代码位于: android/package/apps/Nfc/... 编译生成Nfc的apk和libnfc_nci_jni.so Nfc的协议栈和Hal相关的代码位于: system/n ...
- android源码分析
01_Android系统概述 02_Android系统的开发综述 03_Android的Linux内核与驱动程序 04_Android的底层库和程序 05_Android的JAVA虚拟机和JAVA环境 ...
- wpa_supplicant 源码分析 --conf 配置文件
原文:wpa_supplicant源码分析--conf配置文件 | Winddoing's Notes 解析 wpa_supplicant 的配置文件,一般叫做 wpa_supplicant.conf ...
- 【Golang源码分析】Go Web常用程序包gorilla/mux的使用与源码简析
目录[阅读时间:约10分钟] 一.概述 二.对比: gorilla/mux与net/http DefaultServeMux 三.简单使用 四.源码简析 1.NewRouter函数 2.HandleF ...
- SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)
[SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...
- SpringBoot-web开发(二): 页面和图标定制(源码分析)
[SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) 目录 一.首页 1. 源码分析 2. 访问首页测试 二.动态页面 1. 动态资源目录t ...
最新文章
- 关于 ListBox 自动换行
- SLAM算法总结——经典SLAM算法框架总结
- java类sample是公共的_应在名samle.java的文件_Andoid NDK编程 1 - 注册native函数
- JFinal interceptor - Deal with session attributes
- 数组的几个重要方法以及如何清空数组
- 1080. MOOC期终成绩 (25)-PAT乙级真题
- [wbia 1.1] heritrix抓取网页信息
- Spring AOP之XML配置
- DOC命令大全--(转)
- 设置路由器当作交换机使用
- 计量经济学计算机第1章习题,计量经济学第1章习题.pdf
- 用python写网络爬虫-下载百思不得姐视频
- SpringMVC接受参数
- L1-058 6翻了 (15 分)循环的妙用
- KiCad V6使用记录
- UrlRewrite.xml
- C语言——相关学习资源网站及工具
- UWA学堂上新:如何绕过Unity打造自己的HUD UI系统
- 后台管理框架 :花裤衩 / vue-admin-template
- 智慧城市同城V4 v2.1.5 同城小程序 同城信息