Android12 显示框架之SurfaceFlinger启动(六)

18 篇文章 0 订阅
10 篇文章 1 订阅

目录:Android显示终极宝典

SurfaceFlinger::init()

本节来看看init()的最后一部分内容initializeDisplays()。

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::init() {
    //省略

    initializeDisplays();

    //省略
}

initializeDisplays()

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::initializeDisplays() {
    // Async since we may be called from the main thread.
    static_cast<void>(schedule([this]() MAIN_THREAD { onInitializeDisplays(); }));
}


template <typename F, typename T>
inline std::future<T> SurfaceFlinger::schedule(F&& f) {
    auto [task, future] = makeTask(std::move(f));
    mEventQueue->postMessage(std::move(task));
    return std::move(future);
}

//frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.h
template <typename F>
inline auto makeTask(F&& f) {
    sp<Task<F>> task = new Task<F>(std::move(f));
    return std::make_pair(task, task->mTask.get_future());
}

initializeDisplays()方法内调用了schedule()模板函数,而schedule()方法内部首先创建一个Task,然后再将这个Task发送到MessageQueue中(关于MessageQueue的工作原理后续章节讲解),MessageQueue监测到队列(其实内部实现是vector,习惯性叫队列,听起来符合大众认知)中有消息,那么就处理。这里其实就是执行Task实现的handleMessage()函数。

//frameworks/native/services/surfaceflinger/Scheduler/MessageQueue.h
template <typename F>
class Task : public MessageHandler {
    template <typename G>
    friend auto makeTask(G&&);

    explicit Task(F&& f) : mTask(std::move(f)) {}

    void handleMessage(const Message&) override { mTask(); }

    using T = std::invoke_result_t<F>;
    std::packaged_task<T()> mTask;
};

从代码可以看到handleMessage()调用的是mTask()函数,而这个函数就是前面被赋值的schedule()函数参数传进来的那个lambda表达式。也就是说,MessageQueue处理消息时,最终调用的就是onInitializeDisplays()方法。

那么接下来就继续看onInitializeDisplays()方法。

onInitializeDisplays()

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onInitializeDisplays() {
    const auto display = getDefaultDisplayDeviceLocked();
    if (!display) return;

    const sp<IBinder> token = display->getDisplayToken().promote();
    LOG_ALWAYS_FATAL_IF(token == nullptr);

    // reset screen orientation and use primary layer stack
    Vector<ComposerState> state;
    Vector<DisplayState> displays;
    DisplayState d;
    d.what = DisplayState::eDisplayProjectionChanged |
             DisplayState::eLayerStackChanged;
    d.token = token;
    d.layerStack = 0;
    d.orientation = ui::ROTATION_0;
    d.orientedDisplaySpaceRect.makeInvalid();
    d.layerStackSpaceRect.makeInvalid();
    d.width = 0;
    d.height = 0;
    displays.add(d);

    nsecs_t now = systemTime();
    // It should be on the main thread, apply it directly.
    applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands,
                          /* desiredPresentTime */ now, true, {}, /* postTime */ now, true, false,
                          {}, getpid(), getuid(), 0 /* Undefined transactionId */);

    setPowerModeInternal(display, hal::PowerMode::ON);
    const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
    mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
    mDefaultDisplayTransformHint = display->getTransformHint();
    // Use phase of 0 since phase is not known.
    // Use latency of 0, which will snap to the ideal latency.
    DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
    setCompositorTimingSnapped(stats, 0);
}

开头直接获取primary display的DisplayDevice,再从中取出和它绑定的身份令牌token。创建一个DisplayState并初始化其内部各个变量,同时将前面的token也保存到其中。将这个DisplayState加入到Vector中保存起来。

再接下来就进入到applyTransactionState()函数中了。

applyTransactionState()

通过传入的参数可以发现:除了刚刚创建的名叫displays的Vector,其他的参数要么是空值要么就是false,没几个实质行的参数传入。这样的话,该函数内部很多部分就执行不到了,暂时就不用关注。

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
                                           const Vector<ComposerState>& states,
                                           const Vector<DisplayState>& displays, uint32_t flags,
                                           const InputWindowCommands& inputWindowCommands,
                                           const int64_t desiredPresentTime, bool isAutoTimestamp,
                                           const client_cache_t& uncacheBuffer,
                                           const int64_t postTime, uint32_t permissions,
                                           bool hasListenerCallbacks,
                                           const std::vector<ListenerCallbacks>& listenerCallbacks,
                                           int originPid, int originUid, uint64_t transactionId) {
    uint32_t transactionFlags = 0;
    for (const DisplayState& display : displays) {
        transactionFlags |= setDisplayStateLocked(display);
    }
    //省略
    if (permissions & Permission::ACCESS_SURFACE_FLINGER) {
        transactionFlags |= addInputWindowCommands(inputWindowCommands);
    } else if (!inputWindowCommands.empty()) {
        ALOGE("Only privileged callers are allowed to send input commands.");
    }
    //省略
    if (transactionFlags) {
        //省略
        if (transactionFlags) {
            setTransactionFlags(transactionFlags);
        }
        //省略
    }
}

把执行不到的内容省略后,看上去还是挺简洁的。

  • setDisplayStateLocked()其实挺简单的,就是将mCurrentState和当前的DisplayState的一些值进行比较来判定是否要设置transactionFLags为eDisplayTransactionNeeded。
  • addInputWindowCommands()传入的参数在其内部其实就是自己和自己进行运算,返回结果为0。
  • setTransactionFlags()函数做了两件事情,其一是更新surfaceflinger中的各项work duration值,其二是向MessageQueue发送invalidate消息。但是这个阶段其实两者都没有执行到。

我们来看下setTransactionFlags()的代码:

setTransactionFlags()
//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
    return setTransactionFlags(flags, TransactionSchedule::Late);
}

uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, TransactionSchedule schedule,
                                             const sp<IBinder>& token) {
    uint32_t old = mTransactionFlags.fetch_or(flags);
    modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, token);
    if ((old & flags) == 0) signalTransaction();
    return old;
}

其实setTransactionFlags()在前面(onComposerHalHotplug()函数中)已经被调用过一次了,且flags传入的值也是为eDisplayTransactionNeeded,所以在本次调用时获取到的old和当前传入的flags值是一样的,那么本次就不会再调用signalTransaction()。那么,就看看modulateVsync()做了什么事:

//frameworks/native/services/surfaceflinger/SurfaceFlinger.h
template <typename... Args,
		  typename Handler = VsyncModulator::VsyncConfigOpt (VsyncModulator::*)(Args...)>
void modulateVsync(Handler handler, Args... args) {
	if (const auto config = (*mVsyncModulator.*handler)(args...)) {
		const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
		setVsyncConfig(*config, vsyncPeriod);
	}
}

这里的mVsyncModulator已经在前面的章节中讲解过了,不记得的可以翻到前面回顾一下,看下类图就明白了。

其实if()里面执行的就是mVsyncModulator的setTransactionSchedule()函数:

//frameworks/native/services/surfaceflinger/Scheduler/VsyncModulator.cpp
VsyncModulator::VsyncConfigOpt VsyncModulator::setTransactionSchedule(TransactionSchedule schedule,
                                                                      const sp<IBinder>& token) {
    std::lock_guard<std::mutex> lock(mMutex);
    switch (schedule) {
        case Schedule::EarlyStart:
            if (token) {
                mEarlyWakeupRequests.emplace(token);
                token->linkToDeath(this);
            } else {
                ALOGW("%s: EarlyStart requested without a valid token", __func__);
            }
            break;
        case Schedule::EarlyEnd: {
            if (token && mEarlyWakeupRequests.erase(token) > 0) {
                token->unlinkToDeath(this);
            } else {
                ALOGW("%s: Unexpected EarlyEnd", __func__);
            }
            break;
        }
        case Schedule::Late:
            // No change to mEarlyWakeup for non-explicit states.
            break;
    }

    if (mTraceDetailedInfo) {
        ATRACE_INT("mEarlyWakeup", static_cast<int>(mEarlyWakeupRequests.size()));
    }

    if (mEarlyWakeupRequests.empty() && schedule == Schedule::EarlyEnd) {
        mEarlyTransactionFrames = MIN_EARLY_TRANSACTION_FRAMES;
        mEarlyTransactionStartTime = mNow();
    }

    // An early transaction stays an early transaction.
    if (schedule == mTransactionSchedule || mTransactionSchedule == Schedule::EarlyEnd) {
        return std::nullopt;
    }
    mTransactionSchedule = schedule;
    return updateVsyncConfigLocked();
}

setTransactionSchedule()函数在此时传入了两个参数:一个为TransactionSchedule::Late,另个为空指针。而且,mVsyncModulator的成员mTransactionSchedule的初始值也为TransactionSchedule::Late,所以,函数执行到最后一个if()条件的时候,schedule == mTransactionSchedule是成立的,故而直接返回std::nullopt,下面的updateVsyncConfigLocked()执行不到。返回到modulateVsync()中的if()条件中config也为空,因此setVsyncConfig()也不会执行。

到这里applyTransactionState()执行结束。

setPowerModeInternal()

该函数传入的参数是primary diplay对应的DisplayDevice和hal::PowerMode::ON。

//frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {
    //省略

    const auto displayId = display->getPhysicalId();
    ALOGD("Setting power mode %d on display %s", mode, to_string(displayId).c_str());

    const hal::PowerMode currentMode = display->getPowerMode();
    if (mode == currentMode) {
        return;
    }

    display->setPowerMode(mode);

    //省略
    const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
    if (currentMode == hal::PowerMode::OFF) {
        // Keep uclamp in a separate syscall and set it before changing to RT due to b/190237315.
        // We can merge the syscall later.
        if (SurfaceFlinger::setSchedAttr(true) != NO_ERROR) {
            ALOGW("Couldn't set uclamp.min on display on: %s\n", strerror(errno));
        }
        if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
            ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
        }
        getHwComposer().setPowerMode(displayId, mode);
        if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) {
            getHwComposer().setVsyncEnabled(displayId, mHWCVsyncPendingState);
            mScheduler->onScreenAcquired(mAppConnectionHandle);
            mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
        }

        mVisibleRegionsDirty = true;
        mHasPoweredOff = true;
        repaintEverything();
    }
    //省略

    if (display->isPrimary()) {
        mTimeStats->setPowerMode(mode);
        mRefreshRateStats->setPowerMode(mode);
        mScheduler->setDisplayPowerState(mode == hal::PowerMode::ON);
    }

    ALOGD("Finished setting power mode %d on display %s", mode, to_string(displayId).c_str());
}

获取到的currentMode等于hal::PowerMode::OFF,所以只走第一个条件分支。setPowerMode()的功能:将PowerMode保存进自己的mPowerMode中、使能Output的OutputCompositionState的composition以及暂时设置dirtyRegion为全屏大小,OutputCompositionState的注释还是很丰富的:

//frameworks/native/services/surfaceflinger/CompositionEngine/src/Output.cpp
struct OutputCompositionState {
    // If false, composition will not be performed for this display
    bool isEnabled{false};

    // If false, this output is not considered secure
    bool isSecure{false};

    // If true, the current frame on this output uses client composition
    bool usesClientComposition{false};

    // If true, the current frame on this output uses device composition
    bool usesDeviceComposition{false};

    // If true, the client target should be flipped when performing client composition
    bool flipClientTarget{false};

    // If true, the current frame reused the buffer from a previous client composition
    bool reusedClientComposition{false};

    // If true, this output displays layers that are internal-only
    bool layerStackInternal{false};

    // The layer stack to display on this display
    uint32_t layerStackId{~0u};

    // The common space for all layers in the layer stack. layerStackSpace.content is the Rect
    // which gets projected on the display. The orientation of this space is always ROTATION_0.
    ProjectionSpace layerStackSpace;

    // Oriented physical display space. It will have the same size as displaySpace oriented to
    // match the orientation of layerStackSpace. The orientation of this space is always ROTATION_0.
    ProjectionSpace orientedDisplaySpace;

    // The space of the framebuffer. Its bounds match the size of the framebuffer and its
    // orientation matches the orientation of the display. Typically the framebuffer space will
    // be identical to the physical display space.
    ProjectionSpace framebufferSpace;

    // The space of the physical display. It is as big as the currently active display mode. The
    // content in this space can be rotated.
    ProjectionSpace displaySpace;

    // Transformation from layerStackSpace to displaySpace
    ui::Transform transform;

    // If true, RenderEngine filtering should be enabled
    bool needsFiltering{false};

    // The logical coordinates for the dirty region for the display.
    // dirtyRegion is semi-persistent state. Dirty rectangles are added to it
    // by the FE until composition happens, at which point it is cleared.
    Region dirtyRegion;

    // The logical coordinates for the undefined region for the display.
    // The undefined region is internal to the composition engine. It is
    // updated every time the geometry changes.
    Region undefinedRegion;

    // True if the last composition frame had visible layers
    bool lastCompositionHadVisibleLayers{false};

    // The color transform matrix to apply
    mat4 colorTransformMatrix;

    // Current active color mode
    ui::ColorMode colorMode{ui::ColorMode::NATIVE};

    // Current active render intent
    ui::RenderIntent renderIntent{ui::RenderIntent::COLORIMETRIC};

    // Current active dataspace
    ui::Dataspace dataspace{ui::Dataspace::UNKNOWN};

    // Current target dataspace
    ui::Dataspace targetDataspace{ui::Dataspace::UNKNOWN};

    // The earliest time to send the present command to the HAL
    std::chrono::steady_clock::time_point earliestPresentTime;

    // The previous present fence. Used together with earliestPresentTime
    // to prevent an early presentation of a frame.
    std::shared_ptr<FenceTime> previousPresentFence;

    // Current display brightness
    float displayBrightnessNits{-1.f};

    // SDR white point
    float sdrWhitePointNits{-1.f};

    // Debugging
    void dump(std::string& result) const;
};

getHwComposer().setPowerMode()最终会一路调用到HWC中,HWC需要调用DPU driver的接口power on硬件。

getHwComposer().setVsyncEnabled()同样也是调用到HWC中打开硬件VSYNC功能。

mScheduler->onScreenAcquired(mAppConnectionHandle)这个没有仔细的去研究,不过大概是这样的:打开Scheduler中mAppConnectionHandle中的vsync使能(synthetic设置为false)标记位,这里为什么要传入mAppConnectionHandle呢?我个人猜测可能是为BootAnimation的启动服务的,因为它在surfaceflinger启动完成以后就要紧接着运行显示起来,它要通过DisplayEventReceiver取获取vsync信号。

mScheduler->resyncToHardwareVsync()使surfaceflinger内部的vsync模型开始和硬件vsync同步。

最后是更新mTimeStats、mRefreshRateStats、mScheduler三个state的状态。

setCompositorTimingSnapped()函数暂未仔细研究,大概的功能是设置 SurfaceFlinger 的合成器时间,使其与显示的 vsync周期对齐。这有助于减少由于调度抖动(scheduling jitter)引起的合成和显示时间的误差,从而提高显示效果的准确性和一致性。

到这里,initializeDisplays()函数就讲完了。

primeShaderCache

在图形渲染中,着色器(Shader)是用于在 GPU 上执行渲染操作的小程序。着色器需要先编译,然后在运行时链接到特定的渲染管线中。这一过程可能会带来一定的性能开销,特别是在首次使用特定着色器时。

primeShaderCache用于控制是否在启动时预先加载(prime)着色器缓存(shader cache)。这个设置选项的意义在于提高首次渲染性能,减少应用程序在第一次使用特定着色器时的延迟。

但是这个功能有利也有弊,如果打开该功能surfaceflinger启动过程中会导致启动时间延长好几秒。对于开机时间要求比较严格的产品(如车机),建议将该功能关闭。

onPrimaryDisplaySizeChanged()

在之前创建FrameBufferSurface之后已经执行过一次了,不知再执行一次是为了什么,后续再研究。

StartPropertySetThread

首先,从HWC中获取硬件是否具备PRESENT_FENCE_IS_NOT_RELIABLE的能力。然后,创建一个StartPropertySetThread线程并将PRESENT_FENCE_IS_NOT_RELIABLE的结果保存在内,关于PRESENT_FENCE_IS_NOT_RELIABLE这个功能暂时没有去关注过。StartPropertySetThread线程的作用主要是启动Android的BootAnimation动画功能。BootAnimation的停止播放则是由WMS通知。

结尾

到这里,surfaceflinger的启动过程就整体结束了。本节没有去画图了,因为这节内容只创建了一个新内容:StartPropertySetThread。其他的内容在前面的章节都总结过了。

总体来看,启动过程还是蛮复杂的,画时间去整理一遍是很有必要的。

  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值