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.
     *
     * 

If this object has been created with {@link #createForSubscriptionId}, applies to the * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} * *

Requires Permission: * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling * app has carrier privileges (see {@link #hasCarrierPrivileges}). *

* 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(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 reasonWithNetworkTypes =
                            (Pair) 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 RadioImpl_1_6::setAllowedNetworkTypesBitmap(
        uint32_t serial, hidl_bitfield 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 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.jianshu.com/p/a661982ecfee

你可能感兴趣的:(Android S Preferred network type设置流程)