androidN拨打电话流程
本⽂主要分析从拨号盘拨号发出Intent开始,最终到中执⾏拨号操作的过程。
(1)⾸先拨号盘应⽤发送了action为的Intent,被UrCallActivity接收处理,UrCallActivity调⽤
UrCallIntentProcessor来处理:
@Override
protectedvoidonCreate(Bundlebundle){
te(bundle);
ession("");
try{
Intentintent=getIntent();
verifyCallAction(intent);
finalUrManagerurManager=(UrManager)getSystemService(_SERVICE);
finalUrHandleurHandle=newUrHandle(rHandle());
newUrCallIntentProcessor(this,urHandle).processIntent(getIntent(),
getCallingPackage(),true/*hasCallAppOp*/);
}finally{
sion();
}
finish();
(2)UrCallIntentProcessor通过processOutgoingCallIntent(),ndBroadcastToReceiver()调⽤PrimaryCallReceiver来处理:
privatebooleanndBroadcastToReceiver(Intentintent){
ra(_IS_INCOMING_CALL,fal);
gs(_RECEIVER_FOREGROUND);
ss(mContext,);
Log.d(this,"SendingbroadcastasurtoCallReceiver");
oadcastAsUr(intent,);
returntrue;
}
(3)(3)PrimaryCallReceiver中处理:PrimaryCallReceiver中处理:
publicvoidonReceive(Contextcontext,Intentintent){
ession("");
synchronized(getTelecomSystem().getLock()){
getTelecomSystem().getCallIntentProcessor().processIntent(intent);
}
sion();
}
(3)(3)CallIntentProcessor中处理:CallIntentProcessor中处理:
publicvoidprocessIntent(Intentintent){
finalbooleanisUnknownCall=leanExtra(KEY_IS_UNKNOWN_CALL,fal);
Log.i(this,"onReceive-isUnknownCall:%s",isUnknownCall);
ection("processNewCallCallIntent");
if(isUnknownCall){
processUnknownCallIntent(mCallsManager,intent);
}el{
processOutgoingCallIntent(mContext,mCallsManager,intent);
}
tion();
}
在processOutgoingCallIntent中主要的跳转逻辑
Callcall=callsManager
.startOutgoingCall(handle,phoneAccountHandle,clientExtras,initiatingUr);
if(call!=null){
NewOutgoingCallIntentBroadcasterbroadcaster=newNewOutgoingCallIntentBroadcaster(
context,callsManager,call,intent,neNumberUtilsAdapter(),
isPrivilegedDialer);
finalintresult=sIntent();
finalbooleansuccess=result==_DISCONNECTED;
if(!success&&call!=null){
endingMOEmergencyCall();
disconnectCallAndShowErrorDialog(context,call,result);
}
}
其中重点通过CallManager的startOutgoingCall⽅法构造了⼀个Call对象,其中重点会为该Call设置PhoneAccountHandle
CallstartOutgoingCall(Urihandle,PhoneAccountHandlephoneAccountHandle,Bundleextras,
UrHandleinitiatingUr){
booleanisReudCall=true;
Callcall=reuOutgoingCall(handle);
//dlemaybechangedwhenthecallisattached
//toaconnectionrvice,butinmostcaswillremainthesame.
if(call==null){
call=newCall(getNextCallId(),mContext,
this,
mLock,
mConnectionServiceRepository,
mContactsAsyncHelper,
mCallerInfoAsyncQueryFactory,
mPhoneNumberUtilsAdapter,
handle,
null/*gatewayInfo*/,
null/*connectionManagerPhoneAccount*/,
null/*phoneAccountHandle*/,
_DIRECTION_OUTGOING/*callDirection*/,
fal/*forceAttachToExistingConnection*/,
fal/*isConference*/
);
if((extras!=null)&&
lean(_DIAL_CONFERENCE_URI,fal)){
//RetPostDialDigitswithemptystringforConfURIcall.
tDialDigits("");
}
alytics();
tiatingUr(initiatingUr);
isReudCall=fal;
}
...
List
constructPossiblePhoneAccounts(handle,initiatingUr,scheme);
if(phoneAccountHandle!=null){
if(!ns(phoneAccountHandle)){
if(!ns(phoneAccountHandle)){
phoneAccountHandle=null;
}
}
if(phoneAccountHandle==null&&()>0){
if(()>1){
PhoneAccountHandledefaultPhoneAccountHandle=
goingPhoneAccountForScheme(scheme,
initiatingUr);
if(defaultPhoneAccountHandle!=null&&
ns(defaultPhoneAccountHandle)){
phoneAccountHandle=defaultPhoneAccountHandle;
}
}el{
phoneAccountHandle=(0);
}
}
getPhoneAccount(phoneAccountHandle);
...
booleanneedsAccountSelection=phoneAccountHandle==null&&()>1&&
!gencyCall();
if(needsAccountSelection){
te(_PHONE_ACCOUNT,"needsaccountlection");
//Createourowninstancetomodify()
extras=newBundle(extras);
celableList(BLE_PHONE_ACCOUNTS,accounts);
}el{
te(
TING,
phoneAccountHandle==null?"no-handle":ng());
}
...
returncall;
}
(3)(3)NewOutgoingCallIntentBroadcaster中主要逻辑:NewOutgoingCallIntentBroadcaster中主要逻辑:
if(callImmediately){
Stringscheme=isUriNumber?_SIP:_TEL;
booleanspeakerphoneOn=leanExtra(
_START_CALL_WITH_SPEAKERPHONE,fal);
intvideoState=Extra(
_START_CALL_WITH_VIDEO_STATE,
_AUDIO_ONLY);
OutgoingCallIntentBroadcastIsDone();
utgoingCall(mCall,rts(scheme,number,null),null,
speakerphoneOn,videoState);
}
重点调⽤CallsManager的placeOutgoingCal()⽅法
在placeOutgoingCal中核⼼调⽤了reateConnection(mPhoneAccountRegistrar);
if(getPhoneAccount()!=null||gencyCall()){
if(!gencyCall()){
updateLchStatus(getPhoneAccount().getId());
}
if(mPendingMOEmerCall==null){
reateConnection(mPhoneAccountRegistrar);
}
}elif(lCapablePhoneAccounts(
requireCallCapableAccountByHandle?dle().getScheme():null,fal,
tiatingUr()).isEmpty()){
markCallAsDisconnected(call,newDisconnectCau(ED,
"NoregisteredPhoneAccounts"));
markCallAsRemoved(call);
}
(4)(4)startCreateConnection中处理:startCreateConnection中处理:
voidstartCreateConnection(PhoneAccountRegistrarphoneAccountRegistrar){
if(mCreateConnectionProcessor!=null){
Log.w(this,""+
"duetoaracebetweenNewOutgoingCallIntentBroadcasterand"+
"phoneAccountSelected,butisharmlesslyresolvedbyignoringthecond"+
"invocation.");
return;
}
mCreateConnectionProcessor=newCreateConnectionProcessor(this,mRepository,this,
phoneAccountRegistrar,mContext);
s();
}
(5)(5)CreateConnectionProcessor中处理:CreateConnectionProcessor中处理:
publicvoidprocess(){
Log.v(this,"process");
clearTimeout();
mAttemptRecords=newArrayList<>();
if(getPhoneAccount()!=null){
(newCallAttemptRecord(
getPhoneAccount(),getPhoneAccount()));
}
adjustAttemptsForConnectionManager();
adjustAttemptsForEmergency(getPhoneAccount());
mAttemptRecordIterator=or();
attemptNextPhoneAccount();
}
其中重点逻辑在attemptNextPhoneAccount();
privatevoidattemptNextPhoneAccount(){
CallAttemptRecordattempt=null;
if(t()){
attempt=();
if(!ccountRequiresBindPermission(
tionManagerPhoneAccount)){
attemptNextPhoneAccount();
return;
}
if(!(PhoneAccount)&&
!ccountRequiresBindPermission(
PhoneAccount)){
attemptNextPhoneAccount();
return;
}
}
if(mCallRespon!=null&&attempt!=null){
PhoneAccountHandlephoneAccount=tionManagerPhoneAccount;
mService=vice(ponentName(),
rHandle());
if(mService==null){
Log.i(this,"Foundnoconnectionrviceforattempt%s",attempt);
attemptNextPhoneAccount();
}el{
mConnectionAttempt++;
nectionManagerPhoneAccount(tionManagerPhoneAccount);
getPhoneAccount(PhoneAccount);
nectionService(mService);
tTimeoutIfNeeded(mService,attempt);
Connection(mCall,this);
}
}el{
DisconnectCaudisconnectCau=mLastErrorDisconnectCau!=null?
mLastErrorDisconnectCau:newDisconnectCau();
notifyCallConnectionFailure(disconnectCau);
}
其中主要逻辑是找到⼀个正确的PhoneAccount然后通过调⽤Connection(mCall,this),其中mService为
ConnectionServiceWrapper类型的对象。
(6)(6)ConnectionServiceWrapper中处理:ConnectionServiceWrapper中处理:
publicvoidcreateConnection(finalCallcall,finalCreateConnectionResponrespon){
BindCallbackcallback=newBindCallback(){
@Override
publicvoidonSuccess(){
StringcallId=lId(call);
(callId,respon);
GatewayInfogatewayInfo=ewayInfo();
Bundleextras=entExtras();
if(gatewayInfo!=null&&ewayProviderPackageName()!=null&&
ginalAddress()!=null){
extras=(Bundle)();
ing(
Y_PROVIDER_PACKAGE,
ewayProviderPackageName());
celable(
Y_ORIGINAL_ADDRESS,
ginalAddress());
}
try{
Connection(
nectionManagerPhoneAccount(),
callId,
newConnectionRequest(
getPhoneAccount(),
dle(),
extras,
eoState(),
callId),
AttachToExistingConnection(),
own());
}catch(RemoteExceptione){
Log.e(this,e,"FailuretocreateConnection--%s",getComponentName());
(callId).handleCreateConnectionFailure(
newDisconnectCau(,ng()));
}
}
};
(callback,call);
}
其中最主要的⼀步还是下⾯的代码
Connection(
nectionManagerPhoneAccount(),
callId,
newConnectionRequest(
getPhoneAccount(),
dle(),
extras,
eoState(),
callId),
AttachToExistingConnection(),
own());
那么问题来了mServiceInterface到底是什么东西,上⾯所有的分析都是在Telecomm中发⽣的,众所周知,android中的phone是运⾏
在⾃⼰单独的进程中的,到此为⽌,以后的流程都是发⽣在phone进程中的,马上分析⼀下mServiceInterface是⼀个什么东西。
可以看出上⾯的代码是在调⽤(callback,call)后回调函数中调⽤的(mBinder是ConnectionServiceWrapper的⽗类
ServiceBinder中的⼀个内部类),所以才可应该是bind操作后对mServiceInterface进⾏了赋值。
voidbind(BindCallbackcallback,Callcall){
Log.d(,"bind()");
//Retanyabortrequestifwe'reaskedtobindagain.
clearAbort();
if(!y()){
//Bindingalreadyinprogress,appendtothelistofcallbacksandbailout.
(callback);
return;
}
(callback);
if(mServiceConnection==null){
IntentrviceIntent=newIntent(mServiceAction).tComponent(mComponentName);
ServiceConnectionconnection=newServiceBinderConnection(call);
(call,_CS,mComponentName);
finalintbindingFlags=_AUTO_CREATE|_FOREGROUND_SERVICE;
finalbooleanisBound;
if(mUrHandle!=null){
isBound=rviceAsUr(rviceIntent,connection,bindingFlags,
mUrHandle);
}el{
isBound=rvice(rviceIntent,connection,bindingFlags);
}
if(!isBound){
handleFailedConnection();
return;
}
}el{
Log.d(,"Serviceisalreadybound.");
otNull(mBinder);
handleSuccessfulConnection();
}
}
可以看出果然去bind了rvice,然后绑定成功后,应该会回调ServiceBinderConnection的onServiceConnected:
publicvoidonServiceConnected(ComponentNamecomponentName,IBinderbinder){
try{
synchronized(mLock){
mCall=null;
if(mIsBindingAborted){
clearAbort();
logServiceDisconnected("onServiceConnected");
Service(this);
handleFailedConnection();
return;
}
mServiceConnection=this;
tBinder(binder);
handleSuccessfulConnection();
}
}finally{
sion();
}
}
可以看出在绑定成功后回调⽤tBinder(binder)来保存获取到的远程Binder对象,看看tBinder的实现:
privatevoidtBinder(IBinderbinder){
if(mBinder!=binder){
if(binder==null){
removeServiceInterface();
mBinder=null;
for(Listenerl:mListeners){
nd(this);
}
}el{
mBinder=binder;
tServiceInterface(binder);
}
}
}
可以看出如果绑定成功的话会调⽤tServiceInterface⽅法,该⽅法是ServiceBinder的⼀个抽象函数,看看ServiceBinder的⼦类
ConnectionServiceWrapper的实现:
@Override
protectedvoidtServiceInterface(IBinderbinder){
mServiceInterface=rface(binder);
Log.v(this,"AddingConnectionServiceAdapter.");
addConnectionServiceAdapter(mAdapter);
}
真相⼤⽩,原来mServiceInterface就是(callback,call)中绑定服务返回的远程Binder对象,下⾯分析到底bind了那个服
务,在bind函数中明确指定了Intent的ComponentName。
IntentrviceIntent=newIntent(mServiceAction).tComponent(mComponentName);
ServiceConnectionconnection=newServiceBinderConnection(call);
mComponentName是从哪⾥来的?
publicclassConnectionServiceWrapperextendsServiceBinder{
ConnectionServiceWrapper(
ComponentNamecomponentName,
ConnectionServiceRepositoryconnectionServiceRepository,
PhoneAccountRegistrarphoneAccountRegistrar,
CallsManagercallsManager,
Contextcontext,
otlock,
UrHandleurHandle){
super(E_INTERFACE,componentName,context,lock,urHandle);
mConnectionServiceRepository=connectionServiceRepository;
tener(er(){
});
mPhoneAccountRegistrar=phoneAccountRegistrar;
mCallsManager=callsManager;
mAppOpsManager=(AppOpsManager)temService(_OPS_SERVICE);
}
}
protectedServiceBinder(StringrviceAction,ComponentNamecomponentName,Contextcontext,
otlock,UrHandleurHandle){
tate(!y(rviceAction));
otNull(componentName);
mContext=context;
mLock=lock;
mServiceAction=rviceAction;
mComponentName=componentName;
mUrHandle=urHandle;
}
可以看出mComponentName是在构造ConnectionServiceWrapper对象时候传⼊的。回到attemptNextPhoneAccount⽅法中:
privateConnectionServiceWrappermService;
mService=vice(ponentName(),
rHandle());
publicConnectionServiceWrappergetService(ComponentNamecomponentName,UrHandleurHandle){
Pair
ConnectionServiceWrapperrvice=(cacheKey);
if(rvice==null){
rvice=newConnectionServiceWrapper(
componentName,
this,
mPhoneAccountRegistrar,
mCallsManager,
mContext,
mLock,
urHandle);
tener(mUnbindListener);
(cacheKey,rvice);
}
returnrvice;
}
可以看出mComponentName来源于ponentName()(PhoneAccount为PhoneAccountHandle类型变
量,PhoneAccount类中有个成员变量PhoneAccountHandle,android有时候起得变量名容易让⼈混淆,PhoneAccountHandle主要
是保存了创建链接的服务的包名类名信息,PhoneAccount中包含了PhoneAccountHandle,还有最关键的该Account的Capabilities,
⽀持不⽀持语⾳通话等),现在问题⼜来了phoneAccount是怎么来的。对于PhoneAccount我理解就是可以安卓为了打电话功能可以扩
展新加的东西,现在我们⼿机⼤部分情况通过SIM卡打电话,⾛的是运营商⽹络,但是还有其他电话类型⽐如VOIP,具体我也不了解,所
以系统可能也可以有很多的PhoneAccount。当然现在我们还是⾛的标准的打电话流程,我们去看看SIM卡的PhoneAccount是在哪⾥创
建的。
在TelecomAccountRegistry中注册了PhoneAccount
privatePhoneAccountregisterPstnPhoneAccount(booleanisEmergency,booleanisDummyAccount){
StringdummyPrefix=isDummyAccount?"Dummy":"";
PhoneAccountHandlephoneAccountHandle=
tnPhoneAccountHandleWithPrefix(
mPhone,dummyPrefix,isEmergency);
PhoneAccountaccount=r(phoneAccountHandle,label)
.tAddress(rts(_TEL,line1Number,null))
.tSubscriptionAddress(
rts(_TEL,subNumber,null))
.tCapabilities(capabilities)
.tIcon(icon)
.tHighlightColor(color)
.tShortDescription(description)
.tSupportedUriSchemes((
_TEL,_VOICEMAIL))
.tExtras(instantLetteringExtras)
.tGroupId(groupId)
.build();
erPhoneAccount(account);
returnaccount;
}
此时我们关⼼的mComponentName就是在下⾯代码中创建的:
PhoneAccountHandlephoneAccountHandle=
tnPhoneAccountHandleWithPrefix(
mPhone,dummyPrefix,isEmergency);
在PhoneUtils中:
privatestaticfinalComponentNamePSTN_CONNECTION_SERVICE_COMPONENT=
newComponentName("",
"onyConnectionService");
可以看出是在phone进程中的⼀个服务,所以回到最上⾯的代码Connection(),其实调⽤的是
TelephonyConnectionService的createConnection⽅法,好,继续往下⾛(注意,此时后已经进⼊phone进程了,上⾯的所有操作都不
是在phone进程中的),发现TelephonyConnectionService没有实现该⽅法,⽤的⽗类ConnectionService的⽅法。该类代码路径为
frameworks/ba/telecomm/java/android/telecom/.给我们⼀个启⽰,我们想扩展电话功能需要继承实现该
类,并注册我们⾃⼰的PhoneAccount。
privatevoidcreateConnection(
finalPhoneAccountHandlecallManagerAccount,
finalStringcallId,
finalConnectionRequestrequest,
booleanisIncoming,
booleanisUnknown){
Connectionconnection=isUnknown?onCreateUnknownConnection(callManagerAccount,request)
:isIncoming?onCreateIncomingConnection(callManagerAccount,request)
:onCreateOutgoingConnection(callManagerAccount,request);
}
我们现在是呼出,所以调⽤的是onCreateOutgoingConnection,该⽅法在ConnectionService中是空的实现,所以⼜回到了
TelephonyConnectionService中,在onCreateOutgoingConnection中,代码很长我就不贴了,主要是创建了⼀个链接:
ConnectionresultConnection=getTelephonyConnection(request,numberToDial,
isEmergencyNumber,handle,phone);
然后处理该链接
placeOutgoingConnection((TelephonyConnection)resultConnection,phone,request);
重点就在该⽅法
privatevoidplaceOutgoingConnection(
TelephonyConnectionconnection,Phonephone,intvideoState,Bundleextras,
ConnectionRequestrequest){
tionoriginalConnection=null;
try{
if(phone!=null){
if(isAddParticipant){
ticipant(number);
return;
}el{
originalConnection=(number,null,eoState(),bundle);
}
}
}
}
终于,我们看见了我们想看见的,以下的情节就是俗套了,⼜调⽤CT(CallTracker)的dail⽅法,CT⼜调⽤
CI(CommandsInterface也就是RIL),最终java层拨号流程就已经分析完了,下篇⽂章想分析⼀下,打电话过程中和UI(InCallUI)的交
互。
本文发布于:2023-01-04 03:45:52,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/88403.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |