zoukankan      html  css  js  c++  java
  • BootAnimation使用surfaceflinger分析


    首先,从BootAnimation开始分析,BootAnimation在启动脚本init。Rc被配置成一个服务

    1. 1.service bootanim /system/bin/bootanimation    
    2. 2.    class main    
    3. 3.    user graphics    
    4. 4.    group system audio graphics cw_access    
    5. 5.    disabled    
    6. 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



    1. BootAnimation::BootAnimation() : Thread(false)  
    2. {  
    3.     mSession = new SurfaceComposerClient();  
    4. }  


    首先 创建 SurfaceFilinger Client


    ========================================


    1. void BootAnimation::onFirstRef() {  
    2.     status_t err = mSession->linkToComposerDeath(this);  
    3.     ALOGE_IF(err, "linkToComposerDeath failed (%s) ", strerror(-err));  
    4.     if (err == NO_ERROR) {  
    5.         run("BootAnimation", PRIORITY_DISPLAY);  
    6.     }  

    可以看出BootAnimation最终继承了RefBase在main函数里的boot 是一个sp 的智能指针,

    第一次对 BootAnimation 引用调用sp<BootAnimation>时 会调用 BootAnimation 的onFirstRef()方法;

    最后 调用run,让BootAnimation线程跑起来,Thread会先跑到readyToRun(),然后再跑:threadLoop()




    SurfaceComposerClientlinkToComposerDeath函数获取了SurfaceFlinger服务,

    linkTocomposerDeath的作用是 当surfaceflinger死掉时,当前Bootanimation service 就会得到通知,会自动调用 BootAnimation::binderDied。  



    1. tatus_t BootAnimation::readyToRun() {  
    2.     mAssets.addDefaultAssets();  
    3.   
    4.     sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(  
    5.             ISurfaceComposer::eDisplayIdMain));  
    6.     DisplayInfo dinfo;  
    7.     status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);  
    8.     if (status)  
    9.         return -1;  
    10.   
    11.     // create the native surface  
    12.     sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),  
    13.             dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);  
    14.   
    15.     SurfaceComposerClient::openGlobalTransaction();  
    16.     control->setLayer(0x40000000);  //设置图层;
    17.     SurfaceComposerClient::closeGlobalTransaction();  
    18.   
    19.     sp<Surface> s = control->getSurface();  
    20.   
    21.     // initialize opengl and egl  
    22.     const EGLint attribs[] = {  
    23.             EGL_RED_SIZE,   8,  
    24.             EGL_GREEN_SIZE, 8,  
    25.             EGL_BLUE_SIZE,  8,  
    26.             EGL_DEPTH_SIZE, 0,  
    27.             EGL_NONE  
    28.     };  
    29.     EGLint w, h, dummy;  
    30.     EGLint numConfigs;  
    31.     EGLConfig config;  
    32.     EGLSurface surface;  
    33.     EGLContext context;  
    34.   
    35.     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);  
    36.   
    37.     eglInitialize(display, 0, 0);  
    38.     eglChooseConfig(display, attribs, &config, 1, &numConfigs);  
    39.     surface = eglCreateWindowSurface(display, config, s.get(), NULL);  
    40.     context = eglCreateContext(display, config, NULL, NULL);  
    41.     eglQuerySurface(display, surface, EGL_WIDTH, &w);  
    42.     eglQuerySurface(display, surface, EGL_HEIGHT, &h);  
    43.   
    44.     if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)  
    45.         return NO_INIT;  
    46.    mDisplay = display;  
    47.     mContext = context;  
    48.     mSurface = surface;  
    49.     mWidth = w;  
    50.     mHeight = h;  
    51.     mFlingerSurfaceControl = control;  
    52.     mFlingerSurface = s;  
    53.   
    54.     mAndroidAnimation = true;  
    55.   
    56.     // If the device has encryption turned on or is in process   
    57.     // of being encrypted we show the encrypted boot animation.  
    58.     char decrypt[PROPERTY_VALUE_MAX];  
    59.     property_get("vold.decrypt", decrypt, "");  
    60.   
    61.     bool encryptedAnimation = atoi(decrypt) != 0 || !strcmp("trigger_restart_min_framework", decrypt);  
    62.   
    63.     if ((encryptedAnimation &&  
    64.             (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&  
    65.             (mZip.open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE) == NO_ERROR)) ||  
    66.   
    67.             ((access(USER_BOOTANIMATION_FILE, R_OK) == 0) &&  
    68.             (mZip.open(USER_BOOTANIMATION_FILE) == NO_ERROR)) ||  
    69.   
    70.             ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&  
    71.             (mZip.open(SYSTEM_BOOTANIMATION_FILE) == NO_ERROR))) {  
    72.         mAndroidAnimation = false;  
    73.     }  
    74.   
    75.     return NO_ERROR;  
    76. }  

    首先,通过向surfaceflinger service发送

    1. sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(  
    2.             ISurfaceComposer::eDisplayIdMain));  

    告诉surfaceflinger service 获取DisplayIdBinder

    rameworks/native/libs/gui/ISurfaceComposer.cpp

    1. class BpSurfaceComposer : public BpInterface<ISurfaceComposer>  
    2. {  
    3.    ...  
    4. virtual sp<IBinder> getBuiltInDisplay(int32_t id)  
    5.     {  
    6.         Parcel data, reply;  
    7.         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());  
    8.         data.writeInt32(id);  
    9.         remote()->transact(BnSurfaceComposer::GET_BUILT_IN_DISPLAY, data, &reply);  
    10.         return reply.readStrongBinder();  
    11.     }  
    12.  ....  
    13. };  
    14.   
    15. status_t BnSurfaceComposer::onTransact(  
    16.     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
    17. {  
    18. switch(code) {  
    19. case GET_BUILT_IN_DISPLAY: {  
    20.             CHECK_INTERFACE(ISurfaceComposer, data, reply);  
    21.             int32_t id = data.readInt32();  
    22.             sp<IBinder> display(getBuiltInDisplay(id));  
    23.             reply->writeStrongBinder(display);  
    24.             return NO_ERROR;  
    25.         } break;  
    26. }  
    27. }  

    接着获取一个 DisplayInfo dinfo;

    1. status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);  

    同样看SurfaceFlinger.cpp

    1. status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info)  
    2. {  
    3.     int32_t type = NAME_NOT_FOUND;  
    4.     for (int i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {  
    5.         if (display == mBuiltinDisplays[i]) {  
    6.             type = i;  
    7.             break;  
    8.         }  
    9.     }  
    10.   
    11.     if (type < 0) {  
    12.         return type;  
    13.     }  
    14.   
    15.     const HWComposer& hwc(getHwComposer());  
    16.     float xdpi = hwc.getDpiX(type);  
    17.     float ydpi = hwc.getDpiY(type);  
    18.   
    19.     // TODO: Not sure if display density should handled by SF any longer  
    20.     class Density {  
    21.         static int getDensityFromProperty(char const* propName) {  
    22.             char property[PROPERTY_VALUE_MAX];  
    23.             int density = 0;  
    24.             if (property_get(propName, property, NULL) > 0) {  
    25.                 density = atoi(property);  
    26.             }  
    27.             return density;  
    28.         }  
    29.     public:  
    30.         static int getEmuDensity() {  
    31.             return getDensityFromProperty("qemu.sf.lcd_density"); }  
    32.         static int getBuildDensity()  {  
    33.             return getDensityFromProperty("ro.sf.lcd_density"); }  
    34.     };  
    35.   
    36.     if (type == DisplayDevice::DISPLAY_PRIMARY) {  
    37.         // The density of the device is provided by a build property  
    38.         float density = Density::getBuildDensity() / 160.0f;  
    39.         if (density == 0) {  
    40.             // the build doesn't provide a density -- this is wrong!  
    41.             // use xdpi instead  
    42.             ALOGE("ro.sf.lcd_density must be defined as a build property");  
    43.             density = xdpi / 160.0f;  
    44.         }  
    45.         if (Density::getEmuDensity()) {  
    46.             // if "qemu.sf.lcd_density" is specified, it overrides everything  
    47.             xdpi = ydpi = density = Density::getEmuDensity();  
    48.             density /= 160.0f;  
    49.         }  
    50.         info->density = density;  
    51.   
    52.         // TODO: this needs to go away (currently needed only by webkit)  
    53.         sp<const DisplayDevice> hw(getDefaultDisplayDevice());  
    54.         info->orientation = hw->getOrientation();  
    55.         getPixelFormatInfo(hw->getFormat(), &info->pixelFormatInfo);  
    56.     } else {  
    57.         // TODO: where should this value come from?  
    58.         static const int TV_DENSITY = 213;  
    59.         info->density = TV_DENSITY / 160.0f;  
    60.         info->orientation = 0;  
    61.     }  
    62.   
    63.     info->w = hwc.getWidth(type);  
    64.     info->h = hwc.getHeight(type);  
    65.     info->xdpi = xdpi;  
    66.     info->ydpi = ydpi;  
    67.     info->fps = float(1e9 / hwc.getRefreshPeriod(type));  
    68.   
    69.     // All non-virtual displays are currently considered secure.  
    70.     info->secure = true;  
    71.   
    72.     return NO_ERROR;  
    73. }  

    接着,按返回的DisplayInfo创建一个native surface

    1. / create the native surface  
    2.     sp<SurfaceControl> control = session()->createSurface(String8("BootAnimation"),  
    3.             dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);  

    接着

    1. SurfaceComposerClient::openGlobalTransaction();  //增加一个 全局Transaction计数
    2.     control->setLayer(0x40000000);  //设置图层;
    3. SurfaceComposerClient::closeGlobalTransaction();  //减少一个全局Transaction计数,当这个全局Transaction计数减少至0的时候,把mStates发送给SurfaceFlinger处理

    setLayer从代码里看是设置z-order,层级越高越接近客户

    设置完Z-order

    1. sp<Surface> s = control->getSurface();  

    1. 通过SurfaceControl获取了一个Surface  

    1. sp<Surface> SurfaceControl::getSurface() const  
    2. {  
    3.     Mutex::Autolock _l(mLock);  
    4.     if (mSurfaceData == 0) {  
    5.         mSurfaceData = new Surface(mGraphicBufferProducer);  
    6.     }  
    7.     return mSurfaceData;  
    8. }  

    Surface的创建则通过createsurface时创建的mGraphicBufferProducer(SurfaceTextureLayer)来初始化

    1. Surface::Surface(  
    2.         const sp<IGraphicBufferProducer>& bufferProducer)  
    3.     : mGraphicBufferProducer(bufferProducer)  
    4. {  
    5.     // Initialize the ANativeWindow function pointers.  
    6.     ANativeWindow::setSwapInterval  = hook_setSwapInterval;  
    7.     ANativeWindow::dequeueBuffer    = hook_dequeueBuffer;  
    8.     ANativeWindow::cancelBuffer     = hook_cancelBuffer;  
    9.     ANativeWindow::queueBuffer      = hook_queueBuffer;  
    10.     ANativeWindow::query            = hook_query;  
    11.     ANativeWindow::perform          = hook_perform;  
    12.   
    13.     ANativeWindow::dequeueBuffer_DEPRECATED = hook_dequeueBuffer_DEPRECATED;  
    14.     ANativeWindow::cancelBuffer_DEPRECATED  = hook_cancelBuffer_DEPRECATED;  
    15.     ANativeWindow::lockBuffer_DEPRECATED    = hook_lockBuffer_DEPRECATED;  
    16.     ANativeWindow::queueBuffer_DEPRECATED   = hook_queueBuffer_DEPRECATED;  
    17.   
    18.     const_cast<int&>(ANativeWindow::minSwapInterval) = 0;  
    19.     const_cast<int&>(ANativeWindow::maxSwapInterval) = 1;  
    20.   
    21.     mReqWidth = 0;  
    22.     mReqHeight = 0;  
    23.     mReqFormat = 0;  
    24.     mReqUsage = 0;  
    25.     mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;  
    26.     mCrop.clear();  
    27.     mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;  
    28.     mTransform = 0;  
    29.     mDefaultWidth = 0;  
    30.     mDefaultHeight = 0;  
    31.     mUserWidth = 0;  
    32.     mUserHeight = 0;  
    33.     mTransformHint = 0;  
    34.     mConsumerRunningBehind = false;  
    35.     mConnectedToCpu = false;  
    36. }  

    1. 接着通过这个surface对象初始化egl  

    surface = eglCreateWindowSurface(display, config, s.get(), NULL);

    其他都是走egl流程

    然后,继续分析BootAnimation,跑完systemReadyRun,则会跑threadloop循环

    1. bool BootAnimation::threadLoop()  
    2. {  
    3.     bool r;  
    4.     if (mAndroidAnimation) {  
    5.         r = android();  
    6.     } else {  
    7.         r = movie();  
    8.     }  
    9.   
    10.     // No need to force exit anymore  
    11.     property_set(EXIT_PROP_NAME, "0");  
    12.   
    13.     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);  
    14.     eglDestroyContext(mDisplay, mContext);  
    15.     eglDestroySurface(mDisplay, mSurface);  
    16.     mFlingerSurface.clear();  
    17.     mFlingerSurfaceControl.clear();  
    18.     eglTerminate(mDisplay);  
    19.     IPCThreadState::self()->stopProcess();  
    20.     return r;  
    21. }  


    可以看出,如果mAndroidAnimationtrue则跑Android,不成功则跑movie


















  • 相关阅读:
    Unity Shader入门精要之 screen post-processing effect
    Unity---关于游戏小包的记录
    计算机基础补充之原码、反码、补码
    C#接口实现技巧之借助第三方
    lua中产生 1
    游戏文本本地化(一)
    xlua修复C#的委托事件的时候,需要提前做好配置
    xlua 实现协程替换Unity中的协程
    C#定义只能处理枚举类型的泛型类型
    C# : 泛型的继承关系实现的一个可以存放不同数据类型的链表
  • 原文地址:https://www.cnblogs.com/liulaolaiu/p/11744457.html
Copyright © 2011-2022 走看看