Android5.0 Telephony框架初步分析--telecomm
3.2???Telecomm關(guān)鍵類初始化和相互關(guān)系
?
3.2.1??????????Telecomm簡(jiǎn)述
Android5.0在Telephony的變化又比較大,增加了一個(gè)Telecomm模塊,它位于界面應(yīng)用如InCallUI和Phone框架之間,其具體的設(shè)計(jì)意圖尚不明確,從代碼分析上來看,流程比原來的架構(gòu)復(fù)雜很多,可能是想把Phone進(jìn)程獨(dú)立得更開一些,類似于RIL進(jìn)程,給應(yīng)用提供一個(gè)扁平的Phone接口,不希望像以前一樣,呼叫流程在Phone進(jìn)程和應(yīng)用進(jìn)程的縱深過大,引起函數(shù)的耦合性太大,有些相同的函數(shù)會(huì)在不同的流程執(zhí)行在不同的進(jìn)程里面。
其改變前后的關(guān)系可用下面的圖來簡(jiǎn)述:
?
之前函數(shù)的調(diào)用流程在不同進(jìn)程間的接口不夠平滑,現(xiàn)在添加新的Telecomm層后,整個(gè)軟件框架就比較有序和易于管理。
?
?
對(duì)于telephony相關(guān)的部分,從5.0和4.4的代碼比較來看,
1)在framework下面,5.0新增了telecomm和ims部分的代碼,截圖如下,
?
?
結(jié)合后面的代碼分析,我們知道在framework部分的telecomm代碼的作用是承上啟下的關(guān)系,它通過aidl接口,一方面和Phone進(jìn)行交互,這一層是以InCallService、ConnectionService為代表,它的相關(guān)部分會(huì)運(yùn)行在Phone進(jìn)程;另一方面,和TelecommApp進(jìn)程下的服務(wù)如TelecomService通信,這一層以TelecomManager等為代表,但他們往往運(yùn)行在應(yīng)用進(jìn)程里面。
?
2)在Package目錄下,5.0的應(yīng)用部分InCallUI下沒有了manifest文件,Service目錄則多了MMS、Telecomm目錄,MMS部分為短彩信增加了新的服務(wù)流程,telecomm部分則添加了一些關(guān)鍵文件,如作為進(jìn)程載體的TelecomApp.java文件,作為服務(wù)載體的TelecomServiceImpl.java,還有CallsManager、CallActivity等文件,這些文件的關(guān)系和作用將在后面逐步分解。。
?
?
?
?
?
3.2.2??????????Phone
?
新增加的Phone.java在?(frameworks\base\telecomm\java\android\telecom)目錄下,其功能是“A unified virtual device providing a means of voice (and other) communication on a device.”,即作為一個(gè)虛擬設(shè)備提供通信服務(wù)。其類型如下,
???????????public final class Phone {
它的方法的實(shí)現(xiàn)主要依賴3個(gè)輔助類,InCallAdapter、Listener、Call,即呼叫適配器、監(jiān)聽器、控制器(?),后續(xù)展開分析。
?
對(duì)于Phone的初始化,我們可以通過其方法的調(diào)用關(guān)系找到,例如查找internalAddCall,我們就會(huì)發(fā)現(xiàn)調(diào)用者為InCallService,其中mPhone即為Phone的實(shí)例,
case MSG_ADD_CALL:
mPhone.internalAddCall((ParcelableCall) msg.obj);
?
在InCallService里,當(dāng)收到MSG_SET_IN_CALL_ADAPTER消息時(shí),會(huì)創(chuàng)建一個(gè)Phone實(shí)例,同時(shí)也順帶創(chuàng)建了一個(gè)InCallAdapter實(shí)例,
????????????????case MSG_SET_IN_CALL_ADAPTER:
????????????????????mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
????????????????????onPhoneCreated(mPhone);
????????????????????break;??????????
?
MSG_SET_IN_CALL_ADAPTER消息是setInCallAdapter發(fā)出的,它是在InCallService里實(shí)現(xiàn)的AIDL接口類的服務(wù)端方法,
????private final class InCallServiceBinder extends IInCallService.Stub {
????????@Override
????????public void setInCallAdapter(IInCallAdapter inCallAdapter) {
????????????mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
????????}??????????
?
根據(jù)我們對(duì)service的了解,它在service類創(chuàng)建時(shí)創(chuàng)建binder,在service的onbind()方法里將binder實(shí)例傳入,執(zhí)行客戶端的ServiceConnection的onServiceConnected方法,所以在客戶端,onConnected被執(zhí)行,之后就是客戶端InCallController里的setInCallAdapter被調(diào)用,再間接調(diào)用前面提到的服務(wù)端的setInCallAdapter。
private class InCallServiceConnection implements ServiceConnection {
????????/** {@inheritDoc} */
????????@Override public void?onServiceConnected(ComponentName name, IBinder service) {
????????????Log.d(this, "onServiceConnected: %s", name);
????????????onConnected(name, service);
????????}?
?
????private void?onConnected(ComponentName componentName, IBinder service) {
????????ThreadUtil.checkOnMainThread();
?
????????Log.i(this, "onConnected to %s", componentName);
?
????????IInCallService inCallService = IInCallService.Stub.asInterface(service);
?
????????try {
????????????inCallService.setInCallAdapter(new InCallAdapter(CallsManager.getInstance(),
????????????????????mCallIdMapper));
????????????mInCallServices.put(componentName, inCallService);
????????} catch (RemoteException e) {
????????????Log.e(this, e, "Failed to set the in-call adapter.");
????????????return;
????????}
?
所以可以看出,Phone的實(shí)例就是在InCallService服務(wù)啟動(dòng)過程中創(chuàng)建的。
?
?
3.2.3??????????InCallController
?
?
?
前面提到的binder的客戶端InCallController位于(packages\services\telecomm\src \com\android\server\telecom)目錄,根據(jù)manifest文件,它運(yùn)行在TelecomApp這個(gè)應(yīng)用里,這是一個(gè)的5.0新進(jìn)程。又根據(jù)android:persistent="true"這個(gè)屬性我們知道,TelecomApp是開機(jī)自啟動(dòng)的。
?
InCallController是在CallsManager的構(gòu)造函數(shù)里創(chuàng)建的,CallsManager又是在TelecomApp的onCreate方法里面創(chuàng)建的,
????public void onCreate() {
????????super.onCreate();
?
????????if (UserHandle.myUserId() == UserHandle.USER_OWNER) {
????????????// Note: This style of initialization mimics what will be performed once Telecom is
????????????// moved
????????????// to run in the system service. The emphasis is on ensuring that initialization of all
????????????// telecom classes happens in one place without relying on Singleton initialization.
????????????mMissedCallNotifier = new MissedCallNotifier(this);
????????????mPhoneAccountRegistrar = new PhoneAccountRegistrar(this);
?
????????????mCallsManager = new?CallsManager(this, mMissedCallNotifier, mPhoneAccountRegistrar);
????????????CallsManager.initialize(mCallsManager);
?
????????????mTelecomService = new TelecomServiceImpl(mMissedCallNotifier, mPhoneAccountRegistrar,
????????????????????mCallsManager, this);
????????????ServiceManager.addService(Context.TELECOM_SERVICE, mTelecomService);
?
????????????// Start the BluetoothPhoneService
????????????BluetoothPhoneService.start(this);
????????}
????}??????????
?
所以,TelecomApp進(jìn)程的啟動(dòng)過程中,創(chuàng)建了InCallController和CallsManager兩個(gè)實(shí)例,這兩個(gè)類實(shí)例相互關(guān)聯(lián)。
?
?
3.2.4??????????TelecomService
?
實(shí)際上,并不存在TelecomService這個(gè)名字的文件或類名,但存在一個(gè)這樣的服務(wù)。
?
還是在TelecomApp的onCreate方法里(如上),創(chuàng)建了一個(gè)TelecomServiceImpl類實(shí)例,它對(duì)應(yīng)于TelecomService服務(wù)的AIDL服務(wù)端,它就是以類實(shí)例為服務(wù)端,并不像service里面bind的binder接口,并且,它被作為一個(gè)服務(wù)添加到serviceManager里面。
mTelecomService = new TelecomServiceImpl(mMissedCallNotifier, mPhoneAccountRegistrar,
????????????????????mCallsManager, this);
ServiceManager.addService(Context.TELECOM_SERVICE, mTelecomService);
?
…
public class TelecomServiceImpl extends ITelecomService.Stub {??????????
TelecomServiceImpl依賴CallsManager、PhoneAccountRegistrar、MissedCallNotifier這幾個(gè)類完成相應(yīng)的功能。
?
TelecomService的客戶端是TelecomManager,它通過getTelecomService獲取到服務(wù)端接口,然后通過這個(gè)接口使用服務(wù)端的遠(yuǎn)程接口,
?????private ITelecomService getTelecomService() {
????????return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));
????}
?
?
3.2.5??????????TelecomManager
?
TelecomManager在framework的android.telecom包里面,它在ContextImpl被創(chuàng)建,并加入到注冊(cè)列表里,屬于系統(tǒng)級(jí)的服務(wù),
????????registerService(TELECOM_SERVICE, new ServiceFetcher() {
????????????????public Object createService(ContextImpl ctx) {
????????????????????return new TelecomManager(ctx.getOuterContext());
????????????????}});
…
?
應(yīng)用要獲取其實(shí)例,可以通過其from方法,也可以直接通過context.getSystemService(Context.TELECOM_SERVICE)這個(gè)語句來獲取。
?
TelecomManager的功能則主要是對(duì)TelecomService提供的遠(yuǎn)程接口的封裝,然后提供給應(yīng)用使用,例如對(duì)于showInCallScreen方法,在TelecomServiceImpl提供服務(wù)端的遠(yuǎn)程方法,TelecomManager提供客戶端訪問接口,DialpadFragment等應(yīng)用組件使用這個(gè)接口,
?TelecomServiceImpl.java (packages\services\telecomm\src\com\android\server\telecom):????public void showInCallScreen(boolean showDialpad)
?
TelecomManager.java (frameworks\base\telecomm\java\android\telecom):????public void showInCallScreen(boolean showDialpad)
?
DialpadFragment.java (packages\apps\dialer\src\com\android\dialer\dialpad):????????getTelecomManager().showInCallScreen(showDialpad);
DialtactsActivity.java (packages\apps\dialer\src\com\android\dialer):????????????getTelecomManager().showInCallScreen(false);
?
雖然TelecomServiceImpl是在packages目錄下,TelecomManager在frameworks目錄下,但前者作為一個(gè)服務(wù),在單獨(dú)進(jìn)程里為后者提供服務(wù),后者則為應(yīng)用進(jìn)程提供接口服務(wù),再通過binder進(jìn)程通信訪問前者的服務(wù),其關(guān)系如下,
?
?
?
?
3.2.6??????????InCallService
?
InCallService是一個(gè)抽象類,繼承于service,它由四大部分組成,Handler、InCallServiceBinder、VideoCall以及自身的一些方法,其中InCallServiceBinder是aidl接口的服務(wù)端實(shí)現(xiàn),對(duì)應(yīng)于前面提到的InCallController,它主要是給當(dāng)前服務(wù)發(fā)送消息,Handler接收并處理這些消息,如前面提到,Handler會(huì)創(chuàng)建一個(gè)Telecom的Phone實(shí)例,然后使用Phone的接口處理應(yīng)用請(qǐng)求,所以實(shí)際上,客戶端的請(qǐng)求實(shí)際上是Phone來完成的,至于Phone是如何實(shí)現(xiàn)功能的,請(qǐng)參見Phone的分析,這里的幾個(gè)關(guān)鍵類的相互關(guān)系如下,
?
?
InCallService的主要功能是給應(yīng)用提供管理Phone call的途徑,它的子類InCallServiceImpl完成真正服務(wù)實(shí)例的創(chuàng)建,當(dāng)存在呼叫連接時(shí),它bind到Telecomm,并接受呼叫狀態(tài)的更新。
?
服務(wù)實(shí)例的綁定過程是在InCallController里面完成的,
?????private void bind() {…
????????????Intent serviceIntent = new Intent(InCallService.SERVICE_INTERFACE);
????????????for (ResolveInfo entry : packageManager.queryIntentServices(serviceIntent, 0)) {
????????????????????InCallServiceConnection inCallServiceConnection = new InCallServiceConnection();
????????????????????ComponentName componentName = new ComponentName(serviceInfo.packageName,
????????????????????????????serviceInfo.name);
????????????????????????Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
????????????????????????intent.setComponent(componentName);
?
????????????????????????if (mContext.bindServiceAsUser(intent, inCallServiceConnection,
????????????????????????????????Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) {
????????????????????????????mServiceConnections.put(componentName, inCallServiceConnection);
????????????????????????}
…}
這個(gè)bind()是在onCallAdded()里被調(diào)用的,onCallAdded被調(diào)用的地方有兩個(gè):
CallsManager.java (packages\services\telecomm\src\com\android\server\telecom):????????????listener.onCallAdded(call);
Phone.java (frameworks\base\telecomm\java\android\telecom):????????????listener.onCallAdded(this, call);
?
他們都是通過listener的方式被調(diào)用的,通過分析兩個(gè)類的listener,發(fā)現(xiàn)Phone的監(jiān)聽器主要在應(yīng)用文件中注冊(cè),
CallList.java (packages\apps\incallui\src\com\android\incallui):????????mPhone.addListener(mPhoneListener);
InCallPresenter.java (packages\apps\incallui\src\com\android\incallui):????????mPhone.addListener(mPhoneListener);
?
CallsManager的監(jiān)聽器在其構(gòu)造函數(shù)中注冊(cè),并且監(jiān)聽器類型為CallsManagerListener,
????private final Set<CallsManagerListener> mListeners = Collections.newSetFromMap(????????????new ConcurrentHashMap<CallsManagerListener, Boolean>(16, 0.9f, 1));
?
?????CallsManager(Context context, MissedCallNotifier missedCallNotifier,
?????????????PhoneAccountRegistrar phoneAccountRegistrar) {…
????????mCallLogManager = new CallLogManager(context);
????????mInCallController = new InCallController(context);
?
????????mListeners.add(statusBarNotifier);
????????mListeners.add(mCallLogManager);
????????mListeners.add(mPhoneStateBroadcaster);
????????mListeners.add(mInCallController);
????????mListeners.add(mRinger);
…}
所以是CallsManager. addCall調(diào)用了InCallController的onCallAdded。addCall則會(huì)被來電、去電、會(huì)議電話等接口方法調(diào)用,如startOutgoingCall。
?
所以當(dāng)有通話連接要產(chǎn)生時(shí),會(huì)啟動(dòng)InCallService服務(wù),其大致過程如下:
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的Android5.0 Telephony框架初步分析--telecomm的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 敏感词过滤及反垃圾文本的相关知识(欢迎收
- 下一篇: Android CTS测试