目 录
1. 概述 .......................................................................................................................... 2 2. modm部分开机原因 ................................................................................................ 2 3. LK与kernel部分设置充电模式 ............................................................................. 4 4. Android进入充电模式 ............................................................................................. 6
i
深圳国速科技有限公司
1. 概述
本文档将要分析手机充电模式下的流程,用android4.0的代码分析在关机时插入USB到android识别为充电模式的大致过程。主要涉及模块有高通modem部分、LK的cmdline部分、kernel的cmdline部分、android的init部分和android的charger部分。最为关键的是LK部分使启动模式进入充电模式,android才能具体的识别为充电模式。 2. modm部分开机原因
在USB插入时最先检测到USB插入的是PMIC,这时会触发一个上电时序,在代码执行到oemsbl_mc.c的oemsbl_shared_ram_init( )函数用于初始化共享内存时,会进入如下流程:
oemsbl_shared_ram_init( Adjust_pwr_on_status( )
最终在Adjust_pwr_on_status( )这个函数里面会根据文件hsu_chg_boot.c中的函数Get_Power_On_Composite_Event( )所得到的开机原因来判断最终的开机原因。
int Adjust_pwr_on_status(int * PowerOnReason)
)
->
oemsbl_smem_store_pon_status(
)
->
{
int temp = (Pwr_Composite_Event | Pwr_Original_Composite_Event);
int AdjustedPowerReason = pwr_on_status;
int i;
2
深圳国速科技有限公司
if(PM_PWR_ON_EVENT_USB_CHG & temp)
{ // usb chg
AdjustedPowerReason = PM_PWR_ON_EVENT_USB_CHG;
}
if(PM_PWR_ON_EVENT_WALL_CHG & temp)
{ // wall chg
AdjustedPowerReason = PM_PWR_ON_EVENT_WALL_CHG;
}
if(PM_PWR_ON_EVENT_KEYPAD & temp)
{ // keypad
AdjustedPowerReason = PM_PWR_ON_EVENT_KEYPAD;
}
******
3
深圳国速科技有限公司
*PowerOnReason = AdjustedPowerReason;
return 0;
}
在关机插入USB后会执行AdjustedPowerReason =
PM_PWR_ON_EVENT_USB_CHG,将开机原因设置为充电模式,已经过验证不管是插入USB还是AC都是执行这一段代码。开机原因保存在共享内存后,在LK中就可以通过读取共享内存的数据获取开机原因。 3. LK与kernel部分设置充电模式
在进入到LK后,会执行主函数void kmain(void),在这个函数中会创建一个线程bootstrap2用于执行bootstrap2(void *arg)这个函数,bootstrap2( )中调用函数apps_init( )对app进行初始化,这个函数所调用的函数都是已经通过宏定义#define APP_START(appname)声明,bootable\\bootloader\\lk\\app\\aboot.c
中使用
APP_START(aboot) .init = aboot_init, APP_END对aboot_init进行了声明。在apps_init( )中就会调用aboot_init( ),然后进入如下调用流程,
aboot_init( ) -> aboot_init( ) -> boot_linux_from_mmc( ) -> boot_linux( ) 在boot_linux( )中,通过以下代码判断是否需要进入充电模式,通过将pause_at_bootup赋值为1来标识是USB插入开机,在下面的代码中通过这个标识来决定是否进入充电模式。
if (target_pause_for_battery_charge() == PWR_ON_EVENT_USB_CHG && enter_charging_pause)
4
深圳国速科技有限公司
{
pause_at_bootup = 1;
cmdline_len += strlen(battchg_pause);
}
其中函数target_pause_for_battery_charge( )就是通过读取modem写入共享内存的数据来判断开机原因,调用流程如下:target_pause_for_battery_charge( ) –> target_check_power_on_reason( ) -> smem_read_alloc_entry( )
接下来通过如下代码将设置为充电模式的字符串char *battchg_pause = \" androidboot.mode=charger\"保存到cmdline中。最后调用entry(0, machtype, tags)通过tags将cmdline传入并启动kernel。
if (pause_at_bootup)
{
src = battchg_pause;
if (have_cmdline) --dst;
while ((*dst++ = *src++));
}
5
深圳国速科技有限公司
在通过函数void __init start_kernel(void)进入到kernel后,需要执行的函数setup_arch( )和setup_command_line( )读取boot中的cmdline,并且解析里面的信息保存到saved_command_line字符串中,\\qics1003\\kernel\\fs\\proc\\ cmdline.c文件中的proc_cmdline_init( )会创建proc/cmdline节点输出saved_command_line中的信息,android在初始化时就会读取这个节点里面保存的启动模式。 4. Android进入充电模式
在进入到android后会根据LK里面所获取的cmdline来决定是否进入充电模式,首先进入qics1003\\system\\core\\init.c中的main( )函数开始对android进行初始化。这里会调用函数import_kernel_cmdline(0, import_kernel_nv)读取proc/cmdline节点的数据,并且通过函数import_kernel_nv( )将充电的开机原因保存在bootmode中:
static void import_kernel_nv(char *name, int in_qemu)
{
******
} else if (!strcmp(name,\"androidboot.console\")) {
strlcpy(console, value, sizeof(console));
} else if (!strcmp(name,\"androidboot.mode\")) {
strlcpy(bootmode, value, sizeof(bootmode));
6
深圳国速科技有限公司
} else if (!strcmp(name,\"androidboot.serialno\")) {
strlcpy(serialno, value, sizeof(serialno));
******
}
其中androidboot.mode就是在进入充电模式后会是字符串\"
androidboot.mode=charger\"。
通过函数queue_builtin_action(set_init_properties_action, \"set_init_properties\")设置android系统的属性,其中set_init_properties_action( )函数中:
static int set_init_properties_action(int nargs, char **args)
{
char tmp[PROP_VALUE_MAX];
if (qemu[0])
import_kernel_cmdline(1, import_kernel_nv);
if (!strcmp(bootmode,\"factory\"))
property_set(\"ro.factorytest\
7
深圳国速科技有限公司
else if (!strcmp(bootmode,\"factory2\"))
property_set(\"ro.factorytest\
else
property_set(\"ro.factorytest\
property_set(\"ro.serialno\
property_set(\"ro.bootmode\
property_set(\"ro.baseband\
property_set(\"ro.carrier\
property_set(\"ro.bootloader\
property_set(\"ro.bootupmode\
if (modelno[0])
property_set(\"ro.boot.modelno\
property_set(\"ro.hardware\
8
深圳国速科技有限公司
snprintf(tmp, PROP_VALUE_MAX, \"%d\
property_set(\"ro.revision\
property_set(\"ro.emmc\
return 0;
}
通过函数property_set( )设置ro.bootmode为charger,就会触发qics1003\\system\\core\\init.rc中定义的配置文件:
on charger
class_start charger
这里会调用所有声明为class_start类的服务,在
qics1003\\system\\core\\rootdir\\init.qcom.rc中就配置了所需要执行的服务。
service charger /charger
class charger
oneshot
service chg-post-boot /system/bin/sh /system/etc/init.qcom.post_boot.sh
9
深圳国速科技有限公司
class charger
oneshot
在进入到充电服务后就进入\\qics1003\\system\\core\\charger.c文件中的main(int argc, char **argv),这里主要是关机状态充电图标显示、长按按键开机检测和USB拔出后的关机动作。
进入到event_loop( )中。 handle_input_state(charger,
now)
->
process_key(
)
->
exit_offmode_charging( ) 函数实现了在充电模式下长按按键开机功能,update_screen_state(charger, now)实现充电模式下电池图标的显示。
以下代码实现了在充电模式拔下USB后关机功能: if (curr_time_ms() - first_time > 2000){
if ((!is_usb_exist()) && (!is_ac_exist()) && (!is_unknown_exist())){
LOGI(\"[%lld] shutting down\\n\
android_reboot(ANDROID_RB_POWEROFF, 0, 0);
}
}
10
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- igat.cn 版权所有 赣ICP备2024042791号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务