拨打电话流程(Contacts--App层)



   这里以MTK4.0代码为基础进行分析

 首先是Contacts.apk

 拨号盘是依附于DialpadFragment上的。查看源码可以发现。无论是普通拨号还是视频拨号都会调用如下方法

protected void dialButtonPressedInner(String number, int type) {
       if (TextUtils.isEmpty(number)) { / .....}
       ......
       final Intent intent = newDialNumberIntent(number, type);
                if (getActivity() instanceof DialtactsActivity) {
                    intent.putExtra(DialtactsActivity.EXTRA_CALL_ORIGIN,
                            DialtactsActivity.CALL_ORIGIN_DIALTACTS);
                }
                mCallOptionHandler.startActivity(intent);
}

其中

 private Intent newDialNumberIntent(String number, int type) {
        final Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
                                         Uri.fromParts("tel", number, null));

        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        if((type & DIAL_NUMBER_INTENT_IP) != 0)
            intent.putExtra(Constants.EXTRA_IS_IP_DIAL, true);

        if((type & DIAL_NUMBER_INTENT_VIDEO) != 0)
            intent.putExtra(Constants.EXTRA_IS_VIDEO_CALL, true);

        return intent;
    }

会加入Intent.ACTION_CALL_PRIVILEGED,Uri.fromParts("tel", number, null)和是否是VIDEO_CALL / IP_CALL的Extra.调用CallOptionHandler的StartActivity方法

 public void startActivity(Intent intent) {
             .......
            if(PhoneNumberUtils.isEmergencyNumber(mNumber) || intent.getIntExtra(Constants.EXTRA_SLOT_ID, -1) != -1) {
                               final Intent broadcastIntent = newCallBroadcastIntent(mNumber, CallOptionHelper.DIAL_TYPE_VOICE, 0);
                mContext.sendBroadcast(broadcastIntent);
                 return;
            }
            mCallOptionHelper.makeCall(intent);
        } else {
            intent.setClassName(Constants.PHONE_PACKAGE, Constants.OUTGOING_CALL_BROADCASTER);
            mContext.startActivity(intent);
        }
        Profiler.trace(Profiler.CallOptionHandlerLeaveStartActivity);
    }

 这里会判断是否是紧急拨号。如果是紧急拨号则调用 newCallBroadcastIntent返回的Intent发送广播。不是则CallOptionHandler.makeCall

public void makeCall(Intent intent) {
        int type = DIAL_TYPE_VOICE;

        if(intent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false))
            type = DIAL_TYPE_VIDEO;
        
        final Uri uri = intent.getData();
        final String scheme = uri.getScheme();
        
        if(scheme.equals("sip") && !followSimSetting)
            type = DIAL_TYPE_SIP;

        if(Constants.VOICEMAIL_URI.equals(intent.getData().toString()))
            type = DIAL_TYPE_VOICE;
         ......
        makeCall(number, type, originalSim);
    }

这里又将Type类型分为3种  DIAL_TYPE_VOICE,DIAL_TYPE_VIDEO,DIAL_TYPE_SIP

 protected void makeCall(String number, int type, long originalSim) {
        ....         
        switch(type) {
            case DIAL_TYPE_SIP:
               .....
                break;
            case DIAL_TYPE_VIDEO:{
                .....                                        
                break;
            case DIAL_TYPE_VOICE:
                makeVoiceCall(number, type, originalSim, callbackArgs);
                break;
        }
        mCallback.onMakeCall(callbackArgs);
    }

 这里会根据type的类型去实现CallbackArgs callbackArgs对象的不同属性。其中这3种type会存放在callbackArgs.type属性中。然后调用mCallback.onMakeCall方法。查找可以知道onMakeCall是在CallOptionHandler里面实现的。

public void onMakeCall(final CallbackArgs args) {
    int slot = -1;
    switch (args.reason) {
            case CallOptionHelper.MAKE_CALL_REASON_OK: {
            if(args.type == CallOptionHelper.DIAL_TYPE_VOICE){
                          //获取slot
             }
           if(args.type == ...){
                       //获取slot
           }
           mIntent.putExtra(Constants.EXTRA_SLOT_ID, slot);
            ....
           afterCheckSIMStatus(com.mediatek.CellConnService.CellConnMgr.RESULT_STATE_NORMAL, slot);
           ....
           break;
           case MAKE_CALL_REASON_3G_SERVICE_OFF:
           .....
           ....       }
 }
}

这里的mIntent为CallOptionHAndler.startActivity中的intent,在onMakeCall方法中加入了slot字段。然后调用afterCheckSIMStatus方法。

【笔者这里理解的slot字段是一个标志电话类型的标志位。如果slot =1 则是一般电话,slot = 0则是紧急拨号,slot<0则是没有插入SIM卡,不知道正确与否。】

    private boolean afterCheckSIMStatus(int result, int slot) {
        ...
        // ip dial only support voice call
        boolean noSim = SIMInfoWrapper.getDefault().getInsertedSimCount() == 0;
        if(!mIntent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false) && mIntent.getBooleanExtra(Constants.EXTRA_IS_IP_DIAL, false) && !noSim) {
                  ..
            }
        }

        // a little tricky here, check the voice mail number
        if(Constants.VOICEMAIL_URI.equals(mIntent.getData().toString())) {
              //VoiceMailNumber   
                        ..
       }
        }

        String number = getInitialNumber(mIntent);
        final int type = mIntent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false) ? CallOptionHelper.DIAL_TYPE_VIDEO : CallOptionHelper.DIAL_TYPE_VOICE;
        final Intent broadcastIntent = newCallBroadcastIntent(number, type, slot);
        mContext.sendBroadcast(broadcastIntent);
        return true;
    }

 这里最后将调用newCallBroadcastIntent。我们发现紧急拨号或者其他的拨号,如果拨号成功,都是使用newCallBroadcastIntent返回的Intent来发送广播。

  private Intent newCallBroadcastIntent(String number, int type, int slot) {
        Intent intent = new Intent(OUTGOING_CALL_RECEIVER);
        intent.setClassName(PACKAGE, OUTGOING_CALL_RECEIVER);

        if(type == CallOptionHelper.DIAL_TYPE_VIDEO)
            intent.putExtra(Constants.EXTRA_IS_VIDEO_CALL, true);

        if(type == CallOptionHelper.DIAL_TYPE_SIP)
            intent.setData(Uri.fromParts("sip", number, null));
        else
            intent.setData(Uri.fromParts("tel", number, null));

        intent.putExtra(Constants.EXTRA_SLOT_ID, slot);

        return intent;
    }

 到这里会发现,最后发送出去的intent只会包含2个有用的信息。就是Uri和Constants.EXTRA_SLOT_ID。最后该广播将在Phone.apk中的OutgoingCallReceiver中截获。

猜你喜欢

转载自h529820165.iteye.com/blog/1677877