BootAnimation使用surfaceflinger分析
首先,从BootAnimation开始分析,BootAnimation在启动脚本init。Rc被配置成一个服务
- 1.service bootanim /system/bin/bootanimation
- 2. class main
- 3. user graphics
- 4. group system audio graphics cw_access
- 5. disabled
- 6. oneshot
而其代码在 frameworks/cmds/bootanimation
int main(int argc, char** argv)
{
#if defined(HAVE_PTHREADS)
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
#endif
char value[PROPERTY_VALUE_MAX];
property_get("debug.sf.nobootanimation", value, "0");
int noBootAnimation = atoi(value);
ALOGI_IF(noBootAnimation, "boot animation disabled");
if (!noBootAnimation) {
sp<ProcessState> proc(ProcessState::self());
ProcessState::self()->startThreadPool();
// create the boot animation object
sp<BootAnimation> boot = new BootAnimation();
IPCThreadState::self()->joinThreadPool();
}
return 0;
}
从代码可以看出,bootanimation的启动是通过new一个BootAnimation
- BootAnimation::BootAnimation() : Thread(false)
- {
- mSession = new SurfaceComposerClient();
- }
首先 创建 SurfaceFilinger Client;
========================================
- void BootAnimation::onFirstRef() {
- status_t err = mSession->linkToComposerDeath(this);
- ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));
- if (err == NO_ERROR) {
- run("BootAnimation", PRIORITY_DISPLAY);
- }
- }
可以看出BootAnimation最终继承了RefBase,在main函数里的boot 是一个sp 的智能指针,
最后 调用run,让BootAnimation线程跑起来,Thread会先跑到readyToRun(),然后再跑:threadLoop()
而SurfaceComposerClient的linkToComposerDeath函数获取了SurfaceFlinger服务,
linkTocomposerDeath的作用是 当surfaceflinger死掉时,当前Bootanimation service
就会得到通知,会自动调用 BootAnimation::binderDied。
- tatus_t BootAnimation::readyToRun() {
- mAssets.addDefaultAssets();
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
- DisplayInfo dinfo;
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
- if (status)
- return -1;
- // create the native surface
- sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
- dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
- SurfaceComposerClient::openGlobalTransaction();
- control->setLayer(0x40000000); //设置图层;
- SurfaceComposerClient::closeGlobalTransaction();
- sp<Surface> s = control->getSurface();
- // initialize opengl and egl
- const EGLint attribs[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_DEPTH_SIZE, 0,
- EGL_NONE
- };
- EGLint w, h, dummy;
- EGLint numConfigs;
- EGLConfig config;
- EGLSurface surface;
- EGLContext context;
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(display, 0, 0);
- eglChooseConfig(display, attribs, &config, 1, &numConfigs);
- surface = eglCreateWindowSurface(display, config, s.get(), NULL);
- context = eglCreateContext(display, config, NULL, NULL);
- 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;
- mWidth = w;
- mHeight = h;
- mFlingerSurfaceControl = control;
- mFlingerSurface = s;
- mAndroidAnimation = true;
- // If the device has encryption turned on or is in process
- // of being encrypted we show the encrypted boot animation.
- char decrypt[PROPERTY_VALUE_MAX];
- property_get("vold.decrypt", decrypt, "");
- bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);
- if ((encryptedAnimation &&
- (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
- (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||
- ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&
- (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||
- ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
- (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {
- mAndroidAnimation = false;
- }
- return NO_ERROR;
- }
首先,通过向surfaceflinger service发送
- sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
告诉surfaceflinger service 获取DisplayId的Binder
rameworks/native/libs/gui/ISurfaceComposer.cpp
- class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
- {
- ...
- virtual sp<IBinder> getBuiltInDisplay(int32_t id)
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeInt32(id);
- remote()->transact(BnSurfaceComposer::GET_BUILT_IN_DISPLAY, data, &reply);
- return reply.readStrongBinder();
- }
- ....
- };
- status_t BnSurfaceComposer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
- {
- switch(code) {
- case GET_BUILT_IN_DISPLAY: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int32_t id = data.readInt32();
- sp<IBinder> display(getBuiltInDisplay(id));
- reply->writeStrongBinder(display);
- return NO_ERROR;
- } break;
- }
- }
接着获取一个 DisplayInfo dinfo;
- status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);
同样看SurfaceFlinger.cpp
- status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info)
- {
- int32_t type = NAME_NOT_FOUND;
- for (int i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {
- if (display == mBuiltinDisplays[i]) {
- type = i;
- break;
- }
- }
- if (type < 0) {
- return type;
- }
- const HWComposer& hwc(getHwComposer());
- float xdpi = hwc.getDpiX(type);
- float ydpi = hwc.getDpiY(type);
- // TODO: Not sure if display density should handled by SF any longer
- class Density {
- static int getDensityFromProperty(char const* propName) {
- char property[PROPERTY_VALUE_MAX];
- int density = 0;
- if (property_get(propName, property, NULL) > 0) {
- density = atoi(property);
- }
- return density;
- }
- public:
- static int getEmuDensity() {
- return getDensityFromProperty("qemu.sf.lcd_density"); }
- static int getBuildDensity() {
- return getDensityFromProperty("ro.sf.lcd_density"); }
- };
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
- // The density of the device is provided by a build property
- float density = Density::getBuildDensity() / 160.0f;
- if (density == 0) {
- // the build doesn't provide a density -- this is wrong!
- // use xdpi instead
- ALOGE("ro.sf.lcd_density must be defined as a build property");
- density = xdpi / 160.0f;
- }
- if (Density::getEmuDensity()) {
- // if "qemu.sf.lcd_density" is specified, it overrides everything
- xdpi = ydpi = density = Density::getEmuDensity();
- density /= 160.0f;
- }
- info->density = density;
- // TODO: this needs to go away (currently needed only by webkit)
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- info->orientation = hw->getOrientation();
- getPixelFormatInfo(hw->getFormat(), &info->pixelFormatInfo);
- } else {
- // TODO: where should this value come from?
- static const int TV_DENSITY = 213;
- info->density = TV_DENSITY / 160.0f;
- info->orientation = 0;
- }
- info->w = hwc.getWidth(type);
- info->h = hwc.getHeight(type);
- info->xdpi = xdpi;
- info->ydpi = ydpi;
- info->fps = float(1e9 / hwc.getRefreshPeriod(type));
- // All non-virtual displays are currently considered secure.
- info->secure = true;
- return NO_ERROR;
- }
接着,按返回的DisplayInfo创建一个native surface
- / create the native surface
- sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),
- dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
接着
- SurfaceComposerClient::openGlobalTransaction(); //增加一个 全局Transaction计数
- control->setLayer(0x40000000); //设置图层;
- SurfaceComposerClient::closeGlobalTransaction(); //减少一个全局Transaction计数,当这个全局Transaction计数减少至0的时候,把mStates发送给SurfaceFlinger处理
setLayer从代码里看是设置z-order,层级越高越接近客户
设置完Z-order后
- sp<Surface> s = control->getSurface();
- 通过SurfaceControl获取了一个Surface
- sp<Surface> SurfaceControl::getSurface() const
- {
- Mutex::Autolock _l(mLock);
- if (mSurfaceData == 0) {
- mSurfaceData = new Surface(mGraphicBufferProducer);
- }
- return mSurfaceData;
- }
Surface的创建则通过createsurface时创建的mGraphicBufferProducer(SurfaceTextureLayer)来初始化
- Surface::Surface(
- const sp<IGraphicBufferProducer>& bufferProducer)
- : mGraphicBufferProducer(bufferProducer)
- {
- // Initialize the ANativeWindow function pointers.
- ANativeWindow::setSwapInterval = hook_setSwapInterval;
- ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
- ANativeWindow::cancelBuffer = hook_cancelBuffer;
- ANativeWindow::queueBuffer = hook_queueBuffer;
- ANativeWindow::query = hook_query;
- ANativeWindow::perform = hook_perform;
- ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;
- ANativeWindow::cancelBuffer_DEPRECATED = hook_cancelBuffer_DEPRECATED;
- ANativeWindow::lockBuffer_DEPRECATED = hook_lockBuffer_DEPRECATED;
- ANativeWindow::queueBuffer_DEPRECATED = hook_queueBuffer_DEPRECATED;
- const_cast<int&>(ANativeWindow::minSwapInterval) = 0;
- const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;
- mReqWidth = 0;
- mReqHeight = 0;
- mReqFormat = 0;
- mReqUsage = 0;
- mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
- mCrop.clear();
- mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
- mTransform = 0;
- mDefaultWidth = 0;
- mDefaultHeight = 0;
- mUserWidth = 0;
- mUserHeight = 0;
- mTransformHint = 0;
- mConsumerRunningBehind = false;
- mConnectedToCpu = false;
- }
- 接着通过这个surface对象初始化egl
surface = eglCreateWindowSurface(display, config, s.get(), NULL);
其他都是走egl流程
然后,继续分析BootAnimation,跑完systemReadyRun,则会跑threadloop循环
- bool BootAnimation::threadLoop()
- {
- bool r;
- if (mAndroidAnimation) {
- r = android();
- } else {
- r = movie();
- }
- // No need to force exit anymore
- property_set(EXIT_PROP_NAME, "0");
- eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroyContext(mDisplay, mContext);
- eglDestroySurface(mDisplay, mSurface);
- mFlingerSurface.clear();
- mFlingerSurfaceControl.clear();
- eglTerminate(mDisplay);
- IPCThreadState::self()->stopProcess();
- return r;
- }
可以看出,如果mAndroidAnimation为true则跑Android,不成功则跑movie