Android 8.1 (O)信号强度介绍和定制

一、在Android中对移动数据操作的几个类和接口如下:

1 TelephonyManager 类 主要提供了一系列用于访问与手机通讯相关的状态和信息的get方法。其中包括手机SIM的状态和信息、电信网络的状态及手机用户的信息,在应用程序中可以使用这些get方法获取相关数据

  TelephonyManager类的对象可以通过Context.getSystemService(Context.TELEPHONY_SERVICE)方法来获得,需要注意的是有些通讯信息的获取对应用程序的权限有一定的限制,在开发的时候需要为其添加相应的权限。

2 PhoneStateListener类方法: (移动数据强度和类型 在打电话、SIM卡插拔、连接状态等状态改变而受影响,因此需要在状态下分别检测数据强度和类型 监听回调)

1.onDataActivity(intdirection) :activity 数据状态改变时监听回调

2.onServiceStateChanged(ServiceState serviceState) {//设备服务状态改变监听回调

3.onSignalStrengthsChanged(SignalStrength signalStrength) {//信号强度改变监听回调

4.onDataConnectionStateChanged(intstate) {//数据连接状态

5.onCallStateChanged(intstate, String incomingNumber) {//电话状态改变

当信号强度发生变化时,打印log如下

                  

二、SystemUI对于信号强度的客制化

MobileSignalController 对于信号强度的监听:

 class MobilePhoneStateListener extends PhoneStateListener {
        public MobilePhoneStateListener(int subId, Looper looper) {
            super(subId, looper);
        }

        @Override
        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
            if (DEBUG) {
                Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength +
                        ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel())));
            }
            mSignalStrength = signalStrength;
            updateTelephony();
        }
.....................................
}
    /**
     * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
     * mDataState, and mSimState.  It should be called any time one of these is updated.
     * This will call listeners if necessary.
     */
    private final void updateTelephony() {
        if (DEBUG && FeatureOptions.LOG_ENABLE) {
            Log.d(mTag, "updateTelephonySignalStrength: hasService=" + hasService()
                    + " ss=" + mSignalStrength);
        }
        mCurrentState.connected = hasService() && mSignalStrength != null;
        handleIWLANNetwork();
        if (mCurrentState.connected) { //如果有SIM卡信号
                    获取信号强度
            if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
                mCurrentState.level = mSignalStrength.getCdmaLevel();
            } else {
                mCurrentState.level = mSignalStrength.getLevel();
            }
            /// M: Customize the signal strength level. @ {
            mCurrentState.level = mStatusBarExt.getCustomizeSignalStrengthLevel(
                    mCurrentState.level, mSignalStrength, mServiceState);
            /// @ }
        }
        if (mNetworkToIconLookup.indexOfKey(mDataNetType) >= 0) {
            mCurrentState.iconGroup = mNetworkToIconLookup.get(mDataNetType);
        } else {
            mCurrentState.iconGroup = mDefaultIcons;
        }
        /// M: Add for data network type.
        mCurrentState.dataNetType = mDataNetType;
        mCurrentState.dataConnected = mCurrentState.connected
                && mDataState == TelephonyManager.DATA_CONNECTED;
        /// M: Add for op network tower type.
        mCurrentState.customizedState = mStatusBarExt.getCustomizeCsState(mServiceState,
                mCurrentState.customizedState);
        /// M: Add for op signal strength tower icon.
        mCurrentState.customizedSignalStrengthIcon = mStatusBarExt.getCustomizeSignalStrengthIcon(
                mSubscriptionInfo.getSubscriptionId(),
                mCurrentState.customizedSignalStrengthIcon,
                mSignalStrength,
                mDataNetType,
                mServiceState);

        mCurrentState.roaming = isRoaming();
        if (isCarrierNetworkChangeActive()) {
            mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
        } else if (isDataDisabled()) {
            mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
        }
        if (isEmergencyOnly() != mCurrentState.isEmergency) {
            mCurrentState.isEmergency = isEmergencyOnly();
            mNetworkController.recalculateEmergency();
        }
        // Fill in the network name if we think we have it.
        if (mCurrentState.networkName == mNetworkNameDefault && mServiceState != null
                && !TextUtils.isEmpty(mServiceState.getOperatorAlphaShort())) {
            mCurrentState.networkName = mServiceState.getOperatorAlphaShort();
        }
        /// M: For network type big icon.
        mCurrentState.networkIcon =
            NetworkTypeUtils.getNetworkTypeIcon(mServiceState, mConfig, hasService());
        /// M: For volte type icon.
        mCurrentState.volteIcon = getVolteIcon();

        notifyListenersIfNecessary(); //状态栏或下拉状态栏信号格显示
    }

针对于信号强度,经过一系列的调用到

vendor/mediatek/proprietary/frameworks/opt/telephony-base/java/mediatek/telephony/MtkSignalStrength.java

 @Override
    public int getLevel() {
        return super.getLevel();
    }

frameworks/base/telephony/java/android/telephony/SignalStrength.java

    public int getLevel() {
        int level = 0;
        if (isGsm) { //移动或联通卡
            level = getLteLevel(); //首先获取4G信号格
            if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { //未获取到
                level = getTdScdmaLevel(); //获取移动或联通的3G信号格
                if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {//仍然未获取
                    level = getGsmLevel(); //获取移动或联通的2G信号格
                }
            }
        } else {//电信
            int cdmaLevel = getCdmaLevel(); //获取电信2G信号格
            int evdoLevel = getEvdoLevel(); //获取电信3G信号格
            if (evdoLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
                /* We don't know evdo, use cdma */
                level = cdmaLevel;
            } else if (cdmaLevel == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
                /* We don't know cdma, use evdo */
                level = evdoLevel;
            } else {
                /* We know both, use the lowest level */
                level = cdmaLevel < evdoLevel ? cdmaLevel : evdoLevel;
            }
        }
        if (DBG) log("getLevel=" + level);
        return level;
    }

在此介绍下手机是几模的配置:GSM是移动和联通公用的band;LTE从编码方式上分为TDD和FDD,从频段上分有各种不同的band

移动:GSM、TDSCDMA、LTE(TDD)

联通:GSM、WCDMA、LTE(FDD)

电信:CDMA、EVDO、LTE(FDD)

因此如果手机支持GSM、WCDMA、TDSCDMA、TDD-LTE、FDD-LTE 这是五模;加上 CDMA、EVDO 就是七模

对于移动和联通,是先获取4G信号;在MtkSignalStrength中:

    /**
     * Get LTE as level 0..4
     *
     * @hide
     */
    @Override
    public int getLteLevel() {
        int rsrpIconLevel = -1;
        ISignalStrengthExt ssExt = getOpInstance(); //获取ISignalStrengthExt实例
        if (ssExt != null) {
            rsrpIconLevel = ssExt.mapLteSignalLevel(mLteRsrp, mLteRssnr, mLteSignalStrength);
            return rsrpIconLevel;
        } else {
            log("[getLteLevel] null op customization instance");
        }

        return super.getLteLevel(); //如果上述获取不到信号格。则调用父类SignalStrength的getLteLevel方法
    }

 vendor/mediatek/proprietary/frameworks/opt/telephony-base/java/mediatek/telephony/SignalStrengthExt.java

    public int mapLteSignalLevel(int mLteRsrp, int mLteRssnr, int mLteSignalStrength) {
        /*
         * TS 36.214 Physical Layer Section 5.1.3 TS 36.331 RRC RSSI = received
         * signal + noise RSRP = reference signal dBm RSRQ = quality of signal
         * dB= Number of Resource blocksxRSRP/RSSI SNR = gain=signal/noise ratio
         * = -10log P1/P2 dB
         */
        int rssiIconLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        int rsrpIconLevel = -1;
        int snrIconLevel = -1;

        if (mLteRsrp > -44) {
            rsrpIconLevel = -1;
        } else if (mLteRsrp >= -85) {
            rsrpIconLevel = SignalStrength.SIGNAL_STRENGTH_GREAT; //4格
        } else if (mLteRsrp >= -95) {
            rsrpIconLevel = SignalStrength.SIGNAL_STRENGTH_GOOD; //3格
        } else if (mLteRsrp >= -105) {
            rsrpIconLevel = SignalStrength.SIGNAL_STRENGTH_MODERATE; //2格
        } else if (mLteRsrp >= -115) {
            rsrpIconLevel = SignalStrength.SIGNAL_STRENGTH_POOR;  //1格
        } else if (mLteRsrp >= -140) { //0格
            rsrpIconLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        }

        /*
         * Values are -200 dB to +300 (SNR*10dB) RS_SNR >= 13.0 dB =>4 bars 4.5
         * dB <= RS_SNR < 13.0 dB => 3 bars 1.0 dB <= RS_SNR < 4.5 dB => 2 bars
         * -3.0 dB <= RS_SNR < 1.0 dB 1 bar RS_SNR < -3.0 dB/No Service Antenna
         * Icon Only
         */
        if (mLteRssnr > 300) {
            snrIconLevel = -1;
        } else if (mLteRssnr >= 130) {
            snrIconLevel = SignalStrength.SIGNAL_STRENGTH_GREAT;
        } else if (mLteRssnr >= 45) {
            snrIconLevel = SignalStrength.SIGNAL_STRENGTH_GOOD;
        } else if (mLteRssnr >= 10) {
            snrIconLevel = SignalStrength.SIGNAL_STRENGTH_MODERATE;
        } else if (mLteRssnr >= -30) {
            snrIconLevel = SignalStrength.SIGNAL_STRENGTH_POOR;
        } else if (mLteRssnr >= -200) {
            snrIconLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        }
        Rlog.i(TAG, "getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);

        /* Choose a measurement type to use for notification */
        if (snrIconLevel != -1 && rsrpIconLevel != -1) {
            /*
             * The number of bars displayed shall be the smaller of the bars
             * associated with LTE RSRP and the bars associated with the LTE
             * RS_SNR
             */
            return (rsrpIconLevel < snrIconLevel ? rsrpIconLevel : snrIconLevel);
        }

        if (snrIconLevel != -1) {
            return snrIconLevel;
        }

        if (rsrpIconLevel != -1) {
            return rsrpIconLevel;
        }

        /* Valid values are (0-63, 99) as defined in TS 36.331 */
        if (mLteSignalStrength > 63) {
            rssiIconLevel = SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
        } else if (mLteSignalStrength >= 12) {
            rssiIconLevel = SignalStrength.SIGNAL_STRENGTH_GREAT;
        } else if (mLteSignalStrength >= 8) {
            rssiIconLevel = SignalStrength.SIGNAL_STRENGTH_GOOD;
        } else if (mLteSignalStrength >= 5) {
            rssiIconLevel = SignalStrength.SIGNAL_STRENGTH_MODERATE;
        } else if (mLteSignalStrength >= 0) {
            rssiIconLevel = SignalStrength.SIGNAL_STRENGTH_POOR;
        }
        Rlog.i(TAG, "getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
                + rssiIconLevel);
        return rssiIconLevel;
    }

 因此如果想修改强度对应的信号格显示,请修改上述对应强度值;对于上述变量的介绍请参考博客关于LTE RSRP、RSSI、SINR、RSRQ定义

三、状态栏或下拉状态栏信号格显示

MobileSignalController

  public void notifyListenersIfNecessary() {
        if (isDirty()) {
            saveLastState();
            notifyListeners();
        }
    }
    public final void notifyListeners() {
        notifyListeners(mCallbackHandler);
    }

因此调用到SignalClusterView

 @Override
    public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
             int networkType, int volteIcon, int qsType, boolean activityIn, boolean activityOut,
             String typeContentDescription, String description, boolean isWide, int subId,
              boolean roaming) {
        PhoneState state = getState(subId);
        if (state == null) {
            return;
        }
        state.mMobileVisible = statusIcon.visible && !mBlockMobile;
        state.mMobileStrengthId = statusIcon.icon;
        state.mMobileTypeId = statusType;
        state.mMobileDescription = statusIcon.contentDescription;
        state.mMobileTypeDescription = typeContentDescription;
        state.mIsMobileTypeIconWide = statusType != 0 && isWide;
        /// M: for big network icon and volte icon.
        state.mNetworkIcon = networkType;
        state.mVolteIcon = volteIcon;
        state.mRoaming = roaming;
        state.mActivityIn = activityIn && mActivityEnabled;
        state.mActivityOut = activityOut && mActivityEnabled;

        /// M: Add for plugin features. @ {
        state.mDataActivityIn = activityIn;
        state.mDataActivityOut = activityOut;
        /// @ }

        apply();
    }
        public boolean apply(boolean isSecondaryIcon) { //信号格显示到状态栏
            if (mMobileVisible && !mIsAirplaneMode) {
                if (mLastMobileStrengthId != mMobileStrengthId) {
                    mMobile.getDrawable().setLevel(mMobileStrengthId);
                    mMobileDark.getDrawable().setLevel(mMobileStrengthId);
                    mLastMobileStrengthId = mMobileStrengthId;
                }

                if (mLastMobileTypeId != mMobileTypeId) {
                    if (!mPhoneStateExt.disableHostFunction()) {
                        mMobileType.setImageResource(mMobileTypeId);
                    }
                    mLastMobileTypeId = mMobileTypeId;
                }

                mMobileGroup.setContentDescription(mMobileTypeDescription
                        + " " + mMobileDescription);
                mMobileGroup.setVisibility(View.VISIBLE);
                showViewInWfcCase();
            } else {
                if (mIsAirplaneMode && (mIsWfcEnable && mVolteIcon != 0)) {
                    /// M:Bug fix for show vowifi icon in flight mode
                    mMobileGroup.setVisibility(View.VISIBLE);
                    hideViewInWfcCase();
                } else {
                    if (DEBUG) {
                        Log.d(TAG, "setVisibility as GONE, this = " + this
                                + ", mMobileVisible = " + mMobileVisible
                                + ", mIsAirplaneMode = " + mIsAirplaneMode
                                + ", mIsWfcEnable = " + mIsWfcEnable
                                + ", mVolteIcon = " + mVolteIcon);
                    }
                    mMobileGroup.setVisibility(View.GONE);
                }
            }
 ..............................................

            return mMobileVisible;
        }

四、信号格的获取

MobileSignalController

    @Override
    public int getCurrentIconId() {
        if (mCurrentState.iconGroup == TelephonyIcons.CARRIER_NETWORK_CHANGE) {
            return SignalDrawable.getCarrierChangeState(getNumLevels());
        } else if (mCurrentState.connected) {
            int level = mCurrentState.level; //信号强度等级,即信号格
            if (mConfig.inflateSignalStrengths) { //系统默认false,不走该分支
                level++;
            }
            return SignalDrawable.getState(level, getNumLevels(),
                    mCurrentState.inetCondition == 0);
        } else if (mCurrentState.enabled) {
            return SignalDrawable.getEmptyState(getNumLevels());
        } else {
            return 0;
        }
    }
对于mCurrentState.level 信号格的等级获取是在函数updateTelephony方法中有
        if (mCurrentState.connected) {
            if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
                mCurrentState.level = mSignalStrength.getCdmaLevel();
            } else {
                mCurrentState.level = mSignalStrength.getLevel();
            }
            /// M: Customize the signal strength level. @ {
            mCurrentState.level = mStatusBarExt.getCustomizeSignalStrengthLevel(
                    mCurrentState.level, mSignalStrength, mServiceState);
            /// @ }
        }

 因此,从该处就明白了,信号等级的强度和显示刷新就会回到Android 8.1 (O)信号强度介绍和定制一开始讨论的地方。

参考链接:SystemUI 之状态上的手机信号显示

对于dB和dBm的介绍:

1 dB:一个表征相对值的值,纯粹的比值,只表示两个量的相对大小关系,无单位;当考虑甲的功率相比于乙的功率大或小多少个dB时,按照下面的计算公式:10log(甲的功率/乙的功率),如果采用两者的电压比计算,要用20log(甲的电压/乙的电压)

例 甲的功率比乙的功率大一倍,那么10lg(甲的功率/乙的功率)=10lg2 = 3dB.也就是说,甲的功率比乙的功率大3 dB。

2 dBm 是一个表示功率绝对值的值(也可以认为是以1mW功率为基准的一个比值),计算公式为:10log(功率值/1mw)。

[例]如果功率P为1mw,折算为dBm后为0dBm。

[例]对于40W的功率,按dBm单位进行折算后的值应为:

10log(40W/1mw)=10log(40000)=10log4+10log10000=46dBm。

总之,dB是两个量之间的比值,表示两个量间的相对大小,而dBm则是表示功率绝对大小的值。在dB,dBm计算中,要注意基本概念,

用一个dBm减另外一个dBm时,得到的结果是dB,如:30dBm - 0dBm = 30dB。

在安卓手机设置里,我们可以看到关于信号强度的状态信息,里面可以看到关于信号强度的一项,单位为dBm和asu。其中dBm(1毫瓦的分贝数)是衡量手机信号强度的通用指标,asu(alone signal unit 独立信号单元)是Google给Android手机定义的特有信号单位, 它们之间的关系是:dBm =-113+2*asu

猜你喜欢

转载自blog.csdn.net/CodingNotes/article/details/82530847