开机动画位置:device\xxx\common\logo\bootanimation\bootanimation.zip
desc.txt用于描述动画如何显示
文件格式如下:
WIDTH HEIGHT FPS
//WIDTH 图片宽度(px)
//HEIGHT 图片高度(px)
//FPS:每秒帧数
TYPE COUNT PAUSE PATH
//TYPE:动画类型,p:如果系统启动完毕,会中断播放。默认;c:一直播放完毕,无论系统有没启动完毕
//COUNT:播放次数,0-无限循环
//PAUSE:本组播放完毕后,停留的帧数。
第一行的三个数字分别表示开机动画在屏幕中的显示宽度、高度以及帧速(fps)。
剩余的每一行都用来描述一个动画片断,这些行必须要以指定字符开头,后面紧跟着两个数字以及一个文件目录路径名称。第一个数字表示一个片断的循环显示次数,如果它的值等于0,那么就表示无限循环地显示该动画片断。第二个数字表示每一个片断在两次循环显示之间的时间间隔。这个时间间隔是以一个帧的时间为单位的。文件目录下面保存的是一系列png文件,这些png文件会被依次显示在屏幕中
动画的开始与结束是由属性控制的,由/system/bin/surfaceflinger来控制,然后相关的动画处理程序为/system/bin/bootanimation,在init.rc中指定。
bootanimation 需要 由property_set(“ctl.start”, “bootanim”);来启动进程,
由property_set(“ctl.stop”, “bootanim”);来关掉进程。
”service.bootanim.exit”:这个属性在bootanimation进程里会周期检查,=1时就退出动画,=0表示要播放动画。
开机动画是由应用程序bootanimation来负责显示的,先看一下其rc文件。
frameworks\base\cmds\bootanimation\bootanim.rc
- service bootanim /system/bin/bootanimation
- class core animation
- user graphics
- group graphics audio
- disabled //系统启动时,不会自动启动bootanimation
- oneshot //只启动一次
- ioprio rt 0
- task_profiles MaxPerformance
frameworks\native\services\surfaceflinger\surfaceflinger.rc
- service surfaceflinger /system/bin/surfaceflinger
- class core animation
- user system
- group graphics drmrpc readproc
- capabilities SYS_NICE
- onrestart restart zygote
- task_profiles HighPerformance
- socket pdx/system/vr/display/client stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
- socket pdx/system/vr/display/manager stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
- socket pdx/system/vr/display/vsync stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0
在高版本的Android上,如AndroidP,surfaceflinger进程并不是直接在init.rc文件中启动的,而是通过Android.bp文件去包含启动surfaceflinger.rc文件,然后在该文件中再去启动surfaceflinger:
frameworks\native\services\surfaceflinger\Android.bp
- cc_binary {
- name: "surfaceflinger",
- defaults: ["libsurfaceflinger_binary"],
- init_rc: ["surfaceflinger.rc"],
- srcs: [
- ":surfaceflinger_binary_sources",
- // Note: SurfaceFlingerFactory is not in the filegroup so that it
- // can be easily replaced.
- "SurfaceFlingerFactory.cpp",
- ],
- shared_libs: [
- "libSurfaceFlingerProp",
- ],
-
- logtags: ["EventLog/EventLogTags.logtags"],
- }
surfaceflinger启动了,就会跑到它的main函数:
SurfaceFlinger服务的入口在main_surfaceflinger.cpp中
frameworks\native\services\surfaceflinger\main_surfaceflinger.cpp
- int main(int, char**) {
- signal(SIGPIPE, SIG_IGN);
-
- hardware::configureRpcThreadpool(1 /* maxThreads */,
- false /* callerWillJoin */);
-
- startGraphicsAllocatorService();
-
- // When SF is launched in its own process, limit the number of
- // binder threads to 4.
- ProcessState::self()->setThreadPoolMaxThreadCount(4);
-
- // start the thread pool
- sp<ProcessState> ps(ProcessState::self());
- ps->startThreadPool();
-
- // instantiate surfaceflinger
- sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
-
- setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
-
- set_sched_policy(0, SP_FOREGROUND);
-
- // Put most SurfaceFlinger threads in the system-background cpuset
- // Keeps us from unnecessarily using big cores
- // Do this after the binder thread pool init
- if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
-
- // initialize before clients can connect
- flinger->init();
-
- // publish surface flinger
- sp<IServiceManager> sm(defaultServiceManager());
- sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
- IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
-
- startDisplayService(); // dependency on SF getting registered above
-
- if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
- ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
- }
-
- // run surface flinger in this thread
- flinger->run();
-
- return 0;
- }
frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
init方法中 start mStartPropertySetThread
- const bool presentFenceReliable =
- !getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE);
- mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);
-
- if (mStartPropertySetThread->Start() != NO_ERROR) {
- ALOGE("Run StartPropertySetThread failed!");
- }
-
- ALOGV("Done initializing");
frameworks\native\services\surfaceflinger\SurfaceFlingerDefaultFactory.cpp
- sp
DefaultFactory::createStartPropertySetThread( - bool timestampPropertyValue) {
- return new StartPropertySetThread(timestampPropertyValue);
- }
frameworks\native\services\surfaceflinger\StartPropertySetThread.cpp
- #include <cutils/properties.h>
- #include "StartPropertySetThread.h"
-
- namespace android {
-
- StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):
- Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}
-
- status_t StartPropertySetThread::Start() {
- return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
- }
-
- bool StartPropertySetThread::threadLoop() {
- // Set property service.sf.present_timestamp, consumer need check its readiness
- property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
- // Clear BootAnimation exit flag
- property_set("service.bootanim.exit", "0");
- // Start BootAnimation if not started
- property_set("ctl.start", "bootanim");
- // Exit immediately
- return false;
- }
-
- } /
这里设置属性【service.bootanim.exit】并采用【ctl.start】的方式启动开机动画:
在这之后,开机动画就会启动,由bootanimation进程实现具体动画播放
名称等于"bootanim"的服务所对应的应用程序为/system/bin/bootanimation,应用程序入口函数的实现在frameworks/base/cmds/bootanimation/bootanimation_main.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(audioplay::createAnimationCallbacks());
-
- waitForSurfaceFlinger();
-
- boot->run("BootAnimation", PRIORITY_DISPLAY);
-
- ALOGV("Boot animation set up. Joining pool.");
-
- IPCThreadState::self()->joinThreadPool();
- }
- return 0;
- }
首先检查系统属性“debug.sf.nobootnimaition”的值是否等于0。如果不等于的话,那么接下来就会启动一个Binder线程池,并且创建一个BootAnimation对象。这个Binder线程用于同SurfaceFlinger服务通信。
frameworks\base\cmds\bootanimation\BootAnimation.cpp
BootAnimation类间接地继承了RefBase类,并且重写了RefBase类的成员函数onFirstRef,因此,当一个BootAnimation对象第一次被智能指针引用的时,这个BootAnimation对象的成员函数onFirstRef就会被调用。其中几个重要的函数说明如下:
onFirstRef()—— 属于其父类RefBase,该函数在强引用sp新增引用计数時调用,就是当有sp包装的类初始化的时候调用;
binderDied() ——当对象死掉或者其他情况导致该Binder结束时,就会回调binderDied()方法;
readyToRun() ——Thread执行前的初始化工作;
threadLoop() ——每个线程类都要实现的,在这里定义thread的执行内容。这个函数如果返回true,且没有调用requestExit(),则该函数会再次执行;如果返回false,则threadloop中的内容仅仅执行一次,线程就会退出。
其他函数简述如下:android()——显示系统默认的开机画面;
movie()——显示用户自定义的开机动画;
loadAnimation(const String8&)——加载动画;
playAnimation(const Animation&)——播放动画;
checkExit()——检查是否退出动画;
- 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());
- }
- }
mSession是BootAnimation类的一个成员变量,它的类型为SurfaceComposerClient,是用来和SurfaceFlinger执行Binder进程间通信的,它是在BootAnimation类的构造函数中创建的
mSession = new SurfaceComposerClient();
由于BootAnimation类引用了SurfaceFlinger服务,因此,当SurfaceFlinger服务意外死亡时,BootAnimation类就需要得到通知,这是通过调用成员变量mSession的成员函数linkToComposerDeath来注册SurfaceFlinger服务的死亡接收通知来实现的。
BootAnimation类继承了Thread类,因此,当bootanimation_main.cpp调用了Thread的成员函数run之后,系统就会创建一个线程,这个线程在第一次运行之前,会调用BootAnimation类的成员函数readyToRun来执行一些初始化工作,后面再调用BootAnimation类的成员函数threadLoop来显示第三个开机画面。
- bool BootAnimation::threadLoop() {
- bool result;
- // We have no bootanimation file, so we use the stock android logo
- // animation.
- if (mZipFileName.isEmpty()) {
- 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;
- }
如果mZipFileName不为空,那么接下来就会调用BootAnimation类的成员函数android来显示系统默认的开机动画,否则的话,就会调用BootAnimation类的成员函数movie来显示用户自定义的开机动画
- bool BootAnimation::findBootAnimationFileInternal(const std::vector<std::string> &files) {
- for (const std::string& f : files) {
- if (access(f.c_str(), R_OK) == 0) {
- mZipFileName = f.c_str();
- return true;
- }
- }
- return false;
- }
init启动zygote进程之后,由zygote孵化出了system_server,然后system_server启动了各种各种的系统所需的服务,其中就有AMS,AMS启动并ready后,会执行startHomeActivityLocked:
- void SurfaceFlinger::bootFinished()
- {
- if (mBootFinished == true) {
- ALOGE("Extra call to bootFinished");
- return;
- }
- mBootFinished = true;
- if (mStartPropertySetThread->join() != NO_ERROR) {
- ALOGE("Join StartPropertySetThread failed!");
- }
- const nsecs_t now = systemTime();
- const nsecs_t duration = now - mBootTime;
- ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
-
- mFrameTracer->initialize();
- mTimeStats->onBootFinished();
-
- // wait patiently for the window manager death
- const String16 name("window");
- mWindowManager = defaultServiceManager()->getService(name);
- if (mWindowManager != 0) {
- mWindowManager->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
- }
-
- if (mVrFlinger) {
- mVrFlinger->OnBootFinished();
- }
-
- // 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", "1");
-
- const int LOGTAG_SF_STOP_BOOTANIM = 60110;
- LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
- ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
-
- sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger")));
-
- static_cast<void>(schedule([=] {
- if (input == nullptr) {
- ALOGE("Failed to link to input service");
- } else {
- mInputFlinger = interface_cast<IInputFlinger>(input);
- }
-
- readPersistentProperties();
- mPowerAdvisor.onBootFinished();
- mBootStage = BootStage::FINISHED;
-
- if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
- enableRefreshRateOverlay(true);
- }
- }));
- }
AMS在systemReady后会启动launcher
- if (bootingSystemUser) {
- t.traceBegin("startHomeOnAllDisplays");
- mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
- t.traceEnd();
- }
frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerInternal.java
public abstract boolean startHomeOnAllDisplays(int userId, String reason);
frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
- @Override
- public boolean startHomeOnAllDisplays(int userId, String reason) {
- synchronized (mGlobalLock) {
- return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
- }
- }
frameworks\base\services\core\java\com\android\server\wm\RootWindowContainer.java
- boolean startHomeOnAllDisplays(int userId, String reason) {
- boolean homeStarted = false;
- for (int i = getChildCount() - 1; i >= 0; i--) {
- final int displayId = getChildAt(i).mDisplayId;
- homeStarted |= startHomeOnDisplay(userId, reason, displayId);
- }
- return homeStarted;
- }
-
- void startHomeOnEmptyDisplays(String reason) {
- for (int i = getChildCount() - 1; i >= 0; i--) {
- final DisplayContent display = getChildAt(i);
- for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
- final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
- if (taskDisplayArea.topRunningActivity() == null) {
- startHomeOnTaskDisplayArea(mCurrentUser, reason, taskDisplayArea,
- false /* allowInstrumenting */, false /* fromHomeKey */);
- }
- }
- }
- }
-
- boolean startHomeOnDisplay(int userId, String reason, int displayId) {
- return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
- false /* fromHomeKey */);
- }
-
- boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
- boolean fromHomeKey) {
- // Fallback to top focused display or default display if the displayId is invalid.
- if (displayId == INVALID_DISPLAY) {
- final ActivityStack stack = getTopDisplayFocusedStack();
- displayId = stack != null ? stack.getDisplayId() : DEFAULT_DISPLAY;
- }
-
- final DisplayContent display = getDisplayContent(displayId);
- boolean result = false;
- for (int tcNdx = display.getTaskDisplayAreaCount() - 1; tcNdx >= 0; --tcNdx) {
- final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tcNdx);
- result |= startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
- allowInstrumenting, fromHomeKey);
- }
- return result;
- }
frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java
- void postFinishBooting(boolean finishBooting, boolean enableScreen) {
- mH.post(() -> {
- if (finishBooting) {
- mAmInternal.finishBooting();
- }
- if (enableScreen) {
- mInternal.enableScreenAfterBoot(isBooted());
- }
- });
- }
- @Override
- public void enableScreenAfterBoot(boolean booted) {
- synchronized (mGlobalLock) {
- writeBootProgressEnableScreen(SystemClock.uptimeMillis());
- mWindowManager.enableScreenAfterBoot();
- updateEventDispatchingLocked(booted);
- }
- }
frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
- public void enableScreenAfterBoot() {
- synchronized (mGlobalLock) {
- ProtoLog.i(WM_DEBUG_BOOT, "enableScreenAfterBoot: mDisplayEnabled=%b "
- + "mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. "
- + "%s",
- mDisplayEnabled, mForceDisplayEnabled, mShowingBootMessages, mSystemBooted,
- new RuntimeException("here").fillInStackTrace());
- if (mSystemBooted) {
- return;
- }
- mSystemBooted = true;
- hideBootMessagesLocked();
- // If the screen still doesn't come up after 30 seconds, give
- // up and turn it on.
- mH.sendEmptyMessageDelayed(H.BOOT_TIMEOUT, 30 * 1000);
- }
-
- mPolicy.systemBooted();
-
- performEnableScreen();
- }
enableScreenAfterBoot()经过多次调用就会执行WMS的performEnableScreen()方法,在此方法中我们就可以看到surfaceflinger的身影了,通过transact调用发送BOOT_FINISHED的消息给surfaceflinger。
- frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java
- private void performEnableScreen() {
- ...
-
- try {
- IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
- if (surfaceFlinger != null) {
- Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
- data, null, 0);
- data.recycle();
- }
- } catch (RemoteException ex) {
- Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
- }
- ...
- }
frameworks\native\libs\gui\include\gui\ISurfaceComposer.h
- class BnSurfaceComposer: public BnInterface<ISurfaceComposer> {
- public:
- enum ISurfaceComposerTag {
- // Note: BOOT_FINISHED must remain this value, it is called from
- // Java by ActivityManagerService.
- BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
WMS最终通过binder调用,经过ISurfaceComposer处理,最终通知SurfaceFlinger关闭开机动画。
- frameworks\native\services\surfaceflinger\SurfaceFlinger.cpp
- void SurfaceFlinger::bootFinished()
- {
- if (mStartPropertySetThread->join() != NO_ERROR) {
- ALOGE("Join StartPropertySetThread failed!");
- }
- const nsecs_t now = systemTime();
- const nsecs_t duration = now - mBootTime;
- ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
-
- // wait patiently for the window manager death
- const String16 name("window");
- sp<IBinder> window(defaultServiceManager()->getService(name));
- if (window != 0) {
- window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
- }
-
- if (mVrFlinger) {
- mVrFlinger->OnBootFinished();
- }
-
- // 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", "1");
-
- const int LOGTAG_SF_STOP_BOOTANIM = 60110;
- LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
- ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
-
- sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
- readPersistentProperties();
- });
- postMessageAsync(readProperties);
- }
至此开机动画结束。
frameworks\base\cmds\bootanimation\BootAnimation.cpp
- 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();
- }
- }
requestExit(); kill掉bootanime进程
system\core\libutils\Threads.cpp
- void Thread::requestExit()
- {
- Mutex::Autolock _l(mLock);
- mExitPending = true;
- }
至此bootanime进程死亡。