<Android Framework 之路>BootAnimation(1)

来源:互联网 发布:15个java小项目 文库 编辑:程序博客网 时间:2024/06/05 11:55

介绍

开机动画,BootAnimation,就是Android手机开机郭晨各种以一个展示给用户的界面,实际是一个多个帧组成的动画,在界面上进行一帧一帧的播放,形成开机动画的效果。

本文针对Android5.1源码分析BootAnimation


源码分析

1. 文件产生

Android平台的开机动画由system/bin下的bootanimation文件完成,而这个文件产生于
frameworks/base/cmds/bootanimation/Android.mk

LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_SRC_FILES:= \    bootanimation_main.cpp \    AudioPlayer.cpp \    BootAnimation.cppLOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPESLOCAL_C_INCLUDES += external/tinyalsa/includeLOCAL_SHARED_LIBRARIES := \    libcutils \    liblog \    libandroidfw \    libutils \    libbinder \    libui \    libskia \    libEGL \    libGLESv1_CM \    libgui \    libtinyalsaLOCAL_MODULE:= bootanimationifdef TARGET_32_BIT_SURFACEFLINGERLOCAL_32_BIT_ONLY := trueendifinclude $(BUILD_EXECUTABLE)

编译结果为bootanimation的bin文件,所以,在有足够权限的前提下,在adb shell下执行bootanimation也是可以看到对应的开机动画效果的。

2. 启动开机动画

开机动画是以bin文件的形式存在于手机系统中,开机过程中通过init.rc定义
system/core/rootdir/init.rc

service bootanim /system/bin/bootanimation    class core    user graphics    group graphics audio    disabled//定义了disable,在开机过程中不会自动的启动    oneshot

这里不会启动,那么在哪里启动? 由于开机动画对SurfaceFlinger有依赖,所以应该是在SurfaceFlinger启动之后再开始执行,看一下源码。

SurfaceFlinger的启动在init.rc文件中

service surfaceflinger /system/bin/surfaceflinger    class core    user system    group graphics drmrpc    onrestart restart zygote

与SurfaceFlinger相关的源码存在于
frameworks\native\services\surfaceflinger
入口
frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

#if defined(HAVE_PTHREADS)#include <sys/resource.h>#endif#include <cutils/sched_policy.h>#include <binder/IServiceManager.h>#include <binder/IPCThreadState.h>#include <binder/ProcessState.h>#include <binder/IServiceManager.h>#include "SurfaceFlinger.h"using namespace android;int main(int, char**) {    // When SF is launched in its own process, limit the number of    // binder threads to 4.    ProcessState::self()->setThreadPoolMaxThreadCount(4);    // start the thread pool    sp<ProcessState> ps(ProcessState::self());    ps->startThreadPool();    // instantiate surfaceflinger    sp<SurfaceFlinger> flinger = new SurfaceFlinger();#if defined(HAVE_PTHREADS)    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);#endif    set_sched_policy(0, SP_FOREGROUND);    // initialize before clients can connect    flinger->init();//开机动画在这里执行,接着往下看    // publish surface flinger    sp<IServiceManager> sm(defaultServiceManager());    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);    // run in this thread    flinger->run();    return 0;}

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

void SurfaceFlinger::init() {    ALOGI(  "SurfaceFlinger's main thread ready to run. "            "Initializing graphics H/W...");    ....    // start boot animation    startBootAnim();}

接着执行startBootAnim();

void SurfaceFlinger::startBootAnim() {    // start boot animation    property_set("service.bootanim.exit", "0");    property_set("ctl.start", "bootanim");}

这里采用的是通过property_set中”ctl.start”的方式执行bootanim,这里是通过设置属性值的方式来启动的,属性值的设置采用的是C/S模式,socket连接,这里不详述,大致说下,这行代码会执行到

system/core/init/property_service.c

void handle_property_set_fd(){    ......    switch(msg.cmd) {    case PROP_MSG_SETPROP:        ......        //这里很关键        if(memcmp(msg.name,"ctl.",4) == 0) {            // Keep the old close-socket-early behavior when handling            // ctl.* properties.            close(s);            if (check_control_mac_perms(msg.value, source_ctx)) {                handle_control_message((char*) msg.name + 4, (char*) msg.value);            } else {                ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",                        msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);            }         //这里很关键        } else {            if (check_perms(msg.name, source_ctx)) {                property_set((char*) msg.name, (char*) msg.value);            } else {                ERROR("sys_prop: permission denied uid:%d  name:%s\n",                      cr.uid, msg.name);            }            // Note: bionic's property client code assumes that the            // property server will not close the socket until *AFTER*            // the property is written to memory.            close(s);        }        freecon(source_ctx);        break;    default:        close(s);        break;    }}

接下来执行到
system/core/init/init.c

void handle_control_message(const char *msg, const char *arg){    if (!strcmp(msg,"start")) {        msg_start(arg);//就是这条路    } else if (!strcmp(msg,"stop")) {        msg_stop(arg);    } else if (!strcmp(msg,"restart")) {        msg_restart(arg);    } else {        ERROR("unknown control msg '%s'\n", msg);    }}

接着往下执行->

static void msg_start(const char *name){    struct service *svc = NULL;    char *tmp = NULL;    char *args = NULL;    if (!strchr(name, ':'))        svc = service_find_by_name(name);    else {        tmp = strdup(name);        if (tmp) {            args = strchr(tmp, ':');            *args = '\0';            args++;            svc = service_find_by_name(tmp);        }    }    if (svc) {        service_start(svc, args);    } else {        ERROR("no such service '%s'\n", name);    }    if (tmp)        free(tmp);}

这里找到“bootanim”然后执行service_start函数,这里就是启动bootanim的地方。

1 0
原创粉丝点击