1.init.rc脚本中bootanim是disable的
2.启动界面依赖于android系统的surface管理服务,显示必须初始化完成
3.surfaceflinger服务完成后,才能显示开机界面
4.当system_server启动系统HomeUI的时候关闭bootanim
xref: /frameworks/base/cmds/bootanimation/bootanimation_main.cpp
36 int main()
37 {
38 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
39
40 bool noBootAnimation = bootAnimationDisabled();
41 ALOGI_IF(noBootAnimation, "boot animation disabled");
42 if (!noBootAnimation) {
43
44 sp<ProcessState> proc(ProcessState::self());
45 ProcessState::self()->startThreadPool();
46
47 // create the boot animation object (may take up to 200ms for 2MB zip)
48 sp<BootAnimation> boot = new BootAnimation(audioplay::createAnimationCallbacks());
49
50 waitForSurfaceFlinger();
51
52 boot->run("BootAnimation", PRIORITY_DISPLAY);
53
54 ALOGV("Boot animation set up. Joining pool.");
55
56 IPCThreadState::self()->joinThreadPool();
57 }
58 return 0;
59 }
开启线程池,创建BootAnimation对象,等待SurfaceFlinger的创建,然后执行run方法。
xref: /frameworks/base/cmds/bootanimation/BootAnimation.cpp
103
104 BootAnimation::BootAnimation(sp<Callbacks> callbacks)
105 : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
106 mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
107 mSession = new SurfaceComposerClient();
108
109 std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
110 if (powerCtl.empty()) {
111 mShuttingDown = false;
112 } else {
113 mShuttingDown = true;
114 }
115 ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
116 elapsedRealtime());
117 }
在BootAnimation构造方法中创建了SurfaceComposerClient对象,"sys.powerctl"用于获取开关机的属性。
128 void BootAnimation::onFirstRef() {
129 status_t err = mSession->linkToComposerDeath(this);
130 SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
131 if (err == NO_ERROR) {
132 // Load the animation content -- this can be slow (eg 200ms)
133 // called before waitForSurfaceFlinger() in main() to avoid wait
134 ALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms",
135 mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
136 preloadAnimation();
137 ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms",
138 mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
139 }
140 }
BootAnimation创建的时候使用了智能指针,所以会执行onFirstRef方法。
330 bool BootAnimation::preloadAnimation() {
331 findBootAnimationFile();
332 if (!mZipFileName.isEmpty()) {
333 mAnimation = loadAnimation(mZipFileName);
334 return (mAnimation != nullptr);
335 }
336
337 return false;
338 }
339
340 void BootAnimation::findBootAnimationFile() {
341 // If the device has encryption turned on or is in process
342 // of being encrypted we show the encrypted boot animation.
343 char decrypt[PROPERTY_VALUE_MAX];
344 property_get("vold.decrypt", decrypt, "");
345
346 bool encryptedAnimation = atoi(decrypt) != 0 ||
347 !strcmp("trigger_restart_min_framework", decrypt);
348
349 if (!mShuttingDown && encryptedAnimation) {
350 static const char* encryptedBootFiles[] =
351 {PRODUCT_ENCRYPTED_BOOTANIMATION_FILE, SYSTEM_ENCRYPTED_BOOTANIMATION_FILE};
352 for (const char* f : encryptedBootFiles) {
353 if (access(f, R_OK) == 0) {
354 mZipFileName = f;
355 return;
356 }
357 }
358 }
359
360 const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1;
361 static const char* bootFiles[] =
362 {APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,
363 OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
364 static const char* shutdownFiles[] =
365 {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, ""};
366
367 for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
368 if (access(f, R_OK) == 0) {
369 mZipFileName = f;
370 return;
371 }
372 }
373 }
1092 BootAnimation::Animation* BootAnimation::loadAnimation(const String8& fn)
1093 {
1094 if (mLoadedFiles.indexOf(fn) >= 0) {
1095 SLOGE("File \"%s\" is already loaded. Cyclic ref is not allowed",
1096 fn.string());
1097 return nullptr;
1098 }
1099 ZipFileRO *zip = ZipFileRO::open(fn);
1100 if (zip == nullptr) {
1101 SLOGE("Failed to open animation zip \"%s\": %s",
1102 fn.string(), strerror(errno));
1103 return nullptr;
1104 }
1105
1106 Animation *animation = new Animation;
1107 animation->fileName = fn;
1108 animation->zip = zip;
1109 animation->clockFont.map = nullptr;
1110 mLoadedFiles.add(animation->fileName);
1111
1112 parseAnimationDesc(*animation);
1113 if (!preloadZip(*animation)) {
1114 return nullptr;
1115 }
1116
1117
1118 mLoadedFiles.remove(fn);
1119 return animation;
1120 }
查找开机动画的文件,通过zip文件名去加载动画。
boot->run执行后会运行BootAnimation::::readyToRun方法。
270 status_t BootAnimation::readyToRun() {
271 mAssets.addDefaultAssets();
272
273 mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
274 if (mDisplayToken == nullptr)
275 return -1;
276
277 DisplayInfo dinfo;
278 status_t status = SurfaceComposerClient::getDisplayInfo(mDisplayToken, &dinfo);
279 if (status)
280 return -1;
281
282 // create the native surface
283 sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
284 dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
285
286 SurfaceComposerClient::Transaction t;
287 t.setLayer(control, 0x40000000)
288 .apply();
289
290 sp<Surface> s = control->getSurface();
291
292 // initialize opengl and egl
293 const EGLint attribs[] = {
294 EGL_RED_SIZE, 8,
295 EGL_GREEN_SIZE, 8,
296 EGL_BLUE_SIZE, 8,
297 EGL_DEPTH_SIZE, 0,
298 EGL_NONE
299 };
300 EGLint w, h;
301 EGLint numConfigs;
302 EGLConfig config;
303 EGLSurface surface;
304 EGLContext context;
305
306 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
307
308 eglInitialize(display, nullptr, nullptr);
309 eglChooseConfig(display, attribs, &config, 1, &numConfigs);
310 surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
311 context = eglCreateContext(display, config, nullptr, nullptr);
312 eglQuerySurface(display, surface, EGL_WIDTH, &w);
313 eglQuerySurface(display, surface, EGL_HEIGHT, &h);
314
315 if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
316 return NO_INIT;
317
318 mDisplay = display;
319 mContext = context;
320 mSurface = surface;
321 mWidth = w;
322 mHeight = h;
323 mFlingerSurfaceControl = control;
324 mFlingerSurface = s;
325 mTargetInset = -1;
326
327 return NO_ERROR;
328 }
通过SurfaceComposerClient拿到显示的层并且创建宽和高,然后做一些OpenGL相关的工作。
IPCThreadState::self()->joinThreadPool执行之后,执行BootAnimation::threadLoop方法。
375 bool BootAnimation::threadLoop()
376 {
377 bool r;
378 // We have no bootanimation file, so we use the stock android logo
379 // animation.
380 if (mZipFileName.isEmpty()) {
381 r = android();
382 } else {
383 r = movie();
384 }
385
386 eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
387 eglDestroyContext(mDisplay, mContext);
388 eglDestroySurface(mDisplay, mSurface);
389 mFlingerSurface.clear();
390 mFlingerSurfaceControl.clear();
391 eglTerminate(mDisplay);
392 eglReleaseThread();
393 IPCThreadState::self()->stopProcess();
394 return r;
395 }
如果mZipFileName为空则播放原生android动画,如果不是空则播放zip包里面的动画。使用OpenGL绘制动画。这里主要分析move方法。
832 bool BootAnimation::movie()
833 {
834 if (mAnimation == nullptr) {
835 mAnimation = loadAnimation(mZipFileName);
836 }
837
838 if (mAnimation == nullptr)
839 return false;
840
841 // mCallbacks->init() may get called recursively,
842 // this loop is needed to get the same results
843 for (const Animation::Part& part : mAnimation->parts) {
844 if (part.animation != nullptr) {
845 mCallbacks->init(part.animation->parts);
846 }
847 }
848 mCallbacks->init(mAnimation->parts);
849
850 bool anyPartHasClock = false;
851 for (size_t i=0; i < mAnimation->parts.size(); i++) {
852 if(validClock(mAnimation->parts[i])) {
853 anyPartHasClock = true;
854 break;
855 }
856 }
857 if (!anyPartHasClock) {
858 mClockEnabled = false;
859 }
860
861 // Check if npot textures are supported
862 mUseNpotTextures = false;
863 String8 gl_extensions;
864 const char* exts = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
865 if (!exts) {
866 glGetError();
867 } else {
868 gl_extensions.setTo(exts);
869 if ((gl_extensions.find("GL_ARB_texture_non_power_of_two") != -1) ||
870 (gl_extensions.find("GL_OES_texture_npot") != -1)) {
871 mUseNpotTextures = true;
872 }
873 }
874
875 // Blend required to draw time on top of animation frames.
876 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
877 glShadeModel(GL_FLAT);
878 glDisable(GL_DITHER);
879 glDisable(GL_SCISSOR_TEST);
880 glDisable(GL_BLEND);
881
882 glBindTexture(GL_TEXTURE_2D, 0);
883 glEnable(GL_TEXTURE_2D);
884 glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
885 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
886 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
887 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
888 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
889
890 bool clockFontInitialized = false;
891 if (mClockEnabled) {
892 clockFontInitialized =
893 (initFont(&mAnimation->clockFont, CLOCK_FONT_ASSET) == NO_ERROR);
894 mClockEnabled = clockFontInitialized;
895 }
896
897 if (mClockEnabled && !updateIsTimeAccurate()) {
898 mTimeCheckThread = new TimeCheckThread(this);
899 mTimeCheckThread->run("BootAnimation::TimeCheckThread", PRIORITY_NORMAL);
900 }
901
902 playAnimation(*mAnimation);
903
904 if (mTimeCheckThread != nullptr) {
905 mTimeCheckThread->requestExit();
906 mTimeCheckThread = nullptr;
907 }
908
909 if (clockFontInitialized) {
910 glDeleteTextures(1, &mAnimation->clockFont.texture.name);
911 }
912
913 releaseAnimation(mAnimation);
914 mAnimation = nullptr;
915
916 return false;
917 }
918
919 bool BootAnimation::playAnimation(const Animation& animation)
920 {
921 const size_t pcount = animation.parts.size();
922 nsecs_t frameDuration = s2ns(1) / animation.fps;
923 const int animationX = (mWidth - animation.width) / 2;
924 const int animationY = (mHeight - animation.height) / 2;
925
926 SLOGD("%sAnimationShownTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
927 elapsedRealtime());
928 for (size_t i=0 ; i<pcount ; i++) {
929 const Animation::Part& part(animation.parts[i]);
930 const size_t fcount = part.frames.size();
931 glBindTexture(GL_TEXTURE_2D, 0);
932
933 // Handle animation package
934 if (part.animation != nullptr) {
935 playAnimation(*part.animation);
936 if (exitPending())
937 break;
938 continue; //to next part
939 }
940
941 for (int r=0 ; !part.count || r<part.count ; r++) {
942 // Exit any non playuntil complete parts immediately
943 if(exitPending() && !part.playUntilComplete)
944 break;
945
946 mCallbacks->playPart(i, part, r);
947
948 glClearColor(
949 part.backgroundColor[0],
950 part.backgroundColor[1],
951 part.backgroundColor[2],
952 1.0f);
953
954 for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {
955 const Animation::Frame& frame(part.frames[j]);
956 nsecs_t lastFrame = systemTime();
957
958 if (r > 0) {
959 glBindTexture(GL_TEXTURE_2D, frame.tid);
960 } else {
961 if (part.count != 1) {
962 glGenTextures(1, &frame.tid);
963 glBindTexture(GL_TEXTURE_2D, frame.tid);
964 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
965 glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
966 }
967 int w, h;
968 initTexture(frame.map, &w, &h);
969 }
970
971 const int xc = animationX + frame.trimX;
972 const int yc = animationY + frame.trimY;
973 Region clearReg(Rect(mWidth, mHeight));
974 clearReg.subtractSelf(Rect(xc, yc, xc+frame.trimWidth, yc+frame.trimHeight));
975 if (!clearReg.isEmpty()) {
976 Region::const_iterator head(clearReg.begin());
977 Region::const_iterator tail(clearReg.end());
978 glEnable(GL_SCISSOR_TEST);
979 while (head != tail) {
980 const Rect& r2(*head++);
981 glScissor(r2.left, mHeight - r2.bottom, r2.width(), r2.height());
982 glClear(GL_COLOR_BUFFER_BIT);
983 }
984 glDisable(GL_SCISSOR_TEST);
985 }
986 // specify the y center as ceiling((mHeight - frame.trimHeight) / 2)
987 // which is equivalent to mHeight - (yc + frame.trimHeight)
988 glDrawTexiOES(xc, mHeight - (yc + frame.trimHeight),
989 0, frame.trimWidth, frame.trimHeight);
990 if (mClockEnabled && mTimeIsAccurate && validClock(part)) {
991 drawClock(animation.clockFont, part.clockPosX, part.clockPosY);
992 }
993 handleViewport(frameDuration);
994
995 eglSwapBuffers(mDisplay, mSurface);
996
997 nsecs_t now = systemTime();
998 nsecs_t delay = frameDuration - (now - lastFrame);
999 //SLOGD("%lld, %lld", ns2ms(now - lastFrame), ns2ms(delay));
1000 lastFrame = now;
1001
1002 if (delay > 0) {
1003 struct timespec spec;
1004 spec.tv_sec = (now + delay) / 1000000000;
1005 spec.tv_nsec = (now + delay) % 1000000000;
1006 int err;
1007 do {
1008 err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr);
1009 } while (err<0 && errno == EINTR);
1010 }
1011
1012 checkExit();
1013 }
1014
1015 usleep(part.pause * ns2us(frameDuration));
1016
1017 // For infinite parts, we've now played them at least once, so perhaps exit
1018 if(exitPending() && !part.count && mCurrentInset >= mTargetInset)
1019 break;
1020 }
1021
1022 }
1023
1024 // Free textures created for looping parts now that the animation is done.
1025 for (const Animation::Part& part : animation.parts) {
1026 if (part.count != 1) {
1027 const size_t fcount = part.frames.size();
1028 for (size_t j = 0; j < fcount; j++) {
1029 const Animation::Frame& frame(part.frames[j]);
1030 glDeleteTextures(1, &frame.tid);
1031 }
1032 }
1033 }
1034
1035 return true;
1036 }
拿到move包,对配置文件进行解析,并设置相关的参数。在playAnimation方法中不断的调用for循环进行界面的刷新,通过checkExit检测是否要退出动画。
static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
466 void BootAnimation::checkExit() {
467 // Allow surface flinger to gracefully request shutdown
468 char value[PROPERTY_VALUE_MAX];
469 property_get(EXIT_PROP_NAME, value, "0");
470 int exitnow = atoi(value);
471 if (exitnow) {
472 requestExit();
473 mCallbacks->shutdown();
474 }
475 }
service.bootanim.exit取值为0的时候是启动,取值为1的时候是退出。
xref: /frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp
75 int main(int, char**) {
76 signal(SIGPIPE, SIG_IGN);
77
78 hardware::configureRpcThreadpool(1 /* maxThreads */,
79 false /* callerWillJoin */);
80
81 startGraphicsAllocatorService();
82
83 // When SF is launched in its own process, limit the number of
84 // binder threads to 4.
85 ProcessState::self()->setThreadPoolMaxThreadCount(4);
86
87 // start the thread pool
88 sp<ProcessState> ps(ProcessState::self());
89 ps->startThreadPool();
90
91 // instantiate surfaceflinger
92 sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
93
94 setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
95
96 set_sched_policy(0, SP_FOREGROUND);
97
98 // Put most SurfaceFlinger threads in the system-background cpuset
99 // Keeps us from unnecessarily using big cores
100 // Do this after the binder thread pool init
101 if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);
102
103 // initialize before clients can connect
104 flinger->init();
105
106 // publish surface flinger
107 sp<IServiceManager> sm(defaultServiceManager());
108 sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
109 IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
110
111 startDisplayService(); // dependency on SF getting registered above
112
113 struct sched_param param = {0};
114 param.sched_priority = 2;
115 if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
116 ALOGE("Couldn't set SCHED_FIFO");
117 }
118
119 // run surface flinger in this thread
120 flinger->run();
121
122 return 0;
123 }
对SurfaceFlinger进行初始化,调用init方法。
xref: /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
// Do not call property_set on main thread which will be blocked by init
608 // Use StartPropertySetThread instead.
609 void SurfaceFlinger::init() {
610 ALOGI( "SurfaceFlinger's main thread ready to run. "
611 "Initializing graphics H/W...");
612
613 ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
614
615 Mutex::Autolock _l(mStateLock);
616 // start the EventThread
617 mScheduler =
618 getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
619 mRefreshRateConfigs);
620 auto resyncCallback =
621 mScheduler->makeResyncCallback(std::bind(&SurfaceFlinger::getVsyncPeriod, this));
622
623 mAppConnectionHandle =
624 mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
625 resyncCallback,
626 impl::EventThread::InterceptVSyncsCallback());
627 mSfConnectionHandle = mScheduler->createConnection("sf", mPhaseOffsets->getCurrentSfOffset(),
628 resyncCallback, [this](nsecs_t timestamp) {
629 mInterceptor->saveVSyncEvent(timestamp);
630 });
631
632 mEventQueue->setEventConnection(mScheduler->getEventConnection(mSfConnectionHandle));
633 mVsyncModulator.setSchedulerAndHandles(mScheduler.get(), mAppConnectionHandle.get(),
634 mSfConnectionHandle.get());
635
636 mRegionSamplingThread =
637 new RegionSamplingThread(*this, *mScheduler,
638 RegionSamplingThread::EnvironmentTimingTunables());
639
640 // Get a RenderEngine for the given display / config (can't fail)
641 int32_t renderEngineFeature = 0;
642 renderEngineFeature |= (useColorManagement ?
643 renderengine::RenderEngine::USE_COLOR_MANAGEMENT : 0);
644 renderEngineFeature |= (useContextPriority ?
645 renderengine::RenderEngine::USE_HIGH_PRIORITY_CONTEXT : 0);
646 renderEngineFeature |=
647 (enable_protected_contents(false) ? renderengine::RenderEngine::ENABLE_PROTECTED_CONTEXT
648 : 0);
649
650 // TODO(b/77156734): We need to stop casting and use HAL types when possible.
651 // Sending maxFrameBufferAcquiredBuffers as the cache size is tightly tuned to single-display.
652 mCompositionEngine->setRenderEngine(
653 renderengine::RenderEngine::create(static_cast<int32_t>(defaultCompositionPixelFormat),
654 renderEngineFeature, maxFrameBufferAcquiredBuffers));
655
656 LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
657 "Starting with vr flinger active is not currently supported.");
658 mCompositionEngine->setHwComposer(getFactory().createHWComposer(getBE().mHwcServiceName));
659 mCompositionEngine->getHwComposer().registerCallback(this, getBE().mComposerSequenceId);
660 // Process any initial hotplug and resulting display changes.
661 processDisplayHotplugEventsLocked();
662 const auto display = getDefaultDisplayDeviceLocked();
663 LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback.");
664 LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()),
665 "Internal display is disconnected.");
666
667 if (useVrFlinger) {
668 auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
669 // This callback is called from the vr flinger dispatch thread. We
670 // need to call signalTransaction(), which requires holding
671 // mStateLock when we're not on the main thread. Acquiring
672 // mStateLock from the vr flinger dispatch thread might trigger a
673 // deadlock in surface flinger (see b/66916578), so post a message
674 // to be handled on the main thread instead.
675 postMessageAsync(new LambdaMessage([=] {
676 ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
677 mVrFlingerRequestsDisplay = requestDisplay;
678 signalTransaction();
679 }));
680 };
681 mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(),
682 getHwComposer()
683 .fromPhysicalDisplayId(*display->getId())
684 .value_or(0),
685 vrFlingerRequestDisplayCallback);
686 if (!mVrFlinger) {
687 ALOGE("Failed to start vrflinger");
688 }
689 }
690
691 // initialize our drawing state
692 mDrawingState = mCurrentState;
693
694 // set initial conditions (e.g. unblank default device)
695 initializeDisplays();
696
697 getRenderEngine().primeCache();
698
699 // Inform native graphics APIs whether the present timestamp is supported:
700
701 const bool presentFenceReliable =
702 !getHwComposer().hasCapability(HWC2::Capability::PresentFenceIsNotReliable);
703 mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);
704
705 if (mStartPropertySetThread->Start() != NO_ERROR) {
706 ALOGE("Run StartPropertySetThread failed!");
707 }
708
709 mScheduler->setChangeRefreshRateCallback(
710 [this](RefreshRateType type, Scheduler::ConfigEvent event) {
711 Mutex::Autolock lock(mStateLock);
712 setRefreshRateTo(type, event);
713 });
714 mScheduler->setGetVsyncPeriodCallback([this] {
715 Mutex::Autolock lock(mStateLock);
716 return getVsyncPeriod();
717 });
718
719 mRefreshRateConfigs.populate(getHwComposer().getConfigs(*display->getId()));
720 mRefreshRateStats.setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
721
722 ALOGV("Done initializing");
723 }
mStartPropertySetThread->Start启动线程,对 "service.bootanim.exit"赋值为0,开起开机动画。
xref: /frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp
20 namespace android {
21
22 StartPropertySetThread::StartPropertySetThread(bool timestampPropertyValue):
23 Thread(false), mTimestampPropertyValue(timestampPropertyValue) {}
24
25 status_t StartPropertySetThread::Start() {
26 return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
27 }
28
29 bool StartPropertySetThread::threadLoop() {
30 // Set property service.sf.present_timestamp, consumer need check its readiness
31 property_set(kTimestampProperty, mTimestampPropertyValue ? "1" : "0");
32 // Clear BootAnimation exit flag
33 property_set("service.bootanim.exit", "0");
34 // Start BootAnimation if not started
35 property_set("ctl.start", "bootanim");
36 // Exit immediately
37 return false;
38 }
39
40 } // namespace android
xref: /frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
526 void SurfaceFlinger::bootFinished()
527 {
528 if (mStartPropertySetThread->join() != NO_ERROR) {
529 ALOGE("Join StartPropertySetThread failed!");
530 }
531 const nsecs_t now = systemTime();
532 const nsecs_t duration = now - mBootTime;
533 ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
534
535 // wait patiently for the window manager death
536 const String16 name("window");
537 sp<IBinder> window(defaultServiceManager()->getService(name));
538 if (window != 0) {
539 window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
540 }
541 sp<IBinder> input(defaultServiceManager()->getService(
542 String16("inputflinger")));
543 if (input == nullptr) {
544 ALOGE("Failed to link to input service");
545 } else {
546 mInputFlinger = interface_cast<IInputFlinger>(input);
547 }
548
549 if (mVrFlinger) {
550 mVrFlinger->OnBootFinished();
551 }
552
553 // stop boot animation
554 // formerly we would just kill the process, but we now ask it to exit so it
555 // can choose where to stop the animation.
556 property_set("service.bootanim.exit", "1");
557
558 const int LOGTAG_SF_STOP_BOOTANIM = 60110;
559 LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
560 ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
561
562 postMessageAsync(new LambdaMessage([this]() NO_THREAD_SAFETY_ANALYSIS {
563 readPersistentProperties();
564 mBootStage = BootStage::FINISHED;
565
566 // set the refresh rate according to the policy
567 const auto& performanceRefreshRate =
568 mRefreshRateConfigs.getRefreshRate(RefreshRateType::PERFORMANCE);
569
570 if (performanceRefreshRate && isDisplayConfigAllowed(performanceRefreshRate->configId)) {
571 setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
572 } else {
573 setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
574 }
575 }));
576 }
当主Launcher拉起来了之后会向SurfaceFlinger发送消息调用bootFinished方法,将"service.bootanim.exit"设置为1,结束开机动画。