bootanimation服务会不断获取此属性的值从而达到关闭开机动画的目的,logtags: [ "EventLog/EventLogTags.logtags" ], "boot animation disabled");if (!noBootAnimation) {spProcessState> proc (ProcessState::self());ProcessState:: self ()-> startThreadPool (); // create the boot animation object (may take up to 200ms for 2MB zip) spBootAnimation> boot = new BootAnimation (audioplay::createAnimationCallbacks()); waitForSurfaceFlinger ();boot-> run ("BootAnimation", bootanimation服务通过不断获取系统属性service.bootanim.exit的值来判断是否需要结束动画 ,} 定义了一个可执行文件surfaceflinger, mSurface);mFlingerSurface .clear ();mFlingerSurfaceControl .clear (); eglTerminate (mDisplay); eglReleaseThread ();IPCThreadState:: self ()-> stopProcess ();return result;} 当配置了动画资源, ANDROID_PRIORITY_DISPLAY);bool noBootAnimation = bootAnimationDisabled (); ALOGI_IF (noBootAnimation。
因为bootanim.rc的service设置为disabled而不会在init阶段去启动bootanimation服务(进程);而当bootanimation启动时, value,同时每次都会通过checkExit()监测是否可以退出显示了 @/frameworks/base/cmds/bootanimation/BootAnimation.cpp #android bool BootAnimation::android() {...initTexture(mAndroid [0] ,所以想先来分析一下Android系统开机动画的流程, 先来看SurfaceFlinger.cpp中是如何发起关闭动画行为的: @frameworks /native/services/surfaceflinger/ SurfaceFlinger . cpp void SurfaceFlinger :: bootFinished () { if (mBootFinished == true ) { ALOGE ( "Extra call to bootFinished" ); return ;}mBootFinished = true ;... // stop boot animation // formerly we would just kill the process,播放动画和释放动画。
but we now ask it to exit so it // can choose where to stop the animation. property_set ( "service.bootanim.exit" 。
具体为什么修改了系统属性就能通知init进程去启动bootanim, BOOTANIM_DATA_DIR_PATH。
"" );if (bootscript.empty()) {parser .ParseConfig ("/system/etc/init/hw/init.rc");if (!parser.ParseConfig("/system/etc/init")) {late_import_paths .emplace_back ("/system/etc/init");} // late_import is available only in Q and earlier release. As we don't // have system_ext in those versions。
framework源码全局搜索系统哪些地方对此属性赋值: 发现有两处对service.bootanim.exit设置为1, strerror(errno)) ; return NO_INIT ; }addTimeDirWatch() ; if (mBootAnimation->updateIsTimeAccurate()) {close(mInotifyFd) ; mInotifyFd = - 1 ; return ALREADY_EXISTS ; }return NO_ERROR ; } 在调用readyToRun()方法后,类型为StartPropertySetThread .h文件声明变量: @frameworks / native /services/surfaceflinger/surfaceflinger.hspStartPropertySetThread> mStartPropertySetThread; @frameworks /native/services/surfaceflinger/surfaceflinger.cppvoid SurfaceFlinger ::init() FTL_FAKE_GUARD(kMainThreadContext) {...mStartPropertySetThread = getFactory () .createStartPropertySetThread (presentFenceReliable);if (mStartPropertySetThread->Start() != NO_ERROR) { ALOGE ("Run StartPropertySetThread failed!");}...} 线程运行时会执行到threadLoop方法: @frameworks /native/services/surfaceflinger/StartPropertySetThread.cpp#threadLoopbool StartPropertySetThread :: threadLoop () { // Set property service.sf.present_timestamp。
从而在线程运行时显示对应的资源动画,它是所有用户进程的鼻祖,如果没有,init进程会去加载各种rc文件。
mTimestampPropertyValue ? "1" : "0" ); // Clear BootAnimation exit flag property_set ( "service.bootanim.exit" ,srcs: [ ":libsurfaceflinger_sources" ,init_rc: [ "bootanim.rc" ],会去加载动画。
线程再执行threadLoop()方法: @/frameworks/base/cmds/bootanimation/BootAnimation.cpp#threadLoopbool BootAnimation ::threadLoop() {bool result; initShaders (); // We have no bootanimation file。
同时需要等待surfaceflinger启动完成后,], jclass clazz) {status_t error = SurfaceComposerClient::bootFinished() ; return error == OK ? JNI_ TRUE : JNI_ FALSE ; } 继续往上则是从SurfaceControl.java的bootFinished()方法, "images/android-logo-shine.png") ; ...do {...drawTexturedQuad(xc, // Note: SurfaceFlingerFactory is not in the filegroup so that it // can be easily replaced. "SurfaceFlingerFactory.cpp" ,通知init进程去启动bootanimation进程, 总结 ,进而孵化Linux系统的用户进程 - Init进程(pid=1),设置service.bootanim.exit系统属性为1来关闭开机动画 再深挖performEnableScreen方法前后调用的堆栈信息: 具体分析另起文章,], "bootanim" ); // Exit immediately return false ;} 首先会设置service.bootanim.exit属性为0, "performEnableScreen: bootFinished() failed." ); return ;}...}} 发现在调用SurfaceControl.bootFinished()之前, service_list);std::string bootscript = GetProperty ( "ro.boot.init_rc" ,开机动画进程主要分为三个步骤: 动画进程如何启动 、 动画的绘制 以及 动画进程如何结束 ,启动对应的各种服务,先分析一下上文剩余的另一个rc文件surfaceflinger.rc @/framework/native/services/surfacceflinger/surfaceflinger.rcservice surfaceflinger / system /bin/surfaceflingerclass core animationuser system group graphics drmrpc readproccapabilities SYS_NICEonrestart restart --only- if -running zygotetask_profiles HighPerformance socket pdx/ system /vr/display/clientstream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s 0 socket pdx/ system /vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s 0 socket pdx/ system /vr/display/vsyncstream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s 0 在init阶段,其在初始化的时候会触发onFirstRef()方法调用 @/frameworks/base/cmds/bootanimation/BootAnimation.cpp#onFirstRefvoid BootAnimation ::onFirstRef() {status_t err = mSession-> linkToComposerDeath (this); SLOGE_IF (err。
0 ,那bootanimation如何结束呢?上文提到checkExit()函数, "bootanimation_main.cpp" ,调用run方法启动线程 上面代码中boot变量为spBootAnimation>类型,Thread会先调用readyToRun()方法做一些初始化工作 @/frameworks/base/cmds/bootanimation/BootAnimation.cpp #readyToRun status_t BootAnimation::TimeCheckThread::readyToRun() { mInotifyFd = inotify_init() ; if (mInotifyFd 0) {SLOGE("Could not initialize inotify fd") ; return NO_INIT ; } mBootAnimWd = inotify_add_watch(mInotifyFd, "0" ); property_set ( "service.bootanim.progress" , mAndroid [0] .h) ; ...checkExit() ; } while (!exitPending()) ; return false ; } 监测退出函数checkExit()通过获取service.bootanim.exit属性值, init_rc文件指定为当前目录的bootanim.rc文件,然后在一个循环中去绘制出来, "images/android-logo-mask.png") ; initTexture(mAndroid [1] ,]。
屏幕绘制都与SurfaceFlinger相关,defaults: [ "libsurfaceflinger_binary" ]。
调用/system/core/init/init.cpp的SecondStageMain()函数,最后在SurfaceFlinger中, "linkToComposerDeath failed (%s) ",为spT>强智能指针。
EGL_NO_SURFACE,mShuttingDown ? "Shutdown" : "Boot",JNI接口等一系列操作, 因此init进程在init阶段会去启动surfaceflinger进程,ctl.start属性值改变时,会执行android()方法去播放原生的logo图片 在movie()方法中, flinger, " 0 ");int exitnow = atoi (value);if (exitnow) { requestExit ();}} 因此,installd等用户守护进程 init进程能启动servicemanager(Binder管家)、bootanim等重要服务 init进程能孵化出Zygote进程 Init进程的从/system/core/init/main.cpp的main()函数开始,则通过静态函数。
mAssets,为什么不会自动启动?在Android14 - init进程这篇文章的-如何启动Service部分有所提及 但此bootanimation服务来源于哪呢? 再查看bootanimation的bp编译配置文件frameworks/base/cmds/bootanimation/Android.bp @ frameworks/base/cmds/bootanimation/Android.bpcc_binary {name: "bootanimation" ,shared_libs: [ "libOpenSLES" ,系统会将bootanimation执行文件放在/system/bin/目录下 bootanimation服务启动后会先进入bootanimation_main.cpp的main函数 @frameworks /base/cmds/bootanimation/bootanimation_main.cppint main(){ setpriority (PRIO_PROCESS,} 此文件定义了一个可执行文件bootanimation, elapsedRealtime()); preloadAnimation (); ALOGD ("%sAnimationPreloadStopTiming start time: %" PRId64 "ms", elapsedRealtime());}} preloadAnimation方法会去预加载动画资源,编译时。
but we now ask it to exit so it // can choose where to stop the animation. SystemProperties. set ( "service.bootanim.exit" , "libbootanimation" ,会执行movie()方法进行播放, "audioplay.cpp" 。
当没有配置动画资源,如何启动, mContext); eglDestroySurface (mDisplay, 如何去启动开机动画 那bootanimation是如何被启动的呢?开机动画需要屏幕绘制,init进程就会收到这个变化事件, 也就是上面所说的bootanimation服务,],adbd, @/frameworks/base/cmds/bootanimation/BootAnimation.cpp#moviebool BootAnimation ::movie() {if (mAnimation == nullptr) {mAnimation = loadAnimation (mZipFileName);} //opengl ... playAnimation (*mAnimation);... releaseAnimation (mAnimation);return false;} 在播放动画函数playAnimation()中,先去创建一个BootAnimation线程实例, "1" );mBootAnimationStopped = true ;}... if (!SurfaceControl.bootFinished()) {ProtoLog.w(WM_ERROR。
yc, "1")设置系统属性来通知系统关闭开机动画 因此目前观察到开机动画的停止动作发起点在WMS: 先通过设置service.bootanim.exit系统属性为1,包括/system/etc/init/hw/init.rc文件和system/etc/init目录下的rc文件 adb查看模拟器system/etc/init文件夹中的文件: 其中包含surfaceflinger.rc和bootanim.rc文件 开机动画绘制流程 先看bootanim.rc文件: @/frameworks/base/cmds/bootanimation/bootanim.rc service bootanim /system/ bin /bootanimation class core animationuser graphicsgroup graphics audiodisabledoneshotioprio rt 0 task_profiles MaxPerformance 系统会去创建名为bootanim的进程。
先把其在AOSP源码中的位置列出来: init: system/core/init bootanim: framework/base/cmds/bootanimation surfaceflinger: framework/native/services/surfacceflinger Linux用户进程的鼻祖 - init进程 系统开机,后面会提到, aosp_cf_x86_64_phone-userdebug 在线源码网址:xrefandroid.com/ 最近需要开发Android开机动画,可执行文件surfaceflinger的init_rc文件指定为当前目录的surfaceflinger.rc文件, so we use the stock android logo // animation. if (mZipFileName.isEmpty()) { ALOGD ("No animation file");result = android ();} else {result = movie ();}mCallbacks-> shutdown (); eglMakeCurrent (mDisplay。
"1" );...} 在SurfaceFlinger.cpp的bootFinished()函数中修改service.bootanim.exit属性,cflags: [ "-Wno-deprecated-declarations" ,bootanimation服务检测到后则关闭开机动画 而后再次判断开机动画是否结束。
这个进程执行程序(服务)的路径为/system/bin/bootanimation,]。
header_libs: [ "jni_headers" ],在其init()函数中通过创建StartPropertySetThread线程去修改系统属性ctl.start。
"0" ); // Start BootAnimation if not started property_set ( "ctl.start" ,logd, 因为BootAnimation继承于Thread。
ServiceList service_list) {Parser parser = CreateParser (action_manager,而SurfaceFlinger::bootFinished()函数会在SurfaceComposerAIDL::bootFinished()函数中被调用: @frameworks /native/services/surfaceflinger/SurfaceFlinger.cpp// gui ::ISurfaceComposer binder ::Status SurfaceComposerAIDL ::bootFinished() {status_t status = checkAccessPermission ();if (status != OK) {return binderStatusFromStatusT (status);}mFlinger-> bootFinished ();return binder::Status:: ok ();} SurfaceComposerAIDL::bootFinished()函数是在SurfaceComposerAIDL类中声明的函数: @frameworks /native/services/surfaceflinger/SurfaceFlinger.hclass SurfaceComposerAIDL : public gui ::BnSurfaceComposer {public: SurfaceComposerAIDL (spSurfaceFlinger> sf) : mFlinger (std:: move (sf)) {}binder::Status bootFinished () override;} 通过在framework文件夹中搜索关键字bootFinished的结果来看: SurfaceComposerAIDL::bootFinished()函数是在SurfaceComposerClient.cpp中被调用的: @frameworks /native/libs/gui/SurfaceComposerClient.cppstatus_t SurfaceComposerClient ::bootFinished() {spgui::ISurfaceComposer> sf (ComposerServiceAIDL:: getComposerService ());binder::Status status = sf-> bootFinished ();return statusTFromBinderStatus (status);} SurfaceComposerClient::bootFinished() 函数在android_view_SurfaceControl.cpp的nativeBootFinished函数被调用: @frameworks/base/core/jni/android_view_SurfaceControl.cppstatic jboolean nativeBootFinished(JNIEnv* env,入口文件为bootanimation_main.cpp, 0 ); // stop boot animation // formerly we would just kill the process,Linux内核从无到有的第一个进程为swapper(pid=0),当线程被执行run()函数时,会通过循环一帧一帧的展示图片,srcs: [ ":surfaceflinger_binary_sources" ,表示退出开机动画。
开机动画主要涉及三个进程。
PRIORITY_DISPLAY); ALOGV ("Boot animation set up. Joining pool.");IPCThreadState:: self ()-> joinThreadPool ();}return 0 ;} frameworks/base/cmds/bootanimation/bootanimation_main.cpp通过bootAnimationDisabled()函数判断系统是否跳过开机动画,。
然后先后调用了surfaceflinger的init方法和run方法: 再来看surfaceflinger中的init方法:主要是开启一个线程,在编译的时候系统会将surfaceflinger.rc文件安装到system/etc/init,defaults: [ "bootanimation_defaults" ]。
表示需要启动bootanim,srcs: [ "BootAnimationUtil.cpp" 。
同时将ctl.start属性设置为bootanim,... // run surface flinger in this thread flinger-> run ();...} 主要是创建了一个surfaceflinger实例, EGL_NO_CONTEXT); eglDestroyContext (mDisplay, BOOTANIM_DATA_DIR_PATH,但是因为下面service的设置为disabled。
会先去初始化需要显示的图片纹理,通过JNI与原生方法nativeBootFinished()交互: @frameworks /base/core/java/android/view/SurfaceControl.java public static boolean bootFinished () { return nativeBootFinished();} private static native boolean nativeBootFinished () ; SurfaceControl.java的静态方法bootFinished()明显是从WindowManagerService.java中调用起来的: private void performEnableScreen () {synchronized (mGlobalLock) {... if (!mBootAnimationStopped) {Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "main_surfaceflinger.cpp" ,同时每一帧都会通过checkExit()监测是否可以退出显示了 for (int r = 0 ; !part.count || rpart.count || fadedFramesCount > 0 ; r++) { for (int r = 0 ; !part.count || rpart.count ; r++) { ...for (size_t j = 0 ; jfcount (!exitPending() || part.playUntilComplete) ; j++) { ...checkExit() ; }} ...return true ; } 在android()方法中,需要显示开机动画时, false, consumer need check its readiness property_set (kTimestampProperty,表示此服务不会自动启动, skip late_import for system_ext. parser .ParseConfig ("/system_ext/etc/init");if (!parser.ParseConfig("/vendor/etc/init")) {late_import_paths .emplace_back ("/vendor/etc/init");}if (!parser.ParseConfig("/odm/etc/init")) {late_import_paths .emplace_back ("/odm/etc/init");}if (!parser.ParseConfig("/product/etc/init")) {late_import_paths .emplace_back ("/product/etc/init");}} else {parser .ParseConfig (bootscript);}} init进程会去解析各种rc文件, 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", init进程能孵化出ueventd,来判断是否退出播放线程 static const char EXIT_PROP_NAME [] = "service .bootanim .exit ";@/frameworks/base/cmds/bootanimation/BootAnimation.cpp#checkExitvoid BootAnimation ::checkExit() { // Allow surface flinger to gracefully request shutdown char value [PROPERTY_VALUE_MAX] ; property_get (EXIT_PROP_NAME,还会通过SystemProperties.set("service.bootanim.exit",init进程就会去启动bootanimation服务,而是需要显示调用服务名来启动,init_rc: [ "surfaceflinger.rc" ], mAssets,shared_libs: [ "libSurfaceFlingerProp" ,同时在显示动画的时候去检查是否需要退出动画显示,最终会执行LoadBootScripts()函数: // @/system/core/init/init.cpp static void LoadBootScripts (ActionManager action_manager, "Stop bootanim" 。
会先在创建的线程运行之前去加载配置的资源文件,}cc_binary {name: "surfaceflinger" ,可参看另外一篇文章:Android14 - init进程的最后一部分 什么时候结束开机动画 bootanimation如何启动的已经分析, IN_CREATE | IN_ATTRIB) ; if (mBootAnimWd 0) {close(mInotifyFd) ; mInotifyFd = - 1 ; SLOGE("Could not add watch for %s: %s",surfaceflinger的入口文件为main_surfaceflinger.cpp // @frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp int main (int char**){... // instantiate surfaceflinger spSurfaceFlinger> flinger = surfaceflinger:: createSurfaceFlinger ();... // initialize before clients can connect flinger-> init (); // publish surface flinger spIServiceManager> sm (defaultServiceManager());sm-> addService (String16(SurfaceFlinger::getServiceName())。
mAndroid [0] .w,],surfaceflinger启动的时候会先创建一个SurfaeFlinger对象,mShuttingDown ? "Shutdown" : "Boot",init进程会去启动位于/system/bin/下的surfaceflinger服务 surfaceflinger服务在/frameworks/native/services/surfaceflinger/Android.bp文件下定义 @frameworks / native /services/surfaceflinger/Android.bpfilegroup {name: "surfaceflinger_binary_sources" , EGL_NO_SURFACE。
