本帖最后由 sean 于 2016-9-28 11:11 编辑  
 
由于自己也是第一次分析,如果有错误请指出,谢谢   
ChannelTuning Activity中的 
        mTvChannelManager.switchMSrvDtvRouteCmd(currentRouteIndex); 
        mTvChannelManager.startDtvAutoScan(); 
        TvChannelManager中的getInstance(): 
                 public static TvChannelManager getInstance() { 
        /* Double-checked locking */ 
        if (mInstance == null) { 
            synchronized (TvChannelManager.class) { 
                if (mInstance == null) { 
                    int tvsystem = TvCommonManager.getInstance().getCurrentTvSystem(); 
                    Log.d(TAG, "tvsystem is " + tvsystem); 
                    switch (tvsystem) { 
                        case TvCommonManager.TV_SYSTEM_DVBT: 
                        case TvCommonManager.TV_SYSTEM_DVBC: 
                        case TvCommonManager.TV_SYSTEM_DVBS: 
                        case TvCommonManager.TV_SYSTEM_DVBT2: 
                        case TvCommonManager.TV_SYSTEM_DVBS2: 
                        case TvCommonManager.TV_SYSTEM_DTMB: { 
                            mInstance = TvDvbChannelManager.getInstance(); 
                            break; 
                        } 
                        case TvCommonManager.TV_SYSTEM_ATSC: { 
                            mInstance = TvAtscChannelManager.getInstance(); 
                            break; 
                        } 
                        case TvCommonManager.TV_SYSTEM_ISDB: { 
                            mInstance = TvIsdbChannelManager.getInstance(); 
                            break; 
                        } 
                        default: { 
                            Log.e(TAG, "Tv system is not specified!! getInstance FAIL!!"); 
                            break; 
                        } 
                    } 
                } 
            } 
        } 
        return mInstance; 
    } 
        TvDvbChannelManager中的getInstance(); 
         public static TvDvbChannelManager getInstance() { 
        /* Only dvb system can get this instance */ 
        if ((TvCommonManager.getInstance().getCurrentTvSystem() == TvCommonManager.TV_SYSTEM_ATSC) 
            || (TvCommonManager.getInstance().getCurrentTvSystem() == TvCommonManager.TV_SYSTEM_ISDB)) { 
            throw new IllegalAccessError("Only dvb system can get dvb channelmanager instance"); 
        } 
        /* Double-checked locking */ 
        if (mInstance == null) { 
            synchronized (TvDvbChannelManager.class) { 
                if (mInstance == null) { 
                    try { 
                        mInstance = new TvDvbChannelManager(); 
                    } catch (TvCommonException e) { 
                        e.printStackTrace(); 
                        return null; 
                    } 
                } 
            } 
        } 
        return (TvDvbChannelManager)mInstance; 
    } 
        得到了TvDvbChannelManager对象的实例mInstance,调用 startDtvAutoScan()方法,该方法在TvDvbChannelManager没有定义 
        找到TvDvbChannelManager的父类TvChangeManager,在TVChangeManager中找到了startDtvAutoScan()方法,查看他的具体实现 
        public boolean startDtvAutoScan() { 
        try { 
            return mService.startDtvAutoScan(); 
        } catch (RemoteException e) { 
            e.printStackTrace(); 
        } 
        return false; 
    } 
        查看mService的赋值操作 
        mDvbcScanParam = new DvbcScanParam(); 
        mService = ITvService.Stub.asInterface(b).getTvChannel(); 
        mServices是ITvChannel.aidl类型  找到他的实现类TvChannelService 
        具体实现如下: 
        @Override 
    public boolean startDtvAutoScan() throws RemoteException { 
        makeSourceDtv();//让当前的source切为DTV 
        try { 
            if (DtvManager.getDvbcScanManager() != null) { 
                DtvManager.getDvbcScanManager().startAutoScan(); 
                mTuningStatus = TvChannelManager.TUNING_STATUS_DTV_AUTO_TUNING; 
            } 
        } catch (TvCommonException e) { 
            e.printStackTrace(); 
            return false; 
        } 
        return true; 
    } 
        DtvManager中 
        public static DvbcScanManager getDvbcScanManager() { 
        DtvScanImplProxy implcld = new DtvScanImplProxy(); 
        return (DvbcScanManager) implcld.getScanImplInstance();//返回的实例是DvbcScanManger类型 
    } 
        查看DvbcScanManager类中的startAutoScan()方法。 DvbcScanManager是个接口 找到他的实现类ScanManagerImpl 
        在查看ScanManagerImpl.java中的具体实现,发现是个本地方法 
         public native final void startAutoScan() throws TvCommonException; 
          
        找到对应的jni文件ScanManagerImpl.cpp文件 
        void com_mstar_android_tvapi_impl_ScanManagerImpl_startAutoScan 
        (JNIEnv *env, jobject thiz) { 
                ALOGI("startAutoScan"); 
                sp<ScanManagerImpl> ms = getScanManagerImpl(env, thiz); 
                if (ms == NULL) { 
                        jniThrowException(env, "com/mstar/android/tvapi/common/exception/TvIpcException", "can not connect to server"); 
                        return; 
                } 
                ms->startAutoScan();//调用supernova层中的ScanManagerImpl的startAutoScan()方法。 
        } 
        里面的getScanManagerImpl(env, thiz)方法实现 
        static sp<ScanManagerImpl> getScanManagerImpl(JNIEnv *env, jobject thiz) { 
                //return scanManagerImpl; 
                Mutex::Autolock l(sLock); 
                ScanManagerImpl *c**t p = (ScanManagerImpl *)env->GetLongField(thiz, fields.context); 
                return sp<ScanManagerImpl>(p); //这里的ScanManagerImpl是supernova中的 
        } 
         
        在supernova层 ScanManagerImpl.cpp文件中调用 
        void ScanManagerImpl::startAutoScan() 
        { 
                ALOGV("ScanManagerImpl startAutoScan\n"); 
                mScanManagerImpl->startAutoScan(); 
        } 
        查看mScanManagerImpl的定义可知   
        sp<IScanManagerImpl> mScanManagerImpl; //IScanManagerImpl类型 
        查看IScanManagerImpl中的 
        case DTVSCANMANAGER_START_AUTO_SCAN: 
    { 
        printf("Receive DTVSCANMANAGER_START_AUTO_SCAN\n"); 
        CHECK_INTERFACE(IScanManagerImpl, data, reply); 
        startAutoScan(); 
        return NO_ERROR; 
    } break; 
         
        具体实现看 ScanMnagerImplService中的 
        void ScanManagerImplService::Client::startAutoScan() 
        { 
        #if(RELEASE_BINDER_TEST == 1) 
                TEST_STARTAUTOSCAN() ; 
        #endif 
                TVOS_API_ESTIMATE_START() 
                TVOS_API_ESTIMATE_START(LOCK) 
                Mutex::Autolock lock(m_FuncLock); 
                TVOS_API_ESTIMATE_END(LOCK) 
                printf("ScanManagerImplService::Client::startAutoScan\n"); 
         
                MAPI_INPUT_SOURCE_TYPE enCurrentInputType; 
                enCurrentInputType = MSrv_Control::GetInstance()->GetCurrentInputSource(); 
         
                if (enCurrentInputType != MAPI_INPUT_SOURCE_DTV) 
                { 
                        printf("startAutoScan FAILED, incorrect input source:%d\n", enCurrentInputType); 
                        TVOS_API_ESTIMATE_END() 
                        return; 
                } 
         
                bool ret = MSrv_Control::GetMSrvDtv()->StartAutoScan();//开始自动扫描 
                if (!ret) 
                        printf("MSrv_DTV_Player::StartAutoScan in ScanManagerImplService::Client::startAutoScan FAILED\n"); 
        #if (ATSC_SYSTEM_ENABLE == 1) 
                MSrv_Control::GetMSrvAtvDatabase()->CommondCmd(RESET_ATV_DATA_MANAGER , 0 , 0 , NULL); 
        #endif 
                TVOS_API_ESTIMATE_END() 
        }                               
        看下Msrv_Control中得方法 
        MSrv_DTV_Player * MSrv_Control_TV::GetMSrvDtv(MAPI_SCALER_WIN eWin) 
        { 
                MSRV_CONTROL_TV_INFO("%s line %d\n", __PRETTY_FUNCTION__, __LINE__); 
                EN_MSRV_PLAYER_LIST currentDtvPlayer = (EN_MSRV_PLAYER_LIST)(E_MSRV_DTV_PLAYER_0 + MSrv_PlayerControl::GetInstance()->GetCurrentDtvRoute(eWin)); 
                MSrv_DTV_Player *p = dynamic_cast<MSrv_DTV_Player *>(MSrv_PlayerControl::GetInstance()->GetMSrvPlayer(currentDtvPlayer)); 
                ASSERT(p); 
                return p; 
        } 
        查看MSrv_DTV_Player方法: 
        BOOL MSrv_DTV_Player::StartAutoScan() 
        { 
                MW_DTV_PLAYER_FUNCTION("BOOL MSrv_DTV_Player::StartAutoScan() \n"); 
         
                return AutoScan(); 
        } 
        查看AutoScan()方法: 
        BOOL MSrv_DTV_Player::AutoScan() 
        { 
                MW_DTV_PLAYER_FUNCTION("BOOL MSrv_DTV_Player::AutoScan() \n"); 
         
                if(!m_bInit) 
                { 
                        MW_DTV_PLAYER_ERROR("Error --- DTV Player not Initial !! \n"); 
                        ASSERT(0); 
                        return FALSE; 
                } 
        #if (OAD_ENABLE == 1) 
                if(_IsOadDownloading()) 
                { 
                        //printf("OAD is downlaoding, cannot do AutoScan!!!\n"); 
                        return FALSE; 
                } 
        #endif 
         
        #if (AUTO_TEST == 1) 
                printf("[AT][SN][DTV_AutoScan Function][%u]\n", mapi_time_utility::GetTime0());//会执行这里 日志输出 
        #endif 
         
                m_bIsScanning = TRUE;//For ATSC UI Function 
         
                return SetCMD(MSRV_DTV_BASE_CMD_AUTO_SCAN, 0);//继续调用SetCmd方法 
        } 
        查看SetCMD方法 
        SetCMD方法中有  m_pcDtvEv->Send(cDtvPlayerInfo, bPushFront);发送一个消息 
        在Msrv_DTV_Player.cpp文件中有个DtvPlayerMain方法接收消息  while循环不断的switch判断消息 
        case MSRV_DTV_BASE_CMD_AUTO_SCAN: 
                                                        MW_DTV_PLAYER_INFO("======> MSRV_DTV_BASE_CMD_AUTO_SCAN start \n"); 
        #if (HBBTV_ENABLE == 1) 
                                                        if(MW_HBBTV::GetCheckedInstance()) 
                                                        { 
                                                                MW_HBBTV::GetCheckedInstance()->StopHBBTVService(); 
                                                                ReleaseVideoBroadcastResource(); 
                                                        } 
        #endif 
        #if (AUTO_TEST == 1) 
                                                        printf("[AT][SN][DTV_AutoScanCmd START][%u]\n", mapi_time_utility::GetTime0()); 
        #endif 
         
                                                _DoAutoScan();//开始扫描 
                                                        MW_DTV_PLAYER_INFO("======> MSRV_DTV_BASE_CMD_AUTO_SCAN end \n"); 
                                                        break; 
        查看MSrv_DTV_Player中的_DoAutoScan()方法 
        BOOL MSrv_DTV_Player::_DoAutoScan(void) 
        { 
                return DoAutoScan(); 
        } 
        DoAutoScan方法定义为虚函数 virtual BOOL DoAutoScan(void) = 0; 虚函数  他自己并没有具体的实现 
        找到他的子类,他的子类有很多,不同的信号制式情况下DTV的自动扫描的实现都是不同的,找到对应制式下的 
        class MSrv_DTV_Player_DVB : public MSrv_DTV_Player,但是MSrv_DTV_Player_DVB中仍然没有具体的实现 
        继续找到MSrv_DTV_Player_DVB的一个子类 MSrv_DTV_Player_DTMB(还有其他的子类,这里不同的子类中已经有DoAutoScan的具体实现了) 
         
        查看MSrv_DTV_Player_DTMB中的DoAutoScan()方法 
        BOOL MSrv_DTV_Player_DTMB: oAutoScan() 
        { 
                MSRV_DTMB_PLAYER_FUNCTION("MSrv_DTV_Player_DTMB: oAutoScan()\n"); 
         
                CHECK_DTMB_PLAYER_INITIAL_DONE(); 
         
                if(!m_pcScan) 
                { 
                        DoScanInit();//初始化扫描配置  建立几个事件传输接口 
                } 
                BOOL bRst = FALSE; 
         
                bRst = DisableChannel(); 
         
                m_pcAVMonitor->ResetAVInfo(); 
         
                CHECK_RESULT(bRst); 
         
                m_u16CurUserONID = 0; 
                m_u16CurUserTSID = 0; 
                m_u16CurUserSID = 0; 
                m_u16CurUserServiceNumber = 0; //for MHEG5 
                m_u16CurRealONID = 0; 
                m_u16CurRealTSID = 0; 
                m_u16CurRealSID = 0; 
                m_u16CurRealServiceNumber = 0; 
         
                MW_DTV_Scan_DTMB* pcScanDTMB = dynamic_cast<MW_DTV_Scan_DTMB*>(m_pcScan); 
                if(NULL == pcScanDTMB) 
                { 
                        ASSERT(0); 
                        return FALSE; 
                } 
        bRst = pcScanDTMB->StartAutoScan();//扫描 
 
                CHECK_RESULT(bRst); 
                HandleScanEvent();//处理扫描事件(接收消息,暂停,停止,继续等事件,) 
                return TRUE; 
        } 
        上面中的StartAutoScan()方法是在MW_DTV_Scan_Dtmb中执行的 
        BOOL MW_DTV_Scan_DTMB::StartAutoScan() 
        { 
                MW_DTV_SCAN_DTMB_FUNCTION("MW_DTV_Scan_DTMB::StartAutoScan()\n"); 
         
                CHECK_DTV_SCAN_INITIAL_DONE(); 
                CHECK_DTMB_SCAN_SET_DATA_DONE(); 
         
                MW_DTMB_ScanInfo cScanInfo; 
                U32 u32res; 
         
                cScanInfo.m_enScanCmd = MW_DTMB_ScanInfo::CMD_SCAN; 
                cScanInfo.m_enScanType = MW_DTMB_ScanInfo::SCAN_TYPE_AUTO; 
         
                cScanInfo.m_u8RFCh = 0; 
                cScanInfo.m_u32Frequency = 0; 
         
        u32res = m_pcScanEv->Send(cScanInfo);//发送搜索命令和搜索类型给MW_DTV_Scan_DVBT 开始进入搜索; 
 
                if(u32res == 0) 
                { 
                        return TRUE; 
                } 
         
                return FALSE; 
        } 
 
        HandleScanEvent();接收处理搜索的事件,包括暂停,继续,停止,完成等事件。 
        BOOL MSrv_DTV_Player_DVB::HandleScanEvent() 
        { 
                MSRV_DVB_PLAYER_FUNCTION("MSrv_DTV_Player_DVB::HandleScanEvent()\n"); 
         
                int retcode; 
                MS_DTV_PlayerInfo cDTVInfo; 
                m_bIsScanning=TRUE; 
                BOOL bExitScan = FALSE; 
                while(!bExitScan) 
                { 
                        retcode = PTH_RET_CHK(m_pcDtvEv->Wait(&cDTVInfo, 30)); 
                        if(retcode == 0) 
                        { 
                                if(cDTVInfo.u32Event <= MSRV_DTV_BASE_CMD_MAX) 
                                { 
                                        switch(cDTVInfo.u32Event) 
                                        { 
                                                case MSRV_DTV_BASE_CMD_PAUSE_SCAN:  //For auto scan 
                                                        m_pcScan-> ause(); 
                                                        break; 
                                                case MSRV_DTV_BASE_CMD_RESUME_SCAN: //For auto scan 
                                                        m_pcScan->Resume(); 
                                                        break; 
                                                case MSRV_DTV_BASE_CMD_MANUAL_CHANGE_RF: //For manual scan 
                                                        DoChangScanRF((U8)cDTVInfo.u32Param1); 
                                                        break; 
                                                case MSRV_DTV_BASE_CMD_MANUAL_CHANGE_FREQ: //For manual scan 
                                                        DoChangScanFreq(cDTVInfo.u32Param1); 
                                                        break; 
                                                case MSRV_DTV_BASE_CMD_MANUAL_CONTINUE_SCAN: 
                                                case MSRV_DTV_BASE_CMD_CONTINUE_SCAN: //For manual scan and auto scan 
        #if (CI_PLUS_ENABLE == 1) 
                                                        if (TRUE == IsCiOccupiedTuner(TRUE)) 
                                                        { 
                                                                MSRV_DVB_PLAYER_INFO("Block Manual Scan \n"); 
                                                        } 
                                                        else 
        #endif 
                                                        { 
                                                                m_pcScan->Continue(); 
                                                        } 
                                                        break; 
                                                case MSRV_DTV_BASE_CMD_STOP_SCAN: //For manual scan and auto scan 
                                                        m_pcScan->Stop(); 
                                                        m_u16CurRealServiceNumber = 0; 
                                                        m_u8CurRealServiceType = 0; 
                                                        bExitScan = TRUE; 
                                                        break; 
                                                case MSRV_DTV_BASE_CMD_FINISH_SCAN: 
                                                        m_u16CurRealServiceNumber = 0; 
                                                        m_u8CurRealServiceType = 0; 
                                                        bExitScan = TRUE; 
                                                        break; 
                                                default: 
                                                        MSRV_DVB_PLAYER_ERROR("please send MSRV_DTV_BASE_CMD_STOP_SCAN command! %d\n", cDTVInfo.u32Event); 
                                                        //ASSERT(0);//remove assert, discard old message 
                                                        break; 
         
                                        } 
                                } 
                                else 
                                { 
                                        DoExtendCmd(cDTVInfo.u32Event, cDTVInfo.u32Param1, cDTVInfo.u32Param2, cDTVInfo.u32Param3); 
                                } 
                        } 
                } 
         
                m_bIsScanning=FALSE; 
                return TRUE; 
        } 
        m_pcScan->Init();//调用MW_DTV_Scan_DTMB_Customer 父类的MW_DTV_Scan_DTMB父类MW_DTV_Scan中的Init 由MW_DTV_Scan::Init 再回调 MW_DTV_Scan_DTMB: oInit// bRet = DoInit(); 
        //NOTE:MW_DTV_Scan::Init 时创建了ScanThreadFunc 搜索线程。此线程会回调MW_DTV_Scan_DTMB 中的ScanThreadBody 
        Supernova/projects/msrv/dvb/dtmb/middleware/src/MW_DTV_Scan_DTMB.cpp 
        void MW_DTV_Scan_DTMB::ScanThreadBody() 
        { 
                MW_DTV_SCAN_DTMB_FUNCTION("MW_DTV_Scan_DTMB::ScanThreadBody \n"); 
         
                MW_DTMB_ScanInfo cScanInfo; 
                BOOL bScanExit = FALSE; 
         
                while(!bScanExit) 
                { 
                        MW_DTV_SCAN_DTMB_DBG("MW_DTV_Scan_DTMB::ScanMain -- wait command \n"); 
                        m_pcScanEv->Wait(&cScanInfo);//此处不断的获取ScanInfo 对搜索的命令进行解析  
                        MW_DTV_SCAN_DTMB_DBG("MW_DTV_Scan_DTMB::ScanMain -- Get CMD %d \n", (U32)cScanInfo.m_enScanCmd); 
                        if((cScanInfo.m_enScanCmd == MW_DTMB_ScanInfo::CMD_SCAN) &&  
                        (cScanInfo.m_enScanType != MW_DTMB_ScanInfo::SCAN_TYPE_OADSCAN))//DTMB 的搜台进入此条件 
                        { 
                                m_enScanState = STATE_SCAN_INIT; 
                                m_bSentStop = FALSE; 
                                m_bSentContinue = FALSE; 
                                CopyScanRequirementInfo(&cScanInfo); 
                                if(!ScanMain())//正式进入搜索主体 
                                { 
                                        bScanExit = TRUE; 
                                } 
                                m_enScanState = STATE_SCAN_IDLE; 
                                MW_DTV_SCAN_DTMB_AUTOTEST("DTV_Scan_End\n"); 
                                SendDTMBScanRetInfo(MW_DTV_ScanRetInfo::STATUS_SCAN_END); 
                        } 
        #if (OAD_ENABLE == 1) 
                        else if((cScanInfo.m_enScanCmd == MW_DTMB_ScanInfo::CMD_SCAN) && (cScanInfo.m_enScanType == MW_DTMB_ScanInfo::SCAN_TYPE_OADSCAN)) 
                        { 
                                m_enScanState = STATE_SCAN_INIT; 
                                m_bSentStop = FALSE; 
                                m_bSentContinue = FALSE; 
                                CopyScanRequirementInfo(&cScanInfo); 
                                if(!OadScanMain()) 
                                { 
                                        bScanExit = TRUE; 
                                } 
                                m_enScanState = STATE_SCAN_IDLE; 
                                MW_DTV_SCAN_DTMB_AUTOTEST("DTV_Scan_End\n"); 
                                if(m_bExitToDL == FALSE) 
                                { 
                                        SendDTMBScanRetInfo(MW_DTV_ScanRetInfo::STATUS_SCAN_END); 
                                } 
                                else 
                                { 
                                        SendDTMBScanRetInfo(MW_DTV_ScanRetInfo::STATUS_EXIT_TO_DL); 
                                } 
         
                        } 
        #endif 
                        else if(cScanInfo.m_enScanCmd == MW_DTMB_ScanInfo::CMD_FINALIZE) 
                        { 
                                bScanExit = TRUE; 
                        } 
                } 
        } 
        具体ScanMain实现 
        supernova/projects/msrv/common/middleware/src/MW_DTV_Scan.cpp  
        BOOL MW_DTV_Scan::ScanMain(void) 
        { 
                MW_DTV_SCAN_FUNCTION("MW_DTV_Scan: oStartScan \n"); 
         
                BOOL bFinish = FALSE; 
                BOOL bRst = FALSE; 
         
                while(!bFinish) 
                { 
                        if((m_enScanState != STATE_SCAN_INIT) && (m_enScanState != STATE_SCAN_END)) 
                        { 
                                m_enScanState = DoHandleEvt(); 
                        } 
                        switch(m_enScanState) 
                        { 
                                case STATE_SCAN_INIT: 
                                { 
                                        m_enScanState = ScanState_Init(); 
                                        break; 
                                } 
                                case STATE_SCAN_NEXT_CHANNEL: 
                                        m_enScanState = ScanState_ScanNextChannel(); 
                                        break; 
                                case STATE_SCAN_TUNE_TO_RF_CHANNEL: 
                                        m_enScanState = ScanState_TuneToRFChannel(); 
                                        break; 
                                case STATE_SCAN_GET_PROGRAMS: 
                                        m_enScanState = ScanState_GetPrograms(); 
                                        break; 
                                case STATE_SCAN_SAVE_PROGRAMS: 
                                        m_enScanState = ScanState_SavePrograms();//主要是对上一步搜索到的节目进行存储 
                                        break; 
                                case STATE_SCAN_PAUSE: 
                                        m_enScanState = ScanState_Pause(); 
                                        break; 
                                case STATE_SCAN_END: 
                                { 
                                        m_enScanState = ScanState_End(); 
                                        bRst = DoCMDBReArrange(); 
                                        if(!bRst) 
                                        { 
                                                ASSERT(0); 
                                                return FALSE; 
                                        } 
                                        bRst = DoSetFirstProg(); 
                                        if(!bRst) 
                                        { 
                                                ASSERT(0); 
                                                return FALSE; 
                                        } 
                                        bFinish = TRUE; 
        #if (AUTO_TEST == 1) 
                                        if (m_enScanType == MW_DTV_ScanInfo::SCAN_TYPE_AUTO) 
                                        { 
                                                printf("[AT][SN][DTV_AutoScanCmd END][%u]\n", mapi_time_utility::GetTime0()); 
                                        } 
        #endif 
                                        break; 
                                } 
                                case STATE_SCAN_DVBS_REINIT:    //  DVBS only 
                                        m_enScanState = ScanState_End(); 
                                        bRst = DoCMDBReArrange(); 
                                        if(!bRst) 
                                        { 
                                                ASSERT(0); 
                                                return FALSE; 
                                        } 
                                        m_enScanState = ScanState_Init(); 
                                        break; 
                                default: 
                                        bFinish = TRUE; 
                                        break; 
                        } 
                } 
                return TRUE; 
        } 
 
 
 
 |