美文网首页
Android S Preferred network type

Android S Preferred network type

作者: 无痕1024 | 来源:发表于2022-03-26 10:36 被阅读0次

    该文档来自根据源码的推论,并没有实际的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 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://www.jianshu.com/p/a661982ecfee

    相关文章

      网友评论

          本文标题:Android S Preferred network type

          本文链接:https://www.haomeiwen.com/subject/innjjrtx.html