大家好,我是Zzz今天给大家继续分享android开机动画播放到结束的源码分析,还是主打一个干货分享,这个blog主要就是源代码的分析,环境基于aosp13_r6如有错误请指出立马改成。
前言:在开机启动过程init进程已经把bootanimation拉起来了,拉起来以后首先执行的是bootanimation_main.cpp的main方法
int main()
{
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);//设置进程的属性这里设置为DISPLAY
bool noBootAnimation = bootAnimationDisabled(); //开机动画是否被禁止,一般默认情况为true
ALOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();//启动线程池 ,用来初始化类似binder 跨进程通信的服务
// create the boot animation object (may take up to 200ms for 2MB zip)
//这里创建了一个bootanimation的实例,使用的智能指针回调到bootanimation.cpp的onFirstRef()
sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());
waitForSurfaceFlinger();//绘制
boot->run("BootAnimation", PRIORITY_DISPLAY);
ALOGV("Boot animation set up. Joining pool.");
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
new BootAnimation(audioplay::createAnimationCallbacks()); //这里创建了一个bootanimation的实例 代码路径在frameworks/base/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();//创建一个跨进程通信的client
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());
}
在 bootanimation_main.cpp的main方法中因为new Bootanimation 使用了智能指针所以会回调到Bootanimation.cpp的onFirstRef()方法
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()
bool BootAnimation::preloadAnimation() {
findBootAnimationFile();//找开机动画文件
if (!mZipFileName.isEmpty()) {//当找到文件时
mAnimation = loadAnimation(mZipFileName);//拿着文件去加载动画
return (mAnimation != nullptr);
}
return false;
}
配置开机动画
void BootAnimation::findBootAnimationFile() {
.......
const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1;
//开机动画文件 主要就是这两个文件路径 OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE
static const std::vector<std::string> bootFiles = {
APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,
OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE
};
static const std::vector<std::string> shutdownFiles = {
PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, ""
};
static const std::vector<std::string> userspaceRebootFiles = {
PRODUCT_USERSPACE_REBOOT_ANIMATION_FILE, OEM_USERSPACE_REBOOT_ANIMATION_FILE,
SYSTEM_USERSPACE_REBOOT_ANIMATION_FILE,
};
if (android::base::GetBoolProperty("sys.init.userspace_reboot.in_progress", false)) {
findBootAnimationFileInternal(userspaceRebootFiles);
} else if (mShuttingDown) {
findBootAnimationFileInternal(shutdownFiles);
} else {
findBootAnimationFileInternal(bootFiles);
}
}
加载开机动画
BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn) {
if (mLoadedFiles.indexOf(fn) >= 0) {
SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
fn.string());
return nullptr;
}
ZipFileRO *zip = ZipFileRO::open(fn);
if (zip == nullptr) {
SLOGE("Failed to open animation zip \"%s\": %s",
fn.string(), strerror(errno));
return nullptr;
}
ALOGD("%s is loaded successfully", fn.string());
Animation *animation = new Animation;
animation->fileName = fn;
animation->zip = zip;
animation->clockFont.map = nullptr;
mLoadedFiles.add(animation->fileName);
parseAnimationDesc(*animation);//解析zip的动画
if (!preloadZip(*animation)) {//预加载动画
releaseAnimation(animation);
return nullptr;
}
mLoadedFiles.remove(fn);
return animation;
}
然后执行到readyToRun,因为在Bootanimation_main.cpp中调用了run方法 而Bootanimation.cpp本身就是一个Thread,可以在Bootanimation.h头文件中看到
c++ run Thread之后会先调用readyToRun在执行到threadLoop
boot->run("BootAnimation", PRIORITY_DISPLAY);
readyToRun()主要就是绘制一些画布之类的
status_t BootAnimation::readyToRun() {
.......
// initialize opengl and egl
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, nullptr, nullptr);
EGLConfig config = getEglConfig(display);
EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
// Initialize egl context with client version number 2.0.
EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
EGLContext context = eglCreateContext(display, config, nullptr, contextAttributes);
EGLint w, h;
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
return NO_INIT;
mDisplay = display;
mContext = context;
mSurface = surface;
mInitWidth = mWidth = w;
mInitHeight = mHeight = h;
mFlingerSurfaceControl = control;
mFlingerSurface = s;
mTargetInset = -1;
........
return NO_ERROR;
}
在执行threadLoop() 方法
bool BootAnimation::threadLoop() {
bool result;
initShaders();
// We have no bootanimation file, so we use the stock android logo
// animation.
if (mZipFileName.isEmpty()) {//如果文件为空则使用OpenGL进行绘制反之使用zip
ALOGD("No animation file");
result = android();
} else {
result = movie();
}
mCallbacks->shutdown();
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
mFlingerSurface.clear();
mFlingerSurfaceControl.clear();
eglTerminate(mDisplay);
eglReleaseThread();
IPCThreadState::self()->stopProcess();
return result;
}
这里我们看android()开机动画绘制,这里使用OpenGL
bool BootAnimation::android() {
glActiveTexture(GL_TEXTURE0);
SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
elapsedRealtime());
initTexture(&mAndroid[0], mAssets, "images/android-logo-mask.png");
initTexture(&mAndroid[1], mAssets, "images/android-logo-shine.png");
......
do {
processDisplayEvents();
......
glDisable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[1].name);
drawTexturedQuad(x, yc, mAndroid[1].w, mAndroid[1].h);
drawTexturedQuad(x + mAndroid[1].w, yc, mAndroid[1].w, mAndroid[1].h);
glEnable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
drawTexturedQuad(xc, yc, mAndroid[0].w, mAndroid[0].h);
.....
checkExit();//这里是动画结束退出
} while (!exitPending());
glDeleteTextures(1, &mAndroid[0].name);
glDeleteTextures(1, &mAndroid[1].name);
return false;
}
执行这个方法请求退出checkExit()
void BootAnimation::checkExit() {
// Allow surface flinger to gracefully request shutdown
char value[PROPERTY_VALUE_MAX];
property_get(EXIT_PROP_NAME, value, "0");//设置退出属性 service.bootanim.exit
int exitnow = atoi(value);
if (exitnow) {
requestExit();
}
}
当执行完checkExit()后设置了退出属性,那么是谁执行退出呢?可以在代码中搜索一下在frameworks目录下执行grep "service.bootanim.exit"
property_set("service.bootanim.exit", "1"); 为1的时候是退出 0的时候启动
在这里我们发现了两处一个是WindowManagerService.java:3700: 另外一个是SurfaceFlinger.cpp:664: 也就是说在android系统中会有两处执行退出开机动画操作
./frameworks/base/core/proto/android/os/system_properties.proto:521: optional int32 service_bootanim_exit = 23;
./frameworks/base/cmds/bootanimation/BootAnimation.cpp:105:static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
./frameworks/base/cmds/bootanimation/FORMAT.md:121:the system property `service.bootanim.exit` to a nonzero string.)
./frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java:3700: SystemProperties.set("service.bootanim.exit", "1");
./frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp:33: property_set("service.bootanim.exit", "0");
./frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:664: property_set("service.bootanim.exit", "1");
最后我们看zip动画播放
bool BootAnimation::movie() {
if (mAnimation == nullptr) {
mAnimation = loadAnimation(mZipFileName);//这里加载开机动画
}
if (mAnimation == nullptr)
return false;
.....
// Check if npot textures are supported
mUseNpotTextures = false;
String8 gl_extensions;
......
playAnimation(*mAnimation);//这个播放动画方法,播放完成后会调用的checkExit()方法进行退出
if (mTimeCheckThread != nullptr) {
mTimeCheckThread->requestExit();
mTimeCheckThread = nullptr;
}
....
releaseAnimation(mAnimation);
mAnimation = nullptr;
return false;
}
看到最后,aosp13开机动画的播放就介绍完成了。谢谢大家