/*
 * Copyright (C) 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.
 */

#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)

#include "ExynosPrimaryDisplayModule.h"

#include <android-base/file.h>
#include <json/reader.h>
#include <json/value.h>

#include <cmath>

#include "BrightnessController.h"
#include "ExynosDisplayDrmInterfaceModule.h"
#include "ExynosHWCDebug.h"

#ifdef FORCE_GPU_COMPOSITION
extern exynos_hwc_control exynosHWCControl;
#endif

using namespace gs101;

mpp_phycal_type_t getMPPTypeFromDPPChannel(uint32_t channel) {

    for (int i=0; i < MAX_DECON_DMA_TYPE; i++){
        if(idma_channel_map[i].channel == channel)
            return idma_channel_map[i].type;
    }

    return MPP_P_TYPE_MAX;
}

ExynosPrimaryDisplayModule::ExynosPrimaryDisplayModule(uint32_t index, ExynosDevice* device,
                                                       const std::string& displayName)
      : ExynosPrimaryDisplay(index, device, displayName), mAtcInit(false) {
#ifdef FORCE_GPU_COMPOSITION
    exynosHWCControl.forceGpu = true;
#endif
    mColorManager = std::make_unique<ColorManager>(this, static_cast<ExynosDeviceModule*>(device));
}

ExynosPrimaryDisplayModule::~ExynosPrimaryDisplayModule () {
}

void ExynosPrimaryDisplayModule::usePreDefinedWindow(bool use)
{
#ifdef FIX_BASE_WINDOW_INDEX
    /* Use fixed base window index */
    mBaseWindowIndex = FIX_BASE_WINDOW_INDEX;
    return;
#endif

    if (use) {
        mBaseWindowIndex = PRIMARY_DISP_BASE_WIN[mDevice->mDisplayMode];
        mMaxWindowNum = mDisplayInterface->getMaxWindowNum() - PRIMARY_DISP_BASE_WIN[mDevice->mDisplayMode];
    } else {
        mBaseWindowIndex = 0;
        mMaxWindowNum = mDisplayInterface->getMaxWindowNum();
    }
}

int32_t ExynosPrimaryDisplayModule::validateWinConfigData()
{
    bool flagValidConfig = true;

    if (ExynosDisplay::validateWinConfigData() != NO_ERROR)
        flagValidConfig = false;

    for (size_t i = 0; i < mDpuData.configs.size(); i++) {
        struct exynos_win_config_data &config = mDpuData.configs[i];
        if (config.state == config.WIN_STATE_BUFFER) {
            bool configInvalid = false;
            uint32_t mppType = config.assignedMPP->mPhysicalType;
            if ((config.src.w != config.dst.w) ||
                (config.src.h != config.dst.h)) {
                if ((mppType == MPP_DPP_GF) ||
                    (mppType == MPP_DPP_VG) ||
                    (mppType == MPP_DPP_VGF)) {
                    DISPLAY_LOGE("WIN_CONFIG error: invalid assign id : "
                            "%zu,  s_w : %d, d_w : %d, s_h : %d, d_h : %d, mppType : %d",
                            i, config.src.w, config.dst.w, config.src.h, config.dst.h, mppType);
                    configInvalid = true;
                }
            }
            if (configInvalid) {
                config.state = config.WIN_STATE_DISABLED;
                flagValidConfig = false;
            }
        }
    }
    if (flagValidConfig)
        return NO_ERROR;
    else
        return -EINVAL;
}

void ExynosPrimaryDisplayModule::doPreProcessing() {
    ExynosDisplay::doPreProcessing();

    if (mDevice->checkNonInternalConnection()) {
        mDisplayControl.adjustDisplayFrame = true;
    } else {
        mDisplayControl.adjustDisplayFrame = false;
    }
}

int32_t ExynosPrimaryDisplayModule::getColorModes(
        uint32_t* outNumModes, int32_t* outModes)
{
    return mColorManager->getColorModes(outNumModes, outModes);
}

int32_t ExynosPrimaryDisplayModule::setColorMode(int32_t mode)
{
    return mColorManager->setColorMode(mode);
}

int32_t ExynosPrimaryDisplayModule::getRenderIntents(int32_t mode,
        uint32_t* outNumIntents, int32_t* outIntents)
{
    return mColorManager->getRenderIntents(mode, outNumIntents, outIntents);
}

int32_t ExynosPrimaryDisplayModule::setColorModeWithRenderIntent(int32_t mode,
        int32_t intent)
{
    return mColorManager->setColorModeWithRenderIntent(mode, intent);
}

int32_t ExynosPrimaryDisplayModule::setColorTransform(
        const float* matrix, int32_t hint)
{
    return mColorManager->setColorTransform(matrix, hint);
}

int32_t ExynosPrimaryDisplayModule::getClientTargetProperty(
        hwc_client_target_property_t* outClientTargetProperty,
        HwcDimmingStage *outDimmingStage) {
    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
    if (displayColorInterface == nullptr) {
        ALOGI("%s dc interface not created", __func__);
        return ExynosDisplay::getClientTargetProperty(outClientTargetProperty);
    }

    const DisplayType display = getDcDisplayType();
    hwc::PixelFormat pixelFormat;
    hwc::Dataspace dataspace;
    bool dimming_linear;
    if (!displayColorInterface->GetBlendingProperty(display, pixelFormat, dataspace,
                                                    dimming_linear)) {
        outClientTargetProperty->pixelFormat = toUnderlying(pixelFormat);
        outClientTargetProperty->dataspace = toUnderlying(dataspace);
        if (outDimmingStage != nullptr)
            *outDimmingStage = dimming_linear
                              ? HwcDimmingStage::DIMMING_LINEAR
                              : HwcDimmingStage::DIMMING_OETF;

        return HWC2_ERROR_NONE;
    }

    ALOGW("%s failed to get property of blending stage", __func__);
    return ExynosDisplay::getClientTargetProperty(outClientTargetProperty);
}

int32_t ExynosPrimaryDisplayModule::updateBrightnessTable() {
    std::unique_ptr<const IBrightnessTable> table;
    auto displayColorInterface = getDisplayColorInterface();
    if (displayColorInterface == nullptr) {
        ALOGE("%s displaycolor interface not available!", __func__);
        return HWC2_ERROR_NO_RESOURCES;
    }

    auto displayType = getDcDisplayType();
    auto ret = displayColorInterface->GetBrightnessTable(displayType, table);
    if (ret != android::OK) {
        ALOGE("%s brightness table not available!", __func__);
        return HWC2_ERROR_NO_RESOURCES;
    }
    // BrightnessController is not ready until this step
    mBrightnessController->updateBrightnessTable(table);

    return HWC2_ERROR_NONE;
}

int ExynosPrimaryDisplayModule::deliverWinConfigData()
{
    int ret = 0;
    ExynosDisplayDrmInterfaceModule *moduleDisplayInterface =
        (ExynosDisplayDrmInterfaceModule*)(mDisplayInterface.get());
    GsInterfaceType* displayColorInterface = getDisplayColorInterface();

    bool forceDisplayColorSetting = false;
    if (!getDisplaySceneInfo().displaySettingDelivered || isForceColorUpdate())
        forceDisplayColorSetting = true;

    setForceColorUpdate(false);

    if (displayColorInterface != nullptr) {
        moduleDisplayInterface
                ->setColorSettingChanged(getDisplaySceneInfo().needDisplayColorSetting(),
                                         forceDisplayColorSetting);
    }

    checkAtcHdrMode();

    ret = ExynosDisplay::deliverWinConfigData();

    checkAtcAnimation();

    if (mDpuData.enable_readback &&
       !mDpuData.readback_info.requested_from_service)
        getDisplaySceneInfo().displaySettingDelivered = false;
    else
        getDisplaySceneInfo().displaySettingDelivered = true;

    return ret;
}

int32_t ExynosPrimaryDisplayModule::updateColorConversionInfo()
{
    return mColorManager->updateColorConversionInfo();
}

int32_t ExynosPrimaryDisplayModule::resetColorMappingInfo(ExynosMPPSource* mppSrc) {
    return mColorManager->resetColorMappingInfo(mppSrc);
}

int32_t ExynosPrimaryDisplayModule::updatePresentColorConversionInfo()
{
    int ret = NO_ERROR;
    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
    if (displayColorInterface == nullptr) {
        return ret;
    }

    ExynosDisplayDrmInterfaceModule *moduleDisplayInterface =
        (ExynosDisplayDrmInterfaceModule*)(mDisplayInterface.get());
    auto refresh_rate = moduleDisplayInterface->getDesiredRefreshRate();
    if (refresh_rate > 0) {
        getDisplaySceneInfo().displayScene.refresh_rate = refresh_rate;
    }
    auto operation_rate = moduleDisplayInterface->getOperationRate();
    if (operation_rate > 0) {
        getDisplaySceneInfo().displayScene.operation_rate = static_cast<uint32_t>(operation_rate);
    }

    getDisplaySceneInfo().displayScene.lhbm_on = mBrightnessController->isLhbmOn();
    getDisplaySceneInfo().displayScene.dbv = mBrightnessController->getBrightnessLevel();
    const DisplayType display = getDcDisplayType();
    if ((ret = displayColorInterface->UpdatePresent(display, getDisplaySceneInfo().displayScene)) !=
        0) {
        DISPLAY_LOGE("Display Scene update error (%d)", ret);
        return ret;
    }

    return ret;
}

int32_t ExynosPrimaryDisplayModule::getColorAdjustedDbv(uint32_t &dbv_adj) {
    GsInterfaceType* displayColorInterface = getDisplayColorInterface();
    if (displayColorInterface == nullptr) {
        return NO_ERROR;
    }

    const DisplayType display = getDcDisplayType();
    dbv_adj = displayColorInterface->GetPipelineData(display)->Panel().GetAdjustedBrightnessLevel();
    return NO_ERROR;
}

bool ExynosPrimaryDisplayModule::parseAtcProfile() {
    Json::Value root;
    Json::CharReaderBuilder reader_builder;
    std::unique_ptr<Json::CharReader> reader(reader_builder.newCharReader());
    std::string atc_profile;

    if (!android::base::ReadFileToString(kAtcProfilePath, &atc_profile)) {
        atc_profile = kAtcJsonRaw;
        ALOGI("Use default atc profile file");
    }

    if (!reader->parse(atc_profile.c_str(), atc_profile.c_str() + atc_profile.size(), &root,
                       nullptr)) {
        ALOGE("Failed to parse atc profile file");
        return false;
    }

    ALOGI("Atc Profile version = %s", root[kAtcProfileVersionStr].asString().c_str());
    Json::Value nodes = root[kAtcProfileModesStr];
    atc_mode mode;

    for (Json::Value::ArrayIndex i = 0; i < nodes.size(); ++i) {
        std::string name = nodes[i][kAtcProfileModeNameStr].asString();

        if (nodes[i][kAtcProfileLuxMapStr].size() != nodes[i][kAtcProfileAlMapStr].size() &&
            nodes[i][kAtcProfileAlMapStr].size() != nodes[i][kAtcProfileStMapStr].size()) {
            ALOGE("Atc profile is unavailable !");
            return false;
        }

        uint32_t map_cnt = nodes[i][kAtcProfileLuxMapStr].size();

        mode.lux_map.clear();
        for (uint32_t index = 0; index < map_cnt; ++index) {
            mode.lux_map.emplace_back(atc_lux_map{nodes[i][kAtcProfileLuxMapStr][index].asUInt(),
                                                  nodes[i][kAtcProfileAlMapStr][index].asUInt(),
                                                  nodes[i][kAtcProfileStMapStr][index].asUInt()});
        }

        if (!nodes[i][kAtcProfileStUpStepStr].empty())
            mode.st_up_step = nodes[i][kAtcProfileStUpStepStr].asUInt();
        else
            mode.st_up_step = kAtcStStep;

        if (!nodes[i][kAtcProfileStDownStepStr].empty())
            mode.st_down_step = nodes[i][kAtcProfileStDownStepStr].asUInt();
        else
            mode.st_down_step = kAtcStStep;

        if (nodes[i][kAtcProfileSubSettingStr].size() != kAtcSubSetting.size()) return false;

        for (auto it = kAtcSubSetting.begin(); it != kAtcSubSetting.end(); it++) {
            mode.sub_setting[it->first.c_str()] =
                    nodes[i][kAtcProfileSubSettingStr][it->first.c_str()].asUInt();
        }
        auto ret = mAtcModeSetting.insert(std::make_pair(name.c_str(), mode));
        if (ret.second == false) {
            ALOGE("Atc mode %s is already existed!", ret.first->first.c_str());
            return false;
        }
    }

    if (mAtcModeSetting.find(kAtcModeNormalStr) == mAtcModeSetting.end()) {
        ALOGW("Failed to find atc normal mode");
        return false;
    }
    return true;
}

bool ExynosPrimaryDisplayModule::isLbeSupported() {
    return mLbeSupported;
}

void ExynosPrimaryDisplayModule::initLbe() {
    if (!parseAtcProfile()) {
        ALOGD("Failed to parseAtcMode");
        mAtcInit = false;
        return;
    }

    mAtcInit = true;
    mAtcAmbientLight.node = String8::format(ATC_AMBIENT_LIGHT_FILE_NAME, mIndex);
    mAtcAmbientLight.value.set_dirty();
    mAtcStrength.node = String8::format(ATC_ST_FILE_NAME, mIndex);
    mAtcStrength.value.set_dirty();
    mAtcEnable.node = String8::format(ATC_ENABLE_FILE_NAME, mIndex);
    mAtcEnable.value.set_dirty();

    for (auto it = kAtcSubSetting.begin(); it != kAtcSubSetting.end(); it++) {
        mAtcSubSetting[it->first.c_str()].node = String8::format(it->second.c_str(), mIndex);
        mAtcSubSetting[it->first.c_str()].value.set_dirty();
    }
    mLbeSupported = true;
}

uint32_t ExynosPrimaryDisplayModule::getAtcLuxMapIndex(std::vector<atc_lux_map> map, uint32_t lux) {
    uint32_t index = 0;
    for (uint32_t i = 0; i < map.size(); i++) {
        if (lux < map[i].lux) {
            break;
        }
        index = i;
    }

    return index;
}

int32_t ExynosPrimaryDisplayModule::setAtcStrength(uint32_t strength) {
    mAtcStrength.value.store(strength);
    if (mAtcStrength.value.is_dirty()) {
        if (writeIntToFile(mAtcStrength.node.c_str(), mAtcStrength.value.get()) != NO_ERROR) {
            return -EPERM;
        }
        mAtcStrength.value.clear_dirty();
    }
    return NO_ERROR;
}

int32_t ExynosPrimaryDisplayModule::setAtcAmbientLight(uint32_t ambient_light) {
    mAtcAmbientLight.value.store(ambient_light);
    if (mAtcAmbientLight.value.is_dirty()) {
        if (writeIntToFile(mAtcAmbientLight.node.c_str(), mAtcAmbientLight.value.get()) != NO_ERROR)
            return -EPERM;
        mAtcAmbientLight.value.clear_dirty();
    }

    return NO_ERROR;
}

int32_t ExynosPrimaryDisplayModule::setAtcMode(std::string mode_name) {
    ATRACE_CALL();
    auto mode_data = mAtcModeSetting.find(mode_name);
    uint32_t ambient_light = 0;
    uint32_t strength = 0;
    bool enable = (!mode_name.empty()) && (mode_data != mAtcModeSetting.end());

    if (enable) {
        atc_mode mode = mode_data->second;
        for (auto it = kAtcSubSetting.begin(); it != kAtcSubSetting.end(); it++) {
            mAtcSubSetting[it->first.c_str()].value.store(mode.sub_setting[it->first.c_str()]);
            if (mAtcSubSetting[it->first.c_str()].value.is_dirty()) {
                if (writeIntToFile(mAtcSubSetting[it->first.c_str()].node.c_str(),
                                   mAtcSubSetting[it->first.c_str()].value.get()) != NO_ERROR)
                    return -EPERM;
                mAtcSubSetting[it->first.c_str()].value.clear_dirty();
            }
        }
        mAtcStUpStep = mode.st_up_step;
        mAtcStDownStep = mode.st_down_step;

        uint32_t index = getAtcLuxMapIndex(mode.lux_map, mCurrentLux);
        ambient_light = mode.lux_map[index].al;
        strength = mode.lux_map[index].st;
    }

    if (setAtcAmbientLight(ambient_light) != NO_ERROR) {
        ALOGE("Fail to set atc ambient light for %s mode", mode_name.c_str());
        return -EPERM;
    }

    if (setAtcStDimming(strength) != NO_ERROR) {
        ALOGE("Fail to set atc st dimming for %s mode", mode_name.c_str());
        return -EPERM;
    }

    if (!enable && isInAtcAnimation()) {
        mPendingAtcOff = true;
    } else {
        if (setAtcEnable(enable) != NO_ERROR) {
            ALOGE("Fail to set atc enable = %d", enable);
            return -EPERM;
        }
        mPendingAtcOff = false;
    }

    mCurrentAtcModeName = enable ? mode_name : "NULL";
    ALOGI("atc enable=%d (mode=%s, pending off=%s)", enable, mCurrentAtcModeName.c_str(),
          mPendingAtcOff ? "true" : "false");
    return NO_ERROR;
}
void ExynosPrimaryDisplayModule::setLbeState(LbeState state) {
    if (!mAtcInit) return;

    std::string modeStr;
    bool enhanced_hbm = false;
    bool fullHdrLayer = isFullScreenHdrLayer();

    switch (state) {
        case LbeState::OFF:
            mCurrentLux = 0;
            break;
        case LbeState::NORMAL:
            modeStr = kAtcModeNormalStr;
            break;
        case LbeState::HIGH_BRIGHTNESS:
            modeStr = kAtcModeHbmStr;
            break;
        case LbeState::POWER_SAVE:
            modeStr = kAtcModePowerSaveStr;
            break;
        case LbeState::HIGH_BRIGHTNESS_ENHANCE:
            modeStr = kAtcModeHbmStr;
            enhanced_hbm = true;
            break;
        default:
            ALOGE("Lbe state not support");
            return;
    }

    if (fullHdrLayer && state != LbeState::OFF) checkAtcHdrMode();
    else if (setAtcMode(modeStr) != NO_ERROR) return;

    mBrightnessController->processEnhancedHbm(enhanced_hbm);
    mBrightnessController->setOutdoorVisibility(state);

    if (mCurrentLbeState != state) {
        mCurrentLbeState = state;
        mDevice->onRefresh(mDisplayId);
    }
    ALOGI("Lbe state %hhd", mCurrentLbeState);
}

void ExynosPrimaryDisplayModule::setLbeAmbientLight(int value) {
    if (!mAtcInit) return;

    auto it = mAtcModeSetting.find(mCurrentAtcModeName);
    if (it == mAtcModeSetting.end()) {
        ALOGE("Atc mode not found");
        return;
    }
    atc_mode mode = it->second;

    uint32_t index = getAtcLuxMapIndex(mode.lux_map, value);
    if (setAtcAmbientLight(mode.lux_map[index].al) != NO_ERROR) {
        ALOGE("Failed to set atc ambient light");
        return;
    }

    if (setAtcStDimming(mode.lux_map[index].st) != NO_ERROR) {
        ALOGE("Failed to set atc st dimming");
        return;
    }

    if (mAtcLuxMapIndex != index) {
        mAtcLuxMapIndex = index;
        mDevice->onRefresh(mDisplayId);
    }
    mCurrentLux = value;
}

LbeState ExynosPrimaryDisplayModule::getLbeState() {
    return mCurrentLbeState;
}

PanelCalibrationStatus ExynosPrimaryDisplayModule::getPanelCalibrationStatus() {
    auto displayColorInterface = getDisplayColorInterface();
    if (displayColorInterface == nullptr) {
        return PanelCalibrationStatus::UNCALIBRATED;
    }

    auto displayType = getDcDisplayType();
    auto calibrationInfo = displayColorInterface->GetCalibrationInfo(displayType);

    if (calibrationInfo.factory_cal_loaded) {
        return PanelCalibrationStatus::ORIGINAL;
    } else if (calibrationInfo.golden_cal_loaded) {
        return PanelCalibrationStatus::GOLDEN;
    } else {
        return PanelCalibrationStatus::UNCALIBRATED;
    }
}

int32_t ExynosPrimaryDisplayModule::setAtcStDimming(uint32_t value) {
    Mutex::Autolock lock(mAtcStMutex);
    int32_t strength = mAtcStrength.value.get();
    if (mAtcStTarget != value) {
        mAtcStTarget = value;
        uint32_t step = mAtcStTarget > strength ? mAtcStUpStep : mAtcStDownStep;

        int diff = value - strength;
        uint32_t count = (std::abs(diff) + step - 1) / step;
        mAtcStStepCount = count;
        ALOGI("setup atc st dimming=%d, count=%d, step=%d", value, count, step);
    }

    if (mAtcStStepCount == 0 && !mAtcStrength.value.is_dirty()) return NO_ERROR;

    if ((strength + mAtcStUpStep) < mAtcStTarget) {
        strength = strength + mAtcStUpStep;
    } else if (strength > (mAtcStTarget + mAtcStDownStep)) {
        strength = strength - mAtcStDownStep;
    } else {
        strength = mAtcStTarget;
    }

    if (setAtcStrength(strength) != NO_ERROR) {
        ALOGE("Failed to set atc st");
        return -EPERM;
    }

    if (mAtcStStepCount > 0) mAtcStStepCount--;
    return NO_ERROR;
}

int32_t ExynosPrimaryDisplayModule::setAtcEnable(bool enable) {
    mAtcEnable.value.store(enable);
    if (mAtcEnable.value.is_dirty()) {
        if (writeIntToFile(mAtcEnable.node.c_str(), enable) != NO_ERROR) return -EPERM;
        mAtcEnable.value.clear_dirty();
    }
    return NO_ERROR;
}

void ExynosPrimaryDisplayModule::checkAtcAnimation() {
    if (!isInAtcAnimation()) return;

    if (setAtcStDimming(mAtcStTarget) != NO_ERROR) {
        ALOGE("Failed to set atc st dimming");
        return;
    }

    if (mPendingAtcOff && mAtcStStepCount == 0) {
        if (setAtcEnable(false) != NO_ERROR) {
            ALOGE("Failed to set atc enable to off");
            return;
        }
        mPendingAtcOff = false;
        ALOGI("atc enable is off (pending off=false)");
    }

    mDevice->onRefresh(mDisplayId);
}

int32_t ExynosPrimaryDisplayModule::setPowerMode(int32_t mode) {
    hwc2_power_mode_t prevPowerModeState = mPowerModeState.value_or(HWC2_POWER_MODE_OFF);
    int32_t ret;

    ret = ExynosPrimaryDisplay::setPowerMode(mode);

    if ((ret == HWC2_ERROR_NONE) && isDisplaySwitched(mode, prevPowerModeState)) {
        ExynosDeviceModule* device = static_cast<ExynosDeviceModule*>(mDevice);

        device->setActiveDisplay(mIndex);
        setForceColorUpdate(true);
    }
    return ret;
}

bool ExynosPrimaryDisplayModule::isDisplaySwitched(int32_t mode, int32_t prevMode) {
    ExynosDeviceModule* device = static_cast<ExynosDeviceModule*>(mDevice);

    return (device->getActiveDisplay() != mIndex) && (prevMode == HWC_POWER_MODE_OFF) &&
            (mode != HWC_POWER_MODE_OFF);
}

void ExynosPrimaryDisplayModule::checkAtcHdrMode() {
    ATRACE_CALL();
    if (!mAtcInit) return;

    auto it = mAtcModeSetting.find(kAtcModeHdrStr);
    if (it == mAtcModeSetting.end()) {
        return;
    }

    bool hdrModeActive = (mCurrentAtcModeName == kAtcModeHdrStr);
    bool fullHdrLayer = isFullScreenHdrLayer();

    if (fullHdrLayer) {
        if (!hdrModeActive && (mCurrentLbeState != LbeState::OFF)) {
            setAtcMode(kAtcModeHdrStr);
            ALOGI("HdrLayer on to set atc hdr mode");
        }
    } else {
        if (hdrModeActive) {
            setLbeState(mCurrentLbeState);
            ALOGI("HdrLayer off to restore Lbe State");
        }
    }
}

bool ExynosPrimaryDisplayModule::isFullScreenHdrLayer() {
    return mBrightnessController->getHdrLayerState() == HdrLayerState::kHdrLarge;
}
