本帖最后由 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;
}
|