• Ims通话流程分析


    Ims 是3GPP提出的概念,全称为IP Multimedia Subsystem(ip多媒体子系统),是为了满足IP多媒体业务的需求,基于PS域的一个子系统。

    WCDMA网络从R99版本开始,与2G/2.5G网络相比,最大的变化在于空口技术的改变,空口变化直接造成接入带宽的提高,同时核心网分为CS域和PS域两个部分,CS域(电路域)负责语音业务,PS域(分组域)负责Internet访问业务。
    从R4版本开始,CS域从原来的TDM承载变成IP承载,同时引入软交换系统,实现呼叫控制和承载相分离。R4版本由于对PS域和CS域都统一承载在IP网络上,同时由于软交换架构,目前成为WCDMA建网的主要选择。
    随着用户需求的不断变化,单纯的语音通信和Internet访问业务已经不能满足需求。3GPP从R5版本开始,在原有的PS域的基础上,引入IMS来提供IP多媒体业务。

    WCDMA 即3G网络使用PS域实现internet访问业务,CS域(电路域)负责语音业务,所以我们在3G网络时,打电话时,不能同时上网。4G时PS域和CS域都统一由ip网络承载,即volte高清通话,所以我们在4G时开启了volte,通话时还能同时上网。
    如果开启volte,则会通过csfb(电路域落回)技术,在2G\3G进行语音业务。

    Android 9 引入了一个名为 ImsService 的新 SystemApi 接口,可以帮助实现IP多媒体子系统。ImsService API 是在 Android 平台与供应商或运营商提供的 IMS 实现之间明确定义的接口。即IMS的具体实现是由供应商或运营商实现。 android提供了相关的系统SystemApi接口。

    与普通的CS通话一致,由Dialer拨号应用,到Telecom,TeleService。区别在于,在GsmCdmaPhone#diale()中,判断是否支持ims通话。

    从App侧一直到Telephony Framework,是不区分CS流程还是PS流程的。到了Telephony Framework模块,会依据IMS相关的状态信息(Registration Status,Service Status等)和用户设置相关信息(Volte Enable?Wifi Calling Enable?UT Enable?等)进而判断出,Call,SMS等是否需要优先走IMS的流程。整体来看,IMS架构如下图:
    在这里插入图片描述
    通常由Phone对象或者ImsPhoneCallTracker对象直接得到ImsManager对象,

    ImsManager imsManager = ImsManager.getInstance(mContext, mPhoneId);
    
    • 1

    接着再通过ImsManager对象间接地得到ImsConfig、ImsUt、ImsCall等重要对象,然后根据请求不同,走不同的通道与Vendor RIL通信,与Call相关的走ImsCall,与补充业务相关的走ImsUt、与IMS功能的能力、参数相关的走ImsConfig,所以分工是十分明确的。谷歌为了规范高通\MTK等芯片厂商的行为,所以定义了IImsService、IImsConfig、IImsCallSession和IImsUt等接口,再由芯片厂商来实现这些接口,谷歌只需要处理好上层调用接口的逻辑即可。

    public Connection dial(String dialString, @NonNull DialArgs dialArgs,
                Consumer<Phone> chosenPhoneConsumer) throws CallStateException {
            if (!isPhoneTypeGsm() && dialArgs.uusInfo != null) {
                throw new CallStateException("Sending UUS information NOT supported in CDMA!");
            }
         
            String possibleEmergencyNumber = checkForTestEmergencyNumber(dialString);
            // Record if the dialed number was swapped for a test emergency number.
            boolean isDialedNumberSwapped = !TextUtils.equals(dialString, possibleEmergencyNumber);
            if (isDialedNumberSwapped) {
                logi("dialString replaced for possible emergency number: " + dialString + " -> "
                        + possibleEmergencyNumber);
                dialString = possibleEmergencyNumber;
            }
            TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
            boolean isEmergency = tm.isEmergencyNumber(dialString);
            /** Check if the call is Wireless Priority Service call */
            //检查呼叫是否为无线优先服务呼叫
            boolean isWpsCall = dialString != null ? (dialString.startsWith(PREFIX_WPS)
                    || dialString.startsWith(PREFIX_WPS_CLIR_ACTIVATE)
                    || dialString.startsWith(PREFIX_WPS_CLIR_DEACTIVATE)) : false;
    
            ImsPhone.ImsDialArgs.Builder imsDialArgsBuilder;
            imsDialArgsBuilder = ImsPhone.ImsDialArgs.Builder.from(dialArgs)
                                                     .setIsEmergency(isEmergency)
                                                     .setIsWpsCall(isWpsCall);
            mDialArgs = dialArgs = imsDialArgsBuilder.build();
    
            Phone imsPhone = mImsPhone;
    
            CarrierConfigManager configManager =
                    (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
            //确定是否通过IMS支持无线优先级服务呼叫。
            boolean allowWpsOverIms = configManager.getConfigForSubId(getSubId())
                    .getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL);
            //确认紧急电话是否使用ims
            boolean useImsForEmergency = isEmergency && useImsForEmergency();
    
            String dialPart = PhoneNumberUtils.extractNetworkPortionAlt(PhoneNumberUtils.
                    stripSeparators(dialString));
            boolean isMmiCode = (dialPart.startsWith("*") || dialPart.startsWith("#"))
                    && dialPart.endsWith("#");
            boolean isSuppServiceCode = ImsPhoneMmiCode.isSuppServiceCodes(dialPart, this);
            boolean isPotentialUssdCode = isMmiCode && !isSuppServiceCode;
            boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled();
            boolean useImsForCall = useImsForCall(dialArgs)
                    && (isWpsCall ? allowWpsOverIms : true);
    
    
         
            //绕过仅限WiFi的WFC检查这是否是紧急呼叫-如果可能,我们仍应尝试通过移动网拨打。
            if (!isEmergency) {
                Phone.checkWfcWifiOnlyModeBeforeDial(mImsPhone, mPhoneId, mContext);
            }
            if (imsPhone != null && !allowWpsOverIms && !useImsForCall && isWpsCall
                    && imsPhone.getCallTracker() instanceof ImsPhoneCallTracker) {
                logi("WPS call placed over CS; disconnecting all IMS calls..");
                ImsPhoneCallTracker tracker = (ImsPhoneCallTracker) imsPhone.getCallTracker();
                tracker.hangupAllConnections();
            }
    		//是否使用IMS拨打电话
            if ((useImsForCall && (!isMmiCode || isPotentialUssdCode))
                    || (isMmiCode && useImsForUt)
                    || useImsForEmergency) {
                try {
                    chosenPhoneConsumer.accept(imsPhone);
                    //imsPhone.dial
                    return imsPhone.dial(dialString, dialArgs);
                } catch (CallStateException e) {
                	...
                }
            }
            ...
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74

    在这里插入图片描述
    Android只提供到ImsCallSession,后面的ImsCallSessionImpl具体实现则要供应商或运营商提供,即imsService的具体实现由供应商或运营商提供。

    参考:Android P IMS 相关2
    IP多媒体子系统

  • 相关阅读:
    【Python】-- 115道语法练习题
    Android摄像头横屏的时候_人脸预览横向显示_问题解决---Android原生开发工作笔记164
    Google Earth Engine 教程——降低影像分辨率从0.6降分辨率到30米
    LeetCode C++ 40.组数总和2---未解决
    【STM32学习(1)】详解STM32时钟体系
    python绘图技巧(高清图)
    【Docker】将自定义的镜像上传至dockerhub或阿里云私有仓库,并在其他节点进行拉取
    线程安全,这词你懂了吗?
    维护积极的react native,为什么会有人造谣react native不维护了,停止维护。
    Excel 导入
  • 原文地址:https://blog.csdn.net/qq_41285455/article/details/126836904