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

转载请注明出处!!
原文地址: http://blog.csdn.net/aaa111/article/details/51503295
今天凌晨才写的博客,一天内未经允许被红黑LM转载,而且没有注明原文链接。其实被转载不重要,你跟我打声招呼嘛。(如需转载,这段可删)
----
此篇介绍Android M上的MO流程,并与Android L上做比较。
先看一下Android M整体的一个流程图:

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

AM_AM_compare
AL_AM_compare.jpg
变化集中在红色框内。小方框是新增API。
下面我们开始跟一下MO的流程。

packages/apps/Dialer

以在拨号盘拨号为入口(当然还有很多其他入口,我们就不挨个跟了),DialpadFragment.java  handleDialButtonPressed(),这个方法内部的代码变少了,也可以看作是多了一步startCall()
packages/apps/Dialer   DialpadFragment.java  
    
    
    
    
    private void handleDialButtonPressed () {
       if (isDigitsEmpty()) { // No number entered.
           handleDialButtonClickWithEmptyDigits();
       } else {
           final String number = mDigits.getText().toString();
 
           // "persist.radio.otaspdial" is a temporary hack needed for one carrier's automated
           // test equipment.
           // TODO: clean it up.
           if (number != null
                   && !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp)
                   && number.matches(mProhibitedPhoneNumberRegexp)) {
               Log.i(TAG, "The phone number is prohibited explicitly by a rule.");
               if (getActivity() != null) {
                   DialogFragment dialogFragment = ErrorDialogFragment.newInstance(
                           R.string.dialog_phone_call_prohibited_message);
                   dialogFragment.show(getFragmentManager(), "phone_prohibited_dialog");
               }
 
               // Clear the digits just in case.
               clearDialpad();
           } else {
               startCall(number, OriginCodes.DIALPAD_DIRECT_DIAL);//这里是新增内容
           }
       }
   }

startCall(),这个方法是新增的,其实也可以看作是拆分出来的
    
    
    
    
   private void startCall(String number, String origin) {
       if (mCurrentCallMethodInfo != null && mCurrentCallMethodInfo.mIsInCallProvider &&
               !PhoneNumberUtils.isEmergencyNumber(number)) {
           mCurrentCallMethodInfo.placeCall(origin, number, getActivity(), false, true,
                   new StartInCallCallReceiver.InCallCallListener() {
                       @Override
                       public void onResult(int resultCode) {
                           if (resultCode == StatusCodes.StartCall.CALL_CONNECTED) {
                               hideAndClearDialpad(false);
                           }
                       }
                   });
       } else {
           // If no sim is selected, or emergency callmethod selected, or number is
           // an emergency number, phone account handle should be null, and will use the
           // default account.
           // Else, create PhoneAccountHandle from selected callmethod components and
           // initial call using that account.
           PhoneAccountHandle handle = CallMethodInfo.getPhoneAccountHandleFromCallMethodInfo(
                   getActivity(), mCurrentCallMethodInfo, number);
           final Intent intent = IntentUtil.getCallIntent(number,//返回的action:android.intent.action.CALL而在5.1上是android.intent.action.CALL_PRIVILEGED
                   (getActivity() instanceof DialtactsActivity ?
                           ((DialtactsActivity) getActivity())
                                   .getCallOrigin() : null),
                   handle);
           DialerUtils.startActivityWithErrorToast(getActivity(), intent, origin);//虽然增加了一步startCall,但这里还是调用了方法
           hideAndClearDialpad(false);
       }
   }

注意这里intent的构造,返回值来自 IntentUtil.getCallIntent(),而Android L的则是返回自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,
再有就是在早起的Android M版本中返回的也是 android.intent.action.CALL_PRIVILEGED,后来改成了 android.intent.action.CALL,至于原因和提交在这就不深追了(看IntentUtil的提交历史可知)。

DialerUtils.java

    
    
    
    
  public static void startActivityWithErrorToast ( Context context , Intent intent , int msgId ,
                                                  String origin) {
       try {
           if ((IntentUtil.CALL_ACTION.equals(intent.getAction())
                           && context instanceof Activity)) {
               // All dialer-initiated calls should pass the touch point to the InCallUI
               Point touchPoint = TouchPointManager.getInstance().getPoint();//geiPoint(),对应的setPoint()方法,在点击的时候调用
               if (touchPoint.x != 0 || touchPoint.y != 0) {
                   Bundle extras = new Bundle();
                   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);
               }
               final TelecomManager tm =
                       (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
               tm.placeCall(intent.getData(), intent.getExtras());//直接到TelecomManager里去了。在L 5.1上是调用startActivityForResult(),之后再启动CallActivity
           } else {
               context.startActivity(intent);
           }
       } catch (ActivityNotFoundException e) {
           Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show();
       }
   }
从下面开始就是主要变化的地方

framework/telecomm

framework/base/telecomm  TelecomManager.java
TelecomManager.placeCall是新增的api,
Android M MO流程 并与Android L MO对比_第1张图片
TelecomManager.placeCall.png
其作用注释里面已经写的很清楚了。
    
    
    
    
/**
    * Places a new outgoing call to the provided address using the system telecom service with
    * the specified extras.
    *
    * This method is equivalent to placing an outgoing call using {@link Intent#ACTION_CALL},
    * except that the outgoing call will always be sent via the system telecom service. If
    * method-caller is either the user selected default dialer app or preloaded system dialer
    * app, then emergency calls will also be allowed.
    *
    * Requires permission: {@link android.Manifest.permission#CALL_PHONE}
    *
    * Usage example://举例
    * <pre>
    * Uri uri = Uri.fromParts("tel", "12345", null);//Uri 主要是号码
    * Bundle extras = new Bundle();
    * extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, true);//默认开扬声器
    * telecomManager.placeCall(uri, extras);
    * </pre>
    *
    * The following keys are supported in the supplied extras.
    * <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>
    *
    * @param address The address to make the call to.
    * @param extras Bundle of extras to use with the call.
    */
   public void placeCall(Uri address, Bundle extras) {
       ITelecomService service = getTelecomService();
       if (service != null) {
           if (address == null) {//检查号码
               Log.w(TAG, "Cannot place call to empty address.");
           }
           try {
               service.placeCall(address, extras == null ? new Bundle() : extras,
                       mContext.getOpPackageName());
           } catch (RemoteException e) {
               Log.e(TAG, "Error calling ITelecomService#placeCall", e);
           }
       }
   }

packages/services/Telecomm

TelecomServiceImpl.java  placeCall
    
    
    
    
       /**
        * @see android.telecom.TelecomManager#placeCall
        */
       @Override
       public void placeCall(Uri handle, Bundle extras, String callingPackage) {
           enforceCallingPackage(callingPackage);
           if (!canCallPhone(callingPackage, "placeCall")) {
               throw new SecurityException("Package " + callingPackage
                       + " is not allowed to place phone calls");
           }
 
           // Note: we can still get here for the default/system dialer, even if the Phone
           // permission is turned off. This is because the default/system dialer is always
           // allowed to attempt to place a call (regardless of permission state), in case//注释还是要看
           // it turns out to be an emergency call. If the permission is denied and the
           // call is being made to a non-emergency number, the call will be denied later on
           // by {@link UserCallIntentProcessor}.
 
           final boolean hasCallAppOp = mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE,
                   Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
 
           final boolean hasCallPermission = mContext.checkCallingPermission(CALL_PHONE) ==
                   PackageManager.PERMISSION_GRANTED;
 
           synchronized (mLock) {
               final UserHandle userHandle = Binder.getCallingUserHandle();
               long token = Binder.clearCallingIdentity();
               try {
                   final Intent intent = new Intent(Intent.ACTION_CALL, handle);
                   intent.putExtras(extras);
                   new UserCallIntentProcessor(mContext, userHandle).processIntent(intent,
                           callingPackage, hasCallAppOp && hasCallPermission);
               } finally {
                   Binder.restoreCallingIdentity(token);
               }
           }
       }

看到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算个新东西,从内容和功能上来说。
一起改名和移动的的还有:


    
    
    
    
    /**
    * Processes intents sent to the activity.
    *
    * @param intent The intent.
    */
   public void processIntent(Intent intent, String callingPackageName,
           boolean canCallNonEmergency) {
     
//略过
 
       String action = 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);
       }
   }
ProcessOutgoingCallIntent
处理Intent
    
    
    
    
  private void processOutgoingCallIntent(Intent intent, String callingPackageName,
           boolean canCallNonEmergency) {
       
//略过不关心的  
       int videoState = intent.getIntExtra(
               TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
               VideoProfile.STATE_AUDIO_ONLY);
       Log.d(this, "processOutgoingCallIntent videoState = " + videoState); //videoState = 0 意为AUDIO_ONLY 1和2为单向视频,3为双向视频
 
       if (!isEmergencyVideoCallingSupported() && VideoProfile.isVideo(videoState)
               && TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) {
           Log.d(this, "Emergency call...Converting video call to voice...");
           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, "Rejecting video calls as tty is enabled");
           return;
       }
 
       intent.putExtra(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER,
               isDefaultOrSystemDialer(callingPackageName));
       sendBroadcastToReceiver(intent);
   }
sendBroadcastToReceiver
发送广播
    
    
    
    
   /**
    * Trampolines the intent to the broadcast receiver that runs only as the primary user.
    */
   private boolean sendBroadcastToReceiver(Intent intent) {
       intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false);
       intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
       intent.setClass(mContext, PrimaryCallReceiver.class);//接收者
       Log.d(this, "Sending broadcast as user to CallReceiver");
       mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);//发广播
       return true;
   }

PrimaryCallReceiver.java,中的onReveiver()很像L版本上CallReceiver.java的onReceiver(),但其实是新增的、
     
     
     
     
@Override
   public void onReceive(Context context, Intent intent) {
       synchronized (getTelecomSystem().getLock()) {
           getTelecomSystem().getCallIntentProcessor().processIntent(intent);
       }
   }
log里面也打印了是由CallIntentProcessor接着处理
     
     
     
     
D/Telecom (11638): UserCallIntentProcessor: processOutgoingCallIntent videoState = 0 // videoState = 0 意为AUDIO_ONLY 1和2为单向视频,3为双向视频
D/Telecom (11638): UserCallIntentProcessor: Sending broadcast as user to CallReceiver
I/Telecom (11638): CallIntentProcessor: onReceive - isUnknownCall: false
因为我是拨打的是CS域的电话所以上面log中videoState = 0

CallintentProcessor.java(原名CallReceiver) 这里也可以认为CallReceiver.java拆分成了PrimaryCallReceiver.java和CallintentProcessor.java。
processIntent
    
    
    
    
public void processIntent(Intent intent) {
       final boolean isUnknownCall = 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();
   }
ProcessOutgongCallIntent
    
    
    
    
   /**
    * Processes CALL, CALL_PRIVILEGED, and CALL_EMERGENCY intents.
    *
    * @param intent Call intent containing data about the handle to call.
    */
   static void processOutgoingCallIntent(
           Context context,
           CallsManager callsManager,
           Intent intent) {
       Uri handle = intent.getData();
       String scheme = handle.getScheme();
       String uriString = handle.getSchemeSpecificPart();
       Bundle clientExtras = null;
       String origin = null;
//掠过一些本次不关系的
 
       Log.i(CallIntentProcessor.class, " processOutgoingCallIntent handle = " + handle
               + ",scheme = " + scheme + ", uriString = " + uriString
               + ", isSkipSchemaParsing = " + isSkipSchemaParsing
               + ", isAddParticipant = " + isAddParticipant
               + ", isCallPull = " + isCallPull);
 
       // Ensure call subject is passed on to the connection service.
       if (intent.hasExtra(TelecomManager.EXTRA_CALL_SUBJECT)) {
           String callsubject = intent.getStringExtra(TelecomManager.EXTRA_CALL_SUBJECT);
           clientExtras.putString(TelecomManager.EXTRA_CALL_SUBJECT, callsubject);
       }
 
       final boolean isPrivilegedDialer = intent.getBooleanExtra(KEY_IS_PRIVILEGED_DIALER, false);
 
       // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns //先把InCallUI界面起来
       Call call = callsManager.startOutgoingCall(handle, phoneAccountHandle, clientExtras,
               origin);
 
       if (call != null) {
           // Asynchronous calls should not usually be made inside a BroadcastReceiver because once
           // onReceive is complete, the BroadcastReceiver's process runs the risk of getting
           // killed if memory is scarce. However, this is OK here because the entire Telecom
           // process will be running throughout the duration of the phone call and should never
           // be killed.
           NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
                   context, callsManager, call, intent, isPrivilegedDialer);
           final int result = broadcaster.processIntent();
           final boolean success = result == DisconnectCause.NOT_DISCONNECTED;
 
           if (!success && call != null) {
               disconnectCallAndShowErrorDialog(context, call, result);
           }
       }
   }
NewoutgoingCallIntentBroadcaster.java
注意看前面的注释中的三种action介绍,
    
    
    
    
/**
    * Processes the supplied intent and starts the outgoing call broadcast process relevant to the
    * intent.
    *
    * This method will handle three kinds of actions:
    *
    * - CALL (intent launched by all third party dialers)//第三方的app拨号应用
    * - CALL_PRIVILEGED (intent launched by system apps e.g. system Dialer, voice Dialer)//系统拨号应用,语音拨号应用
    * - CALL_EMERGENCY (intent launched by lock screen emergency dialer)//锁屏界面的紧急拨号器拨打的
    *
    * @return {@link DisconnectCause#NOT_DISCONNECTED} if the call succeeded, and an appropriate
    *         {@link DisconnectCause} if the call did not, describing why it failed.
    */
   int processIntent() {
       Log.v(this, "Processing call intent in OutgoingCallIntentBroadcaster.");
 
       Intent intent = mIntent;
       String action = intent.getAction();
       final Uri handle = intent.getData();
 //略
 
       final boolean isPotentialEmergencyNumber = isPotentialEmergencyNumber(number);
       Log.v(this, "isPotentialEmergencyNumber = %s", isPotentialEmergencyNumber);
 
       rewriteCallIntentAction(intent, isPotentialEmergencyNumber);//这里是重写CALL_ACTION的方法,具体的见下面的插播
       action = intent.getAction();
       // True for certain types of numbers that are not intended to be intercepted or modified
       // by third parties (e.g. emergency numbers).
       boolean callImmediately = false;//一个较为关键的值,赋值受CALL_ACTION影响
 
       if (Intent.ACTION_CALL.equals(action)) {//在目前的版本上默认是这个没啥说的
           if (isPotentialEmergencyNumber) {//是紧急号码的话继续,不是紧急号码的话,那进来就什么都没做。至于紧急号码的判断,在流程中不同的地方可能不一样,请自行了解
               if (!mIsDefaultOrSystemPhoneApp) {
                   Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s "
                           + "unless caller is system or default dialer.", number, intent);
                   launchSystemDialer(intent.getData());//第三方输入紧急号码后点击拨打会调到系统拨号程序(如果不是紧急号码的话会直接跳到系统拨号界面,也就是InCallUI)
                   return DisconnectCause.OUTGOING_CANCELED;
               } else {
                   callImmediately = true;//走到这里的条件是:1.重写后的ACTION是CALL 2.是Potential紧急号码 3.由系统拨号应用发起的拨号
               }
           }
       } else if (Intent.ACTION_CALL_EMERGENCY.equals(action)) {//紧急号码的CALL_ACTION
           if (!isPotentialEmergencyNumber) {
               Log.w(this, "Cannot call non-potential-emergency number %s with EMERGENCY_CALL "
                       + "Intent %s.", number, intent);
               return DisconnectCause.OUTGOING_CANCELED;//用紧急号码的action拨打非紧急号码,是不允许的,返回。
           }
           callImmediately = true;//到这里的条件是:就是action是 android.intent.action.CALL_EMERGENCY
       } else {
           Log.w(this, "Unhandled Intent %s. Ignoring and not placing call.", intent);
           return DisconnectCause.INVALID_NUMBER;
       }
 
       if (callImmediately) {//只有在紧急号码的情况下进入
           Log.i(this, "Placing call immediately instead of waiting for "
                   + " OutgoingCallBroadcastReceiver: %s", intent);
           String scheme = isUriNumber ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL;
           boolean speakerphoneOn = mIntent.getBooleanExtra(
                   TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false);
           int videoState = 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't return but instead continue and send the ACTION_NEW_OUTGOING_CALL broadcast
           // so that third parties can still inspect (but not intercept) the outgoing call. When
           // the broadcast finally reaches the OutgoingCallBroadcastReceiver, we'll know not to
           // initiate the call again because of the presence of the EXTRA_ALREADY_CALLED extra.
       }
 
       Log.i(this, "Sending NewOutgoingCallBroadcast for %s", mCall);
       if (isSkipSchemaParsing) {
           broadcastIntent(intent, handle.toString(), !callImmediately);
       } else {
           broadcastIntent(intent, number, !callImmediately);//又来广播
       }
       return DisconnectCause.NOT_DISCONNECTED;
   }

log
    
    
    
    
V/Telecom (11638): NewOutgoingCallIntentBroadcaster: processIntent isConferenceUri: false isSkipSchemaParsing = false

插播
rewriteCallIntentAction是重写action的方法。 主要目的是把CALL_PRIVILEGED的action根据号码类型转换为CALL或者CALL_EMERGENCY,就是转换为普通和紧急号码action类型。
按照Android L上的设计,系统拨号应用intent默认携带 android.intent.action.CALL_PRIVILEGED,之后在这个方法内部转换。然而现在Android M默认携带的是 android.intent.action.CALL,那么现在这个方法就是废的,从系统拨号应用拨出的紧急号码也不会重写成 android.intent.action.CALL_EMERGENCY了,紧急电话的拨打可能会受到一些影响。
    
    
    
    
/**
    * Given a call intent and whether or not the number to dial is an emergency number, rewrite
    * the call intent action to an appropriate one.
    *
    * @param intent Intent to rewrite the action for
    * @param isPotentialEmergencyNumber Whether or not the number is potentially an emergency
    * number.
    */
   private void rewriteCallIntentAction(Intent intent, boolean isPotentialEmergencyNumber) {
       String action = intent.getAction();
 
       /* Change CALL_PRIVILEGED into CALL or CALL_EMERGENCY as needed. */注释已经很明确了
       if (Intent.ACTION_CALL_PRIVILEGED.equals(action)) {//判断条件是 ACTION_CALL_PRIVILEGED,当前M默认为CALL,所以这个方法基本上也是废的。
           if (isPotentialEmergencyNumber) {//紧急号码的话重写成android.intent.action.CALL_EMERGENCY
               Log.i(this, "ACTION_CALL_PRIVILEGED is used while the number is a potential"
                       + " emergency number. Using ACTION_CALL_EMERGENCY as an action instead.");
               action = Intent.ACTION_CALL_EMERGENCY;
           } else {
               action = Intent.ACTION_CALL;//否则重写成 android.intent.action.CALL
           }
           Log.v(this, " - updating action from CALL_PRIVILEGED to %s", action);
           intent.setAction(action);
       }
   }
好,把前面的稍微总结一下,这个aciton变了,但流程上似乎 并没什么影响callImmediately还是被赋值为true了,至于后面啥影响,还没看出来//
继续走
broadcastIntent()
    
    
    
    
/**
    * Sends a new outgoing call ordered broadcast so that third party apps can cancel the
    * placement of the call or redirect it to a different number.
    *
    * @param originalCallIntent The original call intent.
    * @param number Call number that was stored in the original call intent.
    * @param receiverRequired Whether or not the result from the ordered broadcast should be
    *     processed using a {@link NewOutgoingCallIntentBroadcaster}.
    */
   private void broadcastIntent(
           Intent originalCallIntent,
           String number,
           boolean receiverRequired) {
       Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
       if (number != null) {
           broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);
       }
 
       // Force receivers of this broadcast intent to run at foreground priority because we
       // want to finish processing the broadcast intent as soon as possible.
       broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
       Log.v(this, "Broadcasting intent: %s.", broadcastIntent);
 
       checkAndCopyProviderExtras(originalCallIntent, broadcastIntent);
 
       mContext.sendOrderedBroadcastAsUser(
               broadcastIntent,
               UserHandle.CURRENT,
               android.Manifest.permission.PROCESS_OUTGOING_CALLS,
               AppOpsManager.OP_PROCESS_OUTGOING_CALLS,
               receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null,
               null,  // scheduler
               Activity.RESULT_OK,  // initialCode
               number,  // initialData: initial value for the result data (number to be modified)
               null);  // initialExtras
   }

NewOutgoingCallBroadcastIntentReceiver
    
    
    
    
   /**
    * Processes the result of the outgoing call broadcast intent, and performs callbacks to
    * the OutgoingCallIntentBroadcasterListener as necessary.
    */
   private class NewOutgoingCallBroadcastIntentReceiver extends BroadcastReceiver {
 
       @Override
       public void onReceive(Context context, Intent intent) {
           Trace.beginSection("onReceiveNewOutgoingCallBroadcast");
           Log.v(this, "onReceive: %s", intent);
 
           // Once the NEW_OUTGOING_CALL broadcast is finished, the resultData is used as the
           // actual number to call. (If null, no call will be placed.)
           String resultNumber = getResultData();
           Log.i(this, "Received new-outgoing-call-broadcast for %s with data %s", mCall,
                   Log.pii(resultNumber));
 
         
//略  
           GatewayInfo gatewayInfo = 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();
       }
   }

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

关键log

Event 开头的是新增log
    
    
    
    
I/Telecom (11638): Event: Call 2: CREATED, null
I/Telecom (11638): Event: Call 2: SET_CONNECTING, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, [356a192b7913b04c54574d18c28d46e6395428ab], UserHandle{0}
I/Telecom (11638): Event: Call 2: AUDIO_ROUTE, EARPIECE//audio变化
I/Telecom (11638): Event: Call 2: BIND_CS, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}//CS call bind
I/Telecom (11638): Event: Call 2: CS_BOUND, ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}
I/Telecom (11638): Event: Call 2: START_CONNECTION, tel:10010
I/Telecom (11638): Event: Call 2: SET_DIALING, successful outgoing call//拨号
I/Telecom (11638): Event: Call 2: SET_ACTIVE, active set explicitly//接通
I/Telecom (11638): Event: Call 2: REQUEST_DISCONNECT, null//主动断开
I/Telecom (11638): Event: Call 2: SET_DISCONNECTED, disconnected set explicitly> DisconnectCause [ Code: (LOCAL) Label: () Description: () Reason: (LOCAL) Tone: (27) ]//断开原因
I/Telecom (11638): Event: Call 2: DESTROYED, null


你可能感兴趣的:(android,android,m,6.0,去电流程,MO流程)