日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android5.0 Telephony框架初步分析--telecomm

發布時間:2023/12/20 Android 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android5.0 Telephony框架初步分析--telecomm 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

3.2???Telecomm關鍵類初始化和相互關系

?

3.2.1??????????Telecomm簡述

Android5.0在Telephony的變化又比較大,增加了一個Telecomm模塊,它位于界面應用如InCallUI和Phone框架之間,其具體的設計意圖尚不明確,從代碼分析上來看,流程比原來的架構復雜很多,可能是想把Phone進程獨立得更開一些,類似于RIL進程,給應用提供一個扁平的Phone接口,不希望像以前一樣,呼叫流程在Phone進程和應用進程的縱深過大,引起函數的耦合性太大,有些相同的函數會在不同的流程執行在不同的進程里面。

其改變前后的關系可用下面的圖來簡述:

?

之前函數的調用流程在不同進程間的接口不夠平滑,現在添加新的Telecomm層后,整個軟件框架就比較有序和易于管理。

?

?

對于telephony相關的部分,從5.0和4.4的代碼比較來看,

1)在framework下面,5.0新增了telecomm和ims部分的代碼,截圖如下,

?

?

結合后面的代碼分析,我們知道在framework部分的telecomm代碼的作用是承上啟下的關系,它通過aidl接口,一方面和Phone進行交互,這一層是以InCallService、ConnectionService為代表,它的相關部分會運行在Phone進程;另一方面,和TelecommApp進程下的服務如TelecomService通信,這一層以TelecomManager等為代表,但他們往往運行在應用進程里面。

?

2)在Package目錄下,5.0的應用部分InCallUI下沒有了manifest文件,Service目錄則多了MMS、Telecomm目錄,MMS部分為短彩信增加了新的服務流程,telecomm部分則添加了一些關鍵文件,如作為進程載體的TelecomApp.java文件,作為服務載體的TelecomServiceImpl.java,還有CallsManager、CallActivity等文件,這些文件的關系和作用將在后面逐步分解。。

?

?

?

?

?

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.”,即作為一個虛擬設備提供通信服務。其類型如下,

???????????public final class Phone {

它的方法的實現主要依賴3個輔助類,InCallAdapter、Listener、Call,即呼叫適配器、監聽器、控制器(?),后續展開分析。

?

對于Phone的初始化,我們可以通過其方法的調用關系找到,例如查找internalAddCall,我們就會發現調用者為InCallService,其中mPhone即為Phone的實例,

case MSG_ADD_CALL:

mPhone.internalAddCall((ParcelableCall) msg.obj);

?

在InCallService里,當收到MSG_SET_IN_CALL_ADAPTER消息時,會創建一個Phone實例,同時也順帶創建了一個InCallAdapter實例,

????????????????case MSG_SET_IN_CALL_ADAPTER:

????????????????????mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));

????????????????????onPhoneCreated(mPhone);

????????????????????break;??????????

?

MSG_SET_IN_CALL_ADAPTER消息是setInCallAdapter發出的,它是在InCallService里實現的AIDL接口類的服務端方法,

????private final class InCallServiceBinder extends IInCallService.Stub {

????????@Override

????????public void setInCallAdapter(IInCallAdapter inCallAdapter) {

????????????mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();

????????}??????????

?

根據我們對service的了解,它在service類創建時創建binder,在service的onbind()方法里將binder實例傳入,執行客戶端的ServiceConnection的onServiceConnected方法,所以在客戶端,onConnected被執行,之后就是客戶端InCallController里的setInCallAdapter被調用,再間接調用前面提到的服務端的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的實例就是在InCallService服務啟動過程中創建的。

?

?

3.2.3??????????InCallController

?

?

?

前面提到的binder的客戶端InCallController位于(packages\services\telecomm\src \com\android\server\telecom)目錄,根據manifest文件,它運行在TelecomApp這個應用里,這是一個的5.0新進程。又根據android:persistent="true"這個屬性我們知道,TelecomApp是開機自啟動的。

?

InCallController是在CallsManager的構造函數里創建的,CallsManager又是在TelecomApp的onCreate方法里面創建的,

????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進程的啟動過程中,創建了InCallController和CallsManager兩個實例,這兩個類實例相互關聯。

?

?

3.2.4??????????TelecomService

?

實際上,并不存在TelecomService這個名字的文件或類名,但存在一個這樣的服務。

?

還是在TelecomApp的onCreate方法里(如上),創建了一個TelecomServiceImpl類實例,它對應于TelecomService服務的AIDL服務端,它就是以類實例為服務端,并不像service里面bind的binder接口,并且,它被作為一個服務添加到serviceManager里面。

mTelecomService = new TelecomServiceImpl(mMissedCallNotifier, mPhoneAccountRegistrar,

????????????????????mCallsManager, this);

ServiceManager.addService(Context.TELECOM_SERVICE, mTelecomService);

?

public class TelecomServiceImpl extends ITelecomService.Stub {??????????

TelecomServiceImpl依賴CallsManager、PhoneAccountRegistrar、MissedCallNotifier這幾個類完成相應的功能。

?

TelecomService的客戶端是TelecomManager,它通過getTelecomService獲取到服務端接口,然后通過這個接口使用服務端的遠程接口,

?????private ITelecomService getTelecomService() {

????????return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));

????}

?

?

3.2.5??????????TelecomManager

?

TelecomManager在framework的android.telecom包里面,它在ContextImpl被創建,并加入到注冊列表里,屬于系統級的服務,

????????registerService(TELECOM_SERVICE, new ServiceFetcher() {

????????????????public Object createService(ContextImpl ctx) {

????????????????????return new TelecomManager(ctx.getOuterContext());

????????????????}});

?

應用要獲取其實例,可以通過其from方法,也可以直接通過context.getSystemService(Context.TELECOM_SERVICE)這個語句來獲取。

?

TelecomManager的功能則主要是對TelecomService提供的遠程接口的封裝,然后提供給應用使用,例如對于showInCallScreen方法,在TelecomServiceImpl提供服務端的遠程方法,TelecomManager提供客戶端訪問接口,DialpadFragment等應用組件使用這個接口,

?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目錄下,但前者作為一個服務,在單獨進程里為后者提供服務,后者則為應用進程提供接口服務,再通過binder進程通信訪問前者的服務,其關系如下,

?

?

?

?

3.2.6??????????InCallService

?

InCallService是一個抽象類,繼承于service,它由四大部分組成,Handler、InCallServiceBinder、VideoCall以及自身的一些方法,其中InCallServiceBinder是aidl接口的服務端實現,對應于前面提到的InCallController,它主要是給當前服務發送消息,Handler接收并處理這些消息,如前面提到,Handler會創建一個Telecom的Phone實例,然后使用Phone的接口處理應用請求,所以實際上,客戶端的請求實際上是Phone來完成的,至于Phone是如何實現功能的,請參見Phone的分析,這里的幾個關鍵類的相互關系如下,

?

?

InCallService的主要功能是給應用提供管理Phone call的途徑,它的子類InCallServiceImpl完成真正服務實例的創建,當存在呼叫連接時,它bind到Telecomm,并接受呼叫狀態的更新。

?

服務實例的綁定過程是在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);

????????????????????????}

…}

這個bind()是在onCallAdded()里被調用的,onCallAdded被調用的地方有兩個:

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的方式被調用的,通過分析兩個類的listener,發現Phone的監聽器主要在應用文件中注冊,

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的監聽器在其構造函數中注冊,并且監聽器類型為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調用了InCallController的onCallAdded。addCall則會被來電、去電、會議電話等接口方法調用,如startOutgoingCall。

?

所以當有通話連接要產生時,會啟動InCallService服務,其大致過程如下:

?

?

?

?

?

?

?

?

?

?

總結

以上是生活随笔為你收集整理的Android5.0 Telephony框架初步分析--telecomm的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。