关键词:android 电池关机充电
androidboot.mode charger 关机充电 充电画面显示
平台信息:
内核:linux2.6/linux3.0
系统:android/android4.0
平台:S5PV310(samsungexynos 4210)
电池的基本原理;
android关机充电流程、充电画面显示;
Android开机充电流程,电池电量、低电信息是怎么处理的;
上一篇我们讲了锂电池的充放电的流程和电池的一些特性,这一节我们重点说一下android关机充电是怎么、充电画面显示是怎么实现的,这个在工作中也比较有用,我们开始做这一块的时候也走了不少的弯路。我记得我们做adnroid2.3的时候,关机状态和充电logo显示是在uboot中做的。应该是有两种做法,回头我再看下uboot中做画面显示那一块是怎么做的,这一节我们重点说系统中的充电logo显示。
一、android正常开机流程、关机充电流程
在写这篇文章之前我们先看两个流程:正常开机流程,关机充电系统启动流程
1、正常开机流程,按开机键。
可大致分成三部分
(1)、OS_level:UBOOT、kenrel、init这三步完成系统启动;
(2)、Android_level:这部分完成android部的初始化;
(3)、Home Screen:这部分就是我们看到的launcher部分。
2、关机充电系统启动流程
与前面相比,这个流程只走到init这一部分,就没有往后走了,这部分我们会在后面的代码中分析。
二、关机充电逻辑硬件逻辑
1、插入DC,charger IC从硬件上唤醒系统,相当于长按开机键开机。
下面这部分是charger IC连接系统的控制部分。
三、软件逻辑。
DC插入,其实相当于关机状态下“按开机键”开机。第一步要走UBOOT、kernel 、android init这一流程。
1、UBOOT
UBOOT启动代码我们不在这里详细分析,这里我们只要注意二个问题:
a:如何判断是DC插入;
b:设定setenv("bootargs", "androidboot.mode=charger"),androidboot.mode这个参数相当重要,这个参数决定系统是正常启动、还是关机充电状态。
Uboot/board/samsung/smdk4212/smkd4212.c
int board_late_init (void) { int keystate = 0; printf("check start mode\n"); if ((*(int *)0x10020800==0x19721212) || (*(int *)0x10020804==0x19721212) || (*(int *)0x10020808==0x19721212)) //(1)、检查是否有DC插入; { setenv ("bootargs", "");//(2)、没有DC插入; } else {//DC插入 int tmp=*(int *)0x11000c08; *(int *)0x10020800=*(int *)0x10020804=0x19721212; *(int *)0x11000c08=(tmp&(~0xc000))|0xc000; udelay(10000); if ((*(int *)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) { setenv ("bootargs", "androidboot.mode=charger");//(3)、设定bootargs为charger状态 printf("charger mode\n"); } else { setenv ("bootargs", ""); } *(int *)0x11000c08=tmp; } #ifdef CONFIG_CPU_EXYNOS4X12 int charge_status=CheckBatteryLow();//(4)、检查电池电量; keystate=board_key_check();//(5)、检查按键状态; // fuse bootloader if(second_boot_info != 0) { boot_symbol=1; INF_REG2_REG =0x8; run_command(CONFIG_BOOTCMD_FUSE_BOOTLOADER, NULL); } if((INF_REG4_REG == 0xd)) { // reboot default char buf[10]; sprintf(buf, "%d", CONFIG_BOOTDELAY); setenv ("bootdelay", buf); setenv ("reserved", NULL); saveenv(); } else if((INF_REG4_REG == 0xe) || keystate == (0x1 | 0x2)) {//(6)、按键进入fastboot模式; // reboot bootloader boot_symbol=1; INF_REG2_REG =0x8; printf("BOOTLOADER - FASTBOOT\n"); setenv ("reserved", "fastboot"); setenv ("bootdelay", "0"); } else if((INF_REG4_REG == 0xf) || keystate == (0x1 | 0x2 | 0x4)) {//(7)、按键进入recovery模式; // reboot recovery printf("BOOTLOADER - RECOVERY\n"); boot_symbol=1; INF_REG2_REG =0x8; setenv ("reserved", CONFIG_BOOTCMD_RECOVERY); setenv ("bootdelay", "0"); } else if(keystate == (0x1 | 0x4) || second_boot_info != 0 || partition_check()) {//(8)、按键进入卡升级模式; // 2nd boot printf("BOOTLOADER - 2ND BOOT DEVICE\n"); boot_symbol=1; INF_REG2_REG =0x8; setenv ("bootcmd", CONFIG_BOOTCOMMAND); setenv ("reserved", CONFIG_BOOTCMD_FUSE_RELEASE); setenv ("bootdelay", "0"); } else {//(9)、正常启动; // normal case char buf[10]; sprintf(buf, "%d", CONFIG_BOOTDELAY); setenv ("bootdelay", buf); } INF_REG4_REG = 0; return 0; }
(1)、检查是否有DC插入;
if ((*(int *)0x10020800==0x19721212) || (*(int *)0x10020804==0x19721212) || (*(int *)0x10020808==0x19721212))
这部分检查寄存器的值。
(2)、没有DC插入;
(3)、设定bootargs为charger状态
if ((*(int *)0x11000c04 & 0x80)!=0x80 && INF_REG4_REG != 0xf) { setenv ("bootargs", "androidboot.mode=charger");
这是这部分的重点,如果能过寄存器判断是DC插入,把androidboot.mode设定为charger状态。
以下这部分根据需要加入,通过判断不同的情况进入不同的功能,如fastboot\revovery…………,这部分不做详细解释。
(4)、检查电池电量;
这个在正常开机状态下,如果检测电量太低,则不开机,这部分代码就不做分析。
(5)、检查按键状态;
我们这个平台有几种模式:fastboot\recovery\卡升级等……
(6)、按键进入fastboot模式;
(7)、按键进入recovery模式;
(8)、按键进入卡升级模式
(9)、正常启动;
2、kernel
这部分和正常启动是一样的。
3、init
前面所有的描述其实只有一点和正常启动不太一样,那就是在UBOOT中把androidboot.mode设定为charger状态,内核正常流程启动,然后到init时要对charger这种状态处理。
system\core\init\init.c
int main(int argc, char **argv) { ……………… action_for_each_trigger("early-init", action_add_queue_tail); queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(property_init_action, "property_init"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); //(1)、显示initlogo.rle,也就是android第二张图片; queue_builtin_action(set_init_properties_action, "set_init_properties"); /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); /* skip mounting filesystems in charger mode */ if (strcmp(bootmode, "charger") != 0) {//(2)、这里就是UBOOT中设定的bootmode,如果是charger模式,跳过下面初始化; action_for_each_trigger("early-fs", action_add_queue_tail); action_for_each_trigger("fs", action_add_queue_tail); action_for_each_trigger("post-fs", action_add_queue_tail); action_for_each_trigger("post-fs-data", action_add_queue_tail); } queue_builtin_action(property_service_
package com.juck.test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; public class Base64Code{ //测试主方法 public static void main(String[] args){ final String fileName = "示例文件"; final String fileSuffix = ".jpg"; final String url = "C:\\"; try{ String base64Code=encoderToBase64Code(url); base64CodeToFile(base64Code,"D:\\BASE64编码字符串"+fileName+".txt"); decoderToBase64Code(base64Code,"D:\\解码"+fileName+fileSuffix); }catch(Exception e){ e.printStackTrace(); } } //文件转换程BASE64编码 public static String encoderToBase64Code()String path)throws IOException{ File file = new File(path); FileInputStream input = new FileInputStream(file); byte[] buffer = new byte[(int)file.length()]; input.read(buffer); input.close(); System.out.print(new BASE64Encoder().encode(buffer));//打印---文件经过编码后的字符串 return new BASE64Encoder().encode(buffer); } //BASE64字符串解码并保存文件 public static void decoderToBase64Code(String base64Code,String targetPath) throws IOException{ byte[] buffer = new BASE64Decoder().decodeBuffer(base64Code); FileOutputStream out = new FileOutputStream(targetPath); out.write(buffer); out.close(); //BASE64字符串保存成文本 public static void base64CodeToFile(String base64Code,String targetPath) throws IOException{ byte[] buffer = base64Code.getBytes(); FileOutputStream out = new FileOutputStream(targetPath); out.write(buffer); out.close(); } } }
http://juck.iteye.com
已有 0 人发表留言,猛击->>这里<<-参与讨论
ITeye推荐
- —软件人才免语言低担保 赴美带薪读研!—
全浏览器?其实主要工作还是在IE6上,其他浏览器问题不多,就不说其他浏览器问题了。Ofbiz在IE6下可谓“面目全非”啊,没法正常使用。可能从一开始ofbiz就没有打算兼容IE6吧,想想也对,被微软遗弃的孩子谁会兼容啊。可是,客户几乎多半系统都是在IE6环境下,所以这个IE6的兼容必须要搞。
废话已尽,下面谈谈这些问题,我只归类,不提供具体实现code.
兼容性其实本质就是利用不同浏览器的不同支持以及bug(CSS hack)。
下面给出2个CSS hack
1、
IE6支持属性命名前加“_”.唯一标识IE6,其他浏览器都不支持
2、
<!--[if IE 6]>
------ code -----
<![endif]-->
CSS hack
一、 图片引起的问题
问题:
Ofbiz在IE6下,png的图片几乎都成灰底图片。
原因:是png-32b图片在IE6下没办法完全透明和半透明。
解决:
利用微软浏览器滤镜实现透明,当然这个用多了会影响页面加载效率的,好在ofbiz类似处理不多。
语法:
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/blog_article/Example.png'); /* IE6 */
background-image: none; /* IE6 */
enabled : 可选项。布尔值(Boolean)。设置或检索滤镜是否激活。true | false true : 默认值。滤镜激活。
false : 滤镜被禁止。
sizingMethod : 可选项。字符串(String)。设置或检索滤镜作用的对象的图片在对象容器边界内的显示方式。 crop : 剪切图片以适应对象尺寸。
image : 默认值。增大或减小对象的尺寸边界以适应图片的尺寸。
scale : 缩放图片以适应对象的尺寸边界。
src : 必选项。字符串(String)。使用绝对或相对 url 地址指定背景图像。假如忽略此参数,滤镜将不会作用。
<!--当然,还有其他方法,比如JS,也有好多现成js插件,如IE PNG FIX,Javascript IE PNG FIX,Unit PNG FIX.有兴趣的可以自己去玩玩-->
注意:如果你的png图片是个链接的话,那么滤镜处理后链接会失效。需要给链接加上position:relative;
二、 位置问题
大部分的变形,移位问题,主要是支持的原因,这里不多说了。了解IE6与其他浏览器不同之处,找出问题所在,对症下药。
<!--Ofbiz在IE6下这类问题比较多-->
三、浮动元素无法显示在select元素之上
问题:如ofbiz菜单,在其他浏览器可以正常遮盖住select,但是IE6下,根本遮盖不住,select会刺穿菜单显示于上层。
原因:据说是IE6的国际性bug.
解决:利用透明的iframe遮盖住select。
<iframe ></iframe>
注意:遮盖成功后,每次请求会弹安全信息框,很是烦人,解决办法就是在iframe中引用一个空页面
大致的东西就这些,细节的方面就不多说了。本人兼容性调整后IE6/7/8/9,FF.完美运行
声明:本文原创,转载请注明出处juck.iteye.com
已有 0 人发表留言,猛击->>这里<<-参与讨论
ITeye推荐
- —软件人才免语言低担保 赴美带薪读研!—