Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a77a7b6 authored by Ady Abraham's avatar Ady Abraham
Browse files

SurfaceFlinger: use setActiveConfigWithConstraints

Remove setActiveConfig and use setActiveConfigWithConstraints
instead. Use the return parameter of setActiveConfigWithConstraints to know
whether a refresh is required and when.

Fixes: 142753004
Bug: 141329414
Test: observe refresh rate switching thru systrace
Change-Id: Ie67a3be9180e7a367fc9e73425598d53a5fd6578
parent e0f9edb4
Loading
Loading
Loading
Loading
+25 −4
Original line number Original line Diff line number Diff line
@@ -247,8 +247,8 @@ nsecs_t HWComposer::getRefreshTimestamp(DisplayId displayId) const {
    // the refresh period and whatever closest timestamp we have.
    // the refresh period and whatever closest timestamp we have.
    std::lock_guard lock(displayData.lastHwVsyncLock);
    std::lock_guard lock(displayData.lastHwVsyncLock);
    nsecs_t now = systemTime(CLOCK_MONOTONIC);
    nsecs_t now = systemTime(CLOCK_MONOTONIC);
    auto vsyncPeriod = getActiveConfig(displayId)->getVsyncPeriod();
    auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
    return now - ((now - displayData.lastHwVsync) % vsyncPeriod);
    return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
}
}


bool HWComposer::isConnected(DisplayId displayId) const {
bool HWComposer::isConnected(DisplayId displayId) const {
@@ -291,6 +291,23 @@ std::shared_ptr<const HWC2::Display::Config> HWComposer::getActiveConfig(
    return config;
    return config;
}
}


// Composer 2.4

bool HWComposer::isVsyncPeriodSwitchSupported(DisplayId displayId) const {
    return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
}

nsecs_t HWComposer::getDisplayVsyncPeriod(DisplayId displayId) const {
    nsecs_t vsyncPeriodNanos;
    auto error = mDisplayData.at(displayId).hwcDisplay->getDisplayVsyncPeriod(&vsyncPeriodNanos);
    if (error != HWC2::Error::None) {
        LOG_DISPLAY_ERROR(displayId, "Failed to get Vsync Period");
        return 0;
    }

    return vsyncPeriodNanos;
}

int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
int HWComposer::getActiveConfigIndex(DisplayId displayId) const {
    RETURN_IF_INVALID_DISPLAY(displayId, -1);
    RETURN_IF_INVALID_DISPLAY(displayId, -1);


@@ -541,7 +558,9 @@ status_t HWComposer::setPowerMode(DisplayId displayId, int32_t intMode) {
    return NO_ERROR;
    return NO_ERROR;
}
}


status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) {
status_t HWComposer::setActiveConfigWithConstraints(
        DisplayId displayId, size_t configId, const HWC2::VsyncPeriodChangeConstraints& constraints,
        HWC2::VsyncPeriodChangeTimeline* outTimeline) {
    RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
    RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);


    auto& displayData = mDisplayData[displayId];
    auto& displayData = mDisplayData[displayId];
@@ -550,7 +569,9 @@ status_t HWComposer::setActiveConfig(DisplayId displayId, size_t configId) {
        return BAD_INDEX;
        return BAD_INDEX;
    }
    }


    auto error = displayData.hwcDisplay->setActiveConfig(displayData.configMap[configId]);
    auto error =
            displayData.hwcDisplay->setActiveConfigWithConstraints(displayData.configMap[configId],
                                                                   constraints, outTimeline);
    RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
    RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
    return NO_ERROR;
    return NO_ERROR;
}
}
+15 −6
Original line number Original line Diff line number Diff line
@@ -102,9 +102,6 @@ public:
    // set power mode
    // set power mode
    virtual status_t setPowerMode(DisplayId displayId, int mode) = 0;
    virtual status_t setPowerMode(DisplayId displayId, int mode) = 0;


    // set active config
    virtual status_t setActiveConfig(DisplayId displayId, size_t configId) = 0;

    // Sets a color transform to be applied to the result of composition
    // Sets a color transform to be applied to the result of composition
    virtual status_t setColorTransform(DisplayId displayId, const mat4& transform) = 0;
    virtual status_t setColorTransform(DisplayId displayId, const mat4& transform) = 0;


@@ -180,6 +177,14 @@ public:


    virtual bool isUsingVrComposer() const = 0;
    virtual bool isUsingVrComposer() const = 0;


    // Composer 2.4
    virtual bool isVsyncPeriodSwitchSupported(DisplayId displayId) const = 0;
    virtual nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const = 0;
    virtual status_t setActiveConfigWithConstraints(
            DisplayId displayId, size_t configId,
            const HWC2::VsyncPeriodChangeConstraints& constraints,
            HWC2::VsyncPeriodChangeTimeline* outTimeline) = 0;

    // for debugging ----------------------------------------------------------
    // for debugging ----------------------------------------------------------
    virtual void dump(std::string& out) const = 0;
    virtual void dump(std::string& out) const = 0;


@@ -232,9 +237,6 @@ public:
    // set power mode
    // set power mode
    status_t setPowerMode(DisplayId displayId, int mode) override;
    status_t setPowerMode(DisplayId displayId, int mode) override;


    // set active config
    status_t setActiveConfig(DisplayId displayId, size_t configId) override;

    // Sets a color transform to be applied to the result of composition
    // Sets a color transform to be applied to the result of composition
    status_t setColorTransform(DisplayId displayId, const mat4& transform) override;
    status_t setColorTransform(DisplayId displayId, const mat4& transform) override;


@@ -305,6 +307,13 @@ public:


    bool isUsingVrComposer() const override;
    bool isUsingVrComposer() const override;


    // Composer 2.4
    bool isVsyncPeriodSwitchSupported(DisplayId displayId) const override;
    nsecs_t getDisplayVsyncPeriod(DisplayId displayId) const override;
    status_t setActiveConfigWithConstraints(DisplayId displayId, size_t configId,
                                            const HWC2::VsyncPeriodChangeConstraints& constraints,
                                            HWC2::VsyncPeriodChangeTimeline* outTimeline) override;

    // for debugging ----------------------------------------------------------
    // for debugging ----------------------------------------------------------
    void dump(std::string& out) const override;
    void dump(std::string& out) const override;


+38 −13
Original line number Original line Diff line number Diff line
@@ -59,11 +59,13 @@
namespace android {
namespace android {


Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
                     const scheduler::RefreshRateConfigs& refreshRateConfig)
                     const scheduler::RefreshRateConfigs& refreshRateConfig,
                     ISchedulerCallback& schedulerCallback)
      : mPrimaryDispSync(new impl::DispSync("SchedulerDispSync",
      : mPrimaryDispSync(new impl::DispSync("SchedulerDispSync",
                                            sysprop::running_without_sync_framework(true))),
                                            sysprop::running_without_sync_framework(true))),
        mEventControlThread(new impl::EventControlThread(std::move(function))),
        mEventControlThread(new impl::EventControlThread(std::move(function))),
        mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
        mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
        mSchedulerCallback(schedulerCallback),
        mRefreshRateConfigs(refreshRateConfig) {
        mRefreshRateConfigs(refreshRateConfig) {
    using namespace sysprop;
    using namespace sysprop;


@@ -104,10 +106,12 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,


Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
                     std::unique_ptr<EventControlThread> eventControlThread,
                     std::unique_ptr<EventControlThread> eventControlThread,
                     const scheduler::RefreshRateConfigs& configs)
                     const scheduler::RefreshRateConfigs& configs,
                     ISchedulerCallback& schedulerCallback)
      : mPrimaryDispSync(std::move(primaryDispSync)),
      : mPrimaryDispSync(std::move(primaryDispSync)),
        mEventControlThread(std::move(eventControlThread)),
        mEventControlThread(std::move(eventControlThread)),
        mSupportKernelTimer(false),
        mSupportKernelTimer(false),
        mSchedulerCallback(schedulerCallback),
        mRefreshRateConfigs(configs) {}
        mRefreshRateConfigs(configs) {}


Scheduler::~Scheduler() {
Scheduler::~Scheduler() {
@@ -368,12 +372,7 @@ void Scheduler::chooseRefreshRateForContent() {
        mFeatures.configId = newConfigId;
        mFeatures.configId = newConfigId;
    };
    };
    auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
    auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
    changeRefreshRate(newRefreshRate, ConfigEvent::Changed);
    mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed);
}

void Scheduler::setSchedulerCallback(android::Scheduler::ISchedulerCallback* callback) {
    std::lock_guard<std::mutex> lock(mCallbackLock);
    mSchedulerCallback = callback;
}
}


void Scheduler::resetIdleTimer() {
void Scheduler::resetIdleTimer() {
@@ -486,7 +485,7 @@ void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventO
        }
        }
    }
    }
    const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
    const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
    changeRefreshRate(newRefreshRate, event);
    mSchedulerCallback.changeRefreshRate(newRefreshRate, event);
}
}


HwcConfigIndexType Scheduler::calculateRefreshRateType() {
HwcConfigIndexType Scheduler::calculateRefreshRateType() {
@@ -526,10 +525,36 @@ std::optional<HwcConfigIndexType> Scheduler::getPreferredConfigId() {
    return mFeatures.configId;
    return mFeatures.configId;
}
}


void Scheduler::changeRefreshRate(const RefreshRate& refreshRate, ConfigEvent configEvent) {
void Scheduler::onNewVsyncPeriodChangeTimeline(const HWC2::VsyncPeriodChangeTimeline& timeline) {
    std::lock_guard<std::mutex> lock(mCallbackLock);
    if (timeline.refreshRequired) {
    if (mSchedulerCallback) {
        mSchedulerCallback.repaintEverythingForHWC();
        mSchedulerCallback->changeRefreshRate(refreshRate, configEvent);
    }

    std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
    mLastVsyncPeriodChangeTimeline = std::make_optional(timeline);

    const auto maxAppliedTime = systemTime() + MAX_VSYNC_APPLIED_TIME.count();
    if (timeline.newVsyncAppliedTimeNanos > maxAppliedTime) {
        mLastVsyncPeriodChangeTimeline->newVsyncAppliedTimeNanos = maxAppliedTime;
    }
}

void Scheduler::onDisplayRefreshed(nsecs_t timestamp) {
    bool callRepaint = false;
    {
        std::lock_guard<std::mutex> lock(mVsyncTimelineLock);
        if (mLastVsyncPeriodChangeTimeline && mLastVsyncPeriodChangeTimeline->refreshRequired) {
            if (mLastVsyncPeriodChangeTimeline->refreshTimeNanos < timestamp) {
                mLastVsyncPeriodChangeTimeline->refreshRequired = false;
            } else {
                // We need to send another refresh as refreshTimeNanos is still in the future
                callRepaint = true;
            }
        }
    }

    if (callRepaint) {
        mSchedulerCallback.repaintEverythingForHWC();
    }
    }
}
}


+22 −15
Original line number Original line Diff line number Diff line
@@ -41,22 +41,24 @@ class FenceTime;
class InjectVSyncSource;
class InjectVSyncSource;
struct DisplayStateInfo;
struct DisplayStateInfo;


class Scheduler {
public:
    using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
    using ConfigEvent = scheduler::RefreshRateConfigEvent;

class ISchedulerCallback {
class ISchedulerCallback {
public:
public:
    virtual ~ISchedulerCallback() = default;
    virtual ~ISchedulerCallback() = default;
        virtual void changeRefreshRate(const RefreshRate&, ConfigEvent) = 0;
    virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
                                   scheduler::RefreshRateConfigEvent) = 0;
    virtual void repaintEverythingForHWC() = 0;
};
};


class Scheduler {
public:
    using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
    using ConfigEvent = scheduler::RefreshRateConfigEvent;

    // Indicates whether to start the transaction early, or at vsync time.
    // Indicates whether to start the transaction early, or at vsync time.
    enum class TransactionStart { EARLY, NORMAL };
    enum class TransactionStart { EARLY, NORMAL };


    Scheduler(impl::EventControlThread::SetVSyncEnabledFunction,
    Scheduler(impl::EventControlThread::SetVSyncEnabledFunction,
              const scheduler::RefreshRateConfigs&);
              const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback);


    virtual ~Scheduler();
    virtual ~Scheduler();


@@ -114,9 +116,6 @@ public:
    // Detects content using layer history, and selects a matching refresh rate.
    // Detects content using layer history, and selects a matching refresh rate.
    void chooseRefreshRateForContent();
    void chooseRefreshRateForContent();


    // Called by Scheduler to control SurfaceFlinger operations.
    void setSchedulerCallback(ISchedulerCallback*);

    bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
    bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
    void resetIdleTimer();
    void resetIdleTimer();


@@ -131,6 +130,12 @@ public:
    // Get the appropriate refresh for current conditions.
    // Get the appropriate refresh for current conditions.
    std::optional<HwcConfigIndexType> getPreferredConfigId();
    std::optional<HwcConfigIndexType> getPreferredConfigId();


    // Notifies the scheduler about a refresh rate timeline change.
    void onNewVsyncPeriodChangeTimeline(const HWC2::VsyncPeriodChangeTimeline& timeline);

    // Notifies the scheduler when the display was refreshed
    void onDisplayRefreshed(nsecs_t timestamp);

private:
private:
    friend class TestableScheduler;
    friend class TestableScheduler;


@@ -142,7 +147,7 @@ private:


    // Used by tests to inject mocks.
    // Used by tests to inject mocks.
    Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>,
    Scheduler(std::unique_ptr<DispSync>, std::unique_ptr<EventControlThread>,
              const scheduler::RefreshRateConfigs&);
              const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback);


    std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs,
    std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs,
                                                           nsecs_t offsetThresholdForNextVsync);
                                                           nsecs_t offsetThresholdForNextVsync);
@@ -165,8 +170,6 @@ private:
    void setVsyncPeriod(nsecs_t period);
    void setVsyncPeriod(nsecs_t period);


    HwcConfigIndexType calculateRefreshRateType() REQUIRES(mFeatureStateLock);
    HwcConfigIndexType calculateRefreshRateType() REQUIRES(mFeatureStateLock);
    // Acquires a lock and calls the ChangeRefreshRateCallback with given parameters.
    void changeRefreshRate(const RefreshRate&, ConfigEvent);


    // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
    // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
    struct Connection {
    struct Connection {
@@ -203,8 +206,7 @@ private:
    // Timer used to monitor display power mode.
    // Timer used to monitor display power mode.
    std::optional<scheduler::OneShotTimer> mDisplayPowerTimer;
    std::optional<scheduler::OneShotTimer> mDisplayPowerTimer;


    std::mutex mCallbackLock;
    ISchedulerCallback& mSchedulerCallback;
    ISchedulerCallback* mSchedulerCallback GUARDED_BY(mCallbackLock) = nullptr;


    // In order to make sure that the features don't override themselves, we need a state machine
    // In order to make sure that the features don't override themselves, we need a state machine
    // to keep track which feature requested the config change.
    // to keep track which feature requested the config change.
@@ -223,6 +225,11 @@ private:
    } mFeatures GUARDED_BY(mFeatureStateLock);
    } mFeatures GUARDED_BY(mFeatureStateLock);


    const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
    const scheduler::RefreshRateConfigs& mRefreshRateConfigs;

    std::mutex mVsyncTimelineLock;
    std::optional<HWC2::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
            GUARDED_BY(mVsyncTimelineLock);
    static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
};
};


} // namespace android
} // namespace android
+55 −13
Original line number Original line Diff line number Diff line
@@ -1003,11 +1003,25 @@ bool SurfaceFlinger::performSetActiveConfig() {
    LOG_ALWAYS_FATAL_IF(!displayId);
    LOG_ALWAYS_FATAL_IF(!displayId);


    ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.fps);
    ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.fps);
    getHwComposer().setActiveConfig(*displayId, mUpcomingActiveConfig.configId.value());


    // we need to submit an empty frame to HWC to start the process
    // TODO(b/142753666) use constrains
    HWC2::VsyncPeriodChangeConstraints constraints;
    constraints.desiredTimeNanos = systemTime();
    constraints.seamlessRequired = false;

    HWC2::VsyncPeriodChangeTimeline outTimeline;
    auto status =
            getHwComposer().setActiveConfigWithConstraints(*displayId,
                                                           mUpcomingActiveConfig.configId.value(),
                                                           constraints, &outTimeline);
    if (status != NO_ERROR) {
        LOG_ALWAYS_FATAL("setActiveConfigWithConstraints failed: %d", status);
        return false;
    }

    mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);
    // Scheduler will submit an empty frame to HWC if needed.
    mCheckPendingFence = true;
    mCheckPendingFence = true;
    mEventQueue->invalidate();
    return false;
    return false;
}
}


@@ -1360,8 +1374,7 @@ nsecs_t SurfaceFlinger::getVsyncPeriod() const {
        return 0;
        return 0;
    }
    }


    const auto config = getHwComposer().getActiveConfig(*displayId);
    return getHwComposer().getDisplayVsyncPeriod(*displayId);
    return config ? config->getVsyncPeriod() : 0;
}
}


void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
@@ -1447,9 +1460,13 @@ void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDis
}
}


void SurfaceFlinger::onVsyncPeriodTimingChangedReceived(
void SurfaceFlinger::onVsyncPeriodTimingChangedReceived(
        int32_t /*sequenceId*/, hwc2_display_t /*display*/,
        int32_t sequenceId, hwc2_display_t /*display*/,
        const hwc_vsync_period_change_timeline_t& /*updatedTimeline*/) {
        const hwc_vsync_period_change_timeline_t& updatedTimeline) {
    // TODO(b/142753004): use timeline when changing refresh rate
    Mutex::Autolock lock(mStateLock);
    if (sequenceId != getBE().mComposerSequenceId) {
        return;
    }
    mScheduler->onNewVsyncPeriodChangeTimeline(updatedTimeline);
}
}


void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) {
void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) {
@@ -1760,11 +1777,17 @@ void SurfaceFlinger::handleMessageRefresh() {


    mGeometryInvalid = false;
    mGeometryInvalid = false;


    // Store the present time just before calling to the composition engine so we could notify
    // the scheduler.
    const auto presentTime = systemTime();

    mCompositionEngine->present(refreshArgs);
    mCompositionEngine->present(refreshArgs);
    mTimeStats->recordFrameDuration(mFrameStartTime, systemTime());
    mTimeStats->recordFrameDuration(mFrameStartTime, systemTime());
    // Reset the frame start time now that we've recorded this frame.
    // Reset the frame start time now that we've recorded this frame.
    mFrameStartTime = 0;
    mFrameStartTime = 0;


    mScheduler->onDisplayRefreshed(presentTime);

    postFrame();
    postFrame();
    postComposition();
    postComposition();


@@ -2550,7 +2573,7 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) {
    // start the EventThread
    // start the EventThread
    mScheduler =
    mScheduler =
            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
                                         *mRefreshRateConfigs);
                                         *mRefreshRateConfigs, *this);
    mAppConnectionHandle =
    mAppConnectionHandle =
            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
            mScheduler->createConnection("app", mPhaseOffsets->getCurrentAppOffset(),
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
                                         mPhaseOffsets->getOffsetThresholdForNextVsync(),
@@ -2569,8 +2592,6 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) {
    mRegionSamplingThread =
    mRegionSamplingThread =
            new RegionSamplingThread(*this, *mScheduler,
            new RegionSamplingThread(*this, *mScheduler,
                                     RegionSamplingThread::EnvironmentTimingTunables());
                                     RegionSamplingThread::EnvironmentTimingTunables());

    mScheduler->setSchedulerCallback(this);
}
}


void SurfaceFlinger::commitTransaction()
void SurfaceFlinger::commitTransaction()
@@ -4306,8 +4327,8 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co
                      "  refresh-rate              : %f fps\n"
                      "  refresh-rate              : %f fps\n"
                      "  x-dpi                     : %f\n"
                      "  x-dpi                     : %f\n"
                      "  y-dpi                     : %f\n",
                      "  y-dpi                     : %f\n",
                      1e9 / activeConfig->getVsyncPeriod(), activeConfig->getDpiX(),
                      1e9 / getHwComposer().getDisplayVsyncPeriod(*displayId),
                      activeConfig->getDpiY());
                      activeConfig->getDpiX(), activeConfig->getDpiY());
    }
    }


    StringAppendF(&result, "  transaction time: %f us\n", inTransactionDuration / 1000.0);
    StringAppendF(&result, "  transaction time: %f us\n", inTransactionDuration / 1000.0);
@@ -5400,6 +5421,27 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& disp
void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
                                                      const std::vector<int32_t>& allowedConfigs) {
                                                      const std::vector<int32_t>& allowedConfigs) {
    if (!display->isPrimary()) {
    if (!display->isPrimary()) {
        // TODO(b/144711714): For non-primary displays we should be able to set an active config
        // as well. For now, just call directly to setActiveConfigWithConstraints but ideally
        // it should go thru setDesiredActiveConfig, similar to primary display.
        ALOGV("setAllowedDisplayConfigsInternal for non-primary display");
        const auto displayId = display->getId();
        LOG_ALWAYS_FATAL_IF(!displayId);

        HWC2::VsyncPeriodChangeConstraints constraints;
        constraints.desiredTimeNanos = systemTime();
        constraints.seamlessRequired = false;

        HWC2::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
        getHwComposer().setActiveConfigWithConstraints(*displayId, allowedConfigs[0], constraints,
                                                       &timeline);
        if (timeline.refreshRequired) {
            repaintEverythingForHWC();
        }

        auto configId = HwcConfigIndexType(allowedConfigs[0]);
        display->setActiveConfig(configId);
        mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, configId);
        return;
        return;
    }
    }


Loading