转载请注明出处!! 原文地址: 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                      


更多相关文章

  1. 源码角度分析Android启动流程
  2. android系统启动流程启动画面学习之init和init.rc分析
  3. Android自定义View之View的绘制流程
  4. Android 9(P)应用进程创建流程大揭秘
  5. Android OTA升级原理和流程分析(零)---启动篇
  6. android 系统的开机启动流程源码解析(从linux 内核到android Laun
  7. 为什么微软可以向安卓厂商收取专利费
  8. Android Studio3.0开发JNI流程------在Android原程序添加自己类
  9. Android关机流程源码分析

随机推荐

  1. php 重载与事件委托
  2. 文件上传的实例
  3. 实例演绎pdo在用户登录环节是怎么防sql注
  4. php灭绝手把手教你玩文件上传
  5. mysql简单处理表格与pdo预处理的作用
  6. 前端、后端、测试、研发经理必备技能-Api
  7. react源码解读 getNextLanes
  8. [emerg] bind() to 0.0.0.0:XXXX failed
  9. 08-11 作业 面对对象和自动加载 封装 继
  10. 获取 NodeJS 程序退出码