Android Framework实战视频--BootAnimation的启动源码分析(Android8.1)
课程答疑和新课信息:QQ交流群:422901085进行课程讨论
FrameWork入门课视频链接:https://edu.csdn.net/course/detail/30298
FrameWork实战课1视频链接:https://edu.csdn.net/course/detail/30275
专题博客系列:
Android 8.1 zygote 启动过程源码
Android Framework实战视频–Zygote的fork进程篇
Android Framework实战视频–SystemServer启动篇
Android Framework实战视频–SystemServer启动FallbackHome篇
Android Framework实战视频–FallbackHome进程启动及Activity启动篇
Android Framework实战视频–FallbackHome结束启动Launcher篇
Android Framework实战视频–BootAnimation的启动源码分析(Android8.1)
Android Framework实战视频–init进程的bootanimation启动源码分析(补充Android 10部分的BootAnimation的启动源码分析)
Android Framework实战视频–BootAnimation的启动源码分析
提示:代码基于Android 8.1
代码路径介绍哦:
bootanimation frameworks/base/cmds/bootanimation/
surfaceflinger frameworks/native/services/surfaceflinger/
init system/core/init/
启动流程详细分析:
内核起来后会启动第一个进程,即init进程。
init进程会根据init.rc配置启动surfaceflinger进程。
service surfaceflinger /system/bin/surfaceflinger
class main
user system
group graphics drmrpc
onrestart restart zygote
surfaceflinger进程便启动了,跟着就会跑进程的main()函数。
frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
int main(int argc, char** argv) {
....
// instantiate surfaceflinger
sp<SurfaceFlinger> flinger = new SurfaceFlinger();//创建surfaceflinger服务实例
....
flinger->init();
// publish surface flinger
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);//注册到service manager里
// run in this thread
flinger->run();//开跑
return 0;
}
首先new一个SurfaceFlinger实例,然后init,然后run
frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
// Do not call property_set on main thread which will be blocked by init
// Use StartPropertySetThread instead.
void SurfaceFlinger::init() {
ALOGI( "SurfaceFlinger’s main thread ready to run. "
“Initializing graphics H/W…”);
// Inform native graphics APIs whether the present timestamp is supported:
if (getHwComposer().hasCapability(
HWC2::Capability::PresentFenceIsNotReliable)) {
mStartPropertySetThread = new StartPropertySetThread(false);
} else {
mStartPropertySetThread = new StartPropertySetThread(true);
}
if (mStartPropertySetThread->Start() != NO_ERROR) { //真正启动设置bootanimation的属性线程
ALOGE("Run StartPropertySetThread failed!");
}
ALOGV("Done initializing");
}
初始化graphics之后,mStartPropertySetThread()播放开机动画。//注意已经不是以前的startBootAnim方法
StartPropertySetThread如下定义:
StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):
Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}
status_t StartPropertySetThread::Start() {
return run(“SurfaceFlinger::StartPropertySetThread”, PRIORITY_NORMAL);
}
bool StartPropertySetThread::threadLoop() {
// Set property service.sf.present_timestamp, consumer need check its readiness
property_set(kTimestampProperty, mTimestampPropertyValue ? “1” : “0”);
// Clear BootAnimation exit flag
property_set(“service.bootanim.exit”, “0”);//关键属性
// Start BootAnimation if not started
property_set(“ctl.start”, “bootanim”);//关键属性
// Exit immediately
return false;
}
这样bootanim进程就会启动?凭什么设置了一个属性就启动了?那么下面我们来看,/system/core/init/init.cpp ,在看init进程的init.cpp的main函数中:
int main(int argc, char** argv) {
…
property_load_boot_defaults();
export_oem_lock_status();
start_property_service(); //start_property_service
set_usb_controller();
}
下面来来看看start_property_service方法,在/system/core/init/property_service.cpp:
main函数中start_property_service(),在这个函数中注册一个epoll handle 的机制 register_epoll_handler():
666 void start_property_service() {
667 property_set("ro.property_service.version", "2");
668
669 property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
670 0666, 0, 0, NULL);
671 if (property_set_fd == -1) {
672 PLOG(ERROR) << "start_property_service socket creation failed";
673 exit(1);
674 }
675
676 listen(property_set_fd, 8);
677
678 register_epoll_handler(property_set_fd, handle_property_set_fd);
679 }
init进程会使用epoll机制来轮询事件,其中一个事件是系统属性值被修改。得到该事件后,会执行handle_property_set_fd(),代码如下:通过handle_property_set_fd():
static void handle_property_set_fd() {
…
switch (cmd) {
409 case PROP_MSG_SETPROP: {
410 char prop_name[PROP_NAME_MAX];
411 char prop_value[PROP_VALUE_MAX];
412
413 if (!socket.RecvChars(prop_name, PROP_NAME_MAX, &timeout_ms) ||
414 !socket.RecvChars(prop_value, PROP_VALUE_MAX, &timeout_ms)) {
415 PLOG(ERROR) << “sys_prop(PROP_MSG_SETPROP): error while reading name/value from the socket”;
416 return;
417 }
418
419 prop_name[PROP_NAME_MAX-1] = 0;
420 prop_value[PROP_VALUE_MAX-1] = 0;
421
422 handle_property_set(socket, prop_value, prop_value, true);
423 break;
424 }
该函数会进执行handle_property_set()
static void handle_property_set(SocketConnection& socket,
const std::string& name,
const std::string& value,
bool legacy_protocol) {
。。。。。。
handle_control_message(name.c_str() + 4, value.c_str());
。。。。。。
}
该函数会进一步执行handle_control_message(),在/system/core/init/init.cpp,传入的参数msg.name=ctl.start,msg.value=bootanim
179 void handle_control_message(const std::string& msg, const std::string& name) {
180 Service* svc = ServiceManager::GetInstance().FindServiceByName(name);
181 if (svc == nullptr) {
182 LOG(ERROR) << "no such service '" << name << "'";
183 return;
184 }
185
186 if (msg == "start") {
187 svc->Start();
188 } else if (msg == "stop") {
189 svc->Stop();
190 } else if (msg == "restart") {
191 svc->Restart();
192 } else {
193 LOG(ERROR) << "unknown control msg '" << msg << "'";
194 }
195 }
该函数首先调用FindServiceByName,从service_list中查询要启动的服务是否有存在,若存在,返回服务的相关信息。因为init.rc中有bootanimation的定义,因此在init进程执行parse_config()时,会将该服务添加到service_list中,所以bootanimation应用是存在的。然后,如果找到了该服务,就调用service_start启动服务。
把service.bootanim.exit属性设为0,这个属性bootanimation进程里会周期检查,=1时就退出动画,这里=0表示要播放动画。
后面通过ctl.start的命令启动bootanimation进程,动画就开始播放了。
下面来到bootanimation的实现
frameworks/base/cmds/bootanimation/bootanimation_main.cpp
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp<BootAnimation> boot = new BootAnimation();//创建BootAnimation实例
IPCThreadState::self()->joinThreadPool();//binder线程池,与surfaceflinger通信用的。
}
return 0;
}