马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
android深入相识开机动画
开机动画的种类
- 1:View绘制
- 2:逐帧动画:比较主流的方式,一般动画的文件打包成 bootanimation.zip 存储到 /system/media/ 下。一般.zip文件 > 5M 就会有明显的卡顿,所以一般开机动画只有中间一块有图案,四周是黑色,这样可以采用更小分辨率的图片。
- 3:OpenGL:定义了跨平台语言,跨平台的应用接口API规范,用于生成二维、三维图像。
复制代码 开机动画启动流程
- 代码路径先容
- bootanimation: /frameworks/base/cmds/bootanimation/
- surfaceflinger: /frameworks/native/services/surfaceflinger/
- init: /system/core/init/
内核启动之后启动的第一个进程就是 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
复制代码
- surfaceflinger 进程启动以后,实行了 main_surfaceflinger.cpp 的 main 方法。
- 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() 函数,
[code][/code] |