1.因为学习所以用的Android_8 的代码,很老。新的Android变了很多,所以不一定一样。
2.在bootanimation_main.cpp,这个文件里开始了开机动画,继续跟踪进取看看那里结束。
为什么在这个bootanimation_main.cpp里呢?而不是在BootAnimation里呢。查了一下发现算是一个Android的设计吧,在这个xxx_main.cpp里是入口,然后在main方法里,new一个BootAnimation来进行调用,入口和逻辑相互分离。
3.在bootanimation_main.cpp的main方法里呢,就是开机动画的调用地方了。
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
bool noBootAnimation = bootAnimationDisabled();
ALOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
waitForSurfaceFlinger();
// create the boot animation object
sp<BootAnimation> boot = new BootAnimdation(new AudioAnimationCallbacks());
ALOGV("Boot animation set up. Joining pool.");
IPCThreadState::self()->joinThreadPool();
}
ALOGV("Boot animation exit");
return 0;
第一个setpriority就是设置开机动画的进程优先级,设置为ANDROID_PRIORITY_DISPLAY也就是-4,是android显示级的UI。
第二个是个看看是不是需要跳过开机动画的判断
bool bootAnimationDisabled() {
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
if (atoi(value) > 0) {
return true;
}
property_get("ro.boot.quiescent", value, "0");
return atoi(value) > 0;
}
这第一个属性是一个debug的属性,设置为1就可以设置为不显示开机动画。
debug.sf.nobootanimation
第二个属性是ro.boot.quiescent,是一个静默启动的属性也是不显示开机动画。
接下来是一个
startThreadPool() 开启了Binder线程池,虽然对于binder还不是很了解。
然后等待surfaceflinger开启
开启后是是new 了一个BootAnimation,然后在这里作了很多操作。
- 探究BootAnimation的逻辑
这个BootAnimation继承了Thread,Thread又继承了Refbase,所以可以用智能指针sp那些东西。
然后这个地方,就重写了首次调用的逻辑,执行了线程的run方法。
void BootAnimation::onFirstRef() {
status_t err = mSession->linkToComposerDeath(this);
ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
if (err == NO_ERROR) {
run("BootAnimation", PRIORITY_DISPLAY);
}
}
再往下会执行ReadyToRun方法,其实注释上也有写创建了一个native surface相当于画布,然后初始化opengl,然后是加密动画相关的代码跳过了,然后判断这两个地方有没有文件
static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
如果有就把路径赋给mZipFIleName。
5.进入BootAniamtion threadloop, 如果mZipFIleName没有值就进入android自己的逻辑。
if (mZipFileName.isEmpty()) {
r = android();
} else {
r = movie();
}
靠近下方有一个do while循环开始绘制,然后在最后checkexit()判断一个属性
service.bootanim.exit
是否可以退出。
6.在那里设置了这个属性呢?
./base/services/core/java/com/android/server/wm/WindowManagerService.java:3509: SystemProperties.set("service.bootanim.exit", "1");
然后通过打堆栈的方法,发现是在FallbackHome的地方,这个FallbackHome呢就是显示系统正在启动中的那个界面。
还有另一个地方
./native/services/surfaceflinger/SurfaceFlinger.cpp:388: property_set("service.bootanim.exit", "1");
这个是在bootFInished调用了开机动画结束,然后grep一下发现这个bootFinished是在
./native/libs/gui/ISurfaceComposer.cpp:537: bootFinished();
其他地方也不怎么像。
这是一个switch case,在这里面调用了。
case BOOT_FINISHED: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
bootFinished();
return NO_ERROR;
}
然后这个值是
./native/libs/gui/include/gui/ISurfaceComposer.h:207: BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
然后再查那个 FIRST_CALL_TRANSACTION值。
wangliteng@wangliteng:~/Android_8/frameworks$ grep "FIRST_CALL_TRANSACTION" ./ -rn | grep surface
./base/services/core/java/com/android/server/wm/WindowManagerService.java:3524: surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
发现在WindowManagerService.java:3524,其实就是从第一个fallbackhome里上一个关闭开机动画的下面。
surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
data, null, 0);
好的,那就开机动画结束啦。