参考链接:http://www.mamicode.com/info-detail-399016.html
1.启动surfaceflinger
service surfaceflinger /system/bin/surfaceflinger
class core
user system
group graphics drmrpc
onrestart restart zygote
// 根据UTC信息,可大致计算启动surfaceflinger的时间是:2016-06-05 21:14:15.231112
2.surfaceflinger启动bootanimation
在它的init方法中通过ctl.start的方式启动bootanim。
void SurfaceFlinger::startBootAnim() {
// start boot animation
property_set("service.bootanim.exit", "0");
property_set("ctl.start", "bootanim");
}
log信息:
// SurfaceFlinger started
06-05 13:14:15.917427 206 206 I SurfaceFlinger: SurfaceFlinger is starting
06-05 13:14:15.917584 206 206 I SurfaceFlinger: SurfaceFlinger's main thread ready to run. Initializing graphics H/W...
// init start bootanimation
<14>[ 5.865806] (2)[1:init]init: [PropSet]: pid:206 uid:1000 gid:1003 set service.bootanim.exit=0
<14>[ 5.865817] (2)[1:init]init: PropSet [service.bootanim.exit:0] Start>>
<14>[ 5.865895] (2)[1:init]init: PropSet [service.bootanim.exit:0] Done
<14>[ 5.866460] (2)[1:init]init: [PropSet]: pid:206 uid:1000 gid:1003 ctl.start bootanim
<14>[ 5.866605] (2)[1:init]init: computing context for service '/system/bin/bootanimation'
<13>[ 5.866724] (2)[1:init]init: starting 'bootanim'
<7>[ 5.866838] (2)[1:init][1:init] fork [619:init]
<14>[ 5.866903] (2)[1:init]init: PropSet [init.svc.bootanim:running] Start>>
<14>[ 5.866982] (2)[1:init]init: PropSet [init.svc.bootanim:running] Done
// bootanimation started
06-05 13:14:16.605907 206 206 I SurfaceFlinger: [void android::SurfaceFlinger::checkEnableBootAnim()] boot reason = '0'
06-05 13:14:16.607570 206 206 I boot : BOOTPROF:BootAnimation:Start:5842
06-05 13:14:16.723475 619 619 D BootAnimation: [BootAnimation frameworks/base/cmds/bootanimation/bootanimation_main.cpp main 41]start Jan 19 2015 12:00:29
3. bootanimation何时退出
bootanimation进入循环播放动画过程,但每次循环都会去检查是否需要退出。
也就是退出的方式是service.bootanim.exit这个系统属性被set为非0
#define EXIT_PROP_NAME "service.bootanim.exit"
void BootAnimation::checkExit() {
// Allow surface flinger to gracefully request shutdown
char value[PROPERTY_VALUE_MAX];
property_get(EXIT_PROP_NAME, value, "0");
int exitnow = atoi(value);
if (exitnow) {
requestExit();
}
}
// Threads.cpp
void Thread::requestExit()
{
Mutex::Autolock _l(mLock);
mExitPending = true;
}
bool Thread::exitPending() const
{
Mutex::Autolock _l(mLock);
return mExitPending;
}
log信息:
// 从pid为206可以看到,还是surfaceflinger来关闭bootanim的
// 2016-06-05 21:14:33.204018
<14>[ 22.473645] (0)[1:init]init: [PropSet]: pid:206 uid:1000 gid:1003 set service.bootanim.exit=1
<14>[ 22.473663] (0)[1:init]init: PropSet [service.bootanim.exit:1] Start>>
<14>[ 22.473756] (0)[1:init]init: PropSet [service.bootanim.exit:1] Done
<4>[ 22.474564] (2)[433:Binder_2]BOOTPROF: 22474.555539:BOOT_Animation:END
<4>[ 20.804432][thread:130][RT:20794464385] 2016-06-05 13:14:31.534805 UTC; android time 2016-06-05 21:14:31.534805
4.谁触发surfaceflinger关闭bootanim?
是WMS通过IPC调用surfaceflinger的bootFinished()方法关闭bootanim。
//WindowManagerService.java
public void performEnableScreen() {
... ...
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
if (surfaceFlinger != null) {
Parcel data = Parcel.obtain();
data.writeInterfaceToken("android.ui.ISurfaceComposer");
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
data, null, 0);
data.recycle();
}
mActivityManager.bootAnimationComplete();
... ...
}
//06-05 21:14:33.213177 206 433 I SurfaceFlinger: Boot is finished (17295 ms)
void SurfaceFlinger::bootFinished()
{
const nsecs_t now = systemTime();
const nsecs_t duration = now - mBootTime;
ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
property_set("service.bootanim.exit", "1");
}
// ActivityThread.java
private class Idler implements MessageQueue.IdleHandler {
public final boolean queueIdle() {
IActivityManager am = ActivityManagerNative.getDefault();
am.activityIdle(a.token, a.createdConfig, stopProfiling);
}
}
mStackSupervisor.activityIdleInternalLocked(token, false, config);
mService.postFinishBooting(booting, enableScreen);
enableScreenAfterBoot()
mWindowManager.enableScreenAfterBoot();
performEnableScreen();
// ActivityThread.java
handleResumeActivity
Looper.myQueue().addIdleHandler(new Idler());
// MessageQueue.java
next()
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.