[2018年底]电信短信自注册,rild重启等项目问题总结

这两个月做了两个项目,可以说算是一年当中最忙的阶段了。升级项目问题难度完全不亚于新项目,和其他模块扯了很多皮, 踢过皮球,也提了很多代码。

总的来说,增加了解 bug 经验。此贴记录一下解过的问题,方便以后回顾。

电信短信自注册

  1. 提供相关短信接口给上层app调用,在 ISms.aidl 增加专用接口
  2. 解决短信7bit编码问题,由于这三个特殊字符,0x00,0x01,0x03,在编码过程中,不能正确的编码。
  3. 参照message app,解决短信都是从卡1发送的问题
  4. 短信 pdu 内容格式参考:http://www.cppblog.com/zhangyq/archive/2009/07/04/89245.html

第二步遇到的问题说明一下,
需要对特殊字符做特殊处理,如果不做特殊处理,Telephony framework 会采用 16 bit 编码,这导致短信内容超过一条的长度限制,会分成两条发送出去。
所以只能对这几个特殊字符处理。

cdma采用7位编码发送,在打包的时候针对前四个字符做特殊处理,修改文件
frameworks/base/telephony/java/com/android/internal/telephony/cdma/BearerData.java

try {
int msgLen = msg.length();
BitwiseOutputStream outStream = new BitwiseOutputStream(msgLen);
for (int i = 0; i < msgLen; i++) {
    if(i < 4) {
        outStream.write(7, msg.charAt(i));
    } else {
        int charCode = UserData.charToAscii.get(msg.charAt(i), -1);
        if (charCode == -1) {
            if (force) {
                outStream.write(7, UserData.UNENCODABLE_7_BIT_CHAR);
            } else {
                throw new CodingException("cannot ASCII encode (" + msg.charAt(i) + ")");
            }
        } else {
            outStream.write(7, charCode);
        }
    }
}
return outStream.toByteArray();

ims gsm 短信编码采用7位编码时,电信的 ims 网络收到的短信内容不能正确解码,采用 8 位则正常,所以强制用 8 位编码,修改文件
/frameworks/base/telephony/java/com/android/internal/telephony/GsmAlphabet.java

ret = new byte[msgLen + 1];
ret[1] = (byte)(msg.charAt(0));
ret[2] = (byte)(msg.charAt(1));
ret[3] = (byte)(msg.charAt(2));
ret[4] = (byte)(msg.charAt(3));
stringToGsm8BitUnpackedField(msg.substring(4), ret, 5, ret.length - 5);
ret[0] = (byte)(msgLen);
return ret;

RILD重启问题分析

分析 force cp crash 后,rild2 不能重启问题。这个问题原因需要说明一下。
以前版本,rild2 挂了会强制重启 rild 进程,rild 进程会带动 rild2 进程重启。
现在版本,rild 重启带动rild2 的代码已经被删除,这个时候 rild2 就没法再次启动,只是启动了 rild.

以前 7.1 版本启动 rild 的 rc 文件的配置如下:

service ril-daemon /system/bin/rild
    class main
    socket rild stream 660 root radio
    socket rild-debug stream 660 radio system
    socket rild-cas stream 660  casdrm mmb
    user root

service ril-daemon1 /system/bin/rild -c 2
    class main
    socket rild2 stream 660 root radio
    socket rild-debug2 stream 660 radio system
    user root
    disabled

现在 8.1 版本启动 rild 的 rc 文件的配置如下:

service ril-daemon /vendor/bin/hw/rild -l ${vendor.sec.rild.libpath}
    class main
    user radio
socket rild-cas stream 660  casdrm mmb

service ril-daemon1 /vendor/bin/hw/rild -c 2 -l ${vendor.sec.rild.libpath2}
    class main
    user radio

看到两者的主要差别在于,8.1 版本, ril-daemon1 并没有 disabled 字眼,说明 rild2 挂了的情况,是可以自动重启的。
但是现在问题是不能重启,问题在于这个函数并没有让 rild2 挂掉,而是去让 rild 重启,7.0 能 rild 能带 rild2, 而8.0版本么有,所以重启不了。

int DoModemSilentReset()
{
    RilLogE("%s()", __FUNCTION__);
    RLOGD("RIL_Init start ril-daemon");
    property_set("ctl.stop", "ril-daemon");
    sleep(1);
    property_set("ctl.start", "ril-daemon");
    return 0;
}

修改如下

int DoModemSilentReset()
{
    exit(EXIT_SUCCESS);
}

此时,force cp crash 后,rild 和 rild2 能正常重启。

在调试的过程中发现,如果我们单单杀死 rild2 进程,rild2 依然没法自动重启。

adb shell  
ps -A|grep rild
kill -9 pid

对比发现依旧7.0版本是OK的,是因为 rild2 挂了会强制启动 rild,所以两个 ril-daemon 都会重启。
换句话说,rild2 挂了,必须两个 ril-daemon 都必须重启,才能正常工作。
所以,修改 rc 文件,增加如下代码:

on property:init.svc.ril-daemon1=restarting
    restart ril-daemon

之后,ril-daemon 和 ril-daemon1 都重启,正常工作。

多线程变量问题导致手机无服务

手机手动搜网后,选择一个 forbidden 网络点击注册(这个过程频繁操作),sometime 问题,之后手机发生一直注册不上网络。
调查后发现,手动选择 forbidden 网络后,手机端发送一个 set manul 的命令给 cp,之后,手机端还会发一个 set auto 自动选择网络的命令下去。
然而,这两个命令作为一个消息会用同一个变量 mTxSetNwMsg;
这两个需要和 cp 端进行交互,是一个异步的过程,可以这么简单理解,发送命令是一个发送线程,接收设置的结果是响应线程。

  1. 在 set auto 时候,mTxSetNwMsg 代表 set auto 消息。

  2. cp 响应 set auto 消息,这个消息通过管道的方式继续传递,表示 set auto 处理完成。

  3. rild 的处理流程认为 set auto 消息处理完成了,set manual 消息就发下去,mTxSetNwMsg 此时代表的是 set manul 消息了。

  4. 然而在这个时候,set auto 消息还会去把 mTxSetNwMsg 置为 null, 那么 mTxSetNwMsg 代表的消息 set manul,就无法返回了。

  5. rild 记录着 set manul 消息一直没有返回,所有消息都会卡住,所以手机显示无服务,因为 rild 已经无法正常工作。

他们对应如下命令

10-25 11:04:04.775 radio 15708 15708 D RILJ    : [0709]> SET_NETWORK_SELECTION_MANUAL operatorNumeric = 45413 [SUB0]
10-25 11:04:09.907 radio 15708 15708 D RILJ    : [0734]> SET_NETWORK_SELECTION_AUTOMATIC [SUB0]

10-25 11:04:09.933 radio 15708 16459 D RILJ    : [0709]< SET_NETWORK_SELECTION_MANUAL error 38 [SUB0]
10-25 11:04:09.933 radio 15708 16459 D RilRequest: [0709]< SET_NETWORK_SELECTION_MANUAL error: com.android.internal.telephony.CommandException: INTERNAL_ERR ret=

通过增加一个变量的方式,来规避这个问题(也可以通过加锁的方式,但这个更简单):

修改前:

void QmiNasService::NwSelectionDone(int err)
{
    if (mNwSelectTxn) {
        mModem->ProcessMessageDone(NULL, err, mNwSelectTxn);//通过管道的方式,传递消息
        mNwSelectTxn = NULL;//之后置为null
    }

    mNwSelectRat = SRIL_RAT_UNKNOWN;
    mNwSelectCsgId = 0;
}

修改后:

void QmiNasService::NwSelectionDone(int err)
{
    if (mNwSelectTxn) {
        QmiTransaction *curNwSelectTxn = mNwSelectTxn;//增加一个局部变量
        mNwSelectTxn = NULL;//先把这个置为null,
        mModem->ProcessMessageDone(NULL, err, curNwSelectTxn);//set manul 会消息等待这个传递完,才会发下来。
        curNwSelectTxn = NULL;
    }

    mNwSelectRat = SRIL_RAT_UNKNOWN;
    mNwSelectCsgId = 0;
}

其他项目问题分析

  1. 双 CTC 卡情况下,副卡无法拨打紧急号码问题,需要直接从 cs 域直接拨打。
  2. CTC 无法注册上 volte sometimes 问题,原因是属性设置问题,导致判断条件不对,没有设置到 modem 端。
  3. 插 CTC 卡显示漫游问题,针对中国向,修改 isInPrl 默认值为 true。

你可能感兴趣的:(android,Telephony,Android,Telephony/RIL)