Android S Preferred network type设置流程

该文档来自根据源码的推论,并没有实际的Log佐证。

1 入口

用户可选择的界面最终会使用如下配置开关:
/packages/apps/Settings/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java

    @Override
    public boolean onPreferenceChange(Preference preference, Object object) {
        final int newPreferredNetworkMode = Integer.parseInt((String) object);
        final ListPreference listPreference = (ListPreference) preference;

        if (mTelephonyManager.setPreferredNetworkTypeBitmask(
                MobileNetworkUtils.getRafFromNetworkType(newPreferredNetworkMode))) {
            mBuilder.setPreferenceValueAndSummary(newPreferredNetworkMode);
            listPreference.setValue(Integer.toString(mBuilder.getSelectedEntryValue()));
            listPreference.setSummary(mBuilder.getSummary());
            return true;
        }
        return false;
    }

2 Framework流程

/frameworks/base/telephony/java/android/telephony/TelephonyManager.java

    /**
     * Set the preferred network type bitmask but if {@link #setAllowedNetworkTypes} has been set,
     * only the allowed network type will set to the modem.
     *
     * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
     * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
     *
     * <p>Requires Permission:
     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
     * <p>
     * If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
     * ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
     * setAllowedNetworkTypesBitmap is used on the radio interface.  Otherwise,
     * setPreferredNetworkTypesBitmap is used instead.
     *
     * @param networkTypeBitmask The bitmask of preferred network types.
     * @return true on success; false on any failure.
     * @hide
     * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead.
     */
    @Deprecated
    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
    @SystemApi
    public boolean setPreferredNetworkTypeBitmask(@NetworkTypeBitMask long networkTypeBitmask) {
        try {
            ITelephony telephony = getITelephony();
            if (telephony != null) {
                return telephony.setAllowedNetworkTypesForReason(getSubId(),
                        TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, networkTypeBitmask);
            }
        } catch (RemoteException ex) {
            Rlog.e(TAG, "setPreferredNetworkTypeBitmask RemoteException", ex);
        }
        return false;
    }

/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java

    /**
     * Set the allowed network types of the device and
     * provide the reason triggering the allowed network change.
     *
     * @param subId the id of the subscription.
     * @param reason the reason the allowed network type change is taking place
     * @param allowedNetworkTypes the allowed network types.
     * @return true on success; false on any failure.
     */
    @Override
    public boolean setAllowedNetworkTypesForReason(int subId,
            @TelephonyManager.AllowedNetworkTypesReason int reason,
            @TelephonyManager.NetworkTypeBitMask long allowedNetworkTypes) {
        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
                mApp, subId, "setAllowedNetworkTypesForReason");
        if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
            loge("setAllowedNetworkTypesForReason: Invalid allowed network type reason: " + reason);
            return false;
        }
        if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
            loge("setAllowedNetworkTypesForReason: Invalid subscriptionId:" + subId);
            return false;
        }

        log("setAllowedNetworkTypesForReason: " + reason + " value: "
                + TelephonyManager.convertNetworkTypeBitmaskToString(allowedNetworkTypes));


        if (allowedNetworkTypes == getPhoneFromSubId(subId).getAllowedNetworkTypes(reason)) {
            log("setAllowedNetworkTypesForReason: " + reason + "does not change value");
            return true;
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            Boolean success = (Boolean) sendRequest(
                    CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON,
                    new Pair<Integer, Long>(reason, allowedNetworkTypes), subId);

            if (DBG) log("setAllowedNetworkTypesForReason: " + (success ? "ok" : "fail"));
            return success;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }
                case CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON:
                    request = (MainThreadRequest) msg.obj;
                    onCompleted = obtainMessage(EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE,
                            request);
                    Pair<Integer, Long> reasonWithNetworkTypes =
                            (Pair<Integer, Long>) request.argument;
                    getPhoneFromRequest(request).setAllowedNetworkTypes(
                            reasonWithNetworkTypes.first,
                            reasonWithNetworkTypes.second,
                            onCompleted);
                    break;

/frameworks/opt/telephony/src/java/com/android/internal/telephony/Phone.java

    /**
     * Requests to set the allowed network types for a specific reason
     *
     * @param reason reason to configure allowed network type
     * @param networkTypes one of the network types
     */
    public void setAllowedNetworkTypes(@TelephonyManager.AllowedNetworkTypesReason int reason,
            @TelephonyManager.NetworkTypeBitMask long networkTypes, Message response) {
        int subId = getSubId();
        if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
            loge("setAllowedNetworkTypes: Invalid allowed network type reason: " + reason);
            AsyncResult.forMessage(response, null,
                    new CommandException(CommandException.Error.INVALID_ARGUMENTS));
            response.sendToTarget();
            return;
        }
        if (!SubscriptionManager.isUsableSubscriptionId(subId)
                || !mIsAllowedNetworkTypesLoadedFromDb) {
            loge("setAllowedNetworkTypes: no sim or network type is not loaded. SubscriptionId: "
                    + subId + ", isNetworkTypeLoaded" + mIsAllowedNetworkTypesLoadedFromDb);
            AsyncResult.forMessage(response, null,
                    new CommandException(CommandException.Error.MISSING_RESOURCE));
            response.sendToTarget();
            return;
        }
        String mapAsString = "";
        synchronized (mAllowedNetworkTypesForReasons) {
            mAllowedNetworkTypesForReasons.put(reason, networkTypes);
            mapAsString = mAllowedNetworkTypesForReasons.keySet().stream()
                    .map(key -> convertAllowedNetworkTypeMapIndexToDbName(key) + "="
                            + mAllowedNetworkTypesForReasons.get(key))
                    .collect(Collectors.joining(","));
        }
        SubscriptionManager.setSubscriptionProperty(subId,
                SubscriptionManager.ALLOWED_NETWORK_TYPES,
                mapAsString);
        logd("setAllowedNetworkTypes: SubId" + subId + ",setAllowedNetworkTypes " + mapAsString);

        updateAllowedNetworkTypes(response);
        notifyAllowedNetworkTypesChanged(reason);
    }

Phone.java的如下方法不仅会在配置的时候调用,在其他情况也会被调用:

    protected void updateAllowedNetworkTypes(Message response) {
        int modemRaf = getRadioAccessFamily();
        if (modemRaf == RadioAccessFamily.RAF_UNKNOWN) {
            Rlog.d(LOG_TAG, "setPreferredNetworkType: Abort, unknown RAF: "
                    + modemRaf);
            if (response != null) {
                CommandException ex;
                ex = new CommandException(CommandException.Error.GENERIC_FAILURE);
                AsyncResult.forMessage(response, null, ex);
                response.sendToTarget();
            }
            return;
        }

        int filteredRaf = (int) (modemRaf & getEffectiveAllowedNetworkTypes());

        logd("setAllowedNetworkTypes: modemRafBitMask = " + modemRaf
                + " ,modemRaf = " + TelephonyManager.convertNetworkTypeBitmaskToString(modemRaf)
                + " ,filteredRafBitMask = " + filteredRaf
                + " ,filteredRaf = " + TelephonyManager.convertNetworkTypeBitmaskToString(
                filteredRaf));
        mCi.setAllowedNetworkTypesBitmap(filteredRaf, response);
        mPreferredNetworkTypeRegistrants.notifyRegistrants();
    }

最终会调用:
/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java

    @Override
    public void setAllowedNetworkTypesBitmap(
            @TelephonyManager.NetworkTypeBitMask int networkTypeBitmask, Message result) {
        IRadio radioProxy = getRadioProxy(result);
        if (radioProxy != null) {
            if (mRadioVersion.less(RADIO_HAL_VERSION_1_6)) {
                // For older HAL, redirects the call to setPreferredNetworkType.
                setPreferredNetworkType(
                        RadioAccessFamily.getNetworkTypeFromRaf(networkTypeBitmask), result);
                return;
            }

            android.hardware.radio.V1_6.IRadio radioProxy16 =
                    (android.hardware.radio.V1_6.IRadio) radioProxy;
            RILRequest rr = obtainRequest(RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP, result,
                    mRILDefaultWorkSource);

            if (RILJ_LOGD) {
                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
            }
            mAllowedNetworkTypesBitmask = networkTypeBitmask;
            try {
                radioProxy16.setAllowedNetworkTypesBitmap(rr.mSerial,
                        convertToHalRadioAccessFamily(mAllowedNetworkTypesBitmask));
            } catch (RemoteException | RuntimeException e) {
                handleRadioProxyExceptionForRR(rr, "setAllowedNetworkTypeBitmask", e);
            }
        }
    }

3 RILD流程

3.1 源码

这里假设RILC最终会调用:
/device/google/cuttlefish/guest/hals/ril/reference-libril/ril_service.cpp

Return<void> RadioImpl_1_6::setAllowedNetworkTypesBitmap(
        uint32_t serial, hidl_bitfield<RadioAccessFamily> networkTypeBitmap) {
#if VDBG
    RLOGD("setAllowedNetworkTypesBitmap: serial %d", serial);
#endif
    dispatchInts(serial, mSlotId, RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP, 1, networkTypeBitmap);
    return Void();
}

等Modem有返回时,使用如下方法返回给Framework:
/frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioResponse.java

    private void responseVoid_1_6(android.hardware.radio.V1_6.RadioResponseInfo responseInfo) {
        RILRequest rr = mRil.processResponse_1_6(responseInfo);

        if (rr != null) {
            Object ret = null;
            if (responseInfo.error == RadioError.NONE) {
                sendMessageResponse(rr.mResult, ret);
            }
            mRil.processResponseDone_1_6(rr, responseInfo, ret);
        }
    }

    @Override
    public void setAllowedNetworkTypesBitmapResponse(
            android.hardware.radio.V1_6.RadioResponseInfo info) {
        responseVoid_1_6(info);
    }

3.2 流程图

setAllowedNetworkTypesBitmap.png

4 参考文档

Android源码
http://aospxref.com/android-12.0.0_r3/
http://aosp.opersys.com/xref/android-12.0.0_r2/

版权声明:本文为 无痕1024 原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接://www.greatytc.com/p/a661982ecfee

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,185评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,652评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,524评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,339评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,387评论 6 391
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,287评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,130评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,985评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,420评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,617评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,779评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,477评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,088评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,716评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,857评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,876评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,700评论 2 354