呼叫转移流程分析(一)

Android5.0之后的版本,手机的CallSetting设置一般在package/apps/service/Telephony

下面为呼叫转移流程图,包括应用层与RILrequest

 1.CallFeartureSettingActivity.java为通话设置入口

//在谷歌的源码中没有这个类,可以直接看2、CallFeatureSetting

onResume方法中判断手机是单卡还是双卡

 

单卡直接通过CallFeatureSetting进入补充业务的设置界面,双卡先进入PhoneAccountSettingActivity的双卡选择界面,再通过PhoneAccountSettingFragmentNew选择某个sim卡,以intent进入CallFeatureSettingactivity

 

2.CallFeatureSetting设置补充业务

CallFeatureSetting中的onResume中调用init

       if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL)) {
            cdmaOptions.setIntent(mSubscriptionInfoHelper.getIntent(CdmaCallOptions.class));
            gsmOptions.setIntent(mSubscriptionInfoHelper.getIntent(GsmUmtsCallOptions.class));
        } else {
            prefSet.removePreference(cdmaOptions);
            prefSet.removePreference(gsmOptions);

            int phoneType = mPhone.getPhoneType();
            if (carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL)) {
                prefSet.removePreference(fdnButton);
            } else {
                if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
                    prefSet.removePreference(fdnButton);//固定拨号

                    if (!carrierConfig.getBoolean(
                            CarrierConfigManager.KEY_VOICE_PRIVACY_DISABLE_UI_BOOL)) {
                        addPreferencesFromResource(R.xml.cdma_call_privacy);
                    }
                } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {

                    if (carrierConfig.getBoolean(
                            CarrierConfigManager.KEY_ADDITIONAL_CALL_SETTING_BOOL)) {
                        addPreferencesFromResource(R.xml.gsm_umts_call_options);
                        GsmUmtsCallOptions.init(prefSet, mSubscriptionInfoHelper);
                    }
                } else {
                    throw new IllegalStateException("Unexpected phone type: " + phoneType);
                }
            }

GsmUmtsCallOption.init(PreferenceScreen,SubscriptionIfoHelper)为补充业务的preference建立对应的intent

63    public static void init(PreferenceScreen prefScreen, SubscriptionInfoHelper subInfoHelper) {
64        Preference callForwardingPref = prefScreen.findPreference(CALL_FORWARDING_KEY);
65        callForwardingPref.setIntent(subInfoHelper.getIntent(GsmUmtsCallForwardOptions.class));
66
67        Preference additionalGsmSettingsPref =
68                prefScreen.findPreference(ADDITIONAL_GSM_SETTINGS_KEY);
69        additionalGsmSettingsPref.setIntent(
70                subInfoHelper.getIntent(GsmUmtsAdditionalCallOptions.class));

不同的补充业务会转入不同的activity,呼叫转移业务对应的activityGsmUmtsCallForwardOption

 

3. GsmUmtsCallForwardOption呼叫转移的activity

onResume中进行界面初始化,调用init函数,

    @Override
    public void onResume() {
        super.onResume();

        if (mFirstResume) {
            if (mIcicle == null) {
                if (DBG) Log.d(LOG_TAG, "start to init ");
                mPreferences.get(mInitIndex).init(this, false, mPhone);
            } else {
                mInitIndex = mPreferences.size();

                for (CallForwardEditPreference pref : mPreferences) {
                    Bundle bundle = mIcicle.getParcelable(pref.getKey());
                    pref.setToggled(bundle.getBoolean(KEY_TOGGLE));
                    CallForwardInfo cf = new CallForwardInfo();
                    cf.number = bundle.getString(KEY_NUMBER);
                    cf.status = bundle.getInt(KEY_STATUS);
                    pref.handleCallForwardResult(cf);
                    pref.init(this, true, mPhone);
                }
            }
            mFirstResume = false;
            mIcicle = null;
        }
    }

在初次进入时会进行四种呼叫转移的初始化,因为四个呼叫转移都是CallForwardEditPreference类,所以具体每个Preference的点击动作应该看CallForwardEditPreference类;CallForwardEditPreference通过Myhandle的消息处理handleMessage,分别为handleGetCFResponse(设置新CF)handleSetCFResponse (读取CF状态)。

CallForwardEditPreference分为始终转接,占线时转接,无人接听时转接和无法接听时转接四种情况,也就是四个CallForwardEditPreference,其中init函数是获取当前呼叫转移设置的代码。

    void init(TimeConsumingPreferenceListener listener, boolean skipReading, Phone phone) {
        mPhone = phone;
        mTcpListener = listener;

        if (!skipReading) {
            mPhone.getCallForwardingOption(reason,
                    mHandler.obtainMessage(MyHandler.MESSAGE_GET_CF,
                            // unused in this case
                            CommandsInterface.CF_ACTION_DISABLE,
                            MyHandler.MESSAGE_GET_CF, null));
            if (mTcpListener != null) {
                mTcpListener.onStarted(this, true);
            }
        }
    }

4. GsmCdmaPhone

其中函数getCallForwardingOption这是个phone的接口方法,继承自接口PhoneInternalInterface

作为父类,真正的实现代码在GsmCdmaPhone.java

    @Override
    public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
        if (isPhoneTypeGsm()) {
            Phone imsPhone = mImsPhone;
//判断是否为imsPhone,是的话走ImsPhone(PS)流程,不是的话走CS流程
            if ((imsPhone != null)
                    && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
                    || imsPhone.isUtEnabled())) {
                imsPhone.getCallForwardingOption(commandInterfaceCFReason, onComplete);
                return;
            }

            if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
                if (DBG) logd("requesting call forwarding query.");
                Message resp;
                if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
                    resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete);
                } else {
                    resp = onComplete;
                }
                mCi.queryCallForwardStatus(commandInterfaceCFReason, 0, null, resp);
            }
        } else {
            loge("getCallForwardingOption: not possible in CDMA");
        }
    }

首先分析走CS流程,mCi为Phone类中的CommandsInterface接口,而CommandsInterface的接口方法都在RIL类中实现

 

5.RIL

调用函数RIL.queryCallForwardStatus(int cfReason, int serviceClass, String number, Message response)


    @Override
    public void queryCallForwardStatus(int cfReason, int serviceClass,
                           String number, Message result) {
        IRadio radioProxy = getRadioProxy(result);
//将消息result包装为IRadio发送request到modem
        if (radioProxy != null) {
            RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, result,
                    mRILDefaultWorkSource);

            if (RILJ_LOGD) {
                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                        + " cfreason = " + cfReason + " serviceClass = " + serviceClass);
            }

            android.hardware.radio.V1_0.CallForwardInfo cfInfo =
                    new android.hardware.radio.V1_0.CallForwardInfo();
            cfInfo.reason = cfReason;
            cfInfo.serviceClass = serviceClass;
            cfInfo.toa = PhoneNumberUtils.toaFromString(number);
            cfInfo.number = convertNullToEmptyString(number);
            cfInfo.timeSeconds = 0;

            try {
                radioProxy.getCallForwardStatus(rr.mSerial, cfInfo);
            } catch (RemoteException | RuntimeException e) {
                handleRadioProxyExceptionForRR(rr, "queryCallForwardStatus", e);
            }
        }
    }

 

IRadioc++程序,这是发送Requst的过程,下面就超出了本组的学习内容

 

 

 

 

 

 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值