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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Telephony Call分析

發(fā)布時間:2023/12/20 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Telephony Call分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

關(guān)于Call對象

一共4個

  • ./packages/apps/Dialer/java/com/android/incallui/call/DialerCall.java
  • ./frameworks/base/telecomm/java/android/telecom/Call.java
  • ./packages/services/Telecomm/src/com/android/server/telecom/Call.java
  • ./frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java
  • ?

    • frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java沒有使用,看樣子google打算放棄使用,轉(zhuǎn)用packages/services這個了。
    • Call狀態(tài)最終都是通過CallsManager來廣播出去的,CallsManager承上啟下。通過不同Call的轉(zhuǎn)換,最終在ui上體現(xiàn)出來。InCallService是UI和telecom的接口。InCallController綁定InCallService。
    • 從下往上,Call的傳到是:
      com.android.server.telecom.call (系統(tǒng)進(jìn)程)--> android.telecom.call(framgwork)?--> com.android.incallui.DialerCall(Dialer進(jìn)程)
    • com.android.server.telecom.call對象是撥打電話的時候(CallsManger.startOutgoingCall),或者收到來電intent的時候創(chuàng)建的(CallsManger.processIncomingCallIntent)。inCallController中的toParcelableCall函數(shù)會new ParcelableCall對象,參數(shù)是com.androidservice.telecom.call對象。toParcelableCall有兩個地方可以調(diào)到,一個是onConnected的時候,就是inCallController綁定到incallService后,如果這個時候call不為空,就會走;還有一個地方是CallsManager回調(diào)onCallAdded的時候,也會調(diào)用。android.telecom.call就是通過這個ParcelableCall對象的相關(guān)信息來創(chuàng)建的。即完成了com.android.server.telecom.call到android.telecom.call的映射。
    • incallservice會在綁定的時候,把自己注冊到phone的listener中。當(dāng)incallservice的客戶端(InCallController)調(diào)用addcall的時候,會傳過來一個parcelableCall的對象,incallservice會調(diào)用phone.internalAddCall來處理,在internalAddCall中根據(jù)這個parcelableCall對象生成telecomCall對象,然后phone通過fireCallAdded把這個call對象通過回調(diào)傳到incallservice中,incallservice調(diào)用onCallAdded,這個實(shí)現(xiàn)在incallui里面,即完成了android.telecom.call到 com.android.incallui.call的映射。
    • android.telecom.call作為構(gòu)造參數(shù)創(chuàng)建com.android.incallui.DialerCall,同時incallui.DialerCall注冊telecommCall的回調(diào)函數(shù),這樣有變化的時候,telecommCall會通知incallui.DialerCall來更新UI.

    一,Diale里面的Call ,InCallUi? DialerCall.java

    在以前沒有吧InCallUi合進(jìn)Dialer中的時InCallUi中只有一個Call.java,現(xiàn)在重新構(gòu)建了一遍,吧InCallUi放入Dialer中(要看商場怎么分離)。

    我們來看一下DialerCall的構(gòu)造方法:

    public DialerCall(Context context,DialerCallDelegate dialerCallDelegate,Call telecomCall,LatencyReport latencyReport,boolean registerCallback) {Assert.isNotNull(context);..... }

    這里的Call是framework telecomm? Call中傳入的,調(diào)用邏輯圖:

    大致邏輯? Call先是從系統(tǒng)服務(wù)InCallContrller.java中通過AIDL傳給framework中的InCallSerivce.java中在通過InCallSerive調(diào)用子類方法進(jìn)行傳入。

    Dialer創(chuàng)建是在:CallList.java中onCallAdded初始化:

    public void onCallAdded(final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) {Trace.beginSection("onCallAdded");final DialerCall call =new DialerCall(context, this, telecomCall, latencyReport, true /* registerCallback */);...... if (call.getState() == DialerCall.State.INCOMING|| call.getState() == DialerCall.State.CALL_WAITING) {onIncoming(call); //來電主核心} else {dialerCallListener.onDialerCallUpdate();} }

    這個onCallAdded是InCallServiceImpl中調(diào)用的,而InCallSerivceImpl中的onCallAdded方法是其父類直接調(diào)用,他的父類就是framewok里面的InCallSerivce.java其實(shí)他是一個服務(wù),等待系統(tǒng)服務(wù)調(diào)用。

    二,Serivce.Telecomm 中的Call?

    Telecom Call??
    framework/base/telecomm/src/java/android/telecomm/Phone.java

    public final class Call {}

    他是一個被定義成final類型的類,它是在Phone.java中被創(chuàng)建的internalAddCall()方法中被創(chuàng)建的.interanalAddCall()他是在InCallService中的Hanlder(MSG_ADD_CALL)調(diào)用,來電或去點(diǎn)都會被調(diào)用這個方法.

    final void internalAddCall(ParcelableCall parcelableCall) {//parcelabeCall是通過AIDL進(jìn)行傳輸?shù)?#xff0c;所有需要轉(zhuǎn)換//從ParcelableCall中取出信息用于new Telecom CallCall call = new Call(this, parcelableCall.getId(), mInCallAdapter,parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);mCallByTelecomCallId.put(parcelableCall.getId(), call);//添加調(diào)集合中mCalls.add(call);checkCallTree(parcelableCall);call.internalUpdate(parcelableCall, mCallByTelecomCallId);fireCallAdded(call);}

    這里的ParcelableCall是一個中間者的角色,在InCallController.java中先將Telecom Service中的Call轉(zhuǎn)換成ParcelableCall傳入.

    ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,videoProviderChanged /* includeVideoProvider */,mCallsManager.getPhoneAccountRegistrar(),info.isExternalCallsSupported(),rttInfoChanged && info.equals(mInCallServiceConnection.getInfo()));ComponentName componentName = info.getComponentName();IInCallService inCallService = entry.getValue();componentsUpdated.add(componentName);inCallService.updateCall(parcelableCall);//通過AIDL調(diào)用Framework中的數(shù)據(jù)

    總結(jié):然后通過ParcelableCallUtils進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換成Telecom Call, 這樣子就實(shí)現(xiàn)了serviceTelecomm傳入給frameworkTelecomm

    三,Service Telecomm 系統(tǒng)中Telecomm

    路徑:package/service/telecomm/src/com/android/service/telecomm/Call.java

    public class Call implements CreateConnectionResponse, EventManager.Loggable,ConnectionServiceFocusManager.CallFocus {}

    Call實(shí)現(xiàn)了CreateConnectionResponse接口,說明他負(fù)責(zé)與Connection創(chuàng)建之后處理一些事件,比如創(chuàng)建Connection之后需要UI界面的一些刷新以及更新。

    Service Telecom Call是通話流程中最重要的Call對象,他擁有管理一通電話的能力,(answer,reject,hold,disconnect等等),他由CallsManager創(chuàng)建管理

    在通過過程中,CallsManager是這樣管理的:

    CallsManager.java
    來電創(chuàng)建Call對象processInComingCallIntent()
    去電創(chuàng)建Call對象

    startOutgoingCall()

    發(fā)起撥號請求placeOutgoingCall()
    設(shè)置狀態(tài)setCallState()
    主動掛斷disconnectCall()

    四,framework opt中的Call

    framework/opt/telephony/src/android/internel/Call.java

    public abstract class Call { }

    他是一個抽象類。

    繼承結(jié)構(gòu)

    我們這里關(guān)注一下GsmCdmaCall的關(guān)系:

    GsmCdmaPhone初始化了GsmCdmaCallTracker,GsmCdmaCallTracker是負(fù)責(zé)管理GsmCdmaCall和GsmCdmaConnection的操作類,GsmCdmaCallTracker里面有一個GsmCdmaConnection的數(shù)組:

    public GsmCdmaConnection[] mConnections;

    并且有常量控制著mConnections數(shù)組數(shù)組的大小,一個GsmCdmaConnection代表著一通電話,說明GSM最大允許同時存在19通,CDMA最大同時存在8通。

    public static final int MAX_CONNECTIONS_GSM = 19; //7 allowed in GSM + 12 from IMS for SRVCCprivate static final int MAX_CONNECTIONS_PER_CALL_GSM = 5; //only 5 connections allowed per callprivate static final int MAX_CONNECTIONS_CDMA = 8;private static final int MAX_CONNECTIONS_PER_CALL_CDMA = 1; //only 1 connection allowed per call

    同時,GsmCdmaCallTracker的內(nèi)部也會創(chuàng)建三個GsmCdmaCall(GsmCdmaCall僅僅會在GsmCdmaCallTracker中被創(chuàng)建,創(chuàng)建之后不會再被重新賦值):

    public GsmCdmaCall mRingingCall = new GsmCdmaCall(this);// A call that is ringing or (call) waitingpublic GsmCdmaCall mForegroundCall = new GsmCdmaCall(this);public GsmCdmaCall mBackgroundCall = new GsmCdmaCall(this);

    Telephony Framework Call的狀態(tài)有9種:

    public enum State {IDLE, ACTIVE, HOLDING, DIALING, ALERTING, INCOMING, WAITING, DISCONNECTED, DISCONNECTING;public boolean isAlive() {return !(this == IDLE || this == DISCONNECTED || this == DISCONNECTING);}public boolean isRinging() {return this == INCOMING || this == WAITING;}public boolean isDialing() {return this == DIALING || this == ALERTING;}}

    問題1:那么mRingingCall,mForegroundCall,mBackgroundCall分別對應(yīng)Call的什么狀態(tài)呢?

    由于Telephony Framework Call的”ACTIVE, HOLDING, DIALING, ALERTING, INCOMING, WAITING”這六種狀態(tài)跟DriverCall.State是一一對應(yīng)的
    ?

    public static StatestateFromDCState (DriverCall.State dcState) {switch (dcState) {case ACTIVE: return State.ACTIVE;case HOLDING: return State.HOLDING;case DIALING: return State.DIALING;case ALERTING: return State.ALERTING;case INCOMING: return State.INCOMING;case WAITING: return State.WAITING;default: throw new RuntimeException ("illegal call state:" + dcState);}}

    在GsmCdmaConnection中有依據(jù)DriverCall.State將GsmCdmaCall分類的方法,根據(jù)state來返回相應(yīng)的對象

    private GsmCdmaCallparentFromDCState (DriverCall.State state) {switch (state) {case ACTIVE:case DIALING:case ALERTING:return mOwner.mForegroundCall;//break;case HOLDING:return mOwner.mBackgroundCall;//break;case INCOMING:case WAITING:return mOwner.mRingingCall;//break;default:throw new RuntimeException("illegal call state: " + state);}}

    所以mRingingCall,mForegroundCall,mBackgroundCall與GsmCdmaCall.mState的關(guān)系如下:

    mRingingCallINCOMING,WAITING
    mForegroundCallACTIVE,DIALING,ALERTING
    mBackgroundCallHOLDING

    GsmCdmaCallTracker在初始化的時候就注冊監(jiān)聽了Call狀態(tài)變化的消息,

    public GsmCdmaCallTracker (GsmCdmaPhone phone) {this.mPhone = phone;mCi = phone.mCi;mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);//注冊EVENT_CALL_STATE_CHANGE 狀態(tài)mCi.registerForOn(this, EVENT_RADIO_AVAILABLE, null);mCi.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);// Register receiver for ECM exitIntentFilter filter = new IntentFilter();filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);mPhone.getContext().registerReceiver(mEcmExitReceiver, filter);updatePhoneType(true);}

    所以當(dāng)modem中Call狀態(tài)發(fā)生變化后,便會通知到GsmCdmaCallTracker,GsmCdmaCallTracker通過調(diào)用RILJ的getCurrentCalls()方法發(fā)起查詢modem當(dāng)前的Call狀態(tài)列表,modem返回來的結(jié)果是DriverCall 集合。
    再由GsmCdmaCallTracker的handlePollCalls()方法來對比自身mConnections集合與DriverCall 集合的差異,進(jìn)而依據(jù)DriverCall的信息跟新這對應(yīng)GsmCdmaCall(mRingingCall,mForegroundCall,mBackgroundCall)的狀態(tài),同時將當(dāng)前GsmCdmaConnection與對應(yīng)的GsmCdmaCall綁定。
    ?

    總結(jié)

    以上是生活随笔為你收集整理的Android Telephony Call分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。