zoukankan      html  css  js  c++  java
  • NFCApplication 启动分析(原创)

    在上篇文章NfcService启动中有说到会DoInitialize,会调用到libnxp-nfc-nci的库中的NfcAppliaction.Initialize().

    void NfcAdaptation::Initialize ()
    {    
        ............................
        GKI_init ();
        GKI_enable ();
        GKI_create_task ((TASKPTR)NFCA_TASK, BTU_TASK, (INT8*)"NFCA_TASK", 0, 0, (pthread_cond_t*)NULL, NULL);
        {
            AutoThreadMutex guard(mCondVar);
            GKI_create_task ((TASKPTR)Thread, MMI_TASK, (INT8*)"NFCA_THREAD", 0, 0, (pthread_cond_t*)NULL, NULL);
            mCondVar.wait();
        }
    ............................
    }    
    继续看看 GKI_init()里做了一些什么东东:
    void GKI_init(void)
    {
        pthread_mutexattr_t attr;
        tGKI_OS             *p_os;
    
        memset (&gki_cb, 0, sizeof (gki_cb));
        
        //主要初始化mailboxes置空    
        gki_buffer_init();
        //定时器的初始化归零  
        gki_timers_init();
        ......................
    }

    GKI_enable()没做啥事,直接跳过

    最重要的是两个GKI_Create_Task。

    分别运行NFCA_TASK和Thread.分别来看看:

    UINT32 NfcAdaptation::NFCA_TASK (UINT32 arg)
    {
        const char* func = "NfcAdaptation::NFCA_TASK";
        ALOGD ("%s: enter", func);
        GKI_run (0);
        ALOGD ("%s: exit", func);
        return 0;
    }
    运行GKI_RUN(0):
    void GKI_run (void *p_task_id)
    {
       .......................................................................
        GKI_TRACE_2("GKI_run, run_cond(%x)=%d ", p_run_cond, *p_run_cond);
        for (;GKI_TIMER_TICK_EXIT_COND != *p_run_cond;)
        {
            do
            {
                /* adjust hear bit tick in btld by changning TICKS_PER_SEC!!!!! this formula works only for
                 * 1-1000ms heart beat units! */
                delay.tv_sec = LINUX_SEC / 1000;
                delay.tv_nsec = 1000 * 1000 * (LINUX_SEC % 1000);
    
                /* [u]sleep can't be used because it uses SIGALRM */
                do
                {
                    err = nanosleep(&delay, &delay);
                } while (err < 0 && errno == EINTR);
    
                if (GKI_TIMER_TICK_RUN_COND != *p_run_cond)
                    break; //GKI has shutdown
    
                /* the unit should be alsways 1 (1 tick). only if you vary for some reason heart beat tick
                 * e.g. power saving you may want to provide more ticks
                 */
                GKI_timer_update( 1 );
                /* BT_TRACE_2( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, "update: tv_sec: %d, tv_nsec: %d", delay.tv_sec, delay.tv_nsec ); */
            } while ( GKI_TIMER_TICK_RUN_COND == *p_run_cond);
    
            /* currently on reason to exit above loop is no_timer_suspend == GKI_TIMER_TICK_STOP_COND
             * block timer main thread till re-armed by  */
    #ifdef GKI_TICK_TIMER_DEBUG
            BT_TRACE_0( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, ">>> SUSPENDED GKI_timer_update()" );
    #endif
            if (GKI_TIMER_TICK_EXIT_COND != *p_run_cond) {
                GKI_TRACE_1("%s waiting timer mutex", __func__);
                pthread_mutex_lock( &gki_cb.os.gki_timer_mutex );
                pthread_cond_wait( &gki_cb.os.gki_timer_cond, &gki_cb.os.gki_timer_mutex );
                pthread_mutex_unlock( &gki_cb.os.gki_timer_mutex );
                GKI_TRACE_1("%s exited timer mutex", __func__);
            }
            /* potentially we need to adjust os gki_cb.com.OSTicks */
    
    #ifdef GKI_TICK_TIMER_DEBUG
            BT_TRACE_1( TRACE_LAYER_HCI, TRACE_TYPE_DEBUG, ">>> RESTARTED GKI_timer_update(): run_cond: %d",
                        *p_run_cond );
    #endif
        } /* for */
    ...........................................................
    }

    更新GKI Timer.

    NFCA_TASK的线程工作分析完了,我们来继续分析Thread的工作:

    UINT32 NfcAdaptation::Thread (UINT32 arg)
    {
        const char* func = "NfcAdaptation::Thread";
        ALOGD ("%s: enter", func);
    
        {
            ThreadCondVar    CondVar;
            AutoThreadMutex  guard(CondVar);
            GKI_create_task ((TASKPTR)nfc_task, NFC_TASK, (INT8*)"NFC_TASK", 0, 0, (pthread_cond_t*)CondVar, (pthread_mutex_t*)CondVar);
            CondVar.wait();
        }
    
        NfcAdaptation::GetInstance().signal();
    
        GKI_exit_task (GKI_get_taskid ());
        ALOGD ("%s: exit", func);
        return 0;
    }

    这个又创建了一个GKI_create_task, 会开线程任务运行 nfc_task这个函数。继续看看:

    UINT32 nfc_task (UINT32 param)
    {
        UINT16  event;
        BT_HDR  *p_msg;
        BOOLEAN free_buf;
    
        /* Initialize the nfc control block */
        memset (&nfc_cb, 0, sizeof (tNFC_CB));
        nfc_cb.trace_level = NFC_INITIAL_TRACE_LEVEL;
    
        NFC_TRACE_DEBUG0 ("NFC_TASK started.");
    
        /* main loop */
        while (TRUE)
        {
           //线程挂起等待,直接有事件上来唤醒线程继续往下运行  
            event = GKI_wait (0xFFFF, 0);
    
            /* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */
            if (event & NFC_TASK_EVT_TRANSPORT_READY)
            {
                NFC_TRACE_DEBUG0 ("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY.");
    
                /* Reset the NFC controller. */
                nfc_set_state (NFC_STATE_CORE_INIT);
                nci_snd_core_reset (NCI_RESET_TYPE_RESET_CFG);
            }
    
            if (event & NFC_MBOX_EVT_MASK)
            {
                //从mailboxed中取消息出来读消息,然后根据消息类型做分发处理
                /* Process all incoming NCI messages */
                while ((p_msg = (BT_HDR *) GKI_read_mbox (NFC_MBOX_ID)) != NULL)
                {
                    free_buf = TRUE;
    
                    /* Determine the input message type. */
                    switch (p_msg->event & BT_EVT_MASK)
                    {
                        case BT_EVT_TO_NFC_NCI:
                            free_buf = nfc_ncif_process_event (p_msg);
                            break;
    
                        case BT_EVT_TO_START_TIMER :
                            /* Start nfc_task 1-sec resolution timer */
                            GKI_start_timer (NFC_TIMER_ID, GKI_SECS_TO_TICKS (1), TRUE);
                            break;
    
                        case BT_EVT_TO_START_QUICK_TIMER :
                            /* Quick-timer is required for LLCP */
                            GKI_start_timer (NFC_QUICK_TIMER_ID, ((GKI_SECS_TO_TICKS (1) / QUICK_TIMER_TICKS_PER_SEC)), TRUE);
                            break;
    
                        case BT_EVT_TO_NFC_MSGS:
                            nfc_main_handle_hal_evt ((tNFC_HAL_EVT_MSG*)p_msg);
                            break;
    
                        default:
                            NFC_TRACE_DEBUG1 ("nfc_task: unhandle mbox message, event=%04x", p_msg->event);
                            break;
                    }
    
                    if (free_buf)
                    {
                        GKI_freebuf (p_msg);
                    }
                }
            }
    
            /* Process gki timer tick */
            if (event & NFC_TIMER_EVT_MASK)
            {
                nfc_process_timer_evt ();
            }
    
            /* Process quick timer tick */
            if (event & NFC_QUICK_TIMER_EVT_MASK)
            {
                nfc_process_quick_timer_evt ();
            }
    
    #if (defined (NFA_INCLUDED) && NFA_INCLUDED == TRUE)
            if (event & NFA_MBOX_EVT_MASK)
            {
                while ((p_msg = (BT_HDR *) GKI_read_mbox (NFA_MBOX_ID)) != NULL)
                {
                    nfa_sys_event (p_msg);
                }
            }
    
            if (event & NFA_TIMER_EVT_MASK)
            {
                nfa_sys_timer_update ();
            }
    #endif
    
        }
    
    
        NFC_TRACE_DEBUG0 ("nfc_task terminated");
    
        GKI_exit_task (GKI_get_taskid ());
        return 0;
    }

    分析完这些后,我们一鼓作气,继续往下:

    void NfcAdaptation::InitializeHalDeviceContext ()
    {
    ....................................................................
        ret = hw_get_module (nci_hal_module, &hw_module);
        if (ret == 0)
        {
            ret = nfc_nci_open (hw_module, &mHalDeviceContext);
            if (ret != 0)
                ALOGE ("%s: nfc_nci_open fail", func);
        }
        else
            ALOGE ("%s: fail hw_get_module %s", func, nci_hal_module);
        ALOGD ("%s: exit", func);
    }

    终于看到了要去调用HAL层了。。

    nci_hal_module = "nfc_nci.pn54x"

    nfc_nci_open 会调到nfc_open

    static int nfc_open(const hw_module_t* module, const char* name,
            hw_device_t** device)
    {
        ALOGD("%s: enter; name=%s", __FUNCTION__, name);
        int retval = 0; /* 0 is ok; -1 is error */
    
        if (strcmp(name, NFC_NCI_CONTROLLER) == 0)
        {
            pn547_dev_t *dev = calloc(1, sizeof(pn547_dev_t));
    
            /* Common hw_device_t fields */
            dev->nci_device.common.tag = HARDWARE_DEVICE_TAG;
            dev->nci_device.common.version = 0x00010000; /* [31:16] major, [15:0] minor */
            dev->nci_device.common.module = (struct hw_module_t*) module;
            dev->nci_device.common.close = nfc_close;
    
            /* NCI HAL method pointers */
            dev->nci_device.open = hal_open;
            dev->nci_device.write = hal_write;
            dev->nci_device.ioctl = hal_ioctl;
            dev->nci_device.core_initialized = hal_core_initialized;
            dev->nci_device.pre_discover = hal_pre_discover;
            dev->nci_device.close = hal_close;
            dev->nci_device.control_granted = hal_control_granted;
            dev->nci_device.power_cycle = hal_power_cycle;
    
            *device = (hw_device_t*) dev;
        }
        else
        {
            retval = -EINVAL;
        }
    
        ALOGD("%s: exit %d", __FUNCTION__, retval);
        return retval;
    }

    此时NFC的开关还没有打开,我们再看看NFC 开关打开时,发生了神马:

    从设置中点击开关,会调用NfcEnable 通过Binder 会远端调用NfcService.enable(),这个过程我就不贴代码了,往下看enable() 中做了什么

    public boolean enable() throws RemoteException {
    ....................................
        new EnableDisableTask().execute(TASK_ENABLE);
    .............................
    }

    创建一个异步线程去执行TASK_ENABLE

            boolean enableInternal() {try {
                    mRoutingWakeLock.acquire();
                    try {
                        if (!mDeviceHost.initialize()) {
                            Log.w(TAG, "Error enabling NFC");
                            updateState(NfcAdapter.STATE_OFF);
                            return false;
                        }
                    } finally {
                        mRoutingWakeLock.release();
                    }
                } finally {
                    watchDog.cancel();
                }
                checkSecureElementConfuration();
    
                mIsRouteForced = true;
                if (mIsHceCapable) {
                    // Generate the initial card emulation routing table
                    fAidTableFull = false;
                    mCardEmulationManager.onNfcEnabled();
                }
                mIsRouteForced = false;
    
                synchronized (NfcService.this) {
                    mObjectMap.clear();
                    mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
                    updateState(NfcAdapter.STATE_ON);
                }
    
                synchronized (NfcService.this) {
                    if(mDeviceHost.doCheckJcopDlAtBoot()) {
                        /* start jcop download */
                        Log.i(TAG, "Calling Jcop Download");
         
                    }
                }
    
                initSoundPool();
                /* Start polling loop */
                Log.e(TAG, "applyRouting -3");
                mScreenState = mScreenStateHelper.checkScreenState();
                mDeviceHost.doSetScreenOrPowerState(mScreenState);
                mIsRoutingTableDirty = true;
                applyRouting(true);
                return true;
            }

    看点看三行:

      

    boolean enableInternal() {
    if (mState == NfcAdapter.STATE_ON) {
    return true;
    }
    Log.i(TAG, "Enabling NFC");
    updateState(NfcAdapter.STATE_TURNING_ON);
    int timeout = mDeviceHost.getNfcInitTimeout();
    if (timeout < INIT_WATCHDOG_MS)
    {
    timeout = INIT_WATCHDOG_MS;
    }
    Log.i(TAG, "Enabling NFC timeout" +timeout);
    WatchDogThread watchDog = new WatchDogThread("enableInternal", timeout);
    watchDog.start();
    try {
    mRoutingWakeLock.acquire();
    try {
    if (!mDeviceHost.initialize()) {
    Log.w(TAG, "Error enabling NFC");
    updateState(NfcAdapter.STATE_OFF);
    return false;
    }
    } finally {
    mRoutingWakeLock.release();
    }
    } finally {
    watchDog.cancel();
    }
    checkSecureElementConfuration();

    mIsRouteForced = true;
    if (mIsHceCapable) {
    // Generate the initial card emulation routing table
    fAidTableFull = false;
    mCardEmulationManager.onNfcEnabled();
    }
    mIsRouteForced = false;

    synchronized (NfcService.this) {
    mObjectMap.clear();
    mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
    updateState(NfcAdapter.STATE_ON);
    }

    synchronized (NfcService.this) {
    if(mDeviceHost.doCheckJcopDlAtBoot()) {
    /* start jcop download */
    Log.i(TAG, "Calling Jcop Download");
    jcopOsDownload();
    }
    }

    initSoundPool();
    /* Start polling loop */
    Log.e(TAG, "applyRouting -3");
    mScreenState = mScreenStateHelper.checkScreenState();
    mDeviceHost.doSetScreenOrPowerState(mScreenState);
    mIsRoutingTableDirty = true;
    applyRouting(true);
    return true;
    }
  • 相关阅读:
    aspnet中存储session的各种方法
    Response.ContentType 详细列表
    常用命令行命令
    关于使用request[this.控件名.Unique]获取控件值的问题
    在Asp.net中动态添加css文件,js文件,控件
    关于.Net中垃圾回收机制的理解:
    简单概念
    天健
    (转)高效调用lua函数
    (转)hlsl函数
  • 原文地址:https://www.cnblogs.com/jack2010/p/5508181.html
Copyright © 2011-2022 走看看