1: TvServer架构。
TvServer 作为一个系统service注册到servicemanager,编译成libmiddleware.so && tvserver.so两个library库,通过TvServerService来加载。通过暴露的tvjar为上层app提供服务,
主要包括,SI/PSI table的解析,Tuner Play,TimeShift、parent control,OAD,subtitle
1.1:TvServerService
Tvserver与上层app之间的关系
1.1.1: TvServerService.java
加载*.so
Public class TvServerService extends Service {
……
Private native void startTvServer
Static {
try {
System.loadLibrary("TvMiddlewareCore");
System.loadLibrary("tvserver");
} catch (UnsatisfiedLinkError e) {
Log.e(TAG, "cannot load library due to " + e.getLocalizedMessage());
}
}
……
}
1.1.2: Native 端 tvserver.cpp
extern "C" {
void Java_org_droidtv_tvserver_TvServerService_startTvServer(JNIEnv *env, jobject obj);
}
void Java_org_droidtv_tvserver_TvServerService_startTvServer(JNIEnv *env, jobject obj)
{
LogPrint("starting TvServer");
TvServerService::instantiate();
}
1.1.3:tvserverservice 服务端的实现
类图
其中最为核心的一个类,当属TvMediaResource,它管理者Tvserver内部众多Media,通过该Binder接口,可以获取tvserver服务接口,如OAD,MediaControl,MediaStream等。
1):定义相关的头文件
A:ITvServerService.h
class ITvServerService:public IInterface {
DECLARE_META_INTERFACE(TvServerService);
virtual sp<IBinder> createTvMediaResource(int tokenId)=0;
virtual sp<IBinder> getTvServerConfigInstance() = 0;
virtual void destroy(int tokenId)=0;
virtual void destroyNativeMediaplayerSurface (void) = 0;
};
class BnTvServerService : public BnInterface<ITvServerService> {
public :
virtual status_t onTransact (uint32_t code, const Parcel& data, Parcel * reply, uint32_t flags =0);
};
class BpTvServerService : public BpInterface<ITvServerService> {
public :
BpTvServerService (const sp<IBinder>& impl) : BpInterface<ITvServerService>(impl) {}
virtual sp<IBinder> createTvMediaResource(int tokenId);
virtual sp<IBinder> getTvServerConfigInstance();
virtual void destroy(int tokenId);
virtual void destroyNativeMediaplayerSurface (void);
};
D: TvServerService.h
class TvServerService : public BnTvServerService {
sp<ITvMediaResource> iTvMediaResource;
sp<ITvServerConfig> iTvServerConfig;
int tokenId;
NativeMediaPlayer *tunerMediaPlayerInstance;
KeyedVector< int, sp<IBinder> > strongInstanceMap;
KeyedVector< int, wp<ITvMediaResource> > weakInstanceMap;
char fileName[128];
TvServerPowerManager *tvServerPowerManager;
void createRootTvMediaResource(void);
void playTunerMediaPlayer(void);
void playExtensionMediaPlayer(void);
bool isWowLanWakeup;
static bool mStartAVStatus;
NativeMediaPlayer *extensionsMediaPlayerInstance;
virtual ~TvServerService() {};
static void instantiate();
virtual sp<IBinder> createTvMediaResource(int tokenId);
virtual sp<IBinder> getTvServerConfigInstance();
virtual void destroy(int tokenId);
sp<ITvMediaResource> getTvMediaResource();
void destroyNativeMediaplayerSurface (void);
void destroyRootPlayer(void);
static void muteStartUpAV(bool muteStatus);
static bool getStartUpAVStatus(void);
};
2):Bn/Bp端的实现 ITvServerService.cpp
enum {
CREATETVMEDIARESOURCE=IBinder::FIRST_CALL_TRANSACTION,
GETTVSERVERCONFIGINSTANCE,
DESTROY,
DESTROYMEDIAPLAYERSURFACE
};
status_t BnTvServerService::onTransact (uint32_t code,const Parcel& data,Parcel * reply,uint32_t flags)
{
switch (code){
case CREATETVMEDIARESOURCE: {
CHECK_INTERFACE(ITvServerService, data, reply);
int tokenId=data.readInt32();
sp<IBinder> retval = createTvMediaResource(tokenId);
reply->writeNoException();
reply->writeStrongBinder(retval);
return OK;
}break;
case GETTVSERVERCONFIGINSTANCE:{
CHECK_INTERFACE(ITvServerService, data, reply);
sp<IBinder> retval = getTvServerConfigInstance();
reply->writeNoException();
reply->writeStrongBinder(retval);
return OK;
}break;
case DESTROY: {
CHECK_INTERFACE(ITvServerService, data, reply);
int tokenId=data.readInt32();
destroy(tokenId);
reply->writeNoException();
return OK;
}break;
case DESTROYMEDIAPLAYERSURFACE: {
CHECK_INTERFACE(ITvServerService, data, reply);
;
int tokenId=data.readInt32();
destroyNativeMediaplayerSurface();
reply->writeNoException();
return OK;
}break;
}
return BBinder::onTransact (code, data, reply, flags);
}
BpTvServerService::~BpTvServerService() {
}
sp<IBinder> BpTvServerService::createTvMediaResource(int tokenId) {
sp<IBinder> itssinterface;
Parcel data, reply;
data.writeInterfaceToken (ITvServerService::descriptor);
status_t status = remote ()->transact (CREATETVMEDIARESOURCE, data, &reply);
itssinterface=reply.readStrongBinder();
return itssinterface;
}
sp<IBinder> BpTvServerService::getTvServerConfigInstance() {
sp<IBinder> itscinterface;
Parcel data, reply;
//data.writeInterfaceToken(string16("com.tpvision.TvServerService"));
data.writeInterfaceToken (ITvServerService::descriptor);
status_t status = remote ()->transact (GETTVSERVERCONFIGINSTANCE, data, &reply);
itscinterface=reply.readStrongBinder();
return itscinterface;
}
……
IMPLEMENT_META_INTERFACE(TvServerService, "org.droidtv.tv.media.TvServerService");
3):TvServerService服务端 TvServerService.cpp
- 将tvserver添加到serviceManager
void TvServerService::instantiate ()
{
if (tvServerServiceInstance == NULL)
{
ExtensionsPlayed = false;
tvServerServiceInstance = new TvServerService();
defaultServiceManager()->addService(String16("tvserver"), tvServerServiceInstance);
}
}
- 实现服务端的接口,如createTvMediaResource
sp<IBinder> TvServerService::createTvMediaResource(int tokenId)
{
int cur_index;
//add mutex to avoid new TvMediaResource with the same tokenId, which may cause TvMw init twice.
pthread_mutex_lock(&mMutex);
if ((tokenId == TOKEN_ROOT_TUNER) || (tokenId == TOKEN_ROOT_EXTENSIONS) || (tokenId == TOKEN_AUX_TUNER))
{
if((strongInstanceMap.indexOfKey(tokenId))<0)
{
ALOGE("%s, %d\r\n",__FUNCTION__, __LINE__);
iTvMediaResource = new TvMediaResource(tokenId);
strongInstanceMap.add(tokenId ,iTvMediaResource->asBinder());
pthread_mutex_unlock(&mMutex);
return iTvMediaResource->asBinder();
}
pthread_mutex_unlock(&mMutex);
return strongInstanceMap.valueFor(tokenId);
}
}
1.1.4:TvServerService提供的binder接口
- TvMediaPayer继承MediaPayer,作为tvjar提供给app的接口,提供TvPayer类型,如IPVODMediaPayer,TunerMediaPayer,ExtensionMediaPayer,AuxMediaPayer;
- TvMediaPayerImpl 继承TvMediaPayer,实现TvMediaPayer的接口方法,其中最为主要的一个方法是去new 一个TvMediaPayerContext(token);既是TvMediaPayer传下来的payer类型。
- TvMediaPayerContext,从serviceManager中去获取tvserver的服务,同时根据token类型,创建相应的TVMediaResource,获取binder端。另外TvMediaPayerContext实现ITvMediaPayerContext定义的接口方法。
- ITvServerService,作为TvServer的服务端,其中主要的一个方法是去createTvMediaResourcee。
- ITvMediaResource,则是管理和提供TvServer暴露给App的接口,相当于一个binder poo,向外提供不同类型的binder接口。
App 获取服务的流程
- 先获取一个tvmediaplayer的实例,如TunerMediaPlayer,ExtensionMediaPlayer等,tvMediaPlayer = new TvMediaPlayerImpl(ROOT_TUNER);
- 通过tvMediaPlayer获取TvMediaPlayerContext实例,tvMediaPlayer.getTvMediaPlayerContext();
- 通过TvMediaPlayerContext获取tvserver的接口
1.2:TvMediaResource
类图如下,像TvServerService一样,也会定义一些头文件,如ITvMediaResource,BnTvMediaResource,BpTvMediaResouce,TvMediaResource,ITvMediaResource.cpp,TvMediaResource.cpp;
在这里就只介绍服务端的实现。
TvMediaResource::TvMediaResource(int token)
{
tvServerContext = new TvServerContext(token);
……
iTvMediaCI=new TvMediaCI(tvServerContext);
iTvMediaStream = new TvMediaStream(tvServerContext);
iVsecureManager = new VsecureManager(tvServerContext);
iTvMediaControl = new TvMediaControl(tvServerContext);
iSubtitles = new Subtitles(tvServerContext);
iTvMediaRecordControl = new TvMediaRecordControl(tvServerContext);
iTvOADControl = new TvOADControl(tvServerContext);
iTvMediaAmmi = new TvMediaAmmi(tvServerContext);
iTvMediaMultiFeed = new TvMediaMultiFeed(tvServerContext);
iTvMediaOp=new TvMediaOp(tvServerContext);
tvServerContext->setTvMediaCIInstance(iTvMediaCI);
tvServerContext->setTvMediaStreamInstance(iTvMediaStream);
tvServerContext->setVsecureManagerInstance(iVsecureManager);
tvServerContext->setTvMediaControlInstance(iTvMediaControl);
tvServerContext->setTvSubtitleInstance(iSubtitles);
tvServerContext->setTvMediaRecordControlInstance(iTvMediaRecordControl);
tvServerContext->setTvOADInstance(iTvOADControl);
tvServerContext->setTvMediaAmmiInstance(iTvMediaAmmi);
tvServerContext->setTvMediaMultiFeedInstance(iTvMediaMultiFeed);
tvServerContext->setTvMediaOpInstance(iTvMediaOp);
initTvMW();//create tvserver mw comp
}
在TvMediaResource的构造函数中,会创建一个servercontext,并创建每个comp对应的实例,然后将该实例保存在servercontext->setTv**Instance中,当app需要使用某个comp时,必须通过servercontext->getMWInstane来获取对应的实例。这样ap才可以使用到该comp实例中的功能
后续tvmw中各个comp的功能实现,暂不介绍,这篇文章主要介绍如何实现本地服务,如何通过tvjar暴露本地服务的接口,以及如何管理本地服务组件。
TunerService继承TvInputService,实现一路输入源为TV_INPUT_TYPE_TUNER,实现onCreatSession方法并返回一个TvInputService.Session对象,即TunerSession,当其他app通过TIF创建session type为Tuner,即返回TunerSession,透过TunerSession,返回TunerService返回的一些服务,