是什么原因导致手机不断重启呢?我们来分析一下:
-
现象
手机启动,出现第一屏画面,然后黑屏,继续启动,出现第一屏画面,然后黑屏…… -
原因
手机系统为电池设定了两个电压值,一是开机电压,二是关机电压。达到开机电压才允许开机,低于关机电压,系统会自动关机。开机电压略高于关机电压,因为自动关机后就不能马上开机,电池要充电达到开机电压,才能允许开机。 -
结论
手机不断重启是在电池没电的时候出现,而且都不是新的电池。我的原装电池用了半年,品胜电池用了4个月。所以手机电池是一个原因,电池的电压特性曲线发生了变化。电池的电压会随着电池的电量变化,这种变化很小的。但是当电量严重不足,电压降到某一阙值(特定值)时,电压会急剧下降。电池时间长了,这一电压阙值会有所提高,当它接近开机电压时,不断重启就开始了。
这时,电池电压急剧下降到关机电压,手机自动关机了。关机后电池马上回升到开机电压,这时你插上充电器,手机就会自动重启,然后电压急剧下降,手机自动关机,再重启,再关机不断循环。
在低电量时,插着充电器关机充电,手机会不断重启。
一、lk 阶段重启
低电量关机充电不断重启问题在lk 阶段重启的log如下
Unplugged Usb/Charger in Kernel Charging Mode Before Jumping to Kernel, Power Off
重启原因
设备支持DEVICE_TREE_SUPPORT,在lk启动kernel的
boot_linux_fdt
int boot_linux_fdt(void *kernel, unsigned *tags,
char *cmdline, unsigned machtype,
void *ramdisk, unsigned ramdisk_size)
{
...............
#ifdef MTK_KERNEL_POWER_OFF_CHARGING
/*Prevent the system jumps to Kernel if we unplugged Charger/USB before*/
if(kernel_charging_boot() == -1)
{
dprintf(CRITICAL,"[%s] Unplugged Usb/Charger in Kernel Charging Mode Before Jumping to Kernel, Power Off\n", __func__);
#ifndef NO_POWER_OFF
mt6575_power_off();
#endif
...............
}
}
由于在lk阶段的电流过大,导致charger的电压被拉低到4.3v以下,因为 VCDT_LV_VTH默认的电压是4.3v,所以在detect charger回返回false,由于插充电器的原因在power off之后又起来导致了不断重启的现象,其中VCDT_LV_VTH 的设置可以参考datasheet的设置。
解决方案
1)首先检查lk阶段充电电流设置的大小,注意检查backlight_on设置的level。
2)如果是用的swtich ic charger,首先的开启dpm功能,dpm功能是一种保护 charger vol在大电流的情况下不被拉的很低,Vin-dpm 电压的设置范围是 4.2-4.76v,default的值是4.2,一般要设置为4.5。
3)如果在以上的修改还不生效,就把VCDT_LV_VTH值设置为4.2v。
二、在kernel关机充电阶段重启
在kernel阶段重启有两个原因如下:
在关机充电时,charger detect存在的情况下,但是如果被识别为usb host mode,这时就会放回false,引起了power off
这时应该去检测usb 的id pin硬件上是不是被拉低了
kal_bool upmu_is_chr_det(void)
{
...........
if (mt_usb_is_device()) {
battery_log(BAT_LOG_FULL,
"[upmu_is_chr_det] Charger exist and USB is not host\n");
return KAL_TRUE;
} else {
battery_log(BAT_LOG_CRTI,
"[upmu_is_chr_det] Charger exist but USB is host\n");
...........
}
在charger 电压超过了/kernel-3.10/drivers/power/mediatek/battery_common.c#charger_hv_detect_thread里面设置的电压,默认为6.5v这时,就会产生cable out,接着就会power off
三、关闭异常掉电机制
修改一下异常掉电机制代码
vendor/mediatek/proprietary/bootable/bootloader/preloader/custom/k37mv1_bsp/inc/cust_rtc.h
在 Android 8.0 中,救援程序默认处于启用状态,其实现位于 /services/core/java/com/android/server/RescueParty.java 中。 在出现以下情况时,救援程序会收到有关启动和崩溃事件的信息,然后即会启动:
system_server 在 5 分钟内重启 5 次以上。
永久性系统应用在 30 秒内崩溃 5 次以上。
当检测到上述某种情况时,救援程序会将其上报给下一救援级别、处理与该级别相关联的任务,并让设备继续运行,看看能否恢复。清除或重置内容的程度随级别而增加。最高级别会提示用户将设备恢复出厂设置。
要支持救援程序,无需特别的硬件支持。实现后,设备的恢复系统必须响应 --prompt_and_wipe_data 命令,且设备必须先提供一种方法,让用户确认用户数据是否有任何损坏,然后再继续运行。此外,恢复系统还应为用户提供有关尝试再次启动设备的选项。
由于每个救援级别都会使设备再次变为可运行状态的时间延后(可能长达 5 分钟),因此设备制造商不应添加自定义救援级别。设备处于不可运行的状态的时间越长,用户发出支持请求或保修咨询,而不是自行恢复其设备的可能性就越大。
验证
当设备具有有效的 USB 数据连接时,系统会停止所有救援事件,因为这是一个较强的信号,表示有人正在调试设备。
要停止此类抑制行为,请运行:
adb shell setprop persist.sys.enable_rescue 1
在此处,您可以触发系统或界面崩溃循环。
要触发低级 system_server 崩溃循环,请运行:
adb shell setprop debug.crash_system 1
要触发中级 SystemUI 崩溃循环,请运行:
adb shell setprop debug.crash_sysui 1
这两个崩溃循环都会启动救援逻辑。所有的救援操作也都会记录到存储在 /data/system/uiderrors.txt 中的永久性的 PackageManager 日志中,以供日后进行检查和调试。 此外,“软件包警告消息”部分下的每个错误报告中也会包含这些永久性的日志。
我很有幸分析过一个常驻进程崩溃导致手机进入救援程序并提示用户选择恢复出厂设置的bug
进入救援程序的bug现象非常明显,手机黑屏弹出选项菜单,只能选择恢复出厂设置。
adb logcat -v threadtime | tee log1.txt | grep " events for UID"
以上命令就可以输出崩溃的进程uid,由此追查下去就能知道是哪里出现了崩溃,分析出Root cause。