最近一直在调试Android的4G专网模块;一个困扰了我很久的问题昨天也解决了;就是4G信号强度是怎么报上来的?怎么在右上角通知栏显示的?现在也清楚了;
其实只修改reference-ril.c中的一个函数就解决问题了,只是牵扯到很多理解性的东西;
static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)函数是上报信号强度的,是上层每隔一段时间主动请求下发的函数;注意这个函数中Android4.0(没有validateInput()对信号强度的验证)和Android4.4.3是通过RIL_SignalStrength_v6结构体上报的;framework解析信号强度4G优先解析的是RSRP;ril.h中有注释:RSRP的范围是 * Range: 44 to 140 dBm;注意44信号强度最大;140信号强度最小;几乎所有的专网模块都上报数据不是44~140范围;有的是0~31;有的是0~99;要做相应的转化;不然信号质量格格显示不准;
typedef struct {
int signalStrength; /* Valid values are (0-31, 99) as defined in TS 27.007 8.5 */
int rsrp; /* The current Reference Signal Receive Power in dBm multipled by -1.
* Range: 44 to 140 dBm
* INT_MAX: 0x7FFFFFFF denotes invalid value.
* Reference: 3GPP TS 36.133 9.1.4 */
int rsrq; /* The current Reference Signal Receive Quality in dB multiplied by -1.
* Range: 20 to 3 dB.
* INT_MAX: 0x7FFFFFFF denotes invalid value.
* Reference: 3GPP TS 36.133 9.1.7 */
int rssnr; /* The current reference signal signal-to-noise ratio in 0.1 dB units.
* Range: -200 to +300 (-200 = -20.0 dB, +300 = 30dB).
* INT_MAX : 0x7FFFFFFF denotes invalid value.
* Reference: 3GPP TS 36.101 8.1.1 */
int cqi; /* The current Channel Quality Indicator.
* Range: 0 to 15.
* INT_MAX : 0x7FFFFFFF denotes invalid value.
* Reference: 3GPP TS 36.101 9.2, 9.3, A.4 */
} RIL_LTE_SignalStrength;
static int SignalStrengthTransform(int Signal)
{
if(Signal == 99){
return 140;
}
return (Signal*3 - 140)*(-1); //为了RSRP(44~140)的范围这里要根据AT+CSQ上报的值做相应的转换;不然信号显示不准确;
}
static void requestSignalStrength(void *data, size_t datalen, RIL_Token t)
{
ATResponse *p_response = NULL;
int err;
char *line;
int count =0;
int numofElements;
int *response;
int out;
RIL_SignalStrength_v6 response_v6;
int modem_type;
modem_type = runtime_3g_port_type();
char signal_level[32];
if ((HUAWEI_MODEM == modem_type) ||
(AMAZON_MODEM == modem_type)){
ALOGE("------------------%s@%d---------------------",__func__,__LINE__);
/* Huawei EM770W response is in RIL_GW_SignalStrength form */
//numofElements=sizeof(RIL_GW_SignalStrength)/sizeof(int);
numofElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
}else{
ALOGE("------------------%s@%d---------------------",__func__,__LINE__);
numofElements=sizeof(RIL_SignalStrength_v6)/sizeof(int);
}
response = (int *)calloc(numofElements, sizeof(int));
if (!response) goto error;
//int response[numofElements];
if(sUnsolictedCREG_failed) {
LOGW("Retry the AT+CREG event report setting");
/* Network registration events */
err = at_send_command("AT+CREG=2", &p_response);
/* some handsets -- in tethered mode -- don't support CREG=2 */
if (err < 0 || p_response->success == 0) {
at_response_free(p_response);
err = at_send_command("AT+CREG=1", &p_response);
}
if (err < 0 || p_response->success == 0) {
LOGE("Warning!No network registration events reported");
sUnsolictedCREG_failed = 1;
}
else {
sUnsolictedCREG_failed = 0;
}
at_response_free(p_response);
}
if(sUnsolictedCGREG_failed) {
LOGW("Retry the AT+CGREG event report setting");
/* GPRS registration events */
err = at_send_command("AT+CGREG=1", &p_response);
if (err < 0 || p_response->success == 0) {
LOGE("Warning!No GPRS registration events reported");
sUnsolictedCGREG_failed = 1;
}
else {
sUnsolictedCGREG_failed = 0;
}
at_response_free(p_response);
}
err = at_send_command_singleline("AT+CSQ", "+CSQ:", &p_response);
if (err < 0 || p_response->success == 0) {
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
goto error;
}
memset(&response_v6, 0, sizeof(RIL_SignalStrength_v6));
line = p_response->p_intermediates->line;
err = at_tok_start(&line);
if (err < 0) goto error;
#if 0
for (count =0; count < numofElements; count ++) {
err = at_tok_nextint(&line, &(response[count]));
if (err < 0) goto error;
}
#else
err = at_tok_nextint(&line, &out);
response_v6.LTE_SignalStrength.rsrp = SignalStrengthTransform(out);
if (err < 0) goto error;
err = at_tok_nextint(&line, &(response_v6.GW_SignalStrength.bitErrorRate));
if (err < 0) goto error;
#if 1
response_v6.GW_SignalStrength.signalStrength = 99;
response_v6.GW_SignalStrength.bitErrorRate = -1;
response_v6.CDMA_SignalStrength.dbm = -1;
response_v6.CDMA_SignalStrength.ecio = -1;
response_v6.EVDO_SignalStrength.dbm = -1;
response_v6.EVDO_SignalStrength.ecio = -1;
response_v6.EVDO_SignalStrength.signalNoiseRatio = -1;
response_v6.LTE_SignalStrength.signalStrength = 99;
response_v6.LTE_SignalStrength.rsrq = 0x7FFFFFFF;
response_v6.LTE_SignalStrength.rssnr = 0x7FFFFFFF;
response_v6.LTE_SignalStrength.cqi = 0x7FFFFFFF;
#endif
#endif
ALOGE("------------------%s@%d---------------------out=%d,signalStrengt=%d,rsrp=%d,bitErrorRate=%d",__func__,__LINE__,out,response_v6.LTE_SignalStrength.signalStrength,response_v6.LTE_SignalStrength.rsrp,response_v6.GW_SignalStrength.bitErrorRate);
RIL_onRequestComplete(t, RIL_E_SUCCESS, (int *)(&response_v6), sizeof(response_v6));
at_response_free(p_response);
free(response);
//sprintf(signal_level, "link:%d,sig:%d", link_4g, response[0]);
//WriteFile("/sdcard/tchtc/4g_signal_level.txt", signal_level);
return;
error:
RLOGE("requestSignalStrength must never return an error when radio is on");
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
at_response_free(p_response);
free(response);
}
protected boolean onSignalStrengthResult(AsyncResult ar, boolean isGsm) {
SignalStrength oldSignalStrength = mSignalStrength;
// This signal is used for both voice and data radio signal so parse
// all fields
if ((ar.exception == null) && (ar.result != null)) {
mSignalStrength = (SignalStrength) ar.result;
mSignalStrength.validateInput(); //验证上报的4G信号强度是否在正确范围内?
mSignalStrength.setGsm(isGsm);
} else {
log("onSignalStrengthResult() Exception from RIL : " + ar.exception);
mSignalStrength = new SignalStrength(isGsm);
}
return notifySignalStrength();
}
public void validateInput() {
if (DBG) log("Signal before validate=" + this);
// TS 27.007 8.5
mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99;
// BER no change;
mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1;
mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
// TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
mLteRsrp = ((mLteRsrp >= 44) && (mLteRsrp <= 140)) ? -mLteRsrp : SignalStrength.INVALID; //RSRP ril层上报的必须是正数;
mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
: SignalStrength.INVALID;
// Cqi no change
if (DBG) log("Signal after validate=" + this);
}
SignalStrength.java文件中getLevel() 是对信号的解析;4G信号解析就是getLteLevel() 函数;
public int getLteLevel() {
/*
* 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 = SIGNAL_STRENGTH_NONE_OR_UNKNOWN, rsrpIconLevel = -1, snrIconLevel = -1;
if (mLteRsrp > -44) rsrpIconLevel = -1;
//根据RSRP信号强度转化成UI通知栏的信号强度格格;
else if (mLteRsrp >= -85) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
else if (mLteRsrp >= -95) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
else if (mLteRsrp >= -105) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
else if (mLteRsrp >= -115) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
else if (mLteRsrp >= -140) rsrpIconLevel = 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 = SIGNAL_STRENGTH_GREAT;
else if (mLteRssnr >= 45) snrIconLevel = SIGNAL_STRENGTH_GOOD;
else if (mLteRssnr >= 10) snrIconLevel = SIGNAL_STRENGTH_MODERATE;
else if (mLteRssnr >= -30) snrIconLevel = SIGNAL_STRENGTH_POOR;
else if (mLteRssnr >= -200)
snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
if (DBG) log("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 = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
+ rssiIconLevel);
return rssiIconLevel;
}