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

Commit 22488f69 authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Remove per-display state in scheduler

This CL removes per-display RefreshRateConfigs and AllowedDisplayConfigs
to avoid bugs in the untested multi-display code path of the scheduler,
adds checks to prevent crashes if the internal display is removed, and
cleans up related code by:

1) Replacing AllowedDisplayConfigs with a simple set.
2) Making setAllowedDisplayConfigs consistent with setPowerMode.
3) Removing unnecessary locking and allocation.

Bug: 129433906
Test: Boot with single/multiple display(s)
Change-Id: I3f59e9bdeaceb2cf48b4b9b71cd27f1d6a574680
(cherry picked from commit 64536511)
parent 3c9aec6d
Loading
Loading
Loading
Loading
+0 −68
Original line number Original line Diff line number Diff line
/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <log/log.h>
#include <vector>

/*
 * Used to represent the Display Configurations allowed to be set by SurfaceFlinger
 */
class AllowedDisplayConfigs {
private:
    // Defining ConstructorTag as private to prevent instantiating this class from outside
    // while still allowing it to be constructed by std::make_unique
    struct ConstructorTag {};

public:
    AllowedDisplayConfigs(ConstructorTag) {}

    class Builder {
    public:
        Builder()
              : mAllowedDisplayConfigs(std::make_unique<AllowedDisplayConfigs>(ConstructorTag{})) {}

        std::unique_ptr<const AllowedDisplayConfigs> build() {
            return std::move(mAllowedDisplayConfigs);
        }

        // add a config to the allowed config set
        Builder& addConfig(int32_t config) {
            mAllowedDisplayConfigs->addConfig(config);
            return *this;
        }

    private:
        std::unique_ptr<AllowedDisplayConfigs> mAllowedDisplayConfigs;
    };

    bool isConfigAllowed(int32_t config) const {
        return (std::find(mConfigs.begin(), mConfigs.end(), config) != mConfigs.end());
    }

    void getAllowedConfigs(std::vector<int32_t>* outConfigs) const {
        if (outConfigs) {
            *outConfigs = mConfigs;
        }
    }

private:
    // add a config to the allowed config set
    void addConfig(int32_t config) { mConfigs.push_back(config); }

    std::vector<int32_t> mConfigs;
};
+5 −9
Original line number Original line Diff line number Diff line
@@ -51,13 +51,7 @@ public:


    // TODO(b/122916473): Get this information from configs prepared by vendors, instead of
    // TODO(b/122916473): Get this information from configs prepared by vendors, instead of
    // baking them in.
    // baking them in.
    explicit RefreshRateConfigs(
    const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() const {
            const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
        init(configs);
    }
    ~RefreshRateConfigs() = default;

    const std::map<RefreshRateType, std::shared_ptr<RefreshRate>>& getRefreshRates() {
        return mRefreshRates;
        return mRefreshRates;
    }
    }
    std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) {
    std::shared_ptr<RefreshRate> getRefreshRate(RefreshRateType type) {
@@ -68,8 +62,9 @@ public:
        return nullptr;
        return nullptr;
    }
    }


private:
    void populate(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
    void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
        mRefreshRates.clear();

        // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
        // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
        mRefreshRates.emplace(RefreshRateType::POWER_SAVING,
        mRefreshRates.emplace(RefreshRateType::POWER_SAVING,
                              std::make_shared<RefreshRate>(
                              std::make_shared<RefreshRate>(
@@ -120,6 +115,7 @@ private:
        }
        }
    }
    }


private:
    std::map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates;
    std::map<RefreshRateType, std::shared_ptr<RefreshRate>> mRefreshRates;
};
};


+11 −15
Original line number Original line Diff line number Diff line
@@ -41,12 +41,8 @@ class RefreshRateStats {
    static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;
    static constexpr int64_t MS_PER_DAY = 24 * MS_PER_HOUR;


public:
public:
    explicit RefreshRateStats(const std::shared_ptr<RefreshRateConfigs>& refreshRateConfigs,
    RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats)
                              const std::shared_ptr<TimeStats>& timeStats)
          : mRefreshRateConfigs(refreshRateConfigs), mTimeStats(timeStats) {}
          : mRefreshRateConfigs(refreshRateConfigs),
            mTimeStats(timeStats),
            mPreviousRecordedTime(systemTime()) {}
    ~RefreshRateStats() = default;


    // Sets power mode. We only collect the information when the power mode is not
    // Sets power mode. We only collect the information when the power mode is not
    // HWC_POWER_MODE_NORMAL. When power mode is HWC_POWER_MODE_NORMAL, we collect the stats based
    // HWC_POWER_MODE_NORMAL. When power mode is HWC_POWER_MODE_NORMAL, we collect the stats based
@@ -83,7 +79,7 @@ public:
        flushTime();
        flushTime();


        std::unordered_map<std::string, int64_t> totalTime;
        std::unordered_map<std::string, int64_t> totalTime;
        for (auto [type, config] : mRefreshRateConfigs->getRefreshRates()) {
        for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
            int64_t totalTimeForConfig = 0;
            int64_t totalTimeForConfig = 0;
            if (!config) {
            if (!config) {
                continue;
                continue;
@@ -98,11 +94,11 @@ public:


    // Traverses through the map of config modes and returns how long they've been running in easy
    // Traverses through the map of config modes and returns how long they've been running in easy
    // to read format.
    // to read format.
    std::string doDump() {
    std::string doDump() const {
        std::ostringstream stream;
        std::ostringstream stream;
        stream << "+  Refresh rate: running time in seconds\n";
        stream << "+  Refresh rate: running time in seconds\n";
        for (auto stats : getTotalTimes()) {
        for (const auto& [name, time] : const_cast<RefreshRateStats*>(this)->getTotalTimes()) {
            stream << stats.first.c_str() << ": " << getDateFormatFromMs(stats.second) << "\n";
            stream << name << ": " << getDateFormatFromMs(time) << '\n';
        }
        }
        return stream.str();
        return stream.str();
    }
    }
@@ -126,12 +122,12 @@ private:
        mPreviousRecordedTime = currentTime;
        mPreviousRecordedTime = currentTime;


        mConfigModesTotalTime[mode] += timeElapsedMs;
        mConfigModesTotalTime[mode] += timeElapsedMs;
        for (const auto& [type, config] : mRefreshRateConfigs->getRefreshRates()) {
        for (const auto& [type, config] : mRefreshRateConfigs.getRefreshRates()) {
            if (!config) {
            if (!config) {
                continue;
                continue;
            }
            }
            if (config->configId == mode) {
            if (config->configId == mode) {
                mTimeStats->recordRefreshRate(config->fps, timeElapsed);
                mTimeStats.recordRefreshRate(config->fps, timeElapsed);
            }
            }
        }
        }
    }
    }
@@ -148,17 +144,17 @@ private:
    }
    }


    // Keeps information about refresh rate configs that device has.
    // Keeps information about refresh rate configs that device has.
    std::shared_ptr<RefreshRateConfigs> mRefreshRateConfigs;
    const RefreshRateConfigs& mRefreshRateConfigs;


    // Aggregate refresh rate statistics for telemetry.
    // Aggregate refresh rate statistics for telemetry.
    std::shared_ptr<TimeStats> mTimeStats;
    TimeStats& mTimeStats;


    int64_t mCurrentConfigMode = SCREEN_OFF_CONFIG_ID;
    int64_t mCurrentConfigMode = SCREEN_OFF_CONFIG_ID;
    int32_t mCurrentPowerMode = HWC_POWER_MODE_OFF;
    int32_t mCurrentPowerMode = HWC_POWER_MODE_OFF;


    std::unordered_map<int /* power mode */, int64_t /* duration in ms */> mConfigModesTotalTime;
    std::unordered_map<int /* power mode */, int64_t /* duration in ms */> mConfigModesTotalTime;


    nsecs_t mPreviousRecordedTime;
    nsecs_t mPreviousRecordedTime = systemTime();
};
};


} // namespace scheduler
} // namespace scheduler
+54 −114
Original line number Original line Diff line number Diff line
@@ -558,14 +558,10 @@ void SurfaceFlinger::bootFinished()
        mBootStage = BootStage::FINISHED;
        mBootStage = BootStage::FINISHED;


        // set the refresh rate according to the policy
        // set the refresh rate according to the policy
        const auto displayId = getInternalDisplayIdLocked();
        LOG_ALWAYS_FATAL_IF(!displayId);

        const auto& performanceRefreshRate =
        const auto& performanceRefreshRate =
                mRefreshRateConfigs[*displayId]->getRefreshRate(RefreshRateType::PERFORMANCE);
                mRefreshRateConfigs.getRefreshRate(RefreshRateType::PERFORMANCE);


        if (performanceRefreshRate &&
        if (performanceRefreshRate && isDisplayConfigAllowed(performanceRefreshRate->configId)) {
            isConfigAllowed(*displayId, performanceRefreshRate->configId)) {
            setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
            setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None);
        } else {
        } else {
            setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
            setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None);
@@ -706,12 +702,8 @@ void SurfaceFlinger::init() {
                    setRefreshRateTo(type, event);
                    setRefreshRateTo(type, event);
                });
                });
    }
    }
    mRefreshRateConfigs[*display->getId()] = std::make_shared<scheduler::RefreshRateConfigs>(
    mRefreshRateConfigs.populate(getHwComposer().getConfigs(*display->getId()));
            getHwComposer().getConfigs(*display->getId()));
    mRefreshRateStats.setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));
    mRefreshRateStats =
            std::make_unique<scheduler::RefreshRateStats>(mRefreshRateConfigs[*display->getId()],
                                                          mTimeStats);
    mRefreshRateStats->setConfigMode(getHwComposer().getActiveConfigIndex(*display->getId()));


    ALOGV("Done initializing");
    ALOGV("Done initializing");
}
}
@@ -786,12 +778,14 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps(
    return NO_ERROR;
    return NO_ERROR;
}
}


status_t SurfaceFlinger::getDisplayConfigsLocked(const sp<IBinder>& displayToken,
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken,
                                           Vector<DisplayInfo>* configs) {
                                           Vector<DisplayInfo>* configs) {
    if (!displayToken || !configs) {
    if (!displayToken || !configs) {
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    Mutex::Autolock lock(mStateLock);

    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
    if (!displayId) {
    if (!displayId) {
        return NAME_NOT_FOUND;
        return NAME_NOT_FOUND;
@@ -917,18 +911,6 @@ int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
    ATRACE_CALL();
    ATRACE_CALL();


    // Lock is acquired by setRefreshRateTo.
    const auto display = getDisplayDeviceLocked(info.displayToken);
    if (!display) {
        ALOGE("Attempt to set active config %d for invalid display token %p", info.configId,
              info.displayToken.get());
        return;
    }
    if (display->isVirtual()) {
        ALOGW("Attempt to set active config %d for virtual display", info.configId);
        return;
    }

    // Don't check against the current mode yet. Worst case we set the desired
    // Don't check against the current mode yet. Worst case we set the desired
    // config twice. However event generation config might have changed so we need to update it
    // config twice. However event generation config might have changed so we need to update it
    // accordingly
    // accordingly
@@ -964,23 +946,28 @@ status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mo
void SurfaceFlinger::setActiveConfigInternal() {
void SurfaceFlinger::setActiveConfigInternal() {
    ATRACE_CALL();
    ATRACE_CALL();


    const auto display = getDefaultDisplayDeviceLocked();
    if (!display) {
        return;
    }

    std::lock_guard<std::mutex> lock(mActiveConfigLock);
    std::lock_guard<std::mutex> lock(mActiveConfigLock);
    mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
    mRefreshRateStats.setConfigMode(mUpcomingActiveConfig.configId);


    const auto display = getDisplayDeviceLocked(mUpcomingActiveConfig.displayToken);
    display->setActiveConfig(mUpcomingActiveConfig.configId);
    display->setActiveConfig(mUpcomingActiveConfig.configId);


    mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
    mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
    const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
    mVsyncModulator.setPhaseOffsets(early, gl, late);
    mVsyncModulator.setPhaseOffsets(early, gl, late);
    ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
    ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);

    if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
    if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
        mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
        mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value,
                                    mUpcomingActiveConfig.configId);
                                    mUpcomingActiveConfig.configId);
    }
    }
}
}


bool SurfaceFlinger::performSetActiveConfig() NO_THREAD_SAFETY_ANALYSIS {
bool SurfaceFlinger::performSetActiveConfig() {
    ATRACE_CALL();
    ATRACE_CALL();
    if (mCheckPendingFence) {
    if (mCheckPendingFence) {
        if (mPreviousPresentFence != Fence::NO_FENCE &&
        if (mPreviousPresentFence != Fence::NO_FENCE &&
@@ -1006,7 +993,7 @@ bool SurfaceFlinger::performSetActiveConfig() NO_THREAD_SAFETY_ANALYSIS {
        desiredActiveConfig = mDesiredActiveConfig;
        desiredActiveConfig = mDesiredActiveConfig;
    }
    }


    const auto display = getDisplayDevice(desiredActiveConfig.displayToken);
    const auto display = getDefaultDisplayDeviceLocked();
    if (!display || display->getActiveConfig() == desiredActiveConfig.configId) {
    if (!display || display->getActiveConfig() == desiredActiveConfig.configId) {
        // display is not valid or we are already in the requested mode
        // display is not valid or we are already in the requested mode
        // on both cases there is nothing left to do
        // on both cases there is nothing left to do
@@ -1021,7 +1008,7 @@ bool SurfaceFlinger::performSetActiveConfig() NO_THREAD_SAFETY_ANALYSIS {
    // Desired active config was set, it is different than the config currently in use, however
    // Desired active config was set, it is different than the config currently in use, however
    // allowed configs might have change by the time we process the refresh.
    // allowed configs might have change by the time we process the refresh.
    // Make sure the desired config is still allowed
    // Make sure the desired config is still allowed
    if (!isConfigAllowed(*display->getId(), desiredActiveConfig.configId)) {
    if (!isDisplayConfigAllowed(desiredActiveConfig.configId)) {
        std::lock_guard<std::mutex> lock(mActiveConfigLock);
        std::lock_guard<std::mutex> lock(mActiveConfigLock);
        mDesiredActiveConfig.configId = display->getActiveConfig();
        mDesiredActiveConfig.configId = display->getActiveConfig();
        return false;
        return false;
@@ -1422,29 +1409,19 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
    *compositorTiming = getBE().mCompositorTiming;
    *compositorTiming = getBE().mCompositorTiming;
}
}


bool SurfaceFlinger::isConfigAllowed(const DisplayId& displayId, int32_t config) {
bool SurfaceFlinger::isDisplayConfigAllowed(int32_t configId) {
    std::lock_guard lock(mAllowedConfigsLock);
    return mAllowedDisplayConfigs.empty() || mAllowedDisplayConfigs.count(configId);

    // if allowed configs are not set yet for this display, every config is considered allowed
    if (mAllowedConfigs.find(displayId) == mAllowedConfigs.end()) {
        return true;
    }

    return mAllowedConfigs[displayId]->isConfigAllowed(config);
}
}


void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::ConfigEvent event) {
void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::ConfigEvent event) {
    if (mBootStage != BootStage::FINISHED) {
    const auto display = getDefaultDisplayDeviceLocked();
    if (!display || mBootStage != BootStage::FINISHED) {
        return;
        return;
    }
    }
    ATRACE_CALL();
    ATRACE_CALL();


    // Don't do any updating if the current fps is the same as the new one.
    // Don't do any updating if the current fps is the same as the new one.
    const auto displayId = getInternalDisplayIdLocked();
    const auto& refreshRateConfig = mRefreshRateConfigs.getRefreshRate(refreshRate);
    LOG_ALWAYS_FATAL_IF(!displayId);
    const auto displayToken = getInternalDisplayTokenLocked();

    const auto& refreshRateConfig = mRefreshRateConfigs[*displayId]->getRefreshRate(refreshRate);
    if (!refreshRateConfig) {
    if (!refreshRateConfig) {
        ALOGV("Skipping refresh rate change request for unsupported rate.");
        ALOGV("Skipping refresh rate change request for unsupported rate.");
        return;
        return;
@@ -1452,19 +1429,18 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::Co


    const int desiredConfigId = refreshRateConfig->configId;
    const int desiredConfigId = refreshRateConfig->configId;


    if (!isConfigAllowed(*displayId, desiredConfigId)) {
    if (!isDisplayConfigAllowed(desiredConfigId)) {
        ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId);
        ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId);
        return;
        return;
    }
    }


    mPhaseOffsets->setRefreshRateType(refreshRate);
    mPhaseOffsets->setRefreshRateType(refreshRate);


    const auto display = getDisplayDeviceLocked(displayToken);
    if (desiredConfigId == display->getActiveConfig()) {
    if (desiredConfigId == display->getActiveConfig()) {
        return;
        return;
    }
    }


    setDesiredActiveConfig({refreshRate, desiredConfigId, getInternalDisplayTokenLocked(), event});
    setDesiredActiveConfig({refreshRate, desiredConfigId, event});
}
}


void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
@@ -1604,7 +1580,7 @@ void SurfaceFlinger::updateVrFlinger() {
    setTransactionFlags(eDisplayTransactionNeeded);
    setTransactionFlags(eDisplayTransactionNeeded);
}
}


void SurfaceFlinger::onMessageReceived(int32_t what) {
void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS {
    ATRACE_CALL();
    ATRACE_CALL();
    switch (what) {
    switch (what) {
        case MessageQueue::INVALIDATE: {
        case MessageQueue::INVALIDATE: {
@@ -2483,9 +2459,6 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() {
                state.displayName = info->name;
                state.displayName = info->name;
                mCurrentState.displays.add(mPhysicalDisplayTokens[info->id], state);
                mCurrentState.displays.add(mPhysicalDisplayTokens[info->id], state);
                mInterceptor->saveDisplayCreation(state);
                mInterceptor->saveDisplayCreation(state);
                // TODO(b/123715322): Removes the per-display state that was added to the scheduler.
                mRefreshRateConfigs[info->id] = std::make_shared<scheduler::RefreshRateConfigs>(
                        getHwComposer().getConfigs(info->id));
            }
            }
        } else {
        } else {
            ALOGV("Removing display %s", to_string(info->id).c_str());
            ALOGV("Removing display %s", to_string(info->id).c_str());
@@ -2497,7 +2470,6 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() {
                mCurrentState.displays.removeItemsAt(index);
                mCurrentState.displays.removeItemsAt(index);
            }
            }
            mPhysicalDisplayTokens.erase(info->id);
            mPhysicalDisplayTokens.erase(info->id);
            mRefreshRateConfigs.erase(info->id);
        }
        }


        processDisplayChangesLocked();
        processDisplayChangesLocked();
@@ -4345,10 +4317,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int


    if (display->isPrimary()) {
    if (display->isPrimary()) {
        mTimeStats->setPowerMode(mode);
        mTimeStats->setPowerMode(mode);
        if (mRefreshRateStats) {
        mRefreshRateStats.setPowerMode(mode);
            // Update refresh rate stats.
            mRefreshRateStats->setPowerMode(mode);
        }
    }
    }


    ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str());
    ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str());
@@ -4876,7 +4845,7 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co
    result.append("\nScheduler state:\n");
    result.append("\nScheduler state:\n");
    result.append(mScheduler->doDump() + "\n");
    result.append(mScheduler->doDump() + "\n");
    StringAppendF(&result, "+  Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off");
    StringAppendF(&result, "+  Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off");
    result.append(mRefreshRateStats->doDump() + "\n");
    result.append(mRefreshRateStats.doDump() + "\n");
}
}


const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) {
const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(DisplayId displayId) {
@@ -5816,95 +5785,66 @@ void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& disp
    }
    }
}
}


void SurfaceFlinger::setAllowedDisplayConfigsInternal(
void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
        const android::sp<android::IBinder>& displayToken,
                                                      const std::vector<int32_t>& allowedConfigs) {
        std::unique_ptr<const AllowedDisplayConfigs>&& allowedConfigs) {
    if (!display->isPrimary()) {
    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
    if (!displayId) {
        ALOGE("setAllowedDisplayConfigsInternal: getPhysicalDisplayId failed");
        return;
        return;
    }
    }


    ALOGV("Updating allowed configs");
    ALOGV("Updating allowed configs");
    {
    mAllowedDisplayConfigs = DisplayConfigs(allowedConfigs.begin(), allowedConfigs.end());
        std::lock_guard lock(mAllowedConfigsLock);
        mAllowedConfigs[*displayId] = std::move(allowedConfigs);
    }


    // Set the highest allowed config by iterating backwards on available refresh rates
    // Set the highest allowed config by iterating backwards on available refresh rates
    const auto& refreshRates = mRefreshRateConfigs[*displayId]->getRefreshRates();
    const auto& refreshRates = mRefreshRateConfigs.getRefreshRates();
    for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
    for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) {
        if (iter->second && isConfigAllowed(*displayId, iter->second->configId)) {
        if (iter->second && isDisplayConfigAllowed(iter->second->configId)) {
            ALOGV("switching to config %d", iter->second->configId);
            ALOGV("switching to config %d", iter->second->configId);
            setDesiredActiveConfig({iter->first, iter->second->configId, displayToken,
            setDesiredActiveConfig(
                                    Scheduler::ConfigEvent::Changed});
                    {iter->first, iter->second->configId, Scheduler::ConfigEvent::Changed});
            break;
            break;
        }
        }
    }
    }
}
}


status_t SurfaceFlinger::setAllowedDisplayConfigs(const android::sp<android::IBinder>& displayToken,
status_t SurfaceFlinger::setAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                                  const std::vector<int32_t>& allowedConfigs) {
                                                  const std::vector<int32_t>& allowedConfigs) {
    ATRACE_CALL();
    ATRACE_CALL();


    if (!displayToken) {
    if (!displayToken || allowedConfigs.empty()) {
        ALOGE("setAllowedDisplayConfigs: displayToken is null");
        return BAD_VALUE;
    }

    if (!allowedConfigs.size()) {
        ALOGE("setAllowedDisplayConfigs: empty config set provided");
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    {
        ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
        const auto displayId = getPhysicalDisplayIdLocked(displayToken);
        if (!displayId) {
            ALOGE("setAllowedDisplayConfigs: display not found");
            return NAME_NOT_FOUND;
        }
    }

    auto allowedDisplayConfigsBuilder = AllowedDisplayConfigs::Builder();
    for (int config : allowedConfigs) {
        ALOGV("setAllowedDisplayConfigs: Adding config to the allowed configs = %d", config);
        allowedDisplayConfigsBuilder.addConfig(config);
    }
    auto allowedDisplayConfigs = allowedDisplayConfigsBuilder.build();
    postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
    postMessageSync(new LambdaMessage([&]() NO_THREAD_SAFETY_ANALYSIS {
        setAllowedDisplayConfigsInternal(displayToken, std::move(allowedDisplayConfigs));
        const auto display = getDisplayDeviceLocked(displayToken);
        if (!display) {
            ALOGE("Attempt to set allowed display configs for invalid display token %p",
                  displayToken.get());
        } else if (display->isVirtual()) {
            ALOGW("Attempt to set allowed display configs for virtual display");
        } else {
            setAllowedDisplayConfigsInternal(display, allowedConfigs);
        }
    }));
    }));

    return NO_ERROR;
    return NO_ERROR;
}
}


status_t SurfaceFlinger::getAllowedDisplayConfigs(const android::sp<android::IBinder>& displayToken,
status_t SurfaceFlinger::getAllowedDisplayConfigs(const sp<IBinder>& displayToken,
                                                  std::vector<int32_t>* outAllowedConfigs) {
                                                  std::vector<int32_t>* outAllowedConfigs) {
    ATRACE_CALL();
    ATRACE_CALL();


    if (!displayToken) {
    if (!displayToken || !outAllowedConfigs) {
        ALOGE("getAllowedDisplayConfigs: displayToken is null");
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    if (!outAllowedConfigs) {
    Mutex::Autolock lock(mStateLock);
        ALOGE("getAllowedDisplayConfigs: outAllowedConfigs is null");
        return BAD_VALUE;
    }


    ConditionalLock stateLock(mStateLock, std::this_thread::get_id() != mMainThreadId);
    if (displayToken != getInternalDisplayTokenLocked()) {
    const auto displayId = getPhysicalDisplayIdLocked(displayToken);
        ALOGE("%s is only supported for the internal display", __FUNCTION__);
    if (!displayId) {
        ALOGE("getAllowedDisplayConfigs: display not found");
        return NAME_NOT_FOUND;
        return NAME_NOT_FOUND;
    }
    }


    std::lock_guard allowedConfigLock(mAllowedConfigsLock);
    outAllowedConfigs->assign(mAllowedDisplayConfigs.begin(), mAllowedDisplayConfigs.end());
    auto allowedConfigIterator = mAllowedConfigs.find(displayId.value());
    if (allowedConfigIterator != mAllowedConfigs.end()) {
        allowedConfigIterator->second->getAllowedConfigs(outAllowedConfigs);
    }

    return NO_ERROR;
    return NO_ERROR;
}
}


+13 −29
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@
#include <utils/Trace.h>
#include <utils/Trace.h>
#include <utils/threads.h>
#include <utils/threads.h>


#include "AllowedDisplayConfigs.h"
#include "DisplayDevice.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWC2.h"
#include "DisplayHardware/HWC2.h"
#include "DisplayHardware/PowerAdvisor.h"
#include "DisplayHardware/PowerAdvisor.h"
@@ -74,6 +73,7 @@
#include <thread>
#include <thread>
#include <type_traits>
#include <type_traits>
#include <unordered_map>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <utility>


using namespace android::surfaceflinger;
using namespace android::surfaceflinger;
@@ -407,12 +407,7 @@ private:
            float frameScale, bool childrenOnly) override;
            float frameScale, bool childrenOnly) override;
    status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
    status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
    status_t getDisplayConfigs(const sp<IBinder>& displayToken,
    status_t getDisplayConfigs(const sp<IBinder>& displayToken,
                               Vector<DisplayInfo>* configs) override {
                               Vector<DisplayInfo>* configs) override;
        Mutex::Autolock _l(mStateLock);
        return getDisplayConfigsLocked(displayToken, configs);
    }
    status_t getDisplayConfigsLocked(const sp<IBinder>& displayToken, Vector<DisplayInfo>* configs)
            REQUIRES(mStateLock);
    int getActiveConfig(const sp<IBinder>& displayToken) override;
    int getActiveConfig(const sp<IBinder>& displayToken) override;
    status_t getDisplayColorModes(const sp<IBinder>& displayToken,
    status_t getDisplayColorModes(const sp<IBinder>& displayToken,
                                  Vector<ui::ColorMode>* configs) override;
                                  Vector<ui::ColorMode>* configs) override;
@@ -491,20 +486,10 @@ private:
    struct ActiveConfigInfo {
    struct ActiveConfigInfo {
        RefreshRateType type;
        RefreshRateType type;
        int configId;
        int configId;
        sp<IBinder> displayToken;
        Scheduler::ConfigEvent event;
        Scheduler::ConfigEvent event;


        bool operator!=(const ActiveConfigInfo& other) const {
        bool operator!=(const ActiveConfigInfo& other) const {
            if (type != other.type) {
            return type != other.type || configId != other.configId || event != other.event;
                return true;
            }
            if (configId != other.configId) {
                return true;
            }
            if (displayToken != other.displayToken) {
                return true;
            }
            return (event != other.event);
        }
        }
    };
    };


@@ -519,14 +504,14 @@ private:
    // desired config was set, HWC needs to update the panel on the next refresh, and when
    // desired config was set, HWC needs to update the panel on the next refresh, and when
    // we receive the fence back, we know that the process was complete. It returns whether
    // we receive the fence back, we know that the process was complete. It returns whether
    // we need to wait for the next invalidate
    // we need to wait for the next invalidate
    bool performSetActiveConfig();
    bool performSetActiveConfig() REQUIRES(mStateLock);
    // called on the main thread in response to setPowerMode()
    // called on the main thread in response to setPowerMode()
    void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
    void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);


    // called on the main thread in response to setAllowedDisplayConfigs()
    // called on the main thread in response to setAllowedDisplayConfigs()
    void setAllowedDisplayConfigsInternal(
    void setAllowedDisplayConfigsInternal(const sp<DisplayDevice>& display,
            const sp<IBinder>& displayToken,
                                          const std::vector<int32_t>& allowedConfigs)
            std::unique_ptr<const AllowedDisplayConfigs>&& allowedConfigs) REQUIRES(mStateLock);
            REQUIRES(mStateLock);


    // Returns whether the transaction actually modified any state
    // Returns whether the transaction actually modified any state
    bool handleMessageTransaction();
    bool handleMessageTransaction();
@@ -805,7 +790,7 @@ private:
    // the desired refresh rate.
    // the desired refresh rate.
    void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock);
    void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock);


    bool isConfigAllowed(const DisplayId& displayId, int32_t config);
    bool isDisplayConfigAllowed(int32_t configId) REQUIRES(mStateLock);


    /*
    /*
     * Display identification
     * Display identification
@@ -1111,14 +1096,13 @@ private:
    std::unique_ptr<Scheduler> mScheduler;
    std::unique_ptr<Scheduler> mScheduler;
    sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
    sp<Scheduler::ConnectionHandle> mAppConnectionHandle;
    sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
    sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
    std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;


    std::unordered_map<DisplayId, std::shared_ptr<scheduler::RefreshRateConfigs>>
    scheduler::RefreshRateConfigs mRefreshRateConfigs;
            mRefreshRateConfigs;
    scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats};


    std::mutex mAllowedConfigsLock;
    // All configs are allowed if the set is empty.
    std::unordered_map<DisplayId, std::unique_ptr<const AllowedDisplayConfigs>> mAllowedConfigs
    using DisplayConfigs = std::unordered_set<int32_t>;
            GUARDED_BY(mAllowedConfigsLock);
    DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock);


    std::mutex mActiveConfigLock;
    std::mutex mActiveConfigLock;
    // This bit is set once we start setting the config. We read from this bit during the
    // This bit is set once we start setting the config. We read from this bit during the
Loading