NXP

NFC源码分析-ZGS

2019-07-12 11:35发布

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的初始化.相关代码:
1AndroidManifest.xml2    <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();34        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   }整体时序图:
基本的类图关系:
整体架构分析:
    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的(在android.mk 文件中,通过LOCAL_SRC_FILES +=  $(call all-java-files-under, nci) 来加载nci 的目录,所以,我们公司用的也是NCI目录)。通过Nfc app内部通过JNI调用到libnfc-nci.so当中.
      此时运行的进程是com.android.nfc(就是系统的nfc所在进程)所在的进程和第三
      方应用是处于不同进程的。
    3)、system/nfc的code,是nci芯片的HAL层和协议栈的实现,如NCI的代码实现,
        发送命令和接收event等功能。
        运行在自己的进程中,nxp的类似如下:vendor.nxp.nxpnfc@1.0-service
    4)、最下层就是Nfc Driver了。通过HAL调用到这一层用来和Nfc chip交互.
        暂不清楚。
关于运行的进程的名字:
1xp022430@cnbjlx24729:~$ adb shell ps -A | grep nfc2nfc     897   1 22164 3016 binder_thread_read 70db203f18 S vendor.nxp.nxpnfc@1.0-service3nfc     2785 735 2283348 68876 SyS_epoll_wait 7d0f471e28 S com.android.nfc4u0_a114 7005 735 2249568 39120 SyS_epoll_wait 7d0f471e28 S com.sonymobile.nfcextension  1、NfcService的主要实现
1import com.android.nfc.DeviceHost.DeviceHostListener;2public class NfcService implements DeviceHostListener { }.      实现了一个DeviceHostListener,DeviceHostListener是DeviceHost内部的一个接口。DeviceHost里面定义了,几乎NFC(上层功能)需要的全部interface和API,不同的厂家依据DeviceHost提供的interface,实现对应的
内容,接口是统一规范这样来适配framework层的api。
    所以此处有必要分析DeviceHost的主要功能,列出自己关心的几个,NativeNfcManager实现了DeviceHost的具体功能,里面有很多接口的定义和NFC功能调用的api。
1public interface DeviceHost {2    //NfcService实现了它的具体功能,里面基本上都是描述的整体nfc的状态的接口.3    public interface DeviceHostListener {4        //当检测到远端的tag的时候的回调,TagEndpoint:来表示远端的tag5        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中所用到的tech24        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 Target42        */43        public static final short MODE_P2P_TARGET = 0x00;44        /**45        * Peer-to-Peer Initiator46        */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等,下面只是留了一些关心的部
分。构造如下:
1public 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    //实现方式类似上面的TagService13    mNfcAdapter = new NfcAdapterService();14    //下面省略了一些NxpNfcAdapterService的初始化,暂时不清楚这些类的功能,可能是HiNXP扩展用.15   ......16    //卡模拟的service,现在直接被注释掉了,可能不用了,直接用对应的manager管理17    //mCardEmulationService = new CardEmulationService();1819    //sService是NfcService20    sService = this;2122    //NFC与屏幕锁定状态相关的类,用来方便屏幕状态的管理23    mScreenStateHelper = new ScreenStateHelper(mContext);24    25    //NativeNfcManager里面基本上都是native的方法,用于进一步调用到native层和NFC进行通信.26    //private DeviceHost mDeviceHost;可以看到NativeNfcManager就是DeviceHost27    mDeviceHost = new NativeNfcManager(mContext, this);2829    //在进行一些handover等的时候,NFC对屏幕解锁的一些逻辑(某些状态下)。30    mNfcUnlockManager = NfcUnlockManager.getInstance();31    32    //使用别的技术如蓝牙进行handover的时候的帮助类,目前为止只有对蓝牙的实现,可以通过此类33    //把蓝牙地址、名字等信息封装成对应的标准NDEF Message进行传输.34    mHandoverDataParser = new HandoverDataParser();3536   ......//此处省略了在Nfc在setup wizard阶段接受数据的处理3738    //分发Nfc的不同的EVENT然后根据Android的policy区启动对应的activity处理相应的事件。39    mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);40    41    //基于LLCP连接的服务,含NdefPushService/SnepService/P2pEventManager42    //就是处理NFC进行P2P的时候的一些逻辑43    mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,44            mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());4546    //电源管理模块,主要是处理屏幕状态与NFC是否响应的联系47    mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);4849   ......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);8283    //Nfc和相机的一些交互,如相机启动的时候Nfc能不能工作等84    mCameraManager = (CameraManager)mContext.getSystemService(Context.CAMERA_SERVICE);8586   ......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为例子简单过一下流程.1final class TagService extends INfcTag.Stub{2    @Override3    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 = tag15        tag = (TagEndpoint) findObject(nativeHandle);16       ......17        //判断Tag是否还在范围内18        if (!tag.isPresent()) {19            return ErrorCodes.ERROR_DISCONNECT;20       }21        //调用NativeNfcTag的connect方法,传入technology22        //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    @Override34    public int reconnect(int nativeHandle) throws RemoteException {35       ......36        tag.reconnect())37       ......38   }39    @Override40    public int[] getTechList(int nativeHandle) throws RemoteException {41       ......42        tag.getTechList();43       ......44   }45    @Override46    public boolean isPresent(int nativeHandle) throws RemoteException {47       ......48        return tag.isPresent();49   }50    @Override51    public boolean isNdef(int nativeHandle) throws RemoteException {52       ......53        return tag.checkNdef(ndefInfo);54   }55    @Override56    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 limits63            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    @Override81    public NdefMessage ndefRead(int nativeHandle) throws RemoteException {82       ......83        return new NdefMessage(buf);84       ......85   }86    @Override87    public int ndefWrite(int nativeHandle, NdefMessage msg) throws RemoteException {88       ......89        tag.writeNdef(msg.toByteArray())90       ......91   }92   ......93    @Override94    public int formatNdef(int nativeHandle, byte[] key) throws RemoteException {95       ......96        tag.formatNdef(key)97       ......98   }99   ......100}       走到NativeNfcTag当中的
1public class NativeNfcTag implements TagEndpoint {2    //通过JNI调用到了native层相应的实现处.3    private native int doConnect(int handle);45   ......6    public synchronized boolean connect(int technology) {7        return connectWithStatus(technology) == 0;8   }910    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 connected17                if (mConnectedHandle != mTechHandles[i]) {18                    //如果是没有连接过,19                    if (mConnectedHandle == -1) {20                        //则直接调用到doConnect()  21                        status = doConnect(i);22                   } else {23                        //调用接口再次链接24                        status = reconnectWithStatus(i