android 开机动画执行流程

android深入了解开机动画

开机动画的种类

1:View绘制
2:逐帧动画:比较主流的方式,一般动画的文件打包成 bootanimation.zip 存储到 /system/media/ 下。一般.zip文件 > 5M 就会有明显的卡顿,所以一般开机动画只有中间一块有图案,四周是黑色,这样可以采用更小分辨率的图片。
3:OpenGL:定义了跨平台语言,跨平台的应用接口API规范,用于生成二维、三维图像。

开机动画启动流程

内核启动之后启动的第一个进程就是 init 进程,init进程会根据 init.rc 的配置启动 surfaceflinger 进程,在/frameworks/native/services/surfaceflinger/ 下有 surfaceflinger.rc 如下:

1 service surfaceflinger /system/bin/surfaceflinger
2     class core animation
3     user system
4     group graphics drmrpc readproc
5     onrestart restart zygote
6     writepid /dev/stune/foreground/tasks

bootanim.rc 配置了 disabled ,因此在 init 进程解析时不会启动 bootanimation 进程。

1 service bootanim /system/bin/bootanimation
2     class core animation
3     user graphics
4     group graphics audio
5     disabled
6     oneshot
7     writepid /dev/stune/top-app/tasks
71  int main(int, char**) {
   
		// ..............
83      // start the thread pool
84      sp<ProcessState> ps(ProcessState::self());
85      ps->startThreadPool();
86  
87      // instantiate surfaceflinger 创建 SurfaceFlinger 实例
88      sp<SurfaceFlinger> flinger = new SurfaceFlinger();
89  
99      // 调用 flinger 的 init()
100      flinger->init();
101  
102      // publish surface flinger 将 flinger 服务添加到 ServiceManager 中。
103      sp<IServiceManager> sm(defaultServiceManager());
104      sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
105                     IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
106  
107      // publish GpuService
108      sp<GpuService> gpuservice = new GpuService();
109      sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
110 
119      // run surface flinger in this thread 执行了 run() 方法
120      flinger->run();
121  
122      return 0;
123  }

main_surfaceflinger.cpp 的 main 方法。,创建了 SurfaceFlinger 实例,并执行了其 init() 和 run() 方法。在 init() 函数中,有如下相关代码


637 void SurfaceFlinger::init() {
   
724    if (getHwComposer().hasCapability(
725            HWC2::Capability::PresentFenceIsNotReliable)) {
   
726        mStartPropertySetThread = new StartPropertySetThread(false);
727    } else {
   
728        mStartPropertySetThread = new StartPropertySetThread(true);
729    }
731    if (mStartPropertySetThread->Start() != NO_ERROR) {
   
732        ALOGE("Run StartPropertySetThread failed!");
733    }
739 } 

创建了一个 Thread 并且调用start() , 运行起来该线程以后看一看做了什么工作。接下来,看一下 StartPropertySetThread.cpp 的代码。

17#include <cutils/properties.h>
18#include "StartPropertySetThread.h"
19
20namespace android {
   
21
22StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):
23        Thread(false), mTimestampPropertyValue(timestampPropertyValue) {
   }
24
25status_t StartPropertySetThread::Start() {
   
26    return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
27}
28
29bool StartPropertySetThread::threadLoop() {
   
30    // Set property service.sf.present_timestamp, consumer need check its readiness
31    property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
32    // Clear BootAnimation exit flag  这个不是结束,就是设置初始状态
33    property_set("service.bootanim.exit", "0");
34    // Start BootAnimation if not started 开启 BootAnimation 进程
35    property_set("ctl.start", "bootanim");
36    // Exit immediately
37    return false;
38}
39
40} // namespace android
41

| property_set(“”, “”); 函数是Android框架中的一个函数,用于设置系统属性的值。系统属性是一种用于存储系统配置信息的键值对。property_set()函数的作用是将指定的属性名和属性值存储到系统属性中,并且进行后续动作和调整。

在之前提到的 /system/core/init/init.cpp 中,执行 main 函数有下面的代码

545 int main(int argc, char** argv) {
   

701    property_load_boot_defaults();
702    export_oem_lock_status();
703    start_property_service(); // 关键代码 启动监听 property 的服务
704    set_usb_controller();

790 }


start_property_service(); 调用的是 /system/core/init/property_service.cpp 下的 start_property_service () 函数如下:

840 void start_property_service() {
   
841    selinux_callback cb;
842    cb.func_audit = SelinuxAuditCallback;
843    selinux_set_callback(SELINUX_CB_AUDIT, cb);
844
845    property_set("ro.property_service.version", "2");
846	// 创建了 Socket 来进行跨进程通信。
847    property_set_fd = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
848                                   false, 0666, 0, 0, nullptr);
849    if (property_set_fd == -1) {
   
850        PLOG(FATAL) << "start_property_service socket creation failed";
851    }
852	// 监听 property_set_fd  这个 fd 
853    listen(property_set_fd, 8);
854	// 通过 epoll 机智,来监听 property_set_fd 是否有消息过来,如果有消息进来就会回调 handle_property_set_fd 方法。
855    register_epoll_handler(property_set_fd, handle_property_set_fd);
856 }
857
858 }

上面讲述了,监听到 property_set 以后,会调用到 handle_property_set_fd 方法,接下来看看,设置了 property_set(“ctl.start”, “bootanim”); 后执行流程是怎么样的。

481 static void handle_property_set_fd() {
   
482  
506
507    switch (cmd) {
   
508    case PROP_MSG_SETPROP: {
   
509        char prop_name[PROP_NAME_MAX];
510        char prop_value[PROP_VALUE_MAX];
521        const auto& cr = socket.cred();
522        std::string error;
 	  // 主要代码 
523        uint32_t result =
524            HandlePropertySet(prop_name, prop_value, socket.source_context(), cr, &error);
531        break;
532      }
533
534    case PROP_MSG_SETPROP2: {
   
535        std::string name;
536        std::string value;
546        uint32_t result = HandlePropertySet(name, value, socket.source_context(), cr, &error);
553        break;
554      }
555
556    default:
557        LOG(ERROR) << "sys_prop: invalid command " << cmd;
558        socket.SendUint32(PROP_ERROR_INVALID_CMD);
559        break;
560    }
561}

上述代码,调用时,我们是设置属性,最终会调用到 HandlePropertySet() 函数,


425// This returns one of the enum of PROP_SUCCESS or PROP_ERROR*.
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值