点击打开链接

最近客户反馈了一个Bug,我们的系统用着用着会自动重启,尤其是在拨号的时候极容易死机或者进入下载模式。根据老大和高通的支持得到了一个解决方案。

Android系统中,有这么一个文件夹:sys/bus/msm_subsys/devices,里面分别有三个文件夹:subsys0、subsys1、subsys2,这三个都是android系统中运行的子系统。根据高通的解释,subsys0主要是负责adsp(音视频媒体的相关服务)的启动和运行,subsys1主要负责modem(拨打电话和蓝牙wifi等服务)的业务处理,subsys2主要管理wcnss的相关业务,当然还有很多其它模块的子系统,就不一一举例了。

subsys0、subsys1、subsys2都有个叫restart_level的文件,用cat命令查看发现这些文件的内容都是SYSTEM,就是这个SYSTEM导致系统在遇到问题的时候死机或者下载模式,应该要把restart_level的设置为related,当系统遇到难于处理的问题的时候,比如打电话过程中遇到错误,那就只重启subsys1子系统(子系统都是在后台运行的,重启过程用户是看不到的),android系统本身是不重启或进入下载模式的,这样用户体验也好些。

那有人会问了,既然这样那高通为什么不默认把这些值设为related呢?其实我也有相同的疑问,我老大说如果一遇到问题就让子系统重启那很多BUG就测不出来了,这样做是让有些BUG更好的浮出水面。

现在我们的机器经常在拨打电话的时候死掉或者进入下载模式(download模式),那应该就是subsys1这个子系统出了问题了。找subsys1的相关代码,在init.qcom.ssr.sh中有调用,源码位置:device/qcom/common/rootdir/etc/init.qcom.ssr.sh,是个脚本文件,代码贴出来:

#!/system/bin/sh
# Copyright (c) 2013, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of The Linux Foundation nor
#       the names of its contributors may be used to endorse or promote
#       products derived from this software without specific prior written
#       permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

ssr_str="$1"
IFS=,
ssr_array=($ssr_str)
declare -i subsys_mask=0

# check user input subsystem with system device
ssr_check_subsystem_name()
{
    declare -i i=0
    subsys=`cat /sys/bus/msm_subsys/devices/subsys$i/name`
    while [ "$subsys" != "" ]
    do
        if [ "$subsys" == "$ssr_name" ]; then
            return 1
        fi
        i=$i+1
        subsys=`cat /sys/bus/msm_subsys/devices/subsys$i/name`
    done
    return 0
}

# set subsystem mask to indicate which subsystem needs to be enabled
for num in "${!ssr_array[@]}"
do
    case "${ssr_array[$num]}" in
        "1")
            subsys_mask=0
        ;;
        "riva")
            subsys_mask=$subsys_mask+1
        ;;
        "3")
            subsys_mask=63
        ;;
        "adsp")
            ssr_name=adsp
            if ( ssr_check_subsystem_name ); then
                subsys_mask=$subsys_mask+2
            fi
        ;;
        "modem")
            ssr_name=modem
            if ( ssr_check_subsystem_name ); then
                subsys_mask=$subsys_mask+4
            fi
        ;;
        "wcnss")
            ssr_name=wcnss
            if ( ssr_check_subsystem_name ); then
                subsys_mask=$subsys_mask+8
            fi
        ;;
        "venus")
            ssr_name=venus
            if ( ssr_check_subsystem_name ); then
                subsys_mask=$subsys_mask+16
            fi
        ;;
        "external_modem")
            ssr_name=external_modem
            if ( ssr_check_subsystem_name ); then
                subsys_mask=$subsys_mask+32
            fi
        ;;
    esac
done

# enable selected subsystem restart
if [ $((subsys_mask & 1)) == 1 ]; then
    echo 1 > /sys/module/wcnss_ssr_8960/parameters/enable_riva_ssr
else
    echo 0 > /sys/module/wcnss_ssr_8960/parameters/enable_riva_ssr
fi

if [ $((subsys_mask & 2)) == 2 ]; then
    echo "related" > /sys/bus/msm_subsys/devices/subsys0/restart_level
else
    echo "system" > /sys/bus/msm_subsys/devices/subsys0/restart_level
fi

if [ $((subsys_mask & 4)) == 4 ]; then
    echo "related" > /sys/bus/msm_subsys/devices/subsys1/restart_level
else
    echo "system" > /sys/bus/msm_subsys/devices/subsys1/restart_level
fi

if [ $((subsys_mask & 8)) == 8 ]; then
    echo "related" > /sys/bus/msm_subsys/devices/subsys2/restart_level
else
    echo "system" > /sys/bus/msm_subsys/devices/subsys2/restart_level
fi

if [ $((subsys_mask & 16)) == 16 ]; then
    echo "related" > /sys/bus/msm_subsys/devices/subsys3/restart_level
else
    echo "system" > /sys/bus/msm_subsys/devices/subsys3/restart_level
fi

if [ $((subsys_mask & 32)) == 32 ]; then
    echo "related" > /sys/bus/msm_subsys/devices/subsys4/restart_level
else
    echo "system" > /sys/bus/msm_subsys/devices/subsys4/restart_level
fi

if [ $((subsys_mask & 63)) == 63 ]; then
    echo 3 > /sys/module/subsystem_restart/parameters/restart_level
else
    echo 1 > /sys/module/subsystem_restart/parameters/restart_level
fi

代码中有这么一段:

if [ $((subsys_mask & 4)) == 4 ]; then
    echo "related" > /sys/bus/msm_subsys/devices/subsys1/restart_level
else
    echo "system" > /sys/bus/msm_subsys/devices/subsys1/restart_level
fi

判断subsys_mask和4的位运算来给subsys1赋值, 要么赋值related,要么赋值system。subsys_mask的值是通过调用这个脚本时传进来的参数获得的,再就是找到调用这个脚本的地方,init.qcom.rc, 源码位置:device/qcom/common/rootdir/etc/init.qcom.rc,这里要说明一下,*.rc的文件中加载的都是系统的服务,里面的值都是写在系统文件里的,比如build.prop文件,当这些值发生改变的时候(比如进入shell模式可以setprop xxx yyy来更改系统服务),这个服务就会重新执行一遍,以加载不同的文件属性。

里面有这么一段:

# SSR setting
on property:persist.sys.ssr.restart_level=*
    exec /system/bin/sh /init.qcom.ssr.sh ${persist.sys.ssr.restart_level}

这里就是调用那个脚本的地方,也就是说当property:persist.sys.ssr.restart_level这个属性发生改变的时候就执行init.qcom.ssr.sh这个脚本,并且把自己当参数传给ssr_str。再回到init.qcom.ssr.sh这个脚本文件,ssr_str是个数组,也就是说property:persist.sys.ssr.restart_level这个属性可以是有多个参数的(参数之间以逗号分隔),不同的参数给subsys_mask赋不同的值,因为我们的问题是出在subsys1,所以要让subsys_mask & 4 == 4,就需要将property:persist.sys.ssr.restart_level的参数设为modem,就会将/sys/bus/msm_subsys/devices/subsys1/restart_level的值设为related,让subsys1子系统在遇到处理不了的问题的时候自行后台重启。

剩下的问题就简单了,在系统中预先给property:persist.sys.ssr.restart_level赋值一个modem值,那系统属性subsys1/restart_level的值就是related了,在buildspec.mk中加上这一句:ADDITIONAL_BUILD_PROPERTIES += persist.sys.ssr.restart_level=$(call add2prop,$(PWV_SSR_RESTART_LEVEL)),PWV_SSR_RESTART_LEVEL是自己定义的宏,其值就是modem,编译,升级软件,验证OK。

觉得这些问题还是挺有价值的,就记录下来,以便以后回味。

Android 系统自动重启Bug(高通平台)的更多相关文章

  1. Android高通平台调试Camera驱动全纪录

    项目比较紧,3周内把一个带有外置ISP,MIPI数据通信,800万像素的camera从无驱动到实现客户全部需求. 1日 搭平台,建环境,编译内核,烧写代码. 我是一直在Window下搭个虚拟机登服务器 ...

  2. 高通平台启动log概述(PBL log、sbl1 log、kernel log)【转】

    本文转自:https://blog.csdn.net/RadianceBlau/article/details/78416776?utm_source=blogxgwz9 高通平台启动log概述(PB ...

  3. CentOS 7.1系统自动重启的Bug定位过程

    [问题] 有同事反应最近有多台MongoDB的服务器CentOS 7.1系统会自动重启,分析了下问题原因. [排查过程] 1. 检查系统日志/var/log/message,并没有记录异常信息,jou ...

  4. 高通平台如何避免误入FFBM模式

    前面两篇博客分别介绍了通过fastboot和QFIL工具退出FFBM模式的方法.虽然售后的同学可以这么指导用户做恢复,但步骤多操作也麻烦,且属于事后处理,如果大面积高概率地出现,会严重影响用户体验.这 ...

  5. 高通平台如何使用QPST抓DUMP

    一 :确认手机状态 手机系统死机白屏后,使用USB线 连接手机和计算机.打开计算机设备管理器 ,当其中与手机相关的端口只有DIAG 口 项(9006端口)时,表明手机处于DUMP 模式,可以抓DUMP ...

  6. Android:高通平台性能调试

    1.GPU / CPU 信息打印脚本 gpu_cpu_info.bat @echo off echo "==================GPU====================== ...

  7. 高通平台读写nv总结【转】

    本文转载自:https://blog.csdn.net/suofeng12345/article/details/52713993 一,引言      1. 什么是NV       高通平台的NV,保 ...

  8. 高通平台点亮LCD个人总结

    点击打开链接 高通平台LCD模块大致分为两部分:KERNEL和LK.在进行点屏之前,应该认真查看LCD原理图,弄清楚LCD亮屏需要满足的条件和上电时序,同时可以跟LCD IC原厂拿到初始化代码. 首先 ...

  9. 高通平台读写nv总结

    一,引言      1. 什么是NV       高通平台的NV,保存了系统运行过程中各个模块可能用到的一些参数值,它是以单个文件的形式保存在EFS中,但用户是不能随意访问的,只能通过QXDM来进行读 ...

随机推荐

  1. [POI 2004]ZAW

    Description 在 Byte 山的山脚下有一个洞穴入口. 这个洞穴由复杂的洞室经过隧道连接构成. 洞穴的入口是 1 号点.两个洞室要么就通过隧道连接起来,要么就经过若干隧道间接的相连. 现在决 ...

  2. STL rope

    rope的部分简单操作 函数 功能 push_back(x) 在末尾添加x insert(pos,x) 在pos插入x erase(pos,x) 从pos开始删除x个 replace(pos,x) 从 ...

  3. [AHOI2005]约数研究

    题目描述 科学家们在Samuel星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机“Samuel II”的长时间运算成为了可能.由于在去年一年的辛苦工作取得了不错的成绩,小联被允许用“Samu ...

  4. Django+nginx+uwsgi部署教程(centos7+ubuntu16.4)

    在线教育平台项目演示地址 项目部署教程 1.1.工作原理介绍 django 一个基于python的开源web框架 uwsgi 一是一个web服务器,也可以当做中间件 nginx 常用高性能代理服务器 ...

  5. 笔记7 AOP

    1. 通知(Advice)   切面的工作被称为通知.通知定义了切面是什么以及何时使用.除了描述切面要完成的工作, 通知还解决了何时执行这个工作的问题.它应该应用在某个方法被调 用之前?之后?之前和之 ...

  6. Requests库介绍

    Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...

  7. Arduino抢答器

    0.部分需要掌握的知识点和注意事项 (1)面包板的结构 (2)按键的结构:按键按下时,左右两侧连通:按键松开后,左右两侧断开,但1号与2号相连,3号与4号相连,即按键松开时,同侧不相连,相连不同侧. ...

  8. java中什么是序列化和反序列化

    序列化:能够把一个对象用二进制的表示出来. 类似我第一个字节表示什么属性名词,第二个字节表示什么属性值,第几个字段表示有几个属性等. 而且这个二进制可以写到硬盘或者在网络上传输但不会破坏他的结构.一般 ...

  9. Servlet-----response.getWriter().write()与out.print()的区别

    50313  1.首先介绍write()和print()方法的区别:  (1).write():仅支持输出字符类型数据,字符.字符数组.字符串等  (2).print():可以将各种类型(包括Obje ...

  10. tf.nn.conv2d 和 tf.nn.max_pool 中 padding 分别为 'VALID' 和 'SAME' 的直觉上的经验和测试代码

    这个地方一开始是迷糊的,写代码做比较分析,总结出直觉上的经验. 某人若想看精准的解释,移步这个网址(http://blog.csdn.net/fireflychh/article/details/73 ...