BootAnimation流程
bootanimation源码位于frameworks/base/cmds/bootanimation,正如其名,主要功能是加载播放开机动画,是一个C程序,编译生成的可执行文件位于/system/bin
主要逻辑:解析系统路径下的bootanimation.zip(如/system/media/bootanimation.zip),然后通过openGl方式绘制显示出来
代码目录结构如下:
- Android.bp编译脚本,编译成可执行文件
- bootanimation_main.cpp:程序入口,启动BootAnimation线程
- BootAnimation.cpp:具体的业务逻辑,
- bootanim.rc:rc脚本,配置bootanimation为系统服务
bootanimation/
├── Android.bp
├── audioplay.cpp
├── AudioPlayer.cpp
├── AudioPlayer.h
├── audioplay.h
├── BootAnimation.cpp
├── BootAnimation.h
├── bootanimation_main.cpp
├── BootAnimationUtil.cpp
├── BootAnimationUtil.h
├── bootanim.rc
├── FORMAT.md
└── OWNERS
启动BootAnimation线程
入口main函数中创建了BootAnimation对象,实际上BootAnimation是一个线程,通过run方法启动了这个线程。
Android Native Thread启动后会回调readyToRun()–>threadLoop(),IPCThreadState这个是Android模板写法,可以网上了解下。
// frameworks\base\cmds\bootanimation\BootAnimation.cpp
int 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();
// create the boot animation object (may take up to 200ms for 2MB zip)
sp<BootAnimation> boot = new BootAnimation();
waitForSurfaceFlinger();
boot->run("BootAnimation", PRIORITY_DISPLAY);
ALOGV("Boot animation set up. Joining pool.");
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
接下来,我们看BootAnimation构造方法中做了什么。构造方法中就创建了一个SurfaceComposerClient,先跳过
// frameworks\base\cmds\bootanimation\BootAnimation.cpp
BootAnimation::BootAnimation(sp<Callbacks> callbacks)
: Thread(false), mLooper(new Looper(false)), mClockEnabled(true), mTimeIsAccurate(false),
mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
mSession = new SurfaceComposerClient();
std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
if (powerCtl.empty()) {
mShuttingDown = false;
} else {
mShuttingDown = true;
}
ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
elapsedRealtime());
}
构造方法走完后,会接着后走onFirstRef(),这里做了预加载开机动画资源,为什么叫预加载呢?
在上面main()可以看到会先等SurfaceFlinger起来才会跑BootAnimation线程,不然SurfaceFlinger没起来,UI界面绘制不出来了
// frameworks\base\cmds\bootanimation\BootAnimation.cpp
void BootAnimation::onFirstRef() {
status_t err = mSession->linkToComposerDeath(this);
SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
if (err == NO_ERROR) {
// Load the animation content -- this can be slow (eg 200ms)
// called before waitForSurfaceFlinger() in main() to avoid wait
ALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms",
mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
preloadAnimation();
ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms",
mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
}
}
加载解析资源
preloadAnimation()做了两件事情,先是找到系统中bootanimation.zip开机动画资源,然后在解析成Animation对象。
// frameworks\base\cmds\bootanimation\BootAnimation.cpp
bool BootAnimation::preloadAnimation() {
findBootAnimationFile();
if (!mZipFileName.isEmpty()) {
mAnimation = loadAnimation(mZipFileName);
return (mAnimation != nullptr);
}
return false;
}
findBootAnimationFile()从系统/system/media或者/oem/media等几个位置找bootanimation.zip,如果文件存在就找到了该位置的开机动画资源
loadAnimation()会对bootanimation.zip中文件信息进行解析,转换为Animation对象。
绘制界面播放资源
BootAnimation()线程跑起来后,在readyToRun()方法中会准备Surface和OpenGl,在threadLoop()会创建Shader,然后调用movie()进行绘制
// frameworks\base\cmds\bootanimation\BootAnimation.cpp
bool BootAnimation::threadLoop() {
bool result;
initShaders();
// We have no bootanimation file, so we use the stock android logo
// animation.
if (mZipFileName.isEmpty()) {
ALOGD("No animation file");
result = android();
} else {
result = movie();
}
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
mFlingerSurface.clear();
mFlingerSurfaceControl.clear();
eglTerminate(mDisplay);
eglReleaseThread();
return result;
}
总结
至此,BootAnimation的大体流程介绍完成了,具体细节大家可以去看具体代码。流程图如下:
如果应用需要替换开机动画资源,可以把开机动画资源写入到一个分区,然后在BootAnimation程序里面新增一个查找路径。