android12 开机动画流程分析

8 阅读7分钟

不用翻墙的源码阅读网站 xrefandroid.com/

1、开机动画开始流程: SurfaceFlinger.init()->mStartPropertySetThread->Start()->StartPropertySetThread::threadLoop()

772  // Do not call property_set on main thread which will be blocked by init
773  // Use StartPropertySetThread instead.
774  void SurfaceFlinger::init() {

777      Mutex::Autolock _l(mStateLock);  
801      mCompositionEngine->setTimeStats(mTimeStats);
802      mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName));
803      mCompositionEngine->getHwComposer().setCallback(this);
804      ClientCache::getInstance().setRenderEngine(&getRenderEngine());

         .....

846      mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable);
847  
848      if (mStartPropertySetThread->Start() != NO_ERROR) {
849          ALOGE("Run StartPropertySetThread failed!");
850      }
851  
852      ALOGV("Done initializing");
853  }

//启动线程StartPropertySetThread
 status_t StartPropertySetThread::Start() {
26      return run("SurfaceFlinger::StartPropertySetThread", PRIORITY_NORMAL);
27  }
//启动开机动画
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      property_set("service.bootanim.progress", "0");
35      // Start BootAnimation if not started
36      property_set("ctl.start", "bootanim");
37      // Exit immediately
38      return false;
39  }

开机动画入口 bootanimation_main.cpp,创建BootAnimation对象

 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         //打开 Binder驱动
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.cpp

 BootAnimation::BootAnimation(sp<Callbacks> callbacks)
115          : Thread(false), mLooper(new Looper(false)), mClockEnabled(true), mTimeIsAccurate(false),
116          mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
117      mSession = new SurfaceComposerClient();
118  
119      std::string powerCtl = android::base::GetProperty("sys.powerctl", "");
       //判断是否是关机动画
120      if (powerCtl.empty()) {
121          mShuttingDown = false;
122      } else {
123          mShuttingDown = true;
124      }
125      ALOGD("%sAnimationStartTiming start time: %" PRId64 "ms", mShuttingDown ? "Shutdown" : "Boot",
126              elapsedRealtime());
127  }
 //SP对象初次被引用调用onFirstRef()
 void BootAnimation::onFirstRef() {
139      status_t err = mSession->linkToComposerDeath(this);
140      SLOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
141      if (err == NO_ERROR) {
142          // Load the animation content -- this can be slow (eg 200ms)
143          // called before waitForSurfaceFlinger() in main() to avoid wait
144          ALOGD("%sAnimationPreloadTiming start time: %" PRId64 "ms",
145                  mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
146          preloadAnimation();
147          ALOGD("%sAnimationPreloadStopTiming start time: %" PRId64 "ms",
148                  mShuttingDown ? "Shutdown" : "Boot", elapsedRealtime());
149      }
150  }

//加载动画ZIP
 bool BootAnimation::preloadAnimation() {
544      findBootAnimationFile();
545      if (!mZipFileName.isEmpty()) {
546          mAnimation = loadAnimation(mZipFileName);
547          return (mAnimation != nullptr);
548      }
549  
550      return false;
551  }

//初始化
  status_t BootAnimation::readyToRun() {
400      mAssets.addDefaultAssets();
401  
402      mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
403      if (mDisplayToken == nullptr)
404          return NAME_NOT_FOUND;
405  
406      DisplayMode displayMode;
407      const status_t error =
408              SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &displayMode);
409      if (error != NO_ERROR)
410          return error;
411  
412      mMaxWidth = android::base::GetIntProperty("ro.surface_flinger.max_graphics_width", 0);
413      mMaxHeight = android::base::GetIntProperty("ro.surface_flinger.max_graphics_height", 0);
414      ui::Size resolution = displayMode.resolution;
415      resolution = limitSurfaceSize(resolution.width, resolution.height);
416      // create the native surface
417      sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
418              resolution.getWidth(), resolution.getHeight(), PIXEL_FORMAT_RGB_565);
419  
420      SurfaceComposerClient::Transaction t;
421  
422      // this guest property specifies multi-display IDs to show the boot animation
423      // multiple ids can be set with comma (,) as separator, for example:
424      // setprop persist.boot.animation.displays 19260422155234049,19261083906282754
425      Vector<PhysicalDisplayId> physicalDisplayIds;
426      char displayValue[PROPERTY_VALUE_MAX] = "";
427      property_get(DISPLAYS_PROP_NAME, displayValue, "");
428      bool isValid = displayValue[0] != '\0';
429      if (isValid) {
430          char *p = displayValue;
431          while (*p) {
432              if (!isdigit(*p) && *p != ',') {
433                  isValid = false;
434                  break;
435              }
436              p ++;
437          }
438          if (!isValid)
439              SLOGE("Invalid syntax for the value of system prop: %s", DISPLAYS_PROP_NAME);
440      }
441      if (isValid) {
442          std::istringstream stream(displayValue);
443          for (PhysicalDisplayId id; stream >> id.value; ) {
444              physicalDisplayIds.add(id);
445              if (stream.peek() == ',')
446                  stream.ignore();
447          }
448  
449          // In the case of multi-display, boot animation shows on the specified displays
450          // in addition to the primary display
451          auto ids = SurfaceComposerClient::getPhysicalDisplayIds();
452          constexpr uint32_t LAYER_STACK = 0;
453          for (auto id : physicalDisplayIds) {
454              if (std::find(ids.begin(), ids.end(), id) != ids.end()) {
455                  sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(id);
456                  if (token != nullptr)
457                      t.setDisplayLayerStack(token, LAYER_STACK);
458              }
459          }
460          t.setLayerStack(control, LAYER_STACK);
461      }
462  
463      t.setLayer(control, 0x40000000)
464          .apply();
465  
466      sp<Surface> s = control->getSurface();
467  
468      // initialize opengl and egl
469      EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
470      eglInitialize(display, nullptr, nullptr);
471      EGLConfig config = getEglConfig(display);
472      EGLSurface surface = eglCreateWindowSurface(display, config, s.get(), nullptr);
473      EGLContext context = eglCreateContext(display, config, nullptr, nullptr);
474      EGLint w, h;
475      eglQuerySurface(display, surface, EGL_WIDTH, &w);
476      eglQuerySurface(display, surface, EGL_HEIGHT, &h);
477  
478      if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
479          return NO_INIT;
480  
481      mDisplay = display;
482      mContext = context;
483      mSurface = surface;
484      mWidth = w;
485      mHeight = h;
486      mFlingerSurfaceControl = control;
487      mFlingerSurface = s;
488      mTargetInset = -1;
489  
490      projectSceneToWindow();
491  
492      // Register a display event receiver
493      mDisplayEventReceiver = std::make_unique<DisplayEventReceiver>();
494      status_t status = mDisplayEventReceiver->initCheck();
495      SLOGE_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver failed with status: %d",
496              status);
497      mLooper->addFd(mDisplayEventReceiver->getFd(), 0, Looper::EVENT_INPUT,
498              new DisplayEventCallback(this), nullptr);
499  
500      return NO_ERROR;
501  }


//调用Movie()准备播放动画
 bool BootAnimation::threadLoop() {
604      bool result;
605      // We have no bootanimation file, so we use the stock android logo
606      // animation.
607      if (mZipFileName.isEmpty()) {
608          result = android();
609      } else {
610          result = movie();
611      }
612  
613      mCallbacks->shutdown();
614      eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
615      eglDestroyContext(mDisplay, mContext);
616      eglDestroySurface(mDisplay, mSurface);
617      mFlingerSurface.clear();
618      mFlingerSurfaceControl.clear();
619      eglTerminate(mDisplay);
620      eglReleaseThread();
621      IPCThreadState::self()->stopProcess();
622      return result;
623  }


//播放动画
bool BootAnimation::movie() {
1126      if (mAnimation == nullptr) {
1127          mAnimation = loadAnimation(mZipFileName);
1128      }
1129  
1130      if (mAnimation == nullptr)
1131          return false;
1132  
1133      // mCallbacks->init() may get called recursively,
1134      // this loop is needed to get the same results
1135      for (const Animation::Part& part : mAnimation->parts) {
1136          if (part.animation != nullptr) {
1137              mCallbacks->init(part.animation->parts);
1138          }
1139      }
1140      mCallbacks->init(mAnimation->parts);
1141  
1142    .....
1195  
1196      playAnimation(*mAnimation);
1197  
1198   ......
1206  
1207      releaseAnimation(mAnimation);
1208      mAnimation = nullptr;
1209  
1210      return false;
1211  }

//播放动画的过程中判断是否要退出动画
 bool BootAnimation::playAnimation(const Animation& animation) {
1222      const size_t pcount = animation.parts.size();
1223      nsecs_t frameDuration = s2ns(1) / animation.fps;
1224  
1227      .....
1228      int fadedFramesCount = 0;
1229      int lastDisplayedProgress = 0;
1230      for (size_t i=0 ; i<pcount ; i++) {
1231          
1243         
1353       .....
1354             checkExit();
1355             
1356      }
1357       .....
1380  
1381      return true;
1382  }


 //service.bootanim.exit 等于1则退出开机动画
  void BootAnimation::checkExit() {
694      // Allow surface flinger to gracefully request shutdown
695      char value[PROPERTY_VALUE_MAX];
//static const char EXIT_PROP_NAME[] = "service.bootanim.exit";
696      property_get(EXIT_PROP_NAME, value, "0");
//1.  **`atoi` 来自标准库**:`atoi` 函数是 C 标准库 `<stdlib.h>` 中定义的
697      int exitnow = atoi(value); //service.bootanim.exit 是否等于1
698      if (exitnow) {
699          requestExit();
700      }
701  }


入口ActivityThread.handleResumeActivity中添加IdleHandler

public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
        boolean isForward, String reason) {
    .....
    r.nextIdle = mNewActivities;
    mNewActivities = r;
    if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
    Looper.myQueue().addIdleHandler(new Idler());
}

2.开机动画结束流程: 在桌面启动完成以后调用Idler.queueIdle()

    public final boolean queueIdle() {
        ActivityClientRecord a = mNewActivities;
        ...
        if (a != null) {
            mNewActivities = null;
            final ActivityClient ac = ActivityClient.getInstance();
            ActivityClientRecord prev;
            do {
                if (localLOGV) Slog.v(
                    TAG, "Reporting idle of " + a +
                    " finished=" +
                    (a.activity != null && a.activity.mFinished));
                if (a.activity != null && !a.activity.mFinished) {
                    ac.activityIdle(a.token, a.createdConfig, stopProfiling);
                    a.createdConfig = null;
                }
                prev = a;
                a = a.nextIdle;
                prev.nextIdle = null;
            } while (a != null);
        }
        ...
        return false;
    }
}

ActivityClient.activityIdle

public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
    try {
    //调用ATMS的getActivityClientController()
        getActivityClientController().activityIdle(token, config, stopProfiling);
    } catch (RemoteException e) {
        e.rethrowFromSystemServer();
    }
}

ActivityClientController.activityIdle

public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
    final long origId = Binder.clearCallingIdentity();
    try {
        synchronized (mGlobalLock) {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle");
            final ActivityRecord r = ActivityRecord.forTokenLocked(token);
            if (r == null) {
                return;
            }
            mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */,
                    false /* processPausingActivities */, config);
            if (stopProfiling && r.hasProcess()) {
                r.app.clearProfilerIfNeeded();
            }
        }
    } finally {
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        Binder.restoreCallingIdentity(origId);
    }
}

ActivityTaskSupervisor.activityIdleInternal().checkFinishBootingLocked()

void activityIdleInternal(ActivityRecord r, boolean fromTimeout,
        boolean processPausingActivities, Configuration config) {
   

        ....
        // are idle.
        if ((mService.isBooting() && mRootWindowContainer.allResumedActivitiesIdle())
                || fromTimeout) {
            booting = checkFinishBootingLocked();
        }
        ...
   
}

private boolean checkFinishBootingLocked() {
    final boolean booting = mService.isBooting();
    boolean enableScreen = false;
    //mService是ActivityTaskManagerService
    mService.setBooting(false);
    if (!mService.isBooted()) {
        mService.setBooted(true);
        enableScreen = true;
    }
    if (booting || enableScreen) {
        mService.postFinishBooting(booting, enableScreen);
    }
    return booting;
}

ActivityTaskManagerService.postFinishBooting

void postFinishBooting(boolean finishBooting, boolean enableScreen) {
    mH.post(() -> {
        if (finishBooting) {
            mAmInternal.finishBooting();
        }
        if (enableScreen) {
           //mInternal是ActivityTaskManagerService的内部实现类LocalService
ActivityTaskManagerInternal
            mInternal.enableScreenAfterBoot(isBooted());
        }
    });
}


public void enableScreenAfterBoot(boolean booted) {
    writeBootProgressEnableScreen(SystemClock.uptimeMillis());
    mWindowManager.enableScreenAfterBoot();
    synchronized (mGlobalLock) {
        updateEventDispatchingLocked(booted);
    }
}

调用WindowManagerService.enableScreenAfterBoot()

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();
}


private void performEnableScreen() {
//向SurfaceFlinger写入Boot Finish通知
    synchronized (mGlobalLock) {
       ...
        try {
            IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
            if (surfaceFlinger != null) {
                ProtoLog.i(WM_ERROR, "******* 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) {
            ProtoLog.e(WM_ERROR, "Boot completed: SurfaceFlinger is dead!");
        }

       ....
}