开关VoLTE流程分析(一)

本文详细解析了在Android设备上开启VoLTE功能的具体步骤和技术实现细节,包括开关控件的初始化、监听方法的实现、配置参数的设置等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开关按钮位置:
  设置--> 更多--> 移动网络--> 增强型4G LTE模式

控件初始化addEnhanced4GLteSwitchPreference,该设置开关使用了SwitchPreference控件,addEnhanced4GLteSwitchPreference()添加控件(packages/services/telephony/src/com/android/phone/MobileNetworkSettings.java)

复制代码
    private void addEnhanced4GLteSwitchPreference(PreferenceScreen preferenceScreen) {
        log("[addEnhanced4GLteSwitchPreference] ImsEnabled :"
                + ImsManager.isVolteEnabledByPlatform(this));
        if (mButton4glte != null) { //去掉Google原生开关按钮
            log("[addEnhanced4GLteSwitchPreference] Remove mButton4glte!");
            preferenceScreen.removePreference(mButton4glte);
        }
        if (ImsManager.isVolteEnabledByPlatform(this)) { //判断是否支持VoLTE
            int order = mButtonEnabledNetworks.getOrder() + 1;
                     //VoLTE开关初始化
            mEnhancedButton4glte = new Enhanced4GLteSwitchPreference(this, mPhone.getSubId()); 
            /// Still use Google's key, title, and summary.
            mEnhancedButton4glte.setKey(BUTTON_4G_LTE_KEY); //Key用于SharePreference存储信息
            if (ImsManager.isWfcEnabledByPlatform(this)) { //判断是否支持WIFI Call
                mEnhancedButton4glte.setTitle(R.string.wfc_volte_switch_title);
            } else {
                mEnhancedButton4glte.setTitle(R.string.enhanced_4g_lte_mode_title);
            }
            mEnhancedButton4glte.setSummary(R.string.enhanced_4g_lte_mode_summary);
            mEnhancedButton4glte.setOnPreferenceChangeListener(this); //设置监听接口,状态发生变化onPreferenceChange()方法将被调用
            mEnhancedButton4glte.setOrder(order);
            //preferenceScreen.addPreference(mEnhancedButton4glte);
        }
复制代码

 

监听方法onPreferenceChangeMTK,该接听方法onPreferenceChangeMTK(),重新原生onPreferenceChange();

复制代码
    private boolean onPreferenceChangeMTK(Preference preference, Object objValue) {
        log("[onPreferenceChangeMTK] preference = " + preference.getTitle());
        if (mEnhancedButton4glte == preference) { 
            log("[onPreferenceChangeMTK] IsChecked = " + mEnhancedButton4glte.isChecked());
            Enhanced4GLteSwitchPreference ltePref = (Enhanced4GLteSwitchPreference) preference;
            ltePref.setChecked(!ltePref.isChecked()); //设置控件状态,默认关闭是false,打开即是true
            ImsManager.setEnhanced4gLteModeSetting(this, ltePref.isChecked()); //设置VoLTE参数
            return true;
        }
        return false;
    }
复制代码

有如下打印信息:

 

设置VoLTE状态setEnhanced4gLteModeSetting,frameworks/opt/net/ims/src/java/com/android/ims/ImsManager.java

复制代码
    public static void setEnhanced4gLteModeSetting(Context context, boolean enabled) {
        int value = enabled ? 1 : 0;
          //设置Settings.Global.ENHANCED_4G_MODE_ENABLED变量
        android.provider.Settings.Global.putInt(
                context.getContentResolver(),
                android.provider.Settings.Global.ENHANCED_4G_MODE_ENABLED, value);

        if (isNonTtyOrTtyOnVolteEnabled(context)) { //不支持TTY或者VoLTE支持TTY
            ImsManager imsManager = ImsManager.getInstance(context,
                    SubscriptionManager.getDefaultVoicePhoneId()); //获取ImsManager对象
            if (imsManager != null) {
                try {
                    imsManager.setAdvanced4GMode(enabled); //设置VoLTE
                } catch (ImsException ie) {
                    // do nothing
                }
            }
        }
    }
复制代码

设置VoLTE

复制代码
    private void setAdvanced4GMode(boolean turnOn) throws ImsException {
        checkAndThrowExceptionIfServiceUnavailable();

        try {
            ImsConfig config = getConfigInterface(); //IMS 配置参数
            if (config != null) {
                             //设置FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE网络参数
                config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
                        TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
            }
        } catch (ImsException e) {
            log("setAdvanced4GMode() : " + e);
        }

        log("setAdvanced4GMode():" + turnOn);
        if (turnOn) {
            turnOnIms(); //打开IMS 服务
        } else if (isImsTurnOffAllowed()) {
            log("setAdvanced4GMode() : imsServiceAllowTurnOff -> turnOffIms");
            turnOffIms(); //关闭IMS 服务
        }
复制代码

有如下打印信息:

 

打开IMS 服务

复制代码
    private void turnOnIms() throws ImsException {
        checkAndThrowExceptionIfServiceUnavailable();

        try {
            mImsService.turnOnIms(mPhoneId);
        } catch (RemoteException e) {
            throw new ImsException("turnOnIms() ", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
        }
    }
复制代码

mImsService 是IImsService 的实例对象,该对象在createImsService()中创建:

复制代码
       //绑定IMS Service
    private void createImsService(boolean checkService) {
        if (checkService) { //判断IMS Service 服务是否已经存在
            IBinder binder = ServiceManager.checkService(getImsServiceName(mPhoneId));

            if (binder == null) {
                /// M: add for debug @{
                if (DBG) log("ImsManager: createImsService binder is null");
                /// @}
                return;
            }
        }
        //获取指向Service的IBinder对象
        IBinder b = ServiceManager.getService(getImsServiceName(mPhoneId));

        if (b != null) {
            try {
                b.linkToDeath(mDeathRecipient, 0);
            } catch (RemoteException e) {
            }
        }

        mImsService = IImsService.Stub.asInterface(b);
        /// M: add for debug @{
        if (DBG) log("ImsManager: mImsService = " + mImsService);
        /// @}
        }
复制代码

getImsServiceName()获取IMS Service 名:

    private static String getImsServiceName(int phoneId) {
        // TODO: MSIM implementation needs to decide on service name as a function of phoneId
        return IMS_SERVICE;  //服务名即"ims"
    }

而getImsServiceName()方法在ImsManager类的构造方法中即被调用,所以mImsService对象开机即获取到。

 

方法turnOnIms,调用mImsService的turnOnIms()方法在IImsService.Stub继承类中实现:

vendor/mediatek/proprietary/packages/services/ims/src/com/mediatek/ims/ImsService.java

复制代码
    /**
     * Used for turning on IMS when its in OFF state.
     */
    @Override
    public void turnOnIms(int phoneId) {
        Rlog.d(LOG_TAG, "turnOnIms, mActivePhoneId = " + mActivePhoneId +
            " phoneId = " + phoneId);
        phoneId = getMainCapabilityPhoneId();
        Rlog.d(LOG_TAG, "turnOnIms, MainCapabilityPhoneId = " + phoneId);

        if (mActivePhoneId != phoneId) {
            mActivePhoneId = phoneId;
        }
    }
复制代码
复制代码
   /**
    * to get main capability phone id.
    *
    * @return The phone id with highest capability.
    */
   private int getMainCapabilityPhoneId() { //此接口可能获取主卡phoneID
             //获取服务"phoneEx"
       ITelephonyEx telephony = ITelephonyEx.Stub.asInterface(
               ServiceManager.getService(mContext.TELEPHONY_SERVICE_EX));

       if (telephony != null) {
           try {
               int mainPhoneId = telephony.getMainCapabilityPhoneId(); //调用getMainCapabilityPhoneId()方法
               Rlog.d(LOG_TAG, "getMainCapabilityPhoneId: mainPhoneId = " + mainPhoneId);
               return mainPhoneId;
           }
           ..........
       } 
   }
复制代码

有如下打印信息:

 

获取主PhoneID

PhoneInterfaceManagerEx extends ITelephonyEx.Stub;
packages/services/telephony/src/com/mediatek/phone/PhoneInterfaceManagerEx.java

复制代码
    /**
     * Get main capability phone id.
     * @return The phone id with highest capability.
     */
    public int getMainCapabilityPhoneId() {
        return RadioCapabilitySwitchUtil.getMainCapabilityPhoneId();
    }
复制代码

 

创建ImsConfig,在setAdvanced4GMode()接口中,获取ImsConfig对象:

            ImsConfig config = getConfigInterface();
            if (config != null) {
                config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
                        TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
            }

getConfigInterface()的实现:

复制代码
    public ImsConfig getConfigInterface() throws ImsException {
        checkAndThrowExceptionIfServiceUnavailable();
        // M: Remove cache of ImsConfig in AOSP, always get ImsConfig with mainCapability Id 
        mConfig = getConfigInterface(mPhoneId, mImsService, mContext);
        return mConfig;
    }

    public static ImsConfig getConfigInterface(int phoneId, IImsService service, Context context) throws ImsException {
        ImsConfig config = null;

        try {
            if (service == null) { //获取IMS服务
                IBinder b = ServiceManager.getService(getImsServiceName(phoneId));
                service = IImsService.Stub.asInterface(b); 
            }

            IImsConfig binder = service.getConfigInterface(phoneId); //调用ImsService的getConfigInterface()接口
            if (binder == null) {
                throw new ImsException("getConfigInterface()",
                            ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
            }

            config = new ImsConfig(binder, context); //初始化ImsConfig对象
        } catch (RemoteException e) {
            throw new ImsException("getConfigInterface()", e,
                ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
        }
        if (DBG) log("getConfigInterface(), config= " + config);
        return config;
复制代码

 

根据PhoneID创建IImsConfig

根据Log打印信息,获取Main Phone ID创建ImsConfig配置文件:

 

该接口ImsService.java中定义:
vendor/mediatek/proprietary/packages/services/ims/src/com/mediatek/ims/ImsService.java

复制代码
  //Config interface to get/set IMS service/capability parameters.
    public IImsConfig getConfigInterface(int phoneId) {
        // Always get main capability phone Id for ImsConfig
        phoneId = getMainCapabilityPhoneId();
        Rlog.w(LOG_TAG, "Get config interface on main capability phone " + phoneId);

        IImsConfig instance = null;
        Rlog.w(LOG_TAG, "getConfigInterface phone " + phoneId);
        synchronized (mImsConfigInstanceMap) {
            if (mImsConfigInstanceMap.containsKey(phoneId)) {
                instance = mImsConfigInstanceMap.get(phoneId);
            } else {
                instance = new ImsConfigImpl(mContext, mImsRILAdapter, phoneId);
                mImsConfigInstanceMap.put(phoneId, instance);
            }
        }
        return instance;
复制代码

IImsConfig是一个接口类,定义:
frameworks/base/telephony/java/com/android/ims/internal/IImsConfig.aidl
该类由ImsConfigImpl类继承,实现其接口函数;

 

初始化ImsConfig对象,ImsConfigImpl对象的初始化后,传给ImsConfig类的构造函数,创建ImsConfig:

frameworks/opt/net/ims/src/java/com/android/ims/ImsConfig.java

    public ImsConfig(IImsConfig iconfig, Context context) {
        if (DBG) Rlog.d(TAG, "ImsConfig creates");
        miConfig = iconfig; //IImsConfig对象由ImsConfigImpl初始化完成
        mContext = context;
    }

 

设置FeatureValue,在setAdvanced4GMode()接口中,设置FeatureValue,调用ImsConfig接口:

复制代码
            if (config != null) {
                config.setFeatureValue(ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE,
                        TelephonyManager.NETWORK_TYPE_LTE, turnOn ? 1 : 0, null);
            }

    /**
     * Sets the value for IMS feature item for specified network type.
     *
     * @param feature, as defined in FeatureConstants.
     * @param network, as defined in android.telephony.TelephonyManager#NETWORK_TYPE_XXX.
     * @param value, as defined in FeatureValueConstants.
     * @param listener, provided if caller needs to be notified for set result.
     * @return void
     *
     * @throws ImsException if calling the IMS service results in an error.
     */
    public void setFeatureValue(int feature, int network, int value,
            ImsConfigListener listener) throws ImsException {
        if (DBG) {
            Rlog.d(TAG, "setFeatureValue: feature = " + feature + ", network =" + network +
                    ", value =" + value + ", listener =" + listener);
        }
        try {
            miConfig.setFeatureValue(feature, network, value, listener);
        } catch (RemoteException e) {
            throw new ImsException("setFeatureValue()", e,
                    ImsReasonInfo.CODE_LOCAL_SERVICE_UNAVAILABLE);
        }
    }
复制代码

miConfig是IImsConfig接口类对象,其setFeatureValue()方法在ImsConfigImpl类中实现;

ImsConfigImpl类setFeatureValue()方法的实现:

复制代码
    public void setFeatureValue(int feature, int network, int value, ImsConfigListener listener) {
        try {
            try {
                if (DEBUG) Log.d(TAG, "setFeatureValue(" +
                      feature + ", " + network + ", " + value + ") on phone " + mPhoneId +
                      " from pid " + Binder.getCallingPid() + ", uid " + Binder.getCallingUid() +
                      ", listener " + listener);
                mStorage.setFeatureValue(feature, network, value); //ImsConfigStorage存储变量信息

                    case ImsConfig.FeatureConstants.FEATURE_TYPE_VOICE_OVER_LTE:
                        int oldVoLTEValue = SystemProperties.getInt(PROPERTY_VOLTE_ENALBE, 0);                        
                        int wfcEnable = SystemProperties.getInt(PROPERTY_WFC_ENALBE, 0);
                        if (value != oldVoLTEValue) {
                            if (value == ImsConfig.FeatureValueConstants.ON) {
                                SystemProperties.set(PROPERTY_VOLTE_ENALBE,"1");//根据参数设置变量                                 
                                //mRilAdapter.turnOnVolte(null);
                                if (wfcEnable == 0){
                                    //mRilAdapter.turnOnImsVoice(null);
                                }
                            } else {
                                SystemProperties.set(PROPERTY_VOLTE_ENALBE,"0");
                                //mRilAdapter.turnOffVolte(null);
                                if (wfcEnable == 0){
                                    //mRilAdapter.turnOffImsVoice(null);
                                }
                            }
                        }
                        break;
复制代码

 

<think>好的,我现在需要帮助用户了解关于config_device_volte_available这个Android配置项的用途和使用方法。根据用户提供的引用资料,我需要先整理这些信息,然后结合系统级指令来生成合适的回答。 首先,查看引用[1],其中提到config_device_volte_available属于device config key,用于指定设备是否支持运营商的VoLTE功能。而carrier_volte_available_bool是available config key,决定运营商是否启用VoLTE。这两个配置项需要同时为true,isVolteEnabledByPlatform()才会返回true。这说明了这两个配置的关系和各自的作用。 接下来,引用[3]指出VoLTE和ViLTE的默认开关状态,以及如何通过运营商配置调整VoWIFI的默认值。这里的信息可以帮助解释默认行为,但用户主要关注的是config_device_volte_available,所以可能需要强调设备层面的配置。 引用[5]提到VoWifi的配置可能需要通过补丁申请,但用户的问题是关于VoLTE的,所以这部分可能不直接相关,但可以作为补充说明设备配置可能需要特定流程。 用户的问题中还提到了具体的配置项写法:bool translatable="false" name="config_device_volte_available" true。需要确认这个配置项在代码中的位置和设置方式,可能是在设备的overlay配置文件中,例如在vendor目录下的XML文件里进行设置。 此外,要确保回答符合系统级指令的要求,比如使用正确的LaTeX格式,生成相关问题,结构清晰等。需要检查是否所有数学表达式都正确使用$...$,独立公式是否用$$...$$,并且语法正确。 然后,考虑用户可能的实际需求,比如如何启用或禁用该配置,或者调试相关问题。因此,回答中需要包括配置项的用途、与其他配置的关系、设置方法以及示例代码片段。 最后,生成相关问题时要围绕该配置项可能涉及的方面,比如与其他配置的关系、调试方法、默认值的影响等。 现在需要整合这些信息,确保回答结构清晰,引用正确,并生成相关问题。同时,要使用中文,并遵守所有格式要求。</think>### 关于 `config_device_volte_available` 的用途与使用方法 #### 1. **配置项定义与作用** - **用途**:`config_device_volte_available` 是 Android 设备层级的配置项(**Device Config Key**),用于声明设备硬件和平台是否支持运营商的 VoLTE(Voice over LTE)功能[^1]。 - **逻辑关系**:它与运营商层级的 `carrier_volte_available_bool`(Available Config Key)共同决定 VoLTE 是否可用。**只有当两者均为 `true` 时**,系统函数 `isVolteEnabledByPlatform()` 才会返回 `true`,表明设备与运营商均支持 VoLTE[^1]。 #### 2. **配置项语法与设置** - **典型代码片段**: ```xml <!-- 在设备 Overlay 配置文件中(如 vendor/xxx/configs/xxx.xml) --> <bool name="config_device_volte_available" translatable="false">true</bool> ``` - `translatable="false"` 表示该配置无需国际化翻译。 - 值设为 `true` 表示设备支持 VoLTE。 #### 3. **与其他配置的关联** - **运营商配置**:若 `config_device_volte_available` 为 `true`,但运营商配置 `carrier_volte_available_bool` 为 `false`,则 VoLTE 仍不可用[^1]。 - **默认行为**:VoLTE 开关默认开启(参考 `carrier_default_volte_enabled_bool`)[^3],但实际生效需设备与运营商配置同时满足条件。 #### 4. **应用场景示例** - **设备适配**:若某设备硬件不支持 VoLTE,需将 `config_device_volte_available` 设为 `false`。 - **调试与兼容性**:通过修改此配置,可测试 VoLTE 在不同设备与运营商组合下的行为。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值