Android4.4.2从内核logo到init logo到动态logo的分析及定制

Android开机logo一直都是各大产品定制的重点,如果IC厂家代码完善的话,那就很简单,直接把做好的logo文件放在预制好的文件夹就可以了。还有一些定制服务做得好的IC厂家,可能还会通过烧录软件直接修改升级包里面的logo文件,修改完毕后,直接烧录完事。

这些二次开发做得比较完善的IC厂家一般是各大平板电脑,手机方案商。但如果android代码并没得到很完善的优化怎么办?如在工业领域的android BSP。本人就遇到过这样的情况。Android logo的定制还是需要我们花费一番心机。

下面我们来分析一下android启动过程中logo的显示过程。鉴于不同的平台,可能还有IC厂家会在uboot里面显示开机logo,这部分在这篇文章里面不会介绍到。此文章介绍的是从内核logo,到init logo,到动态logo的过程。

首先,我们来看看内核logo:

打开内核logo 显示配置:

androidkernel boot logo

     -> Device Drivers 

       -> Graphics support

         -> Bootup logo (LOGO [=y])

            [*]   Standard 224-color Linux logo

保证.config文件里面几项被配置上

CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_MONO is not set
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_LOGO_ADVSIGNAGE_CLUT224 is not set

其代码和图片是在内核目录下的“drivers\video\logo”文件夹下,内核logo图片的方法可以到网上搜索,内核logo的代码和logo的制作方法这里就不做分析了。

接下来是init logo:

看到vendor.mk文件里面

PRODUCT_COPY_FILES +=   \
         device/vendor/machine/initlogo.rle:root/initlogo.rle

相信一般的IC厂家都会用这样的做法,把init logo放到平台相关的目录下,然后在编译的时候拷贝,打包到boot.img 下。

接下来我们看看init logo的显示过程。

首先是init logo名字的定义,至于initlogo.rle的制作,可以参考网上的一些资料。有直接现成的制作软件。

system/core/init/init.h
#define INIT_IMAGE_FILE	"/initlogo.rle"

在android init过程里面,执行到console_init_action的时候,会把initlogo.rle 加载到内存里面去,然后显示出来。其实为什么会在console_init_action 里面显示logo,这个函数的本意是用来初始化console, 也就是串口的。其实本人也不是很清楚Google为什么要把init logo的显示放到这个函数里面实现,也没看出有什么特殊的含义,如果有人了解,可以告知。

System/core/init/init.c
 647 static int console_init_action(int nargs, char **args)
 648 {
 649     int fd;
 650 
 651     if (console[0]) {
 652         snprintf(console_name, sizeof(console_name), "/dev/%s", console);
 653     }
 654 
 655     fd = open(console_name, O_RDWR);
 656     if (fd >= 0)
 657         have_console = 1;
 658     close(fd);
 662     if( load_565rle_image(INIT_IMAGE_FILE) ) {
 665         fd = open("/dev/ttymxc0", O_WRONLY);
 666         if (fd >= 0) {
 667             const char *msg;
 668                 msg = "\n"
 669             "\n"
 670             "\n"
 671             "\n"
 672             "\n"
 673             "\n"
 674             "\n"  // console is 40 cols x 30 lines
 675             "\n"
 676             "\n"
 677             "\n"
 678             "\n"
 679             "\n"
 680             "\n"
 681             "\n"
 682             "             A N D R O I D ";
 683             write(fd, msg, strlen(msg));
 684             close(fd);
 685         }
 686     }
 687     return 0;
 688 }

其中load_565rle_image是在system/core/init/logo.c里面定义,如果有兴趣,可以去看看里面做了什么动作。

最后是动态logo的显示过程:

首先还是vendor.mk文件:

PRODUCT_COPY_FILES +=   \
         device/vendor/machine/bootanimation.zip:system/media/bootanimation.zip

跟init logo的做法一样,拷贝到特定的目录下,至于制作的方法,网上也有资料供参考。

接下来,在framework的代码里面会定义bootanimation.zip的存放路径

 55 #define USER_BOOTANIMATION_FILE "/data/local/bootanimation.zip"
 56 #define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
 57 #define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"

至于为什么会定义了三个名称的路径?大家可以去研究一下,这里就不进行详细分析了。

接下来是加载logo的动作

280     if ((encryptedAnimation &&
281             (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
282             (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||
283 
284             ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&
285             (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||
286 
287             ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
288             (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {
289         mAndroidAnimation = false;
290     }

以上是加载logo的过程,这过程里面,如果加载logo成功,会把mAndroidAnimation设置为false,如果mAndroidAnimation为false,就会播放定制好的动态logo的动画,不然,就播放android原始的android动态logo。如下:

bool BootAnimation::threadLoop()
{
    bool r;
    if (mAndroidAnimation) {
        r = android();
    } else {
        r = movie();
}

动态logo的显示开始与结束是由SurfaceFlinger来控制,控制过程是通过设置“service.bootanim.exit”属性的值来完成。

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
653 void SurfaceFlinger::startBootAnim() {
 654     // start boot animation
 655     property_set("service.bootanim.exit", "0");
 656     property_set("ctl.start", "bootanim");
 657 }

显示开始后,SurfaceFlinger会把“service.bootanim.exit”属性设置为0。然后“service.bootanim.exit”会在BootAnimation.cpp里面进行判断,确定是启动了动态logo,才会申请关闭logo。

frameworks/base/cmds/bootanimation/BootAnimation.cpp
383 void BootAnimation::checkExit() {
384     // Allow surface flinger to gracefully request shutdown
385     char value[PROPERTY_VALUE_MAX];
386     property_get(EXIT_PROP_NAME, value, "0");
387     int exitnow = atoi(value);
388     if (exitnow) {
389         requestExit();
390     }
391 }

在启动完成后,SurfaceFlinger在bootFinished方法里面最后把“service.bootanim.exit”属性设置为1.

296 void SurfaceFlinger::bootFinished()
 297 {
 298     const nsecs_t now = systemTime();
 299     const nsecs_t duration = now - mBootTime;
 300     ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
 301     mBootFinished = true;
 302 
 303     // wait patiently for the window manager death
 304     const String16 name("window");
 305     sp<IBinder> window(defaultServiceManager()->getService(name));
 306     if (window != 0) {
 307         window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
 308     }
 309 
 310     // stop boot animation
 311     // formerly we would just kill the process, but we now ask it to exit so it
 312     // can choose where to stop the animation.
 313     property_set("service.bootanim.exit", "1");
 314 }

分析到这里,如果想知道更加详细的过程,可以查看android里面相应的代码。













  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值