NFC源码分析之初始化流程

Nfc的app代码位于:
    android/package/apps/Nfc/... 编译生成Nfc的apk和libnfc_nci_jni.so
Nfc的协议栈和Hal相关的代码位于:
    system/nfc/... (原生的应该是位于/external/libnfc-nci)编译生成libnfc-nci.so
    在Nfc的app的AndroidManifest中查看application的节点,会有 "persisent = true"的属性,所以 这个app会在
Android systemserver启动的时候启动当前NfcApplication这个类,然后调用它的onCreate(), 此处就不讨论这个
流程,需要注意的是在Android N以后有一个FBE(DirectBootMode)模式,就是首次开机用户不解 锁此时的设计
要求是不启动Nfc的。在NfcApplication的onCreate当中会去实例化NfcService,开启Nfc的初始化.
相关代码:
1
AndroidManifest.xml
2
    <application android:name=".NfcApplication"
3
                android:icon="@drawable/icon"
4
                android:label="@string/app_name"
5
                android:theme="@android:style/Theme.Material.Light"
6
                android:persistent="true"
7
                android:hardwareAccelerated="false"
8
                android:backupAgent="com.android.nfc.NfcBackupAgent"
9
                android:killAfterRestore="false"
10
                android:usesCleartextTraffic="false"
11
                android:supportsRtl="true"
12
    >
NfcApplication.java
1
    public void onCreate() {
2
        super.onCreate();
3
4
        boolean isMainProcess = false;
5
        ......
6
        ActivityManager am = (ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
7
        List processes = am.getRunningAppProcesses();
8
        Iterator i = processes.iterator();
9
        while (i.hasNext()) {
10
            RunningAppProcessInfo appInfo = (RunningAppProcessInfo)(i.next());
11
            if (appInfo.pid == Process.myPid()) {
12
                isMainProcess =  (NFC_PROCESS.equals(appInfo.processName));
13
                break;
14
            }
15
        }
16
        if (UserHandle.myUserId() == 0 && isMainProcess) {
17
            mNfcService = new NfcService(this);
18
            ThreadedRenderer.enableForegroundTrimming();
19
        }
20
    }
整体时序图:
NFC源码分析之初始化流程_第1张图片
基本的类图关系:
NFC源码分析之初始化流程_第2张图片
整体架构分析:
    1)、开发第三方的使用Nfc功能应用
      使用framework层的api,路径:android.nfc.*和android.nfc.tech.*
      此时运行的进程是当前应用所在的进程。
    2)、系统Nfc中的包含NfcService等重要的类,很多功能的真正的实现在这个层面
      第三方的应用调用framework的api的接口,最终是通过binder调用到这里的实现
      如:
          NfcAdapterService extends INfcAdapter.Stub
          TagService extends INfcTag.Stub
      注意:这一步还包含了nci和nxp两个中JNI层的接口实现,根据配置的mk决定用那个,
      公司用的是nci的,通过Nfc app内部通过JNI调用到libnfc-nci.so当中.
      此时运行的进程是com.android.nfc(就是系统的nfc所在进程)所在的进程和第三
      方应用是处于不同进程的。
    3)、system/nfc的code,是nci芯片的HAL层和协议栈的实现,如NCI的代码实现,
        发送命令和接收event等功能。
        运行在自己的进程中,nxp的类似如下:[email protected]
    4)、最下层就是Nfc Driver了。通过HAL调用到这一层用来和Nfc chip交互.
        暂不清楚。
关于运行的进程的名字:
1
xp022430@cnbjlx24729:~$ adb shell ps -A | grep nfc
2
nfc      897    1  22164  3016 binder_thread_read 70db203f18 S [email protected]
3
nfc      2785  735 2283348  68876 SyS_epoll_wait 7d0f471e28 S com.android.nfc
4
u0_a114  7005  735 2249568  39120 SyS_epoll_wait 7d0f471e28 S com.sonymobile.nfcextension  
1、NfcService的主要实现
1
import com.android.nfc.DeviceHost.DeviceHostListener;
2
public class NfcService implements DeviceHostListener { }.
      实现了一个DeviceHostListener,DeviceHostListener是DeviceHost内部的一个接口。 DeviceHost里面定义
了,几乎NFC(上层功能)需要的全部interface和API,不同的厂家依据DeviceHost提 供的interface,实现对应的
内容,接口是统一规范这样来适配framework层的api。
    所以此处有必要分析DeviceHost的主要功能,列出自己关心的几个,NativeNfcManager实现了 DeviceHost的
具体功能,里面有很多接口的定义和NFC功能调用的api。
1
public interface DeviceHost {
2
    //NfcService实现了它的具体功能,里面基本上都是描述的整体nfc的状态的接口.
3
    public interface DeviceHostListener {
4
        //当检测到远端的tag的时候的回调,TagEndpoint:来表示远端的tag
5
        public void onRemoteEndpointDiscovered(TagEndpoint tag);
6
        ......
7
        //当卡模拟的Aid被选中的时候
8
        public void onCardEmulationAidSelected(byte[] aid,byte[] data, int evtSrc);
9
        //通知se相关的事件
10
        public void onConnectivityEvent(int evtSrc);
11
        //当P2P链接成功的时候
12
        public void onLlcpLinkActivated(NfcDepEndpoint device);
13
        ......
14
        //作为reader检测到remoteFiled(就是远端的card)的时候
15
        public void onRemoteFieldActivated();
16
        ......
17
    }
18
    //NativeNfcTag类实现了它的具体功能,用来实现Nfc Tag的一些功能。
19
    public interface TagEndpoint {
20
        //Tag建立起了连接
21
        boolean connect(int technology);
22
        ......
23
        //读取Tag中所用到的tech
24
        int[] getTechList();
25
        ......
26
        //读取Tag中的ndef消息
27
        byte[] readNdef();
28
        //向Tag中写入Ndef消息
29
        boolean writeNdef(byte[] data);
30
        ......
31
    }
32
    //Tag断开链接的回调
33
    public interface TagDisconnectedCallback {
34
        void onTagDisconnected(long handle);
35
    }
36
    ......
37
    //NativeP2pDevice类实现它的具体功能,P2P的Initiator发起端的功能实现。
38
    //自己没有跟这里的看起来即可以表示发起端,又可以表示接收端。
39
    public interface NfcDepEndpoint {
40
        /**
41
        * Peer-to-Peer Target
42
        */
43
        public static final short MODE_P2P_TARGET = 0x00;
44
        /**
45
        * Peer-to-Peer Initiator
46
        */
47
        public static final short MODE_P2P_INITIATOR = 0x01;
48
        ......
49
        public byte[] receive();
50
        public boolean send(byte[] data);
51
        public boolean connect();
52
        public boolean disconnect();
53
        ......
54
    }
55
    //NativeLlcpSocket类实现它的具体功能,
56
    //代表了一个llcp链接中的客户端的通信部分.
57
    //那么问题来了P2P的这个连接中谁是客户端?发起方?接收方?还是说并不是P2P才用这个?
58
    //比如read/write模式。这样就比较好定义客户端和服务端了。?这块不太清楚
59
    public interface LlcpSocket {
60
        ......
61
        public void connectToService(String serviceName) throws IOException;
62
        public void close() throws IOException;
63
        public void send(byte[] data) throws IOException;
64
        public int receive(byte[] recvBuff) throws IOException;
65
        public int getRemoteMiu();
66
        ......
67
        public int getLocalSap();
68
        ......
69
    }
70
    //NativeLlcpServiceSocket类实现它的具体功能,表示一个llcp链接中的服务端的通信部分.
71
    public interface LlcpServerSocket {
72
        //监听客户端的链接
73
        public LlcpSocket accept() throws IOException, LlcpException;
74
        //关闭服务
75
        public void close() throws IOException;
76
    }
77
    //NativeLlcpConnectionlessSocket类实现它的具体功能,代表在无连接通信中使用的LLCP对象?不太清楚.
78
    public interface LlcpConnectionlessSocket {
79
        public int getLinkMiu();
80
        public int getSap();
81
        public void send(int sap, byte[] data) throws IOException;
82
        public LlcpPacket receive() throws IOException;
83
        public void close() throws IOException;
84
    }
85
    //以上的接口在内部实现的时候如它们的名字所示,Native...,他们内部基本都有native方法去进一步的
86
    //通过JNI调用到native层实现的地方。
87
    
88
    //下面都是管理NFC功能的api,位于NativeNfcManager当中.
89
    public void checkFirmware();
90
    ......
91
    public boolean initialize();
92
    public String getName();
93
    public void enableDiscovery(NfcDiscoveryParameters params, boolean restart);
94
    public void doSetScreenState(int mScreenState);
95
    ......
96
    public void disableDiscovery();
97
    ......
98
    public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
99
            throws LlcpException;
100
    public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
101
            int rw, int linearBufferLength) throws LlcpException;
102
    public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
103
            int linearBufferLength) throws LlcpException;
104
    ......
105
}
         介绍完DeviceHost以及它内部的接口的实现,回到NfcServie这个类中看它的构造方法初始化了很多重要的
类如:TagService、 NfcAdapterService、NativeNfcManager、NfcDispatcher等,下面只是留了一些关心的部
分。 构造如下:
1
public NfcService(Application nfcApplication) {
2
    ......
3
    //Nfc Tag相关的一些操作.最终调用到的就是DeviceHost里面的interface的
4
    //实现NativeNfcTag此处就是final class TagService extends INfcTag.Stub {...}
5
    //然后在内部的方法中去调用DeviceHost.TagEndpoint,也就是调用到了NativeNfcTag.
6
    //下面的很多service都是这种实现方式,这样framework层api通过binder调用到native层实现的地方
7
    mNfcTagService = new TagService();
8
    
9
    //BluetoothAdapter类似,用于供外部调用NFC功能。个人理解adapter适配,也就是说其实是一个转接口
10
    //它只是提供统一规范,然后在它的内部会再去调用如NativeNfcManager里面真正的native的方法去和NFC打交道
11
    //这样做还有一个好处就是可以一定程度封装代码。结构清晰,代码隐蔽.
12
    //实现方式类似上面的TagService
13
    mNfcAdapter = new NfcAdapterService();
14
    //下面省略了一些NxpNfcAdapterService的初始化,暂时不清楚这些类的功能,可能是HiNXP扩展用.
15
    ......
16
    //卡模拟的service,现在直接被注释掉了,可能不用了,直接用对应的manager管理
17
    //mCardEmulationService = new CardEmulationService();
18
19
    //sService是NfcService
20
    sService = this;
21
22
    //NFC与屏幕锁定状态相关的类,用来方便屏幕状态的管理
23
    mScreenStateHelper = new ScreenStateHelper(mContext);
24
    
25
    //NativeNfcManager里面基本上都是native的方法,用于进一步调用到native层和NFC进行通信.
26
    //private DeviceHost mDeviceHost;可以看到NativeNfcManager就是DeviceHost
27
    mDeviceHost = new NativeNfcManager(mContext, this);
28
29
    //在进行一些handover等的时候,NFC对屏幕解锁的一些逻辑(某些状态下)。
30
    mNfcUnlockManager = NfcUnlockManager.getInstance();
31
    
32
    //使用别的技术如蓝牙进行handover的时候的帮助类,目前为止只有对蓝牙的实现,可以通过此类
33
    //把蓝牙地址、名字等信息封装成对应的标准NDEF Message进行传输.
34
    mHandoverDataParser = new HandoverDataParser();
35
36
    ......//此处省略了在Nfc在setup wizard阶段接受数据的处理
37
38
    //分发Nfc的不同的EVENT然后根据Android的policy区启动对应的activity处理相应的事件。
39
    mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);
40
    
41
    //基于LLCP连接的服务,含NdefPushService/SnepService/P2pEventManager
42
    //就是处理NFC进行P2P的时候的一些逻辑
43
    mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,
44
            mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
45
46
    //电源管理模块,主要是处理屏幕状态与NFC是否响应的联系
47
    mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
48
49
    ......
50
    //注册屏幕亮/灭,用户激活和切换 
51
    IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
52
    filter.addAction(Intent.ACTION_SCREEN_OFF);
53
    filter.addAction(Intent.ACTION_SCREEN_ON);
54
    filter.addAction(Intent.ACTION_USER_PRESENT);
55
    filter.addAction(Intent.ACTION_USER_SWITCHED);
56
    mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
57
    filter = new IntentFilter(Intent.ACTION_SHUTDOWN);
58
    mContext.registerReceiver(mOwnerReceiver, filter);
59
    IntentFilter ownerFilter = new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
60
    ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
61
    mContext.registerReceiver(mOwnerReceiver, ownerFilter);
62
    //关注程序安装和卸载  
63
    ownerFilter = new IntentFilter();
64
    ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
65
    ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
66
    ownerFilter.addDataScheme("package");
67
    mContext.registerReceiver(mOwnerReceiver, ownerFilter);
68
  ......
69
    
70
    //gmsa enable Nfc的时候,可能和一些测试case有关
71
    IntentFilter enableNfc = new IntentFilter();
72
    enableNfc.addAction(NxpConstants.ACTION_GSMA_ENABLE_NFC);
73
    mContext.registerReceiverAsUser(mEnableNfc, UserHandle.ALL, enableNfc, null, null);
74
    //Nfc状态变化的时候的广播
75
    IntentFilter lsFilter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
76
    //mContext.registerReceiver(mAlaReceiver, lsFilter);
77
    mContext.registerReceiverAsUser(mAlaReceiver, UserHandle.ALL, lsFilter, null, null);
78
    ......
79
    //把NfcAdapterService添加到ServiceManager当中,别的就可以通过   
80
    //INfcAdapter.Stub.asInterface(nfcServiceBinder).
81
    ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
82
83
    //Nfc和相机的一些交互,如相机启动的时候Nfc能不能工作等
84
    mCameraManager = (CameraManager)mContext.getSystemService(Context.CAMERA_SERVICE);
85
86
    ......
87
    //TASK_BOOT,异步的开始执行NFC的enable.
88
    new EnableDisableTask().execute(TASK_BOOT);
89
}
2、NfcService中的构造解析。
2.1、TagService
    它是NfcService的一个内部类,,framework层的接口api通过binder可以调用到它内部,它最终是操
NativeNfcTag.其中的方法基本都是一个模式获取到TagEndpoint,然后去调用它的方法,TagEndpoint 这个接口
就是NativeNfcTag实现的. 下面以connect为例子简单过一下流程.
1
final class TagService extends INfcTag.Stub{
2
    @Override
3
    public int connect(int nativeHandle, int technology) throws RemoteException {
4
        //检查权限
5
        NfcPermissions.enforceUserPermissions(mContext);
6
        
7
        TagEndpoint tag = null;
8
        //判断NFC是否可用.
9
        if (!isNfcEnabled()) {
10
            return ErrorCodes.ERROR_NOT_INITIALIZED;
11
        }
12
        //final HashMap mObjectMap = new HashMap();
13
        //tag在发现时候会调用registerTagObject添加到一个集合当中,
14
        //以:key = tag.getHandle() native的handle就是如在c/c++层的对象的代表,value = tag
15
        tag = (TagEndpoint) findObject(nativeHandle);
16
        ......
17
        //判断Tag是否还在范围内
18
        if (!tag.isPresent()) {
19
            return ErrorCodes.ERROR_DISCONNECT;
20
        }
21
        //调用NativeNfcTag的connect方法,传入technology
22
        //technology是Nfc Tag使用技术协议有:
23
        //public static final int NFC_A = 1;
24
        //public static final int NFC_B = 2;
25
        //public static final int ISO_DEP = 3;
26
        //public static final int NDEF = 6;
27
        //.....等等很多
28
        if (tag.connect(technology)) {
29
            return ErrorCodes.SUCCESS;
30
        } 
31
        ......
32
    }
33
    @Override
34
    public int reconnect(int nativeHandle) throws RemoteException {
35
        ......
36
        tag.reconnect())
37
        ......
38
    }
39
    @Override
40
    public int[] getTechList(int nativeHandle) throws RemoteException {
41
        ......
42
        tag.getTechList();
43
        ......
44
    }
45
    @Override
46
    public boolean isPresent(int nativeHandle) throws RemoteException {
47
        ......
48
        return tag.isPresent();
49
    }
50
    @Override
51
    public boolean isNdef(int nativeHandle) throws RemoteException {
52
        ......
53
        return tag.checkNdef(ndefInfo);
54
    }
55
    @Override
56
    public TransceiveResult transceive(int nativeHandle, byte[] data, boolean raw)
57
            throws RemoteException {
58
        ......
59
        /* find the tag in the hmap */
60
        tag = (TagEndpoint) findObject(nativeHandle);
61
        if (tag != null) {
62
            // Check if length is within limits
63
            if (data.length > getMaxTransceiveLength(tag.getConnectedTechnology())) {
64
                return new TransceiveResult(TransceiveResult.RESULT_EXCEEDED_LENGTH, null);
65
            }
66
            int[] targetLost = new int[1];
67
            response = tag.transceive(data, raw, targetLost);
68
            int result;
69
            if (response != null) {
70
                result = TransceiveResult.RESULT_SUCCESS;
71
            } else if (targetLost[0] == 1) {
72
                result = TransceiveResult.RESULT_TAGLOST;
73
            } else {
74
                result = TransceiveResult.RESULT_FAILURE;
75
            }
76
            return new TransceiveResult(result, response);
77
        }
78
        return null;
79
    }
80
    @Override
81
    public NdefMessage ndefRead(int nativeHandle) throws RemoteException {
82
        ......
83
        return new NdefMessage(buf);
84
        ......
85
    }
86
    @Override
87
    public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {
88
        ......
89
        tag.writeNdef(msg.toByteArray())
90
        ......
91
    }
92
    ......
93
    @Override
94
    public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {
95
        ......
96
        tag.formatNdef(key)
97
        ......
98
    }
99
    ......
100
}
       走到NativeNfcTag当中的
1
public class NativeNfcTag implements TagEndpoint {
2
    //通过JNI调用到了native层相应的实现处.
3
    private native int doConnect(int handle);
4
5
    ......
6
    public synchronized boolean connect(int technology) {
7
        return connectWithStatus(technology) == 0;
8
    }
9
10
    public synchronized int connectWithStatus(int technology) {
11
        ......
12
        int status = -1;
13
        for (int i = 0; i < mTechList.length; i++) {
14
            //当要链接的tech包含在支持的Tech的时候
15
            if (mTechList[i] == technology) {
16
                // Get the handle and connect, if not already connected
17
                if (mConnectedHandle != mTechHandles[i]) {
18
                    //如果是没有连接过,
19
                    if (mConnectedHandle == -1) {
20
                        //则直接调用到doConnect()  
21
                        status = doConnect(i);
22
                    } else {
23
                        //调用接口再次链接
24
                        status = reconnectWithStatus(i);
25
                    }
26
                    if (status == 0) {
27
                        mConnectedHandle = mTechHandles[i];
28
                        mConnectedTechIndex = i;
29
                    }
30
                } else {
31
                    //当我们已经连接过Tag的时候要分情况讨论
32
                    // 1) We are connected to a technology which has the same
33
                    //    handle; we do not support connecting at a different
34
                    //    level (libnfc auto-activates to the max level on
35
                    //    any handle).
36
                    // 2) We are connecting to the ndef technology - always
37
                    //    allowed.
38
                    if ((technology == TagTechnology.NDEF) ||
39
                            (technology == TagTechnology.NDEF_FORMATABLE)) {
40
                        // special case for NDEF, this will cause switch to ISO_DEP frame intf
41
                        i = 0;
42
                    }
43
                    status = reconnectWithStatus(i);
44
                    ......
45
                }
46
                break;
47
            }
48
        }
49
        ......
50
        return status;
51
    }
52
    ......
53
    native int doHandleReconnect(int handle);
54
    public synchronized int reconnectWithStatus(int handle) {
55
        ......
56
        int status = doHandleReconnect(handle);
57
        ......
58
        return status;
59
    }
60
}
       此处第一次连接的场景就是最终就是调用doConnect,doConnect是一个native的方法,对应到NativeNfcTag.cpp中的
1
/*******************************************************************************
2
**
3
** Function:        nativeNfcTag_doConnect
4
**
5
** Description:    Connect to the tag in RF field.
6
**                  e: JVM environment.
7
**                  o: Java object.
8
**                  targetHandle: Handle of the tag.
9
**
10
** Returns:        Must return NXP status code, which NFC service expects.
11
**
12
*******************************************************************************/
13
static jint nativeNfcTag_doConnect (JNIEnv*, jobject, jint targetHandle)
14
{
15
    ALOGV("%s: targetHandle = %d", __func__, targetHandle);
16
    int i = targetHandle;
17
    NfcTag& natTag = NfcTag::getInstance ();
18
    int retCode = NFCSTATUS_SUCCESS;
19
    sCurrentConnectedTargetType = natTag.mTechList[i];
20
    sCurrentConnectedTargetProtocol = natTag.mTechLibNfcTypes[i];
21
    ......
22
#if(NXP_EXTNS == TRUE) //可以在mk文件中搜索"DNXP_EXTNS"
23
    sCurrentConnectedHandle = targetHandle;
24
    if(sCurrentConnectedTargetProtocol == NFC_PROTOCOL_T3BT)
25
    {
26
        goto TheEnd;
27
    }
28
#endif
29
    if (sCurrentConnectedTargetProtocol != NFC_PROTOCOL_ISO_DEP)
30
    {
31
        ALOGV("%s() Nfc type = %d, do nothing for non ISO_DEP", __func__, 
32
                    sCurrentConnectedTargetProtocol);
33
        retCode = NFCSTATUS_SUCCESS; //打印Log的时候发现,即使进入到此处也是能打印出来。
34
        goto TheEnd;
35
    }
36
    /* Switching is required for CTS protocol paramter test case.*/
37
    if (sCurrentConnectedTargetType == TARGET_TYPE_ISO14443_3A || sCurrentConnectedTargetType == 
38
                            TARGET_TYPE_ISO14443_3B)
39
    {
40
      retCode = switchRfInterface(NFA_INTERFACE_FRAME) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
41
    }
42
    else
43
    {
44
        //切换NFC chip的RF interface.这样应该不会连接好像再往下会执行好几次的reconnect.
45
        retCode = switchRfInterface(NFA_INTERFACE_ISO_DEP) ? NFA_STATUS_OK : NFA_STATUS_FAILED;
46
    }
47
TheEnd:
48
    ALOGV("%s: exit 0x%X", __func__, retCode);
49
    return retCode;
50
}
        而native方法doHandleReconnect会调用到:
1
/*******************************************************************************
2
**
3
** Function:        nativeNfcTag_doHandleReconnect
4
**
5
** Description:    Re-connect to the tag in RF field.
6
**                  e: JVM environment.
7
**                  o: Java object.
8
**                  targetHandle: Handle of the tag.
9
**
10
** Returns:        Status code.
11
**
12
*******************************************************************************/
13
static jint nativeNfcTag_doHandleReconnect (JNIEnv *e, jobject o, jint targetHandle)
14
{
15
    ALOGV("%s: targetHandle = %d", __func__, targetHandle);
16
    ...
17
    //可以看到又调用到了前面说的nativeNfcTag_doConnect
18
    return nativeNfcTag_doConnect (e, o, targetHandle);
19
}
20
/*******************************************************************************
21
**
22
** Function:        switchRfInterface
23
**
24
** Description:    Switch controller's RF interface to frame, ISO-DEP, or NFC-DEP.
25
**                  rfInterface: Type of RF interface.
26
**
27
** Returns:        True if ok.
28
**
29
*******************************************************************************/
30
static bool switchRfInterface (tNFA_INTF_TYPE rfInterface)
31
{
32
    ALOGV("%s: rf intf = %d", __func__, rfInterface);
33
    ......
34
    bool rVal = true;
35
    if (rfInterface != sCurrentRfInterface)
36
    {
37
        //有变化的话,调用reSelect
38
        //Deactivates the tag and re-selects it with the specified rf interface.
39
        if (0 == reSelect(rfInterface, true))
40
        {
41
            sCurrentRfInterface = rfInterface;
42
            rVal = true;
43
        }
44
        ...
45
    }
46
    return rVal;
47
} 
      再往下才是真正的很复杂的逻辑,自己也不清楚RF相关的概念,先跟踪到这里。
2.2、NfcAdapterService
    也是位于NfcService当中,这个类方便了framework层的api目调用到Nfc app当中.大多从命名就可以看出来大
概的功能 enable和diasble是通过异步的方式执行的EnableDisableTask.最终肯定是走到了JNI层.
1
final class NfcAdapterService extends INfcAdapter.Stub{
2
    @Override
3
    public boolean enable() throws RemoteException {
4
      //检查权限
5
        NfcPermissions.enforceAdminPermissions(mContext);
6
        int val =  mDeviceHost.GetDefaultSE();
7
        Log.i(TAG, "getDefaultSE " + val);
8
        //默认的安全模块策略
9
        saveNfcOnSetting(true);
10
        //对比前面的NfcService的构造中的最后一步,会发现enable/disable都是通过这个Task
11
        new EnableDisableTask().execute(TASK_ENABLE);
12
        return true;
13
    }
14
    @Override
15
    public boolean disable(boolean saveState) throws RemoteException {
16
        ......
17
        new EnableDisableTask().execute(TASK_DISABLE);
18
        return true;
19
    }
20
    ......
21
    @Override
22
    public void resumePolling() {
23
        ......
24
        new ApplyRoutingTask().execute();
25
    }
26
    ......
27
    @Override
28
    public boolean enableNdefPush() throws RemoteException {
29
        ......
30
        mDeviceHost.doEnablep2p(mIsNdefPushEnabled);
31
        mP2pLinkManager.enableDisable(true, true);
32
        ......
33
    }
34
    @Override
35
    public boolean disableNdefPush() throws RemoteException {
36
        ......
37
        mP2pLinkManager.enableDisable(false, true);
38
        ......
39
    }
40
41
    //在activity中置此函数后,收到的消息会只在前台的APP处理。
42
    //场景是进入一个app如taginfo以后再读取nfc tag
43
    @Override
44
    public void setForegroundDispatch(PendingIntent intent,
45
            IntentFilter[] filters, TechListParcel techListsParcel) {
46
        ......
47
        mNfcDispatcher.setForegroundDispatch(intent, filters, techLists);
48
    }
49
    ......
50
    //得到卡模拟的interface
51
    @Override
52
    public INfcFCardEmulation getNfcFCardEmulationInterface() {
53
        ......
54
        return mCardEmulationManager.getNfcFCardEmulationInterface();
55
        ......
56
    }
57
    //返回当前Nfc的state: on/off/turning..
58
    @Override
59
    public int getState() throws RemoteException {
60
        synchronized (NfcService.this) {
61
            return mState;
62
        }
63
    }
64
    ......
65
    //分发检测到的Tag的信息,尝试去启动相应的activity
66
    @Override
67
    public void dispatch(Tag tag) throws RemoteException {
68
        ......
69
        mNfcDispatcher.dispatchTag(tag);
70
    }
71
    @Override
72
    public void setP2pModes(int initiatorModes, int targetModes) throws RemoteException {
73
        NfcPermissions.enforceAdminPermissions(mContext);
74
        mDeviceHost.setP2pInitiatorModes(initiatorModes);
75
        mDeviceHost.setP2pTargetModes(targetModes);
76
        applyRouting(true);
77
    }
78
    //外部第三方app调用,用来做卡模拟的.
79
    @Override
80
    public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras)
81
            throws RemoteException {
82
        ......
83
        synchronized (NfcService.this) {
84
            ...
85
            if (flags != 0) {
86
                mReaderModeParams = new ReaderModeParams();
87
                mReaderModeParams.callback = callback;
88
                mReaderModeParams.flags = flags;
89
                mReaderModeParams.presenceCheckDelay = extras != null
90
                        ? (extras.getInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY,
91
                                DEFAULT_PRESENCE_CHECK_DELAY))
92
                        : DEFAULT_PRESENCE_CHECK_DELAY;
93
                binder.linkToDeath(mReaderModeDeathRecipient, 0);
94
            } else {
95
                ......
96
                mReaderModeParams = null;
97
                binder.unlinkToDeath(mReaderModeDeathRecipient, 0);
98
            }
99
            Log.e(TAG, "applyRouting -4");
100
            applyRouting(false);
101
        }
102
    }
103
    ......
104
}
2.3、NfcDispatcher
        主要是实现收到底层检测道德Tag消息后,依据tag类型进行内容解析和数据分发,然后去启动相应的activity
1
class NfcDispatcher {
2
    ......
3
    //使用前台调度系统的时候最终会回调到这里。
4
    public synchronized void setForegroundDispatch(PendingIntent intent,
5
            IntentFilter[] filters, String[][] techLists) {
6
        //为相应的变量进行初始化
7
        mOverrideIntent = intent;
8
        mOverrideFilters = filters;
9
        mOverrideTechLists = techLists;
10
    }
11
    ......
12
    //分发Tag,内部分发时候调用具体的如:tryOverrides、tryNdef、tryTech去做进一步的处理.
13
    //整体是按照Android Nfc的分发系统来进行不同优先级的处理的,前台的最高,然后是注册
14
    //ACTION_NDEF_DISCOVERED,再然后是ACTION_TECH_DISCOVERED,最后是ACTION_TAG_DISCOVERD
15
    具体策略可查看官方文档:
16
    //https://developer.android.com/guide/topics/connectivity/nfc/nfc.html
17
    public int dispatchTag(Tag tag) {
18
        PendingIntent overrideIntent;
19
        IntentFilter[] overrideFilters;
20
        String[][] overrideTechLists;
21
        String[] provisioningMimes;
22
        boolean provisioningOnly;
23
        synchronized (this) {
24
            overrideFilters = mOverrideFilters;
25
            overrideIntent = mOverrideIntent;
26
            overrideTechLists = mOverrideTechLists;
27
            provisioningOnly = mProvisioningOnly;
28
            provisioningMimes = mProvisioningMimes;
29
        }
30
        //屏幕解锁相关
31
        boolean screenUnlocked = false;
32
        //如果是处在锁屏(屏幕已经点亮)
33
        if (!provisioningOnly &&
34
                mScreenStateHelper.checkScreenState() == 
35
                        ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
36
            //尝试去解锁屏幕
37
            screenUnlocked = handleNfcUnlock(tag);
38
            if (!screenUnlocked) {
39
                return DISPATCH_FAIL;
40
            }
41
        }
42
        ......
43
        //当使用前台调度系统的时候会通过它进行覆盖,成功的话就不去执行NFC基本的分发系统了.
44
        if (tryOverrides(dispatch, tag, message, overrideIntent, overrideFilters,
45
                overrideTechLists)) {
46
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
47
        }
48
        //尝试去进行Handover.如带Nfc的BT耳机、键盘等等.
49
        if (tryPeripheralHandover(message)) {
50
            if (DBG) Log.i(TAG, "matched BT HANDOVER");
51
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
52
        }
53
        //按理说现在Android还没有实现Nfc打开wifi呀?
54
        if (NfcWifiProtectedSetup.tryNfcWifiSetup(ndef, mContext)) {
55
            if (DBG) Log.i(TAG, "matched NFC WPS TOKEN");
56
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
57
        }
58
        ......
59
        //在进行NDEF Message的判断,判断是否为ACTION_NDEF_DISCOVERD
60
        if (tryNdef(dispatch, message)) {
61
            return screenUnlocked ? DISPATCH_UNLOCK : DISPATCH_SUCCESS;
62
        }
63
        ......
64
        //如果前面都没有成功处理消息,判断是否为ACTION_TECH_DISCOVERD.
65
        if (tryTech(dispatch, tag)) {
66
            return DISPATCH_SUCCESS;
67
        }
68
        //最后一种,也是优先级最低的intent为ACTION_TAG_DISCOVERD 。
69
        dispatch.setTagIntent();
70
        //直接尝试查询启动,有多个时候会弹框提示。
71
        if (dispatch.tryStartActivity()) {
72
            if (DBG) Log.i(TAG, "matched TAG");
73
            return DISPATCH_SUCCESS;
74
        }
75
        if (DBG) Log.i(TAG, "no match");
76
        return DISPATCH_FAIL;
77
    }
78
}
       tryOverrides、tryNdef、tryTech流程基本相同,根据传入的tag的不同的intent,最后去调用 DispatchInfo类
中的.
1
boolean tryStartActivity() {
2
    //查询所有注册了的携带指定action的intent的activities
3
    //注意到这之前就已经为intent配置好了对应的action
4
    List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(intent, 0,
5
            ActivityManager.getCurrentUser());
6
    if (activities.size() > 0) {
7
        context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
8
        NfcIddEvent.NfcTag.dispatchedToApp(tag, activities);
9
        return true;
10
    }
11
    return false;
12
}
13
//道理同上
14
boolean tryStartActivity(Intent intentToStart) {
15
    List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(
16
            intentToStart, 0, ActivityManager.getCurrentUser());
17
    if (activities.size() > 0) {
18
        rootIntent.putExtra(NfcRootActivity.EXTRA_LAUNCH_INTENT, intentToStart);
19
        context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
20
        NfcIddEvent.NfcTag.dispatchedToApp(tag, activities);
21
        return true;
22
    }
23
    return false;
24
}
2.4、P2pLinkManager
    在这个java文件中的开头是一个接口,是P2P时的事件回调,这些回调事件都是对应于用户的UI界面的操作。
    //接口由P2pEventManager实现.class P2pEventManager implements P2pEventListener, SendUi.Callback.
    //用于管理P2P的时候的用户交互,如震动、声音、传输动画等.
1
    interface P2pEventListener {
2
        //user想要通过Nfc去share一些数据,但是远端的设备还没有onRange,对用户进行提示.
3
        public void onP2pNfcTapRequested();
4
        //等待传输超时的回调.
5
        public void onP2pTimeoutWaitingForLink();
6
        //表明P2P的设备in range
7
        public void onP2pInRange();
8
        //当一个NDEF的数据准备发送,并且需要确认的时候调用.
9
        public void onP2pSendConfirmationRequested();
10
        //P2P发送完成
11
        public void onP2pSendComplete();
12
        ......
13
        //Called to indicate the remote device does not support connection handover
14
        public void onP2pHandoverNotSupported();
15
        //Called to indicate the device is busy with another handover transfer
16
        public void onP2pHandoverBusy();
17
        //当P2P接受完成的时候
18
        public void onP2pReceiveComplete(boolean playSound);
19
        //Indicates the P2P device went out of range.
20
        public void onP2pOutOfRange();
21
        //Indicates the P2P Beam UI is in idle mode.
22
        public boolean isP2pIdle();
23
        //此处还有两个回调,这两个CallBack是在P2pLinkManager中实现的
24
        public interface Callback {
25
            public void onP2pSendConfirmed();
26
            public void onP2pCanceled();
27
        }
28
    }
        不同于P2pEventManager,此处P2pLinkManager是真正管理通过P2P模式接受和发送的NDEF消息。
1
    class P2pLinkManager implements Handler.Callback, P2pEventListener.Callback {
2
        ......
3
        //构造,创建了很多P2P通信需要的server
4
        public P2pLinkManager(Context context, HandoverDataParser handoverDataParser, int 
5
                              defaultMiu,
6
                int defaultRwSize) {
7
            //用于NdefPushServer:启动NPP Server,等待Client连接
8
            mNdefPushServer = new NdefPushServer(NDEFPUSH_SAP, mNppCallback);
9
            
10
            //用于启动SNPP Server,等待Client连接
11
            mDefaultSnepServer = new SnepServer(mDefaultSnepCallback, defaultMiu, defaultRwSize);
12
            
13
            //启动Handover Server,等待Client连接
14
            mHandoverServer = new HandoverServer(context, HANDOVER_SAP, handoverDataParser, 
15
                                                 mHandoverCallback);
16
            ......
17
            //实例化P2pEventManager,用于将底层消息notify到UI或者上层APP
18
            mEventListener = new P2pEventManager(context, this);
19
            mHandler = new Handler(this);
20
            ......
21
        }
22
        //处理mHandler中的信息,底层处理完请求后会调用NativeNfcManager中相应回调,然后往外发消息。
23
        @Override  
24
        public boolean handleMessage(Message msg) {  
25
            switch (msg.what) {  
26
                case MSG_START_ECHOSERVER:  
27
                    ...  
28
                case MSG_STOP_ECHOSERVER:  
29
                    ...  
30
                case MSG_WAIT_FOR_LINK_TIMEOUT:  
31
                    ...  
32
                case MSG_DEBOUNCE_TIMEOUT:  
33
                    ...  
34
                case MSG_RECEIVE_HANDOVER:  
35
                    ...  
36
                case MSG_RECEIVE_COMPLETE:  
37
                    ...  
38
                case MSG_HANDOVER_NOT_SUPPORTED:  
39
                    ...  
40
                case MSG_SEND_COMPLETE:  
41
                ...  
42
            }  
43
            return true;  
44
        } 
45
    }
       而NdefPushServer、SnepServer和HandoverServer在此处的逻辑处理方式基本相同,不同的是它们按照
各自的协议进行实现的.以NdefPushServer为例:在NfcService中的适当的阶段会调用P2pLinkManager的
enableDisable,进而调用到以上三个server的start方法,还是以NdefPushServer为例. NdefPushServer.java
1
public void start() {
2
    synchronized (this) {
3
        if (mServerThread == null) {
4
            mServerThread = new ServerThread();
5
            mServerThread.start();
6
        }
7
    }
8
}
     实例化ServerThread并调用它的start
1
/** Server class, used to listen for incoming connection request */
2
class ServerThread extends Thread{
3
    boolean mRunning = true;
4
    LlcpServerSocket mServerSocket;
5
    @Override
6
    public void run() {
7
        boolean threadRunning;
8
        synchronized (NdefPushServer.this) {
9
            threadRunning = mRunning;
10
        }
11
        while (threadRunning) {
12
            try {
13
                synchronized (NdefPushServer.this) {
14
                    //创建llcp服务端socket,根据所用的协议,填写不同的参数
15
                    mServerSocket = mService.createLlcpServerSocket(mSap, SERVICE_NAME,
16
                            MIU, 1, 1024);
17
                }
18
                ......
19
                synchronized (NdefPushServer.this) {
20
                    threadRunning = mRunning;
21
                }
22
                
23
                while (threadRunning) {
24
                    LlcpServerSocket serverSocket;
25
                    synchronized (NdefPushServer.this) {
26
                        serverSocket = mServerSocket;
27
                    }
28
                    ......
29
                    //阻塞等待客户端连接,一个server端,可以有多个客户端连接  
30
                    LlcpSocket communicationSocket = serverSocket.accept();
31
                    //每次client端连接都会创建新的thread,用于连接服务端.
32
                    if (communicationSocket != null) {
33
                        new ConnectionThread(communicationSocket).start();
34
                    }
35
                    synchronized (NdefPushServer.this) {
36
                        threadRunning = mRunning;
37
                    }
38
                }
39
                if (DBG) Log.d(TAG, "stop running");
40
            } catch (LlcpException e) {
41
                ......
42
            } finally {
43
                ......
44
                mServerSocket.close();
45
            }
46
        }
47
    }
48
    ......
49
}
当客户端建立起链接后,会调用到ConnectionThread线程的run方法:
1
/** Connection class, used to handle incoming connections */
2
private class ConnectionThread extends Thread {
3
    private LlcpSocket mSock;
4
    ConnectionThread(LlcpSocket sock) {
5
        super(TAG);
6
        mSock = sock;
7
    }
8
    @Override
9
    public void run() {
10
        try {
11
            ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024);
12
            byte[] partial = new byte[1024];
13
            int size;
14
            boolean connectionBroken = false;
15
            //从远程服务端获取数据.
16
            // Get raw data from remote server
17
            while(!connectionBroken) {
18
                try {
19
                    //把收到数据写入buffer
20
                    size = mSock.receive(partial);
21
                    ......
22
                    buffer.write(partial, 0, size);
23
                } catch (IOException e) {...}
24
            }
25
            //把接收到的数据转换成NDEF Message
26
            // Build NDEF message set from the stream
27
            NdefPushProtocol msg = new NdefPushProtocol(buffer.toByteArray());
28
            if (DBG) Log.d(TAG, "got message " + msg.toString());
29
            // Send the intent for the fake tag
30
            //通过回调做进一步的对消息的处理.mCallback是最开始实例化的时候传入的mNppCallback
31
            mCallback.onMessageReceived(msg.getImmediate());
32
        } catch (FormatException e) {
33
            .....
34
        } finally {......}
35
    }
36
}
     callback位于P2pLinkManager当中
1
final NdefPushServer.Callback mNppCallback = new NdefPushServer.Callback() {
2
    @Override
3
    public void onMessageReceived(NdefMessage msg) {
4
        onReceiveComplete(msg);
5
    }
6
};
7
void onReceiveComplete(NdefMessage msg) {
8
    // Make callbacks on UI thread
9
    mHandler.obtainMessage(MSG_RECEIVE_COMPLETE, msg).sendToTarget();
10
    NfcIddEvent.Beam.Ndef.receive(msg);
11
}
     而其它的服务启动的大概流程和上面这个差不多。
     接下来再看P2pLinkManager中对P2pEventManager的处理.
1
//Manages vibration, sound and animation for P2P events.
2
public class P2pEventManager implements P2pEventListener, SendUi.Callback {
3
    public P2pEventManager(Context context, P2pEventListener.Callback callback) {
4
        mNfcService = NfcService.getInstance();
5
        mContext = context;
6
        mCallback = callback;
7
        //实例化震动管理和通知管理。
8
        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
9
        ......
10
        //用于和UI界面交互,SendUi类实现了一些动画。
11
        mSendUi = new SendUi(context, this);
12
        主要函数如下:从名字也能看出大概意思,碰到相关BUG再详细分析.
13
        public void onP2pInRange()  
14
        public void onP2pNfcTapRequested()  
15
        public void onP2pTimeoutWaitingForLink()  
16
        public void onP2pSendConfirmationRequested()  
17
        public void onP2pSendComplete()  
18
        public void onP2pHandoverNotSupported()  
19
        public void onP2pReceiveComplete(boolean playSound)  
20
        public void onP2pOutOfRange()  
21
        public void onSendConfirmed()  
22
        public void onCanceled()  
23
        public void onP2pSendDebounce()  
24
        public void onP2pResumeSend()  
25
}
2.5、NativeNfcManager
      此类是各芯片厂商的自己的具体功能实现通过JNI调用的对应的lib库当中,目前AOSP下包含了 nxp和nci两
类,由于公司是用的nci. 在NativeNfcManager.java当中
1
static {
2
    System.loadLibrary("nfc_nci_jni");//对应于nci包下的jni的实现
3
}
4
//构造:
5
public native boolean initializeNativeStructure();
6
public NativeNfcManager(Context context, DeviceHostListener listener) {
7
    mListener = listener;
8

你可能感兴趣的:(NFC知识)