您的位置:首页 > 移动开发 > Android开发

Android M MO流程 并与Android L MO对比

2016-05-26 00:58 549 查看
转载请注明出处!!

原文地址:http://blog.csdn.net/aaa111/article/details/51503295

今天凌晨才写的博客,一天内未经允许被红黑LM转载,而且没有注明原文链接。其实被转载不重要,你跟我打声招呼嘛。(如需转载,这段可删)

----

此篇介绍AndroidM上的MO流程,并与AndroidL上做比较。

注意:源码是CM13.0并不是AOSP

先看一下AndroidM整体的一个流程图:





变化主要在流程的前半部分,下面是一张对比图:



AM_AM_compare



变化集中在红色框内。小方框是新增API。

下面我们开始跟一下MO的流程。


packages/apps/Dialer

以在拨号盘拨号为入口(当然还有很多其他入口,我们就不挨个跟了),DialpadFragment.javahandleDialButtonPressed(),这个方法内部的代码变少了,也可以看作是多了一步startCall()(更新:这是CM13.0上的代码,AOSP中没有)

packages/apps/DialerDialpadFragment.java

privatevoidhandleDialButtonPressed(){
[code]if(isDigitsEmpty()){//Nonumberentered.
handleDialButtonClickWithEmptyDigits();
}else{
finalStringnumber=mDigits.getText().toString();
//"persist.radio.otaspdial"isatemporaryhackneededforonecarrier'sautomated
//testequipment.
//TODO:cleanitup.
if(number!=null
&&!TextUtils.isEmpty(mProhibitedPhoneNumberRegexp)
&&number.matches(mProhibitedPhoneNumberRegexp)){
Log.i(TAG,"Thephonenumberisprohibitedexplicitlybyarule.");
if(getActivity()!=null){
DialogFragmentdialogFragment=ErrorDialogFragment.newInstance(
R.string.dialog_phone_call_prohibited_message);
dialogFragment.show(getFragmentManager(),"phone_prohibited_dialog");
}
//Clearthedigitsjustincase.
clearDialpad();
}else{
startCall(number,OriginCodes.DIALPAD_DIRECT_DIAL);//这里是新增内容
}
}
}
[/code]

startCall(),这个方法是新增的,其实也可以看作是拆分出来的

privatevoidstartCall(Stringnumber,Stringorigin){
if(mCurrentCallMethodInfo!=null&&mCurrentCallMethodInfo.mIsInCallProvider&&
!PhoneNumberUtils.isEmergencyNumber(number)){
mCurrentCallMethodInfo.placeCall(origin,number,getActivity(),false,true,
newStartInCallCallReceiver.InCallCallListener(){
@Override
publicvoidonResult(intresultCode){
if(resultCode==StatusCodes.StartCall.CALL_CONNECTED){
hideAndClearDialpad(false);
}
}
});
}else{
//Ifnosimisselected,oremergencycallmethodselected,ornumberis
//anemergencynumber,phoneaccounthandleshouldbenull,andwillusethe
//defaultaccount.
//Else,createPhoneAccountHandlefromselectedcallmethodcomponentsand
//initialcallusingthataccount.
PhoneAccountHandlehandle=CallMethodInfo.getPhoneAccountHandleFromCallMethodInfo(
getActivity(),mCurrentCallMethodInfo,number);
finalIntentintent=IntentUtil.getCallIntent(number,//返回的action:android.intent.action.CALL而在5.1上是android.intent.action.CALL_PRIVILEGED
(getActivity()instanceofDialtactsActivity?
((DialtactsActivity)getActivity())
.getCallOrigin():null),
handle);
DialerUtils.startActivityWithErrorToast(getActivity(),intent,origin);//虽然增加了一步startCall,但这里还是调用了方法
hideAndClearDialpad(false);
}
}
[/code]

注意这里intent的构造,返回值来自IntentUtil.getCallIntent(),而AndroidL的则是返回自CallUtil.getCallIntent()。
这俩有啥区别的?最大的不同是他俩返回的ACTION不一样,一个返回的android.intent.action.CALL一个返回android.intent.action.CALL_PRIVILEGED,暂时还没看到有什么明显的影响,不过既然这个action有变化,肯定会对后面的流程有一点影响,后面会提到。
然后另外还有一个CALL_ACTION:android.intent.action.CALL_EMERGENCY,三者在L上的区别可以参考:Android
5.0上紧急电话EmergencyCall与普通电话MO流程区别
然后两个文件所在的目录不同:IntentUtil位于Dialer,CallUtil位于ContactCommon,
还有就是起初IntentUtil.java叫做PrivilegedCallUtil,然后改名为CallIntentUtil,后又改名为现在的IntentUtil,
再有就是在早起的AndroidM版本中返回的也是android.intent.action.CALL_PRIVILEGED,后来改成了android.intent.action.CALL,至于原因和提交在这就不深追了(看IntentUtil的提交历史可知)。

DialerUtils.java

publicstaticvoidstartActivityWithErrorToast(Contextcontext,Intentintent,intmsgId,
Stringorigin){
try{
if((IntentUtil.CALL_ACTION.equals(intent.getAction())
&&contextinstanceofActivity)){
//Alldialer-initiatedcallsshouldpassthetouchpointtotheInCallUI
PointtouchPoint=TouchPointManager.getInstance().getPoint();//geiPoint(),对应的setPoint()方法,在点击的时候调用
if(touchPoint.x!=0||touchPoint.y!=0){
Bundleextras=newBundle();
extras.putParcelable(TouchPointManager.TOUCH_POINT,touchPoint);//是与动画有关咯,将传至InCallUI
intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS,extras);
}
if(origin!=null){
intent.putExtra(PhoneConstants.EXTRA_CALL_ORIGIN,origin);
}
finalTelecomManagertm=
(TelecomManager)context.getSystemService(Context.TELECOM_SERVICE);
tm.placeCall(intent.getData(),intent.getExtras());//直接到TelecomManager里去了。在L5.1上是调用startActivityForResult(),之后再启动CallActivity
}else{
context.startActivity(intent);
}
}catch(ActivityNotFoundExceptione){
Toast.makeText(context,msgId,Toast.LENGTH_SHORT).show();
}
}
[/code]

从下面开始就是主要变化的地方

framework/telecomm

framework/base/telecommTelecomManager.java

TelecomManager.placeCall是新增的api,





其作用注释里面已经写的很清楚了。

/**
*Placesanewoutgoingcalltotheprovidedaddressusingthesystemtelecomservicewith
*thespecifiedextras.
*
*Thismethodisequivalenttoplacinganoutgoingcallusing{@linkIntent#ACTION_CALL},
*exceptthattheoutgoingcallwillalwaysbesentviathesystemtelecomservice.If
*method-calleriseithertheuserselecteddefaultdialerapporpreloadedsystemdialer
*app,thenemergencycallswillalsobeallowed.
*
*Requirespermission:{@linkandroid.Manifest.permission#CALL_PHONE}
*
*Usageexample://举例
*<pre>
*Uriuri=Uri.fromParts("tel","12345",null);//Uri主要是号码
*Bundleextras=newBundle();
*extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,true);//默认开扬声器
*telecomManager.placeCall(uri,extras);
*</pre>
*
*Thefollowingkeysaresupportedinthesuppliedextras.
*<ul>
*<li>{@link#EXTRA_OUTGOING_CALL_EXTRAS}</li>
*<li>{@link#EXTRA_PHONE_ACCOUNT_HANDLE}</li>
*<li>{@link#EXTRA_START_CALL_WITH_SPEAKERPHONE}</li>
*<li>{@link#EXTRA_START_CALL_WITH_VIDEO_STATE}</li>
*</ul>
*
*@paramaddressTheaddresstomakethecallto.
*@paramextrasBundleofextrastousewiththecall.
*/
publicvoidplaceCall(Uriaddress,Bundleextras){
ITelecomServiceservice=getTelecomService();
if(service!=null){
if(address==null){//检查号码
Log.w(TAG,"Cannotplacecalltoemptyaddress.");
}
try{
service.placeCall(address,extras==null?newBundle():extras,
mContext.getOpPackageName());
}catch(RemoteExceptione){
Log.e(TAG,"ErrorcallingITelecomService#placeCall",e);
}
}
}
[/code]

packages/services/Telecomm

TelecomServiceImpl.javaplaceCall

/**
*@seeandroid.telecom.TelecomManager#placeCall
*/
@Override
publicvoidplaceCall(Urihandle,Bundleextras,StringcallingPackage){
enforceCallingPackage(callingPackage);
if(!canCallPhone(callingPackage,"placeCall")){
thrownewSecurityException("Package"+callingPackage
+"isnotallowedtoplacephonecalls");
}
//Note:wecanstillgethereforthedefault/systemdialer,evenifthePhone
//permissionisturnedoff.Thisisbecausethedefault/systemdialerisalways
//allowedtoattempttoplaceacall(regardlessofpermissionstate),incase//注释还是要看
//itturnsouttobeanemergencycall.Ifthepermissionisdeniedandthe
//callisbeingmadetoanon-emergencynumber,thecallwillbedeniedlateron
//by{@linkUserCallIntentProcessor}.
finalbooleanhasCallAppOp=mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
Binder.getCallingUid(),callingPackage)==AppOpsManager.MODE_ALLOWED;
finalbooleanhasCallPermission=mContext.checkCallingPermission(CALL_PHONE)==
PackageManager.PERMISSION_GRANTED;
synchronized(mLock){
finalUserHandleuserHandle=Binder.getCallingUserHandle();
longtoken=Binder.clearCallingIdentity();
try{
finalIntentintent=newIntent(Intent.ACTION_CALL,handle);
intent.putExtras(extras);
newUserCallIntentProcessor(mContext,userHandle).processIntent(intent,
callingPackage,hasCallAppOp&&hasCallPermission);
}finally{
Binder.restoreCallingIdentity(token);
}
}
}
[/code]

看到UserCallIntentProcessor.java不要觉得又是个新东西,它其实原名CallActivity,就是L版本上那个在onCreate中执行了processIntent()之后直接finish()的没有界面的CallActivity。

另外提一下现在M上有的一个类叫做UserCallActivity.java它的工作其实跟L上的CallActivity是一样的,是一个没有界面的Activity,在AndroidManifest.xml中也配置了过滤的action和别名Activity。

是不是有点晕?L上的CallActivity.java升级到M上改名为UserCallIntentProcessor.java,另外新增一个UserCallActivity.java取代其部分工作,也可以说CallActivity.java拆分成了UserCallActivity.java和UserCallIntentProcessor.java。

好吧这样说的话其实UserCallIntentProcessor.java算个新东西,从内容和功能上来说。

一起改名和移动的的还有:





/**
*Processesintentssenttotheactivity.
*
*@paramintentTheintent.
*/
publicvoidprocessIntent(Intentintent,StringcallingPackageName,
booleancanCallNonEmergency){
//略过
Stringaction=intent.getAction();
if(Intent.ACTION_CALL.equals(action)||//满足三种CALL_ACTION的任何一种都往外拨打
Intent.ACTION_CALL_PRIVILEGED.equals(action)||
Intent.ACTION_CALL_EMERGENCY.equals(action)){
processOutgoingCallIntent(intent,callingPackageName,canCallNonEmergency);
}
}
[/code]

ProcessOutgoingCallIntent

处理Intent

privatevoidprocessOutgoingCallIntent(Intentintent,StringcallingPackageName,
booleancanCallNonEmergency){
//略过不关心的
intvideoState=intent.getIntExtra(
TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
VideoProfile.STATE_AUDIO_ONLY);
Log.d(this,"processOutgoingCallIntentvideoState="+videoState);
//
videoState=0意为AUDIO_ONLY1和2为单向视频,3为双向视频
if(!isEmergencyVideoCallingSupported()&&VideoProfile.isVideo(videoState)
&&TelephonyUtil.shouldProcessAsEmergency(mContext,handle)){
Log.d(this,"Emergencycall...Convertingvideocalltovoice...");
videoState=VideoProfile.STATE_AUDIO_ONLY;
intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
videoState);
}
if(VideoProfile.isVideo(videoState)&&isTtyModeEnabled()&&
!TelephonyUtil.shouldProcessAsEmergency(mContext,handle)){
showErrorDialogForRestrictedOutgoingCall(mContext,
R.string.video_call_not_allowed_if_tty_enabled);
Log.d(this,"Rejectingvideocallsasttyisenabled");
return;
}
intent.putExtra(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER,
isDefaultOrSystemDialer(callingPackageName));
sendBroadcastToReceiver(intent);
}
[/code]

sendBroadcastToReceiver

发送广播

/**
*Trampolinestheintenttothebroadcastreceiverthatrunsonlyastheprimaryuser.
*/
privatebooleansendBroadcastToReceiver(Intentintent){
intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL,false);
intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
intent.setClass(mContext,PrimaryCallReceiver.class);//接收者
Log.d(this,"SendingbroadcastasusertoCallReceiver");
mContext.sendBroadcastAsUser(intent,UserHandle.OWNER);//发广播
returntrue;
}
[/code]

PrimaryCallReceiver.java,中的onReveiver()很像L版本上CallReceiver.java的onReceiver(),但其实是新增的、

@Override
publicvoidonReceive(Contextcontext,Intentintent){
synchronized(getTelecomSystem().getLock()){
getTelecomSystem().getCallIntentProcessor().processIntent(intent);
}
}
[/code]

log里面也打印了是由CallIntentProcessor接着处理

D/Telecom(11638):UserCallIntentProcessor:processOutgoingCallIntentvideoState=0//
videoState=0意为AUDIO_ONLY1和2为单向视频,3为双向视频
D/Telecom(11638):UserCallIntentProcessor:SendingbroadcastasusertoCallReceiver
I/Telecom(11638):CallIntentProcessor:onReceive-isUnknownCall:false
[/code]

因为我是拨打的是CS域的电话所以上面log中videoState=0

CallintentProcessor.java(原名CallReceiver)这里也可以认为CallReceiver.java拆分成了PrimaryCallReceiver.java和CallintentProcessor.java。
processIntent

publicvoidprocessIntent(Intentintent){
finalbooleanisUnknownCall=intent.getBooleanExtra(KEY_IS_UNKNOWN_CALL,false);
Log.i(this,"onReceive-isUnknownCall:%s",isUnknownCall);
Trace.beginSection("processNewCallCallIntent");
if(isUnknownCall){
processUnknownCallIntent(mCallsManager,intent);
}else{
processOutgoingCallIntent(mContext,mCallsManager,intent);
}
Trace.endSection();
}
[/code]

ProcessOutgongCallIntent

/**
*ProcessesCALL,CALL_PRIVILEGED,andCALL_EMERGENCYintents.
*
*@paramintentCallintentcontainingdataaboutthehandletocall.
*/
staticvoidprocessOutgoingCallIntent(
Contextcontext,
CallsManagercallsManager,
Intentintent){
Urihandle=intent.getData();
Stringscheme=handle.getScheme();
StringuriString=handle.getSchemeSpecificPart();
BundleclientExtras=null;
Stringorigin=null;
//掠过一些本次不关系的
Log.i(CallIntentProcessor.class,"processOutgoingCallIntenthandle="+handle
+",scheme="+scheme+",uriString="+uriString
+",isSkipSchemaParsing="+isSkipSchemaParsing
+",isAddParticipant="+isAddParticipant
+",isCallPull="+isCallPull);
//Ensurecallsubjectispassedontotheconnectionservice.
if(intent.hasExtra(TelecomManager.EXTRA_CALL_SUBJECT)){
Stringcallsubject=intent.getStringExtra(TelecomManager.EXTRA_CALL_SUBJECT);
clientExtras.putString(TelecomManager.EXTRA_CALL_SUBJECT,callsubject);
}
finalbooleanisPrivilegedDialer=intent.getBooleanExtra(KEY_IS_PRIVILEGED_DIALER,false);
//SendtoCallsManagertoensuretheInCallUIgetskickedoffbeforethebroadcastreturns//先把InCallUI界面起来
Callcall=callsManager.startOutgoingCall(handle,phoneAccountHandle,clientExtras,
origin);
if(call!=null){
//AsynchronouscallsshouldnotusuallybemadeinsideaBroadcastReceiverbecauseonce
//onReceiveiscomplete,theBroadcastReceiver'sprocessrunstheriskofgetting
//killedifmemoryisscarce.However,thisisOKherebecausetheentireTelecom
//processwillberunningthroughoutthedurationofthephonecallandshouldnever
//bekilled.
NewOutgoingCallIntentBroadcasterbroadcaster=newNewOutgoingCallIntentBroadcaster(
context,callsManager,call,intent,isPrivilegedDialer);
finalintresult=broadcaster.processIntent();
finalbooleansuccess=result==DisconnectCause.NOT_DISCONNECTED;
if(!success&&call!=null){
disconnectCallAndShowErrorDialog(context,call,result);
}
}
}
[/code]

NewoutgoingCallIntentBroadcaster.java

注意看前面的注释中的三种action介绍,

/**
*Processesthesuppliedintentandstartstheoutgoingcallbroadcastprocessrelevanttothe
*intent.
*
*Thismethodwillhandlethreekindsofactions:
*
*-CALL(intentlaunchedbyallthirdpartydialers)//第三方的app拨号应用
*-CALL_PRIVILEGED(intentlaunchedbysystemappse.g.systemDialer,voiceDialer)//系统拨号应用,语音拨号应用
*-CALL_EMERGENCY(intentlaunchedbylockscreenemergencydialer)//锁屏界面的紧急拨号器拨打的
*
*@return{@linkDisconnectCause#NOT_DISCONNECTED}ifthecallsucceeded,andanappropriate
*{@linkDisconnectCause}ifthecalldidnot,describingwhyitfailed.
*/
intprocessIntent(){
Log.v(this,"ProcessingcallintentinOutgoingCallIntentBroadcaster.");
Intentintent=mIntent;
Stringaction=intent.getAction();
finalUrihandle=intent.getData();
//略
finalbooleanisPotentialEmergencyNumber=isPotentialEmergencyNumber(number);
Log.v(this,"isPotentialEmergencyNumber=%s",isPotentialEmergencyNumber);
rewriteCallIntentAction(intent,isPotentialEmergencyNumber);//这里是重写CALL_ACTION的方法,具体的见下面的插播
action=intent.getAction();
//Trueforcertaintypesofnumbersthatarenotintendedtobeinterceptedormodified
//bythirdparties(e.g.emergencynumbers).
booleancallImmediately=false;//一个较为关键的值,赋值受CALL_ACTION影响
if(Intent.ACTION_CALL.equals(action)){//在目前的版本上默认是这个没啥说的
if(isPotentialEmergencyNumber){//是紧急号码的话继续,不是紧急号码的话,那进来就什么都没做。至于紧急号码的判断,在流程中不同的地方可能不一样,请自行了解
if(!mIsDefaultOrSystemPhoneApp){
Log.w(this,"Cannotcallpotentialemergencynumber%swithCALLIntent%s"
+"unlesscallerissystemordefaultdialer.",number,intent);
launchSystemDialer(intent.getData());//第三方输入紧急号码后点击拨打会调到系统拨号程序(如果不是紧急号码的话会直接跳到系统拨号界面,也就是InCallUI)
returnDisconnectCause.OUTGOING_CANCELED;
}else{
callImmediately=true;//走到这里的条件是:1.重写后的ACTION是CALL2.是Potential紧急号码3.由系统拨号应用发起的拨号
}
}
}elseif(Intent.ACTION_CALL_EMERGENCY.equals(action)){//紧急号码的CALL_ACTION
if(!isPotentialEmergencyNumber){
Log.w(this,"Cannotcallnon-potential-emergencynumber%swithEMERGENCY_CALL"
+"Intent%s.",number,intent);
returnDisconnectCause.OUTGOING_CANCELED;//用紧急号码的action拨打非紧急号码,是不允许的,返回。
}
callImmediately=true;//到这里的条件是:就是action是
android.intent.action.CALL_EMERGENCY
}else{
Log.w(this,"UnhandledIntent%s.Ignoringandnotplacingcall.",intent);
returnDisconnectCause.INVALID_NUMBER;
}
if(callImmediately){//只有在紧急号码的情况下进入
Log.i(this,"Placingcallimmediatelyinsteadofwaitingfor"
+"OutgoingCallBroadcastReceiver:%s",intent);
Stringscheme=isUriNumber?PhoneAccount.SCHEME_SIP:PhoneAccount.SCHEME_TEL;
booleanspeakerphoneOn=mIntent.getBooleanExtra(
TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,false);
intvideoState=mIntent.getIntExtra(
TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
VideoProfile.STATE_AUDIO_ONLY);
mCallsManager.placeOutgoingCall(mCall,Uri.fromParts(scheme,number,null),null,//直接开始拨打了,可以说这段代码在一定程度上会加快拨打紧急号码的速度
speakerphoneOn,videoState);
//Don'treturnbutinsteadcontinueandsendtheACTION_NEW_OUTGOING_CALLbroadcast
//sothatthirdpartiescanstillinspect(butnotintercept)theoutgoingcall.When
//thebroadcastfinallyreachestheOutgoingCallBroadcastReceiver,we'llknownotto
//initiatethecallagainbecauseofthepresenceoftheEXTRA_ALREADY_CALLEDextra.
}
Log.i(this,"SendingNewOutgoingCallBroadcastfor%s",mCall);
if(isSkipSchemaParsing){
broadcastIntent(intent,handle.toString(),!callImmediately);
}else{
broadcastIntent(intent,number,!callImmediately);//又来广播
}
returnDisconnectCause.NOT_DISCONNECTED;
}
[/code]

log

V/Telecom(11638):NewOutgoingCallIntentBroadcaster:processIntentisConferenceUri:falseisSkipSchemaParsing=false
[/code]

插播

rewriteCallIntentAction是重写action的方法。主要目的是把CALL_PRIVILEGED的action根据号码类型转换为CALL或者CALL_EMERGENCY,就是转换为普通和紧急号码action类型。

按照AndroidL上的设计,系统拨号应用intent默认携带android.intent.action.CALL_PRIVILEGED,之后在这个方法内部转换。然而现在AndroidM默认携带的是android.intent.action.CALL,那么现在这个方法就是废的,从系统拨号应用拨出的紧急号码也不会重写成android.intent.action.CALL_EMERGENCY了,紧急电话的拨打可能会受到一些影响。

/**
*Givenacallintentandwhetherornotthenumbertodialisanemergencynumber,rewrite
*thecallintentactiontoanappropriateone.
*
*@paramintentIntenttorewritetheactionfor
*@paramisPotentialEmergencyNumberWhetherornotthenumberispotentiallyanemergency
*number.
*/
privatevoidrewriteCallIntentAction(Intentintent,booleanisPotentialEmergencyNumber){
Stringaction=intent.getAction();
/*ChangeCALL_PRIVILEGEDintoCALLorCALL_EMERGENCYasneeded.*/注释已经很明确了
if(Intent.ACTION_CALL_PRIVILEGED.equals(action)){//判断条件是ACTION_CALL_PRIVILEGED,当前M默认为CALL,所以这个方法基本上也是废的。
if(isPotentialEmergencyNumber){//紧急号码的话重写成android.intent.action.CALL_EMERGENCY
Log.i(this,"ACTION_CALL_PRIVILEGEDisusedwhilethenumberisapotential"
+"emergencynumber.UsingACTION_CALL_EMERGENCYasanactioninstead.");
action=Intent.ACTION_CALL_EMERGENCY;
}else{
action=Intent.ACTION_CALL;//否则重写成
android.intent.action.CALL
}
Log.v(this,"-updatingactionfromCALL_PRIVILEGEDto%s",action);
intent.setAction(action);
}
}
[/code]

好,把前面的稍微总结一下,这个aciton变了,但流程上似乎并没什么影响,callImmediately还是被赋值为true了,至于后面啥影响,还没看出来//

继续走

broadcastIntent()

/**
*Sendsanewoutgoingcallorderedbroadcastsothatthirdpartyappscancancelthe
*placementofthecallorredirectittoadifferentnumber.
*
*@paramoriginalCallIntentTheoriginalcallintent.
*@paramnumberCallnumberthatwasstoredintheoriginalcallintent.
*@paramreceiverRequiredWhetherornottheresultfromtheorderedbroadcastshouldbe
*processedusinga{@linkNewOutgoingCallIntentBroadcaster}.
*/
privatevoidbroadcastIntent(
IntentoriginalCallIntent,
Stringnumber,
booleanreceiverRequired){
IntentbroadcastIntent=newIntent(Intent.ACTION_NEW_OUTGOING_CALL);
if(number!=null){
broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER,number);
}
//Forcereceiversofthisbroadcastintenttorunatforegroundprioritybecausewe
//wanttofinishprocessingthebroadcastintentassoonaspossible.
broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Log.v(this,"Broadcastingintent:%s.",broadcastIntent);
checkAndCopyProviderExtras(originalCallIntent,broadcastIntent);
mContext.sendOrderedBroadcastAsUser(
broadcastIntent,
UserHandle.CURRENT,
android.Manifest.permission.PROCESS_OUTGOING_CALLS,
AppOpsManager.OP_PROCESS_OUTGOING_CALLS,
receiverRequired?newNewOutgoingCallBroadcastIntentReceiver():null,
null,//scheduler
Activity.RESULT_OK,//initialCode
number,//initialData:initialvaluefortheresultdata(numbertobemodified)
null);//initialExtras
}
[/code]

NewOutgoingCallBroadcastIntentReceiver

/**
*Processestheresultoftheoutgoingcallbroadcastintent,andperformscallbacksto
*theOutgoingCallIntentBroadcasterListenerasnecessary.
*/
privateclassNewOutgoingCallBroadcastIntentReceiverextendsBroadcastReceiver{
@Override
publicvoidonReceive(Contextcontext,Intentintent){
Trace.beginSection("onReceiveNewOutgoingCallBroadcast");
Log.v(this,"onReceive:%s",intent);
//OncetheNEW_OUTGOING_CALLbroadcastisfinished,theresultDataisusedasthe
//actualnumbertocall.(Ifnull,nocallwillbeplaced.)
StringresultNumber=getResultData();
Log.i(this,"Receivednew-outgoing-call-broadcastfor%swithdata%s",mCall,
Log.pii(resultNumber));
//略
GatewayInfogatewayInfo=getGateWayInfoFromIntent(intent,resultHandleUri);
mCallsManager.placeOutgoingCall(mCall,resultHandleUri,gatewayInfo,
mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,??
EXTRA_START_CALL_WITH_SPEAKERPHONE
false),
mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
VideoProfile.STATE_AUDIO_ONLY));
Trace.endSection();
}
}
[/code]

后面与L上的流程几乎都是一样的了,暂时就不细说了,


关键log

Event开头的是新增log

I/Telecom(11638):Event:Call2:CREATED,null
I/Telecom(11638):Event:Call2:SET_CONNECTING,ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService},[356a192b7913b04c54574d18c28d46e6395428ab],UserHandle{0}
I/Telecom(11638):Event:Call2:AUDIO_ROUTE,EARPIECE//audio变化
I/Telecom(11638):Event:Call2:BIND_CS,ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}//CScallbind
I/Telecom(11638):Event:Call2:CS_BOUND,ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}
I/Telecom(11638):Event:Call2:START_CONNECTION,tel:10010
I/Telecom(11638):Event:Call2:SET_DIALING,successfuloutgoingcall//拨号
I/Telecom(11638):Event:Call2:SET_ACTIVE,activesetexplicitly//接通
I/Telecom(11638):Event:Call2:REQUEST_DISCONNECT,null//主动断开
I/Telecom(11638):Event:Call2:SET_DISCONNECTED,disconnectedsetexplicitly>DisconnectCause[Code:(LOCAL)Label:()Description:()Reason:(LOCAL)Tone:(27)]//断开原因
I/Telecom(11638):Event:Call2:DESTROYED,null
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: