Surfaceflinger process流程分析

本文深入解析了SurfaceFlinger的工作原理,包括其初始化过程、线程循环机制、surface和layer的创建,以及如何处理上层命令并通过OpenGL进行图像合成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

根据前面的介绍,surfaceflinger作为一个server process(其进程入口见main_surfaceflinger.cpp中的main函数),上层的应用程序(作为client)通过Binder方式与其进行通信。Surfaceflinger作为一个进程,这里把它分为3个部分,如下:

1、 Thread本身处理部分,包括初始化以及thread loop。

2、 Binder部分,负责接收上层应用的各个设置和命令,并反馈状态标志给上层。

3、 与底层的交互,负责调用底层接口(HAL)。

结构图如下:

注释:

a、 Binder接收到应用程序的命令(如创建surface、设置参数等),传递给flinger。

b、 Flinger完成对应命令后将相关结果状态反馈给上层。

c、 在处理上层命令过程中,根据需要设置event(主要和显示有关),通知Thread Loop进行处理。

d、 Flinger根据上层命令通知底层进行处理(主要是设置一些参数,Layer、position等)

e、 Thread Loop中进行surface的合成并通知底层进行显示(Post buffer)。

f、   DisplayHardware层根据flinger命令调用HAL进行HW的操作。

 

下面来具体分析一些SurfaceFlinger中重要的处理函数以及surface、Layer的属性

1. SurfaceFlinger::readyToRun

   SurfaceFlinger thread的初始化函数,主要任务是分配内存和设置底层接口(EGL&HAL)。

 

status_t SurfaceFlinger::readyToRun()
{
    LOGI(   "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    // we only support one display currently
    int dpy = 0;

    {
        // initialize the main display
        GraphicPlane& plane(graphicPlane(dpy));
        DisplayHardware* const hw = new DisplayHardware(this, dpy);
        plane.setDisplayHardware(hw);
    }

    // create the shared control-block
    mServerHeap = new MemoryHeapBase(4096,
            MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
    LOGE_IF(mServerHeap==0, "can't create shared memory dealer");

    mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
    LOGE_IF(mServerCblk==0, "can't get to shared control block's address");

    new(mServerCblk) surface_flinger_cblk_t;

    // initialize primary screen
    // (other display should be initialized in the same manner, but
    // asynchronously, as they could come and go. None of this is supported
    // yet).
    const GraphicPlane& plane(graphicPlane(dpy));
    const DisplayHardware& hw = plane.displayHardware();
    const uint32_t w = hw.getWidth();
    const uint32_t h = hw.getHeight();
    const uint32_t f = hw.getFormat();
    hw.makeCurrent();

    // initialize the shared control block
    mServerCblk->connected |= 1<<dpy;
    display_cblk_t* dcblk = mServerCblk->displays + dpy;
    memset(dcblk, 0, sizeof(display_cblk_t));
    dcblk->w            = plane.getWidth();
    dcblk->h            = plane.getHeight();
    dcblk->format       = f;
    dcblk->orientation  = ISurfaceComposer::eOrientationDefault;
    dcblk->xdpi         = hw.getDpiX();
    dcblk->ydpi         = hw.getDpiY();
    dcblk->fps          = hw.getRefreshRate();
    dcblk->density      = hw.getDensity();

    // Initialize OpenGL|ES
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glPixelStorei(GL_PACK_ALIGNMENT, 4);
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnable(GL_SCISSOR_TEST);
    glShadeModel(GL_FLAT);
    glDisable(GL_DITHER);
    glDisable(GL_CULL_FACE);

    const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
    const uint16_t g1 = pack565(0x17,0x2f,0x17);
    const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 };
    glGenTextures(1, &mWormholeTexName);
    glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, wormholeTexData);

    const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) };
    glGenTextures(1, &mProtectedTexName);
    glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,
            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);

    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // put the origin in the left-bottom corner
    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h

    mReadyToRunBarrier.open();

    /*
     *  We're now ready to accept clients...
     */

    // start boot animation
    property_set("ctl.start", "bootanim");

    return NO_ERROR;
}


2. SurfaceFlinger::threadLoop

       Surfaceflinger的loop函数,主要是等待其他接口发送的event,进行显示数据的合成以及显示。

 

bool SurfaceFlinger::threadLoop()
{
    waitForEvent();  //等待其他接口的signal event

    // post surfaces (if needed)
    handlePageFlip();   //处理翻页机制

    if (UNLIKELY(mHwWorkListDirty)) {
        // build the h/w work list
        handleWorkList();
    }

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    if (LIKELY(hw.canDraw())) {
        // repaint the framebuffer (if needed)

        const int index = hw.getCurrentBufferIndex();
        GraphicLog& logger(GraphicLog::getInstance());

        logger.log(GraphicLog::SF_REPAINT, index);
        handleRepaint(); //合并所有layer并填充到buffer中去

        // inform the h/w that we're done compositing
        logger.log(GraphicLog::SF_COMPOSITION_COMPLETE, index);
        hw.compositionComplete();

        logger.log(GraphicLog::SF_SWAP_BUFFERS, index);
        postFramebuffer();  //互换front buffer和back buffer,调用EGL接口进行显示

        logger.log(GraphicLog::SF_REPAINT_DONE, index);
    } else {
        // pretend we did the post
        hw.compositionComplete();
        usleep(16667); // 60 fps period,每秒刷新60次
    }
    return true;
}


3. SurfaceFlinger::createSurface 

      提供给应用程序的主要接口,该接口可以创建一个surface,底层会根据参数创建layer以及分配内存(共2个buffer:front/back buffer),surface相关参数会反馈给上层。 

sp<ISurface> SurfaceFlinger::createSurface(
        ISurfaceComposerClient::surface_data_t* params,
        const String8& name,
        const sp<Client>& client,
        DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
        uint32_t flags)
{
    sp<LayerBaseClient> layer;
    sp<ISurface> surfaceHandle;

    if (int32_t(w|h) < 0) {
        LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
                int(w), int(h));
        return surfaceHandle;
    }

    //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
    sp<Layer> normalLayer;
    //创建layer,根据参数(宽高格式)分配内存(共2个buffer:front/back buffer)
    switch (flags & eFXSurfaceMask) {
        case eFXSurfaceNormal:
            normalLayer = createNormalSurface(client, d, w, h, flags, format);
            layer = normalLayer;
            break;
        case eFXSurfaceBlur:
            // for now we treat Blur as Dim, until we can implement it
            // efficiently.
        case eFXSurfaceDim:
            layer = createDimSurface(client, d, w, h, flags);
            break;
        case eFXSurfaceScreenshot:
            layer = createScreenshotSurface(client, d, w, h, flags);
            break;
    }

    if (layer != 0) {
        layer->initStates(w, h, flags);
        layer->setName(name);
        ssize_t token = addClientLayer(client, layer);
        
        //创建surface
        surfaceHandle = layer->getSurface();
        if (surfaceHandle != 0) {
            params->token = token;
            params->identity = layer->getIdentity();
            if (normalLayer != 0) {
                Mutex::Autolock _l(mStateLock);
                mLayerMap.add(layer->getSurfaceBinder(), normalLayer);
            }
        }

        setTransactionFlags(eTransactionNeeded);
    }

    return surfaceHandle;
}


 4. SurfaceFlinger::setTransactionState

处理上层的各个命令,并根据flag设置event通知Threadloop进行处理。

void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& state,
        int orientation) {
    Mutex::Autolock _l(mStateLock);

    uint32_t flags = 0;
    if (mCurrentState.orientation != orientation) {
        if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
            mCurrentState.orientation = orientation;
            flags |= eTransactionNeeded;
            mResizeTransationPending = true;
        } else if (orientation != eOrientationUnchanged) {
            LOGW("setTransactionState: ignoring unrecognized orientation: %d",
                    orientation);
        }
    }

    const size_t count = state.size();
    for (size_t i=0 ; i<count ; i++) {
        const ComposerState& s(state[i]);
        sp<Client> client( static_cast<Client *>(s.client.get()) );
        flags |= setClientStateLocked(client, s.state);
    }
    if (flags) {
        setTransactionFlags(flags);
    }

    signalEvent();

    // if there is a transaction with a resize, wait for it to
    // take effect before returning.
    while (mResizeTransationPending) {
        status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
        if (CC_UNLIKELY(err != NO_ERROR)) {
            // just in case something goes wrong in SF, return to the
            // called after a few seconds.
            LOGW_IF(err == TIMED_OUT, "closeGlobalTransaction timed out!");
            mResizeTransationPending = false;
            break;
        }
    }
}


5. SurfaceFlinger::composeSurfaces

       该接口在threadLoop->handleRepaint中被调用,负责将所有存在的surface进行合并,OpenGL模块负责这个部分。

6. SurfaceFlinger::postFramebuffer

      该接口在threadLoop中被调用,负责将合成好的数据(存在于back buffer中)推入front buffer中,然后调用HAL接口命令底层显示。 

 7. surface与layer

     从3中可知,上层每创建一个surface的时候,底层都会同时创建一个layer,下面看一下surface及layer的相关属性。

Note:code中相关结构体太大,就不全部罗列出来了

   A、Surface相关属性(详细参考文件surface.h)

       a1:SurfaceID:根据此ID把相关surface和layer对应起来

      a2:SurfaceInfo

               包括宽高格式等信息

       a3:2个buffer指针、buffer索引等信息

   B、Layer相关属性(详细参考文件layer.h/layerbase.h/layerbitmap.h)

               包括Layer的ID、宽高、位置、layer、alpha指、前后buffer地址及索引、layer的状态信息(如eFlipRequested、eBusy、eLocked等)

 

 

 

 

 

 

 

 

 

SurfaceFlingerSurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlingerSurfaceFlinger 服务是在 服务是在 服务是在 SystemSystemSystemSystemSystem 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 进程中启动的,并且负责统一管理设备帧缓冲区。 SurfaceFlingerSurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlinger SurfaceFlingerSurfaceFlinger 服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件服务在启动的过程中, 会创建两个线其一用来监控制台事件而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 而另外一个线程用来渲染系统的 UI 。
<think>我们正在分析Android系统中Power键控制屏幕熄灭的代码流程。根据引用内容,我们可以知道在Android 7.0中,当按下Power键时,系统会触发一系列事件,最终可能导致屏幕熄灭(即进入睡眠状态)。 根据引用[2]中的描述,当设备处于亮屏状态(interactive为true)且不是从非交互状态开始时,按下Power键(短按)会进入一个分支处理。在`powerPress`函数中,根据`mShortPressOnPowerBehavior`的值执行不同的操作。其中,`SHORT_PRESS_POWER_GO_TO_SLEEP`表示短按Power键会使设备进入睡眠状态。 具体流程如下: 1. 当用户按下Power键时,硬件产生一个按键事件,该事件被InputReader捕获,然后传递给InputDispatcher,最终到达WindowManagerService(WMS)的`PhoneWindowManager`。 2. 在`PhoneWindowManager`中,会处理Power键的按下事件。在亮屏状态下,短按Power键会触发`powerPress`函数。 3. 在`powerPress`函数中,当满足条件(count=1,设备处于交互状态等)时,根据配置的`mShortPressOnPowerBehavior`值执行相应操作。如果配置为`SHORT_PRESS_POWER_GO_TO_SLEEP`(值为1),则调用`PowerManagerService`的`goToSleep`方法。 4. `PowerManagerService`的`goToSleep`方法会进一步调用到底层的`goToSleepInternal`方法,该方法会请求系统进入睡眠状态。 5. 在`goToSleepInternal`中,会更新电源状态,并调用`nativeSetPowerState`(通过JNI)通知底层进行睡眠操作。同时,它会释放唤醒锁,允许系统进入低功耗状态。 6. 底层(包括HAL层和Kernel)接收到睡眠请求后,会关闭屏幕背光,并可能将CPU置于休眠状态。 值得注意的是,在进入睡眠之前,系统会保存状态,并通知其他服务(如DisplayManagerService)屏幕即将关闭。 下面是一个简化的代码流程: ``` 用户按下Power键 → InputReader捕获事件 → InputDispatcher分发事件到WindowManagerService → PhoneWindowManager.interceptKeyBeforeQueueing() 处理按键事件,判断为短按Power键 → 调用PowerManagerService的powerPress()方法 在powerPress()中,根据条件调用goToSleep() → PowerManagerService.goToSleep() 内部调用goToSleepInternal() → 在goToSleepInternal()中,更新全局状态,通过native方法调用底层 → 底层(HAL和Kernel)执行关闭屏幕和进入睡眠的操作 ``` 另外,根据引用[3],屏幕熄灭过程涉及释放唤醒锁(wake lock)和调用kernel的睡眠流程。 注意:以上分析基于Android 7.0的代码,不同版本可能有所差异。 相关问题: 1. 在Android系统中,除了Power键,还有其他方式可以使屏幕熄灭吗? 2. 如何配置短按Power键的行为(例如修改为锁屏而不是睡眠)? 3. Power键长按事件的流程是怎样的?</think>### Power键控制屏幕熄灭功能的代码流程分析 在Android系统中,Power键控制屏幕熄灭的流程涉及多个系统层的协作。以下是基于Android 7.0源码的分析流程在不同版本中可能略有差异): #### 1. **Input事件捕获** 当用户按下Power键时: - Linux内核通过`input`子系统捕获硬件中断 - InputReader线程读取`/dev/input/eventX`设备事件 - 事件被传递到WindowManagerService(WMS)的`InputManager`模块 #### 2. **WindowManagerService处理** 在`PhoneWindowManager.java`中处理按键事件: ```java // frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java public int interceptKeyBeforeQueueing(...) { if (keyCode == KeyEvent.KEYCODE_POWER) { if (down) { // 按下事件 powerPress(eventTime, interactive, mPowerKeyWakeLock); } else { // 释放事件 powerRelease(); } } } ``` #### 3. **短按Power键处理** 在`powerPress()`方法中判断短按行为: ```java private void powerPress(long eventTime, boolean interactive, int count) { if (interactive) { switch (mShortPressOnPowerBehavior) { case SHORT_PRESS_POWER_GO_TO_SLEEP: // 配置值为1 mPowerManager.goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); break; // 其他case处理... } } } ``` [^2] #### 4. **PowerManagerService执行睡眠** 在`PowerManagerService.java`中执行睡眠操作: ```java // frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java @Override public void goToSleep(long eventTime, int reason, int flags) { goToSleepInternal(eventTime, reason, flags, Process.SYSTEM_UID); } private void goToSleepInternal(...) { // 1. 更新唤醒状态 setWakefulnessLocked(WAKEFULNESS_ASLEEP, reason); // 2. 通知DisplayManagerService关闭屏幕 mDisplayManagerInternal.setDisplayPowerState(...); // 3. 释放唤醒锁 updatePowerStateLocked(); } ``` #### 5. **底层驱动执行** 最终通过HAL层和内核关闭屏幕: 1. 通过JNI调用`com_android_server_power_PowerManagerService.cpp` 2. 写入`/sys/power/state`触发内核睡眠流程 3. 显示驱动关闭背光并进入低功耗模式 ```cpp // 内核电源管理 static int suspend_enter(suspend_state_t state) { // 关闭显示控制器 fb_suspend(); // 进入CPU休眠状态 cpu_suspend(); } ``` [^3] ### 关键配置点 在`config.xml`中定义Power键行为: ```xml <!-- 短按行为:0=无操作 1=睡眠 2=挂断电话 3=锁屏 --> <integer name="config_shortPressOnPowerBehavior">1</integer> ``` ### 流程总结 ``` 硬件中断 → Input子系统 → WindowManagerService → PhoneWindowManager.powerPress() → PowerManagerService.goToSleep() → DisplayManagerService → SurfaceFlinger → Framebuffer驱动 → 内核电源管理(suspend) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值