1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 //#define LOG_NDEBUG 0
17 
18 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
19 
20 #include "ExynosPrimaryDisplay.h"
21 
22 #include <android-base/properties.h>
23 
24 #include <linux/fb.h>
25 #include <poll.h>
26 
27 #include <chrono>
28 #include <fstream>
29 
30 #include "../libvrr/FileNode.h"
31 #include "../libvrr/VariableRefreshRateVersion.h"
32 #include "../libvrr/interface/Panel_def.h"
33 #include "BrightnessController.h"
34 #include "DisplayTe2Manager.h"
35 #include "ExynosDevice.h"
36 #include "ExynosDisplayDrmInterface.h"
37 #include "ExynosDisplayDrmInterfaceModule.h"
38 #include "ExynosExternalDisplay.h"
39 #include "ExynosHWCDebug.h"
40 #include "ExynosHWCHelper.h"
41 #include "ExynosLayer.h"
42 #include "HistogramController.h"
43 
44 extern struct exynos_hwc_control exynosHWCControl;
45 
46 using namespace SOC_VERSION;
47 
48 namespace {
49 
50 using android::hardware::graphics::composer::kPanelRefreshCtrlFrameInsertionAutoMode;
51 using android::hardware::graphics::composer::kPanelRefreshCtrlFrameInsertionAutoModeOffset;
52 using android::hardware::graphics::composer::kPanelRefreshCtrlMrrV1OverV2;
53 using android::hardware::graphics::composer::kPanelRefreshCtrlMrrV1OverV2Offset;
54 using android::hardware::graphics::composer::kRefreshControlNodeEnabled;
55 using android::hardware::graphics::composer::kRefreshControlNodeName;
56 
57 constexpr auto nsecsPerSec = std::chrono::nanoseconds(1s).count();
58 
59 inline constexpr int kDefaultNotifyExpectedPresentConfigHeadsUpNs =
60         std::chrono::nanoseconds(30ms).count();
61 inline constexpr int kDefaultNotifyExpectedPresentConfigTimeoutNs =
62         std::chrono::nanoseconds(30ms).count();
63 
64 static constexpr int kMaximumPropertyIdentifierLength = 128;
65 
66 static const std::map<const DisplayType, const std::string> panelSysfsPath =
67         {{DisplayType::DISPLAY_PRIMARY, "/sys/devices/platform/exynos-drm/primary-panel/"},
68 #ifdef USES_IDISPLAY_INTF_SEC
69          {DisplayType::DISPLAY_SECONDARY, "/sys/devices/platform/exynos-drm/secondary-panel/"}
70 #endif
71 
72 };
73 } // namespace
74 
getPropertyBootModeStr(const int32_t dispId)75 static String8 getPropertyBootModeStr(const int32_t dispId) {
76     String8 str;
77     if (dispId == 0) {
78         str.appendFormat("persist.vendor.display.primary.boot_config");
79     } else {
80         str.appendFormat("persist.vendor.display.%d.primary.boot_config", dispId);
81     }
82     return str;
83 }
84 
loadPanelGammaCalibration(const std::string & file)85 static std::string loadPanelGammaCalibration(const std::string &file) {
86     std::ifstream ifs(file);
87 
88     if (!ifs.is_open()) {
89         ALOGW("Unable to open gamma calibration '%s', error = %s", file.c_str(), strerror(errno));
90         return {};
91     }
92 
93     std::string raw_data, gamma;
94     char ch;
95     while (std::getline(ifs, raw_data, '\r')) {
96         gamma.append(raw_data);
97         gamma.append(1, ' ');
98         ifs.get(ch);
99         if (ch != '\n') {
100             gamma.append(1, ch);
101         }
102     }
103     ifs.close();
104 
105     /* eliminate space character in the last byte */
106     if (!gamma.empty()) {
107         gamma.pop_back();
108     }
109 
110     return gamma;
111 }
112 
ExynosPrimaryDisplay(uint32_t index,ExynosDevice * device,const std::string & displayName)113 ExynosPrimaryDisplay::ExynosPrimaryDisplay(uint32_t index, ExynosDevice* device,
114                                            const std::string& displayName)
115       : ExynosDisplay(HWC_DISPLAY_PRIMARY, index, device, displayName),
116         mMinIdleRefreshRate(0),
117         mRrThrottleFps{0},
118         mRrThrottleNanos{0},
119         mRefreshRateDelayNanos(0),
120         mLastRefreshRateAppliedNanos(0),
121         mAppliedActiveConfig(0),
122         mDisplayIdleTimerEnabled(false),
123         mDisplayIdleTimerNanos{0},
124         mDisplayIdleDelayNanos(-1),
125         mDisplayNeedHandleIdleExit(false) {
126     // TODO : Hard coded here
127     mNumMaxPriorityAllowed = 5;
128 
129     /* Initialization */
130     mFramesToReachLhbmPeakBrightness =
131             property_get_int32("vendor.primarydisplay.lhbm.frames_to_reach_peak_brightness", 3);
132 
133     DisplayType displayType = getDcDisplayType();
134     std::string displayTypeIdentifier;
135     if (displayType == DisplayType::DISPLAY_PRIMARY) {
136         displayTypeIdentifier = "primarydisplay";
137     } else if (displayType == DisplayType::DISPLAY_EXTERNAL) {
138         displayTypeIdentifier = "externaldisplay";
139     }
140 #ifdef USES_IDISPLAY_INTF_SEC
141     else if (displayType == DisplayType::DISPLAY_SECONDARY) {
142         displayTypeIdentifier = "secondarydisplay";
143     }
144 #endif
145     if (!displayTypeIdentifier.empty()) {
146         // Blocking zone
147         auto propertyName =
148                 "ro.vendor." + displayTypeIdentifier + ".blocking_zone.min_refresh_rate_by_nits";
149         auto minRefreshRateByBrightnessString = android::base::GetProperty(propertyName, "");
150         ALOGD("%s brightness blocking zone propterty = %s", __func__,
151               minRefreshRateByBrightnessString.c_str());
152         if (!minRefreshRateByBrightnessString.empty()) {
153             std::vector<std::string> patterns;
154             size_t pos = 0;
155             while ((pos = minRefreshRateByBrightnessString.find(',')) != std::string::npos) {
156                 patterns.emplace_back(minRefreshRateByBrightnessString.substr(0, pos));
157                 minRefreshRateByBrightnessString.erase(0, pos + 1);
158             }
159             patterns.emplace_back(minRefreshRateByBrightnessString);
160             std::string brightnessString, fpsString;
161             for (auto& pattern : patterns) {
162                 int brightness, fps;
163                 char* endPos;
164                 pos = pattern.find(':');
165                 if (pos == std::string::npos) {
166                     ALOGE("%s(): cannot find the delimiter ':' of the pattern {brightness}:{fps} "
167                           "in "
168                           "pattern = %s",
169                           __func__, pattern.c_str());
170                     break;
171                 } else {
172                     brightnessString = pattern.substr(0, pos);
173                     pattern.erase(0, pos + 1);
174                     if (pattern.empty()) {
175                         ALOGE("%s(): miss the {fps} of the pattern = %s", __func__,
176                               pattern.c_str());
177                         break;
178                     } else {
179                         fpsString = pattern;
180                     }
181                     brightness = brightnessString.empty()
182                             ? INT_MAX
183                             : std::strtol(brightnessString.c_str(), &endPos, 10);
184                     fps = std::strtol(fpsString.c_str(), &endPos, 10);
185                 }
186                 mBrightnessBlockingZonesLookupTable[brightness] = fps;
187             }
188             ALOGI("Brightness blocking zone lookup table:");
189             int upperBound;
190             int lowerBound = INT_MIN;
191             for (const auto& brightnessBlockingZone : mBrightnessBlockingZonesLookupTable) {
192                 upperBound = brightnessBlockingZone.first;
193                 ALOGI("Brightness blocking zone: range [%s %s) fps = %d",
194                       (lowerBound == INT_MIN ? "Min" : std::to_string(lowerBound).c_str()),
195                       (upperBound == INT_MAX ? "Max" : std::to_string(upperBound).c_str()),
196                       brightnessBlockingZone.second);
197                 lowerBound = upperBound;
198             }
199         }
200         // XRR version
201         auto xrrVersion =
202                 android::hardware::graphics::composer::getDisplayXrrVersion(displayTypeIdentifier);
203         mXrrSettings.versionInfo.majorVersion = xrrVersion.first;
204         mXrrSettings.versionInfo.minorVersion = xrrVersion.second;
205         ALOGI("%s() xRR version = %d.%d", __func__, mXrrSettings.versionInfo.majorVersion,
206               mXrrSettings.versionInfo.minorVersion);
207 
208         uint32_t refreshControlCommand = 0;
209         if (mXrrSettings.versionInfo.needVrrParameters()) {
210             char pathBuffer[PROP_VALUE_MAX] = {0};
211             sprintf(pathBuffer, "ro.vendor.%s.vrr.expected_present.headsup_ns",
212                     displayTypeIdentifier.c_str());
213             mXrrSettings.notifyExpectedPresentConfig.HeadsUpNs =
214                     property_get_int32(pathBuffer, kDefaultNotifyExpectedPresentConfigHeadsUpNs);
215             sprintf(pathBuffer, "ro.vendor.%s.vrr.expected_present.timeout_ns",
216                     displayTypeIdentifier.c_str());
217             mXrrSettings.notifyExpectedPresentConfig.TimeoutNs =
218                     property_get_int32(pathBuffer, kDefaultNotifyExpectedPresentConfigTimeoutNs);
219             mXrrSettings.configChangeCallback =
220                     std::bind(&ExynosPrimaryDisplay::onConfigChange, this, std::placeholders::_1);
221         } else {
222             setBit(refreshControlCommand, kPanelRefreshCtrlMrrV1OverV2Offset);
223             setBit(refreshControlCommand, kPanelRefreshCtrlFrameInsertionAutoModeOffset);
224         }
225 
226         std::string displayFileNodePath = getPanelSysfsPath();
227         if (displayFileNodePath.empty()) {
228             ALOGE("%s(): cannot find file node %s of display %s", __func__,
229                   displayFileNodePath.c_str(), mDisplayName.c_str());
230         } else {
231             auto& fileNodeManager =
232                     android::hardware::graphics::composer::FileNodeManager::getInstance();
233             auto fileNode = fileNodeManager.getFileNode(displayFileNodePath);
234             auto content = fileNode->readString(kRefreshControlNodeName);
235             if (content.has_value() &&
236                 !(content.value().compare(0, kRefreshControlNodeEnabled.length(),
237                                           kRefreshControlNodeEnabled))) {
238                 bool ret = fileNode->writeValue(kRefreshControlNodeName, refreshControlCommand);
239                 if (!ret) {
240                     ALOGE("%s(): write command to file node %s%s failed.", __func__,
241                           displayFileNodePath.c_str(), kRefreshControlNodeName.c_str());
242                 }
243             } else {
244                 ALOGI("%s(): refresh control is not supported", __func__);
245             }
246         }
247         mIsDisplayTempMonitorSupported = initDisplayTempMonitor(displayTypeIdentifier);
248     }
249 
250     // Allow to enable dynamic recomposition after every power on
251     // since it will always be disabled for every power off
252     // TODO(b/268474771): to enable DR by default if video mode panel is detected
253     if (property_get_int32("vendor.display.dynamic_recomposition", 0) & (1 << index)) {
254         mDRDefault = true;
255         mDREnable = true;
256     }
257 
258     // Prepare multi resolution
259     // Will be exynosHWCControl.multiResoultion
260     mResolutionInfo.nNum = 1;
261     mResolutionInfo.nResolution[0].w = 1440;
262     mResolutionInfo.nResolution[0].h = 2960;
263     mResolutionInfo.nDSCYSliceSize[0] = 40;
264     mResolutionInfo.nDSCXSliceSize[0] = 1440 / 2;
265     mResolutionInfo.nPanelType[0] = PANEL_DSC;
266     mResolutionInfo.nResolution[1].w = 1080;
267     mResolutionInfo.nResolution[1].h = 2220;
268     mResolutionInfo.nDSCYSliceSize[1] = 30;
269     mResolutionInfo.nDSCXSliceSize[1] = 1080 / 2;
270     mResolutionInfo.nPanelType[1] = PANEL_DSC;
271     mResolutionInfo.nResolution[2].w = 720;
272     mResolutionInfo.nResolution[2].h = 1480;
273     mResolutionInfo.nDSCYSliceSize[2] = 74;
274     mResolutionInfo.nDSCXSliceSize[2] = 720;
275     mResolutionInfo.nPanelType[2] = PANEL_LEGACY;
276 
277     char value[PROPERTY_VALUE_MAX];
278     const char *earlyWakeupNodeBase = early_wakeup_node_0_base;
279     if (getDcDisplayType() == DisplayType::DISPLAY_SECONDARY &&
280         property_get("vendor.display.secondary_early_wakeup_node", value, "") > 0) {
281         earlyWakeupNodeBase = value;
282     }
283     mEarlyWakeupDispFd = fopen(earlyWakeupNodeBase, "w");
284     if (mEarlyWakeupDispFd == nullptr)
285         ALOGE("open %s failed! %s", earlyWakeupNodeBase, strerror(errno));
286     mBrightnessController = std::make_unique<BrightnessController>(
__anon1d2a27210202() 287             mIndex, [this]() { mDevice->onRefresh(mDisplayId); },
__anon1d2a27210302() 288             [this]() { updatePresentColorConversionInfo(); });
289     mHistogramController = std::make_unique<HistogramController>(this);
290 
291     mDisplayControl.multiThreadedPresent = true;
292 
293     int fixedTe2DefaultRateHz =
294             property_get_int32("vendor.primarydisplay.fixed_te2.default_rate_hz", 0);
295     if (fixedTe2DefaultRateHz) {
296         mDisplayTe2Manager =
297                 std::make_unique<DisplayTe2Manager>(this, mIndex, fixedTe2DefaultRateHz);
298     }
299 }
300 
~ExynosPrimaryDisplay()301 ExynosPrimaryDisplay::~ExynosPrimaryDisplay()
302 {
303     if (mEarlyWakeupDispFd) {
304         fclose(mEarlyWakeupDispFd);
305         mEarlyWakeupDispFd = nullptr;
306     }
307 
308     if (mDisplayNeedHandleIdleExitOfs.is_open()) {
309         mDisplayNeedHandleIdleExitOfs.close();
310     }
311 
312     if (mIsDisplayTempMonitorSupported) {
313         mTMLoopStatus.store(false, std::memory_order_relaxed);
314         mTMCondition.notify_one();
315         if (mTMThread.joinable()) {
316             mTMThread.join();
317         }
318     }
319 }
320 
setDDIScalerEnable(int width,int height)321 void ExynosPrimaryDisplay::setDDIScalerEnable(int width, int height) {
322 
323     if (exynosHWCControl.setDDIScaler == false) return;
324 
325     ALOGI("DDISCALER Info : setDDIScalerEnable(w=%d,h=%d)", width, height);
326     mNewScaledWidth = width;
327     mNewScaledHeight = height;
328     mXres = width;
329     mYres = height;
330 }
331 
getDDIScalerMode(int width,int height)332 int ExynosPrimaryDisplay::getDDIScalerMode(int width, int height) {
333 
334     if (exynosHWCControl.setDDIScaler == false) return 1;
335 
336     // Check if panel support support resolution or not.
337     for (uint32_t i=0; i < mResolutionInfo.nNum; i++) {
338         if (mResolutionInfo.nResolution[i].w * mResolutionInfo.nResolution[i].h ==
339                 static_cast<uint32_t>(width * height))
340             return i + 1;
341     }
342 
343     return 1; // WQHD
344 }
345 
doDisplayConfigInternal(hwc2_config_t config)346 int32_t ExynosPrimaryDisplay::doDisplayConfigInternal(hwc2_config_t config) {
347     if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
348         !isConfigSettingEnabled()) {
349         mPendingConfig = config;
350         mConfigRequestState = hwc_request_state_t::SET_CONFIG_STATE_DONE;
351         DISPLAY_LOGI("%s:: Pending desired Config: %d", __func__, config);
352         return NO_ERROR;
353     }
354     return ExynosDisplay::doDisplayConfigInternal(config);
355 }
356 
getActiveConfigInternal(hwc2_config_t * outConfig)357 int32_t ExynosPrimaryDisplay::getActiveConfigInternal(hwc2_config_t *outConfig) {
358     if (outConfig && mPendingConfig != UINT_MAX) {
359         *outConfig = mPendingConfig;
360         return HWC2_ERROR_NONE;
361     }
362     return ExynosDisplay::getActiveConfigInternal(outConfig);
363 }
364 
setActiveConfigInternal(hwc2_config_t config,bool force)365 int32_t ExynosPrimaryDisplay::setActiveConfigInternal(hwc2_config_t config, bool force) {
366     hwc2_config_t cur_config;
367 
368     getActiveConfigInternal(&cur_config);
369     if (cur_config == config) {
370         ALOGI("%s:: Same display config is set", __func__);
371         return HWC2_ERROR_NONE;
372     }
373     if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON) ||
374         !isConfigSettingEnabled()) {
375         mPendingConfig = config;
376         return HWC2_ERROR_NONE;
377     }
378     return ExynosDisplay::setActiveConfigInternal(config, force);
379 }
380 
381 // If a display is Off, applyPendingConfig() calls to setActiveConfig() that also
382 // power on the display by a blocking commit.
applyPendingConfig()383 int32_t ExynosPrimaryDisplay::applyPendingConfig() {
384     if (!isConfigSettingEnabled()) {
385         ALOGI("%s:: config setting is disabled", __func__);
386         if (mPowerModeState.has_value() && (*mPowerModeState == HWC2_POWER_MODE_ON)) {
387             ALOGI("%s:: skip apply pending config", __func__);
388             return HWC2_ERROR_NONE;
389         }
390     }
391 
392     hwc2_config_t config;
393     if (mPendingConfig != UINT_MAX) {
394         ALOGI("%s:: mPendingConfig: %d", __func__, mPendingConfig);
395         config = mPendingConfig;
396         mPendingConfig = UINT_MAX;
397     } else {
398         getActiveConfigInternal(&config);
399     }
400 
401     return ExynosDisplay::setActiveConfigInternal(config, true);
402 }
403 
setBootDisplayConfig(int32_t config)404 int32_t ExynosPrimaryDisplay::setBootDisplayConfig(int32_t config) {
405     auto hwcConfig = static_cast<hwc2_config_t>(config);
406 
407     const auto &it = mDisplayConfigs.find(hwcConfig);
408     if (it == mDisplayConfigs.end()) {
409         DISPLAY_LOGE("%s: invalid config %d", __func__, config);
410         return HWC2_ERROR_BAD_CONFIG;
411     }
412 
413     const auto &mode = it->second;
414     if (mode.vsyncPeriod == 0)
415         return HWC2_ERROR_BAD_CONFIG;
416 
417     char modeStr[PROPERTY_VALUE_MAX];
418     int ret = snprintf(modeStr, sizeof(modeStr), "%dx%d@%d:%d", mode.width, mode.height,
419                        mode.refreshRate, nanoSec2Hz(mode.vsyncPeriod));
420     if (ret <= 0)
421         return HWC2_ERROR_BAD_CONFIG;
422 
423     ALOGD("%s: mode=%s (%d)", __func__, modeStr, config);
424     ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), modeStr);
425 
426     return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
427 }
428 
clearBootDisplayConfig()429 int32_t ExynosPrimaryDisplay::clearBootDisplayConfig() {
430     auto ret = property_set(getPropertyBootModeStr(mDisplayId).c_str(), nullptr);
431 
432     ALOGD("%s: clearing boot mode", __func__);
433     return !ret ? HWC2_ERROR_NONE : HWC2_ERROR_BAD_CONFIG;
434 }
435 
getPreferredDisplayConfigInternal(int32_t * outConfig)436 int32_t ExynosPrimaryDisplay::getPreferredDisplayConfigInternal(int32_t *outConfig) {
437     char modeStr[PROPERTY_VALUE_MAX];
438     auto ret = property_get(getPropertyBootModeStr(mDisplayId).c_str(), modeStr, "");
439 
440     if (ret <= 0) {
441         return mDisplayInterface->getDefaultModeId(outConfig);
442     }
443 
444     int width, height;
445     int fps = 0, vsyncRate = 0;
446 
447     ret = sscanf(modeStr, "%dx%d@%d:%d", &width, &height, &fps, &vsyncRate);
448     if (ret < 4) {
449         ret = sscanf(modeStr, "%dx%d@%d", &width, &height, &fps);
450         if ((ret < 3) || !fps) {
451             ALOGW("%s: unable to find boot config for mode: %s", __func__, modeStr);
452             return HWC2_ERROR_BAD_CONFIG;
453         }
454         if (lookupDisplayConfigs(width, height, fps, fps, outConfig) != HWC2_ERROR_NONE) {
455             ALOGE("%s: kernel doesn't support mode: %s", __func__, modeStr);
456             return HWC2_ERROR_BAD_CONFIG;
457         }
458         ret = setBootDisplayConfig(*outConfig);
459         if (ret == HWC2_ERROR_NONE)
460             ALOGI("%s: succeeded to replace %s with new format", __func__, modeStr);
461         else
462             ALOGE("%s: failed to replace %s with new format", __func__, modeStr);
463         return ret;
464     }
465     if (!fps || !vsyncRate || (fps > vsyncRate)) {
466         ALOGE("%s: bad boot config: %s", __func__, modeStr);
467         return HWC2_ERROR_BAD_CONFIG;
468     }
469     return lookupDisplayConfigs(width, height, fps, vsyncRate, outConfig);
470 }
471 
setPowerOn()472 int32_t ExynosPrimaryDisplay::setPowerOn() {
473     ATRACE_CALL();
474     updateAppliedActiveConfig(0, 0);
475     int ret = NO_ERROR;
476     if (mDisplayId != 0 || !mFirstPowerOn) {
477         if (mDevice->hasOtherDisplayOn(this)) {
478             mResourceManager->prepareResources(mDisplayId);
479             // TODO: This is useful for cmd mode, and b/282094671 tries to handles video mode
480             mDisplayInterface->triggerClearDisplayPlanes();
481         }
482         ret = applyPendingConfig();
483     }
484 
485     if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
486         // check the dynamic recomposition thread by following display
487         mDevice->checkDynamicRecompositionThread();
488         if (ret) {
489             mDisplayInterface->setPowerMode(HWC2_POWER_MODE_ON);
490         }
491         setGeometryChanged(GEOMETRY_DISPLAY_POWER_ON);
492     }
493 
494     {
495         std::lock_guard<std::mutex> lock(mPowerModeMutex);
496         mPowerModeState = HWC2_POWER_MODE_ON;
497         if (mNotifyPowerOn) {
498             mPowerOnCondition.notify_one();
499             mNotifyPowerOn = false;
500         }
501     }
502 
503     if (mDisplayTe2Manager) mDisplayTe2Manager->restoreTe2FromDozeMode();
504 
505     if (mFirstPowerOn) {
506         firstPowerOn();
507     }
508 
509     return HWC2_ERROR_NONE;
510 }
511 
setPowerOff()512 int32_t ExynosPrimaryDisplay::setPowerOff() {
513     ATRACE_CALL();
514 
515     clearDisplay(true);
516 
517     // check the dynamic recomposition thread by following display
518     mDevice->checkDynamicRecompositionThread();
519 
520     mDisplayInterface->setPowerMode(HWC2_POWER_MODE_OFF);
521 
522     {
523         std::lock_guard<std::mutex> lock(mPowerModeMutex);
524         mPowerModeState = HWC2_POWER_MODE_OFF;
525     }
526 
527     /* It should be called from validate() when the screen is on */
528     mSkipFrame = true;
529     setGeometryChanged(GEOMETRY_DISPLAY_POWER_OFF);
530     if ((mRenderingState >= RENDERING_STATE_VALIDATED) &&
531         (mRenderingState < RENDERING_STATE_PRESENTED))
532         closeFencesForSkipFrame(RENDERING_STATE_VALIDATED);
533     mRenderingState = RENDERING_STATE_NONE;
534 
535     // in the case user turns off screen when LHBM is on
536     // TODO: b/236433238 considering a lock for mLhbmOn state
537     mLhbmOn = false;
538     return HWC2_ERROR_NONE;
539 }
540 
setPowerDoze(hwc2_power_mode_t mode)541 int32_t ExynosPrimaryDisplay::setPowerDoze(hwc2_power_mode_t mode) {
542     ATRACE_CALL();
543 
544     if (!mDisplayInterface->isDozeModeAvailable()) {
545         return HWC2_ERROR_UNSUPPORTED;
546     }
547 
548     if (mPowerModeState.has_value() &&
549         ((*mPowerModeState == HWC2_POWER_MODE_OFF) || (*mPowerModeState == HWC2_POWER_MODE_ON))) {
550         if (mDisplayInterface->setLowPowerMode()) {
551             ALOGI("Not support LP mode.");
552             return HWC2_ERROR_UNSUPPORTED;
553         }
554     }
555 
556     {
557         std::lock_guard<std::mutex> lock(mPowerModeMutex);
558         mPowerModeState = mode;
559     }
560 
561     // LHBM will be disabled in the kernel while entering AOD mode if it's
562     // already enabled. Reset the state to avoid the sync problem.
563     mBrightnessController->resetLhbmState();
564     mLhbmOn = false;
565 
566     ExynosDisplay::updateRefreshRateHint();
567 
568     if (mDisplayTe2Manager) mDisplayTe2Manager->updateTe2ForDozeMode();
569 
570     return HWC2_ERROR_NONE;
571 }
572 
setPowerMode(int32_t mode)573 int32_t ExynosPrimaryDisplay::setPowerMode(int32_t mode) {
574     Mutex::Autolock lock(mDisplayMutex);
575 
576     if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE)) {
577         mode = HWC2_POWER_MODE_OFF;
578         mPauseDisplay = true;
579     } else if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
580         mode = HWC2_POWER_MODE_ON;
581         mPauseDisplay = false;
582     } else if (mPauseDisplay) {
583         ALOGI("Skip power mode transition due to pause display.");
584         return HWC2_ERROR_NONE;
585     }
586 
587     if (mPowerModeState.has_value() && (mode == static_cast<int32_t>(mPowerModeState.value()))) {
588         ALOGI("Skip power mode transition due to the same power state.");
589         return HWC2_ERROR_NONE;
590     }
591 
592     if (mode == HWC2_POWER_MODE_ON && mDevice->mNumPrimaryDisplays >= 2) {
593         ExynosDisplay* external_display =
594                 mDevice->getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
595         ExynosDisplayDrmInterface* external_display_intf = external_display
596                 ? static_cast<ExynosDisplayDrmInterface*>(external_display->mDisplayInterface.get())
597                 : nullptr;
598         if (external_display_intf && external_display_intf->borrowedCrtcFrom() == this) {
599             ALOGI("Display %s is powering on, adjusting decon assignments",
600                   mDisplayTraceName.c_str());
601             hwc2_config_t activeConfig = 0;
602             external_display->getActiveConfig(&activeConfig);
603             external_display->clearDisplay(true);
604             external_display->setPowerMode(HWC2_POWER_MODE_OFF);
605             // Restore the original decon assigned to external display, this will ensure
606             // primary displays remain on the same initially assigned decons.
607             external_display_intf->swapCrtcs(this);
608             // This display is about to be powered on, but its mPowerModeState is not updated yet,
609             // so we need to exclude it from consideration explicitly here.
610             ExynosDisplay* poweredOffPrimaryDisplay = mDevice->findPoweredOffPrimaryDisplay(this);
611             if (poweredOffPrimaryDisplay) {
612                 ALOGI("Found powered off primary display %s, will use its decon for external "
613                       "display",
614                       poweredOffPrimaryDisplay->mDisplayTraceName.c_str());
615                 external_display_intf->swapCrtcs(poweredOffPrimaryDisplay);
616             } else {
617                 ALOGE("Could not find a powered off primary display!");
618             }
619             external_display->mActiveConfig = 0;
620             external_display->setActiveConfig(activeConfig);
621             external_display->setPowerMode(HWC2_POWER_MODE_ON);
622         }
623     }
624 
625     int fb_blank = (mode != HWC2_POWER_MODE_OFF) ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
626     ALOGD("%s:: FBIOBLANK mode(%d), blank(%d)", __func__, mode, fb_blank);
627 
628     if (fb_blank == FB_BLANK_POWERDOWN)
629         mDREnable = false;
630     else
631         mDREnable = mDRDefault;
632 
633     if (mOperationRateManager) {
634         mOperationRateManager->onPowerMode(mode);
635         mBrightnessController->processOperationRate(
636                 mOperationRateManager->getTargetOperationRate());
637     }
638 
639     std::lock_guard<std::mutex> minIdleRefreshRateLock(mMinIdleRefreshRateMutex);
640     if (mVariableRefreshRateController) {
641         if ((mode == HWC2_POWER_MODE_DOZE) || (mode == HWC2_POWER_MODE_DOZE_SUSPEND)) {
642             mVariableRefreshRateController->setFixedRefreshRateRange(kMinIdleRefreshRateForDozeMode,
643                                                                      0);
644         }
645         mVariableRefreshRateController->preSetPowerMode(mode);
646     }
647 
648     int32_t res = HWC2_ERROR_BAD_PARAMETER;
649     switch (mode) {
650         case HWC2_POWER_MODE_DOZE:
651         case HWC2_POWER_MODE_DOZE_SUSPEND: {
652             if (mode == HWC2_POWER_MODE_DOZE && mDisplayInterface->needRefreshOnLP()) {
653                 ALOGI("Refresh before setting power doze.");
654                 mDevice->onRefresh(mDisplayId);
655             }
656             res = setPowerDoze(static_cast<hwc2_power_mode_t>(mode));
657             break;
658         }
659         case HWC2_POWER_MODE_OFF:
660             res = setPowerOff();
661             break;
662         case HWC2_POWER_MODE_ON:
663             res = setPowerOn();
664             break;
665         default:
666             return res;
667     }
668     if (res != HWC2_ERROR_NONE) {
669         return res;
670     }
671 
672     ExynosDisplay::updateRefreshRateHint();
673     if (mVariableRefreshRateController) {
674         mVariableRefreshRateController->postSetPowerMode(mode);
675         if (mode == HWC2_POWER_MODE_ON) {
676             mVariableRefreshRateController->setFixedRefreshRateRange(mMinIdleRefreshRate,
677                                                                      mRefreshRateDelayNanos);
678         }
679     }
680 
681     checkTemperatureMonitorThread(mPowerModeState.has_value() && mode == HWC2_POWER_MODE_ON);
682 
683     return res;
684 }
685 
firstPowerOn()686 void ExynosPrimaryDisplay::firstPowerOn() {
687     SetCurrentPanelGammaSource(DisplayType::DISPLAY_PRIMARY, PanelGammaSource::GAMMA_CALIBRATION);
688     mFirstPowerOn = false;
689     getDisplayIdleTimerEnabled(mDisplayIdleTimerEnabled);
690     initDisplayHandleIdleExit();
691 }
692 
getHDRException(ExynosLayer * __unused layer)693 bool ExynosPrimaryDisplay::getHDRException(ExynosLayer* __unused layer)
694 {
695     return false;
696 }
697 
initDisplayInterface(uint32_t interfaceType)698 void ExynosPrimaryDisplay::initDisplayInterface(uint32_t interfaceType)
699 {
700     if (interfaceType == INTERFACE_TYPE_DRM)
701         mDisplayInterface = std::make_unique<ExynosPrimaryDisplayDrmInterfaceModule>((ExynosDisplay *)this);
702     else
703         LOG_ALWAYS_FATAL("%s::Unknown interface type(%d)",
704                 __func__, interfaceType);
705     mDisplayInterface->init(this);
706 
707     if (mXrrSettings.versionInfo.needVrrParameters()) {
708         mDisplayInterface->setXrrSettings(mXrrSettings);
709     }
710 
711     mDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
712     mLastDpuData.init(mMaxWindowNum, mDevice->getSpecialPlaneNum(mDisplayId));
713     ALOGI("window configs size(%zu) rcd configs zie(%zu)", mDpuData.configs.size(),
714           mDpuData.rcdConfigs.size());
715 }
716 
getPanelSysfsPath(const DisplayType & type) const717 std::string ExynosPrimaryDisplay::getPanelSysfsPath(const DisplayType& type) const {
718     if ((type < DisplayType::DISPLAY_PRIMARY) || (type >= DisplayType::DISPLAY_MAX)) {
719         ALOGE("Invalid display panel type %d", type);
720         return {};
721     }
722 
723     const auto& iter = panelSysfsPath.find(type);
724     if (iter == panelSysfsPath.end()) {
725         return {};
726     }
727 
728     return iter->second;
729 }
730 
SetCurrentPanelGammaSource(const DisplayType type,const PanelGammaSource & source)731 int32_t ExynosPrimaryDisplay::SetCurrentPanelGammaSource(const DisplayType type,
732                                                          const PanelGammaSource &source) {
733     std::string &&panel_sysfs_path = getPanelSysfsPath(type);
734     if (panel_sysfs_path.empty()) {
735         return HWC2_ERROR_UNSUPPORTED;
736     }
737 
738     std::ifstream ifs;
739     std::string &&path = panel_sysfs_path + "panel_name";
740     ifs.open(path, std::ifstream::in);
741     if (!ifs.is_open()) {
742         ALOGW("Unable to access panel name path '%s' (%s)", path.c_str(), strerror(errno));
743         return HWC2_ERROR_UNSUPPORTED;
744     }
745     std::string panel_name;
746     std::getline(ifs, panel_name);
747     ifs.close();
748 
749     path = panel_sysfs_path + "serial_number";
750     ifs.open(path, std::ifstream::in);
751     if (!ifs.is_open()) {
752         ALOGW("Unable to access panel id path '%s' (%s)", path.c_str(), strerror(errno));
753         return HWC2_ERROR_UNSUPPORTED;
754     }
755     std::string panel_id;
756     std::getline(ifs, panel_id);
757     ifs.close();
758 
759     std::string gamma_node = panel_sysfs_path + "gamma";
760     if (access(gamma_node.c_str(), W_OK)) {
761         ALOGW("Unable to access panel gamma calibration node '%s' (%s)", gamma_node.c_str(),
762               strerror(errno));
763         return HWC2_ERROR_UNSUPPORTED;
764     }
765 
766     std::string &&gamma_data = "default";
767     if (source == PanelGammaSource::GAMMA_CALIBRATION) {
768         std::string gamma_cal_file(kDisplayCalFilePath);
769         gamma_cal_file.append(kPanelGammaCalFilePrefix)
770                 .append(1, '_')
771                 .append(panel_name)
772                 .append(1, '_')
773                 .append(panel_id)
774                 .append(".cal");
775         if (access(gamma_cal_file.c_str(), R_OK)) {
776             ALOGI("Fail to access `%s` (%s), try golden gamma calibration", gamma_cal_file.c_str(),
777                   strerror(errno));
778             gamma_cal_file = kDisplayCalFilePath;
779             gamma_cal_file.append(kPanelGammaCalFilePrefix)
780                     .append(1, '_')
781                     .append(panel_name)
782                     .append(".cal");
783         }
784         gamma_data = loadPanelGammaCalibration(gamma_cal_file);
785     }
786 
787     if (gamma_data.empty()) {
788         return HWC2_ERROR_UNSUPPORTED;
789     }
790 
791     std::ofstream ofs(gamma_node);
792     if (!ofs.is_open()) {
793         ALOGW("Unable to open gamma node '%s', error = %s", gamma_node.c_str(), strerror(errno));
794         return HWC2_ERROR_UNSUPPORTED;
795     }
796     ofs.write(gamma_data.c_str(), gamma_data.size());
797     ofs.close();
798 
799     currentPanelGammaSource = source;
800     return HWC2_ERROR_NONE;
801 }
802 
isLhbmSupported()803 bool ExynosPrimaryDisplay::isLhbmSupported() {
804     return mBrightnessController->isLhbmSupported();
805 }
806 
isConfigSettingEnabled()807 bool ExynosPrimaryDisplay::isConfigSettingEnabled() {
808     int64_t msSinceDisabled =
809             (systemTime(SYSTEM_TIME_MONOTONIC) - mConfigSettingDisabledTimestamp) / 1000000;
810     return !mConfigSettingDisabled || msSinceDisabled > kConfigDisablingMaxDurationMs;
811 }
812 
enableConfigSetting(bool en)813 void ExynosPrimaryDisplay::enableConfigSetting(bool en) {
814     DISPLAY_ATRACE_INT("ConfigSettingDisabled", !en);
815     ALOGI("%s:: mConfigSettingDisabled: %d", __func__, !en);
816     if (!en) {
817         mConfigSettingDisabled = true;
818         mConfigSettingDisabledTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
819         return;
820     }
821 
822     mConfigSettingDisabled = false;
823 }
824 
getDisplayConfigs(uint32_t * outNumConfigs,hwc2_config_t * outConfigs)825 int32_t ExynosPrimaryDisplay::getDisplayConfigs(uint32_t* outNumConfigs,
826                                                 hwc2_config_t* outConfigs) {
827     int32_t ret = ExynosDisplay::getDisplayConfigs(outNumConfigs, outConfigs);
828     if (ret == HWC2_ERROR_NONE) {
829         if (mXrrSettings.versionInfo.hasVrrController() && mDisplayConfigs.size()) {
830             if (!mVariableRefreshRateController) {
831                 mVariableRefreshRateController =
832                         VariableRefreshRateController::CreateInstance(this, getPanelName());
833                 std::unordered_map<hwc2_config_t, VrrConfig_t> vrrConfigs;
834                 for (const auto& it : mDisplayConfigs) {
835                     if (!it.second.vrrConfig.has_value()) {
836                         ALOGE("Both pseudo and full VRR modes should include VRR configurations.");
837                         return HWC2_ERROR_BAD_CONFIG;
838                     }
839                     vrrConfigs[it.first] = it.second.vrrConfig.value();
840                 }
841                 mVariableRefreshRateController->setVrrConfigurations(std::move(vrrConfigs));
842                 hwc2_config_t activeConfig;
843                 if (ExynosDisplay::getActiveConfig(&activeConfig) == HWC2_ERROR_NONE) {
844                     mVariableRefreshRateController->setActiveVrrConfiguration(activeConfig);
845                     mVariableRefreshRateController->setEnable(true);
846                 }
847             }
848         }
849     }
850     return ret;
851 }
852 
presentDisplay(int32_t * outRetireFence)853 int32_t ExynosPrimaryDisplay::presentDisplay(int32_t* outRetireFence) {
854     auto res = ExynosDisplay::presentDisplay(outRetireFence);
855     // Forward presentDisplay if there is a listener.
856     const auto refreshListener = getRefreshListener();
857     if (res == HWC2_ERROR_NONE && refreshListener) {
858         refreshListener->onPresent(*outRetireFence);
859     }
860     return res;
861 }
862 
onVsync(int64_t timestamp)863 void ExynosPrimaryDisplay::onVsync(int64_t timestamp) {
864     const auto vsyncListener = getVsyncListener();
865     if (vsyncListener) {
866         vsyncListener->onVsync(timestamp, 0);
867     }
868 }
869 
notifyExpectedPresent(int64_t timestamp,int32_t frameIntervalNs)870 int32_t ExynosPrimaryDisplay::notifyExpectedPresent(int64_t timestamp, int32_t frameIntervalNs) {
871     DISPLAY_ATRACE_INT64("expectedPresentTimeDelta", timestamp - systemTime());
872     DISPLAY_ATRACE_INT("frameInterval", frameIntervalNs);
873     if (mVariableRefreshRateController) {
874         mVariableRefreshRateController->notifyExpectedPresent(timestamp, frameIntervalNs);
875     }
876     return NO_ERROR;
877 }
878 
setPresentTimeoutParameters(int timeoutNs,const std::vector<std::pair<uint32_t,uint32_t>> & settings)879 int32_t ExynosPrimaryDisplay::setPresentTimeoutParameters(
880         int timeoutNs, const std::vector<std::pair<uint32_t, uint32_t>>& settings) {
881     if (mVariableRefreshRateController) {
882         mVariableRefreshRateController->setPresentTimeoutParameters(timeoutNs, settings);
883         return NO_ERROR;
884     }
885     return HWC2_ERROR_UNSUPPORTED;
886 }
887 
setPresentTimeoutController(uint32_t controllerType)888 int32_t ExynosPrimaryDisplay::setPresentTimeoutController(uint32_t controllerType) {
889     if (mVariableRefreshRateController) {
890         mVariableRefreshRateController->setPresentTimeoutController(controllerType);
891         return NO_ERROR;
892     }
893     return HWC2_ERROR_UNSUPPORTED;
894 }
895 
setRefreshRateChangedCallbackDebugEnabled(bool enabled)896 int32_t ExynosPrimaryDisplay::setRefreshRateChangedCallbackDebugEnabled(bool enabled) {
897     if (mVariableRefreshRateController) {
898         mVariableRefreshRateController->enableRefreshRateCalculator(enabled);
899     } else {
900         ExynosDisplay::setRefreshRateChangedCallbackDebugEnabled(enabled);
901     }
902     return NO_ERROR;
903 }
904 
setLhbmDisplayConfigLocked(uint32_t peakRate)905 int32_t ExynosPrimaryDisplay::setLhbmDisplayConfigLocked(uint32_t peakRate) {
906     auto hwConfig = mDisplayInterface->getActiveModeId();
907     auto config = getConfigId(peakRate, mDisplayConfigs[hwConfig].width,
908                               mDisplayConfigs[hwConfig].height);
909     if (config == UINT_MAX) {
910         DISPLAY_LOGE("%s: failed to get config for rate=%d", __func__, peakRate);
911         return -EINVAL;
912     }
913 
914     if (mPendingConfig == UINT_MAX && mActiveConfig != config) mPendingConfig = mActiveConfig;
915     if (config != hwConfig) {
916         if (ExynosDisplay::setActiveConfigInternal(config, true) == HWC2_ERROR_NONE) {
917             DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, config, peakRate);
918         } else {
919             DISPLAY_LOGW("%s: failed to set config=%d rate=%d", __func__, config, peakRate);
920         }
921     } else {
922         DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, config, peakRate);
923     }
924     enableConfigSetting(false);
925     return OK;
926 }
927 
restoreLhbmDisplayConfigLocked()928 void ExynosPrimaryDisplay::restoreLhbmDisplayConfigLocked() {
929     enableConfigSetting(true);
930 
931     if (*mPowerModeState == HWC2_POWER_MODE_DOZE ||
932         *mPowerModeState == HWC2_POWER_MODE_DOZE_SUSPEND) {
933         DISPLAY_LOGI("%s: in aod mode(%d), skip restore", __func__, *mPowerModeState);
934         return;
935     }
936 
937     hwc2_config_t pendingConfig = mPendingConfig;
938     auto hwConfig = mDisplayInterface->getActiveModeId();
939     if (pendingConfig != UINT_MAX && pendingConfig != hwConfig) {
940         if (applyPendingConfig() == HWC2_ERROR_NONE) {
941             DISPLAY_LOGI("%s: succeeded to set config=%d rate=%d", __func__, pendingConfig,
942                          getRefreshRate(pendingConfig));
943         } else {
944             DISPLAY_LOGE("%s: failed to set config=%d rate=%d", __func__, pendingConfig,
945                          getRefreshRate(pendingConfig));
946         }
947     } else {
948         mPendingConfig = UINT_MAX;
949         DISPLAY_LOGI("%s: keep config=%d rate=%d", __func__, hwConfig, getRefreshRate(hwConfig));
950     }
951 }
952 
953 // This function should be called by other threads (e.g. sensor HAL).
954 // HWCService can call this function but it should be for test purpose only.
setLhbmState(bool enabled)955 int32_t ExynosPrimaryDisplay::setLhbmState(bool enabled) {
956     int ret = OK;
957     // NOTE: mLhbmOn could be set to false at any time by setPowerOff in another
958     // thread. Make sure no side effect if that happens. Or add lock if we have
959     // to when new code is added.
960     DISPLAY_ATRACE_CALL();
961     DISPLAY_LOGI("%s: enabled=%d", __func__, enabled);
962     {
963         ATRACE_NAME("wait_for_power_on");
964         std::unique_lock<std::mutex> lock(mPowerModeMutex);
965         if (!mPowerModeState.has_value() || (*mPowerModeState != HWC2_POWER_MODE_ON)) {
966             mNotifyPowerOn = true;
967             if (!mPowerOnCondition.wait_for(lock, std::chrono::milliseconds(2000), [this]() {
968                     return (mPowerModeState.has_value() &&
969                             (*mPowerModeState == HWC2_POWER_MODE_ON));
970                 })) {
971                 DISPLAY_LOGW("%s: wait for power mode on timeout !", __func__);
972                 return TIMED_OUT;
973             }
974         }
975     }
976 
977     auto lhbmSysfs = mBrightnessController->GetPanelSysfileByIndex(
978             BrightnessController::kLocalHbmModeFileNode);
979     ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
980                                          {std::to_string(static_cast<int>(
981                                                  BrightnessController::LhbmMode::DISABLED))},
982                                          0);
983     bool wasDisabled = ret == OK;
984     if (!enabled && wasDisabled) {
985         DISPLAY_LOGW("%s: lhbm is at DISABLED state, skip disabling", __func__);
986         return NO_ERROR;
987     } else if (enabled && !wasDisabled) {
988         requestLhbm(true);
989         DISPLAY_LOGI("%s: lhbm is at ENABLING or ENABLED state, re-enable to reset timeout timer",
990                      __func__);
991         return NO_ERROR;
992     }
993 
994     std::vector<std::string> checkingValue;
995     if (!enabled) {
996         ATRACE_NAME("disable_lhbm");
997         requestLhbm(false);
998         {
999             ATRACE_NAME("wait_for_lhbm_off_cmd");
1000             checkingValue = {
1001                     std::to_string(static_cast<int>(BrightnessController::LhbmMode::DISABLED))};
1002             ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
1003                                                           ms2ns(kSysfsCheckTimeoutMs));
1004             if (ret != OK) {
1005                 DISPLAY_LOGW("%s: failed to send lhbm-off cmd", __func__);
1006             }
1007         }
1008         {
1009             Mutex::Autolock lock(mDisplayMutex);
1010             restoreLhbmDisplayConfigLocked();
1011         }
1012         setLHBMRefreshRateThrottle(0);
1013         mLhbmOn = false;
1014         return NO_ERROR;
1015     }
1016 
1017     ATRACE_NAME("enable_lhbm");
1018     int64_t lhbmWaitForRrNanos, lhbmEnablingNanos, lhbmEnablingDoneNanos;
1019     bool enablingStateSupported = !mFramesToReachLhbmPeakBrightness;
1020     uint32_t peakRate = 0;
1021     auto rrSysfs = mBrightnessController->GetPanelRefreshRateSysfile();
1022     lhbmWaitForRrNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1023     {
1024         Mutex::Autolock lock(mDisplayMutex);
1025         peakRate = getPeakRefreshRate();
1026         if (peakRate < 60) {
1027             DISPLAY_LOGE("%s: invalid peak rate=%d", __func__, peakRate);
1028             return -EINVAL;
1029         }
1030         ret = setLhbmDisplayConfigLocked(peakRate);
1031         if (ret != OK) return ret;
1032     }
1033 
1034     if (mBrightnessController->fileExists(rrSysfs)) {
1035         ATRACE_NAME("wait_for_peak_rate_cmd");
1036         ret = mBrightnessController->checkSysfsStatus(rrSysfs, {std::to_string(peakRate)},
1037                                                       ms2ns(kLhbmWaitForPeakRefreshRateMs));
1038         if (ret != OK) {
1039             DISPLAY_LOGW("%s: failed to poll peak refresh rate=%d, ret=%d", __func__, peakRate,
1040                          ret);
1041         }
1042     } else {
1043         ATRACE_NAME("wait_for_peak_rate_blindly");
1044         DISPLAY_LOGW("%s: missing refresh rate path: %s", __func__, rrSysfs.c_str());
1045         // blindly wait for (3 full frames + 1 frame uncertainty) to ensure DM finishes
1046         // switching refresh rate
1047         for (int32_t i = 0; i < 4; i++) {
1048             if (mDisplayInterface->waitVBlank()) {
1049                 DISPLAY_LOGE("%s: failed to blindly wait for peak refresh rate=%d, i=%d", __func__,
1050                              peakRate, i);
1051                 ret = -ENODEV;
1052                 goto enable_err;
1053             }
1054         }
1055     }
1056 
1057     setLHBMRefreshRateThrottle(kLhbmRefreshRateThrottleMs);
1058     checkingValue = {std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLING)),
1059                      std::to_string(static_cast<int>(BrightnessController::LhbmMode::ENABLED))};
1060     lhbmEnablingNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1061     requestLhbm(true);
1062     {
1063         ATRACE_NAME("wait_for_lhbm_on_cmd");
1064         ret = mBrightnessController->checkSysfsStatus(lhbmSysfs, checkingValue,
1065                                                       ms2ns(kSysfsCheckTimeoutMs));
1066         if (ret != OK) {
1067             DISPLAY_LOGE("%s: failed to enable lhbm", __func__);
1068             setLHBMRefreshRateThrottle(0);
1069             goto enable_err;
1070         }
1071     }
1072 
1073     lhbmEnablingDoneNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1074     {
1075         ATRACE_NAME("wait_for_peak_brightness");
1076         if (enablingStateSupported) {
1077             ret = mBrightnessController->checkSysfsStatus(lhbmSysfs,
1078                                             {std::to_string(static_cast<int>(
1079                                                     BrightnessController::LhbmMode::ENABLED))},
1080                                             ms2ns(kSysfsCheckTimeoutMs));
1081             if (ret != OK) {
1082                 DISPLAY_LOGE("%s: failed to wait for lhbm becoming effective", __func__);
1083                 goto enable_err;
1084             }
1085         } else {
1086             // lhbm takes effect at next vblank
1087             for (int32_t i = mFramesToReachLhbmPeakBrightness + 1; i > 0; i--) {
1088                 ret = mDisplayInterface->waitVBlank();
1089                 if (ret) {
1090                     DISPLAY_LOGE("%s: failed to wait vblank for peak brightness, %d", __func__, i);
1091                     goto enable_err;
1092                 }
1093             }
1094         }
1095     }
1096     DISPLAY_LOGI("%s: latency: %04d = %03d|rr@%03d + %03d|en + %03d|boost@%s", __func__,
1097                  getTimestampDeltaMs(0, lhbmWaitForRrNanos),
1098                  getTimestampDeltaMs(lhbmEnablingNanos, lhbmWaitForRrNanos), peakRate,
1099                  getTimestampDeltaMs(lhbmEnablingDoneNanos, lhbmEnablingNanos),
1100                  getTimestampDeltaMs(0, lhbmEnablingDoneNanos),
1101                  enablingStateSupported ? "polling" : "fixed");
1102 
1103     mLhbmOn = true;
1104     if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF && mLhbmOn)) {
1105         mLhbmOn = false;
1106         DISPLAY_LOGE("%s: power off during request lhbm on", __func__);
1107         return -EINVAL;
1108     }
1109     return NO_ERROR;
1110 enable_err:
1111     {
1112         // We may receive LHBM request during the power off sequence due to the
1113         // race condition between display and sensor. If the failure happens
1114         // after requestLhbm(), we will get a wrong LHBM state in the 1st commit
1115         // after power on. We should reset the state in this case.
1116         std::unique_lock<std::mutex> lock(mPowerModeMutex);
1117         if (!mPowerModeState.has_value() || (*mPowerModeState == HWC2_POWER_MODE_OFF)) {
1118             DISPLAY_LOGW("%s: request lhbm during power off sequence, reset the state", __func__);
1119             mBrightnessController->resetLhbmState();
1120         }
1121     }
1122 
1123     Mutex::Autolock lock(mDisplayMutex);
1124     restoreLhbmDisplayConfigLocked();
1125     return ret;
1126 }
1127 
getLhbmState()1128 bool ExynosPrimaryDisplay::getLhbmState() {
1129     return mLhbmOn;
1130 }
1131 
setLHBMRefreshRateThrottle(const uint32_t delayMs)1132 void ExynosPrimaryDisplay::setLHBMRefreshRateThrottle(const uint32_t delayMs) {
1133     ATRACE_CALL();
1134 
1135     if (delayMs) {
1136         // make new throttle take effect
1137         mLastRefreshRateAppliedNanos = systemTime(SYSTEM_TIME_MONOTONIC);
1138         DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
1139     }
1140 
1141     setRefreshRateThrottleNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
1142                                         std::chrono::milliseconds(delayMs))
1143                                         .count(),
1144                                 RrThrottleRequester::LHBM);
1145 }
1146 
setEarlyWakeupDisplay()1147 void ExynosPrimaryDisplay::setEarlyWakeupDisplay() {
1148     if (mEarlyWakeupDispFd) {
1149         writeFileNode(mEarlyWakeupDispFd, 1);
1150     }
1151 }
1152 
setExpectedPresentTime(uint64_t timestamp,int frameIntervalNs)1153 void ExynosPrimaryDisplay::setExpectedPresentTime(uint64_t timestamp, int frameIntervalNs) {
1154     DISPLAY_ATRACE_INT64("expectedPresentTimeDelta", timestamp - systemTime());
1155     DISPLAY_ATRACE_INT("frameInterval", frameIntervalNs);
1156 
1157     mExpectedPresentTimeAndInterval.store(std::make_tuple(timestamp, frameIntervalNs));
1158     // Forward presentDisplay if there is a listener.
1159     const auto refreshListener = getRefreshListener();
1160     if (refreshListener) {
1161         refreshListener->setExpectedPresentTime(timestamp, frameIntervalNs);
1162     }
1163 }
1164 
getPendingExpectedPresentTime()1165 uint64_t ExynosPrimaryDisplay::getPendingExpectedPresentTime() {
1166     if (mExpectedPresentTimeAndInterval.is_dirty()) {
1167         return std::get<0>(mExpectedPresentTimeAndInterval.get());
1168     }
1169 
1170     return 0;
1171 }
1172 
getPendingFrameInterval()1173 int ExynosPrimaryDisplay::getPendingFrameInterval() {
1174     if (mExpectedPresentTimeAndInterval.is_dirty()) {
1175         return std::get<1>(mExpectedPresentTimeAndInterval.get());
1176     }
1177 
1178     return 0;
1179 }
1180 
applyExpectedPresentTime()1181 void ExynosPrimaryDisplay::applyExpectedPresentTime() {
1182     mExpectedPresentTimeAndInterval.clear_dirty();
1183 }
1184 
setDisplayIdleTimer(const int32_t timeoutMs)1185 int32_t ExynosPrimaryDisplay::setDisplayIdleTimer(const int32_t timeoutMs) {
1186     bool support = false;
1187     if (getDisplayIdleTimerSupport(support) || support == false) {
1188         return HWC2_ERROR_UNSUPPORTED;
1189     }
1190 
1191     if (timeoutMs < 0) {
1192         return HWC2_ERROR_BAD_PARAMETER;
1193     }
1194 
1195     if (timeoutMs > 0) {
1196         setDisplayIdleDelayNanos(std::chrono::duration_cast<std::chrono::nanoseconds>(
1197                                          std::chrono::milliseconds(timeoutMs))
1198                                          .count(),
1199                                  DispIdleTimerRequester::SF);
1200     }
1201 
1202     bool enabled = (timeoutMs > 0);
1203     if (enabled != mDisplayIdleTimerEnabled) {
1204         if (setDisplayIdleTimerEnabled(enabled) == NO_ERROR) {
1205             mDisplayIdleTimerEnabled = enabled;
1206         }
1207     }
1208 
1209     return HWC2_ERROR_NONE;
1210 }
1211 
getDisplayIdleTimerEnabled(bool & enabled)1212 int32_t ExynosPrimaryDisplay::getDisplayIdleTimerEnabled(bool &enabled) {
1213     bool support = false;
1214     if (getDisplayIdleTimerSupport(support) || support == false) {
1215         return HWC2_ERROR_UNSUPPORTED;
1216     }
1217 
1218     const std::string path = getPanelSysfsPath() + "panel_idle";
1219     std::ifstream ifs(path);
1220     if (!ifs.is_open()) {
1221         ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1222         return errno;
1223     } else {
1224         std::string panel_idle;
1225         std::getline(ifs, panel_idle);
1226         ifs.close();
1227         enabled = (panel_idle == "1");
1228         ALOGI("%s() get panel_idle(%d) from the sysfs node", __func__, enabled);
1229     }
1230     return NO_ERROR;
1231 }
1232 
setDisplayIdleTimerEnabled(const bool enabled)1233 int32_t ExynosPrimaryDisplay::setDisplayIdleTimerEnabled(const bool enabled) {
1234     const std::string path = getPanelSysfsPath() + "panel_idle";
1235     std::ofstream ofs(path);
1236     if (!ofs.is_open()) {
1237         ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1238         return errno;
1239     } else {
1240         ofs << enabled;
1241         ofs.close();
1242         ALOGI("%s() writes panel_idle(%d) to the sysfs node", __func__, enabled);
1243     }
1244     return NO_ERROR;
1245 }
1246 
setDisplayIdleDelayNanos(const int32_t delayNanos,const DispIdleTimerRequester requester)1247 int32_t ExynosPrimaryDisplay::setDisplayIdleDelayNanos(const int32_t delayNanos,
1248                                                        const DispIdleTimerRequester requester) {
1249     std::lock_guard<std::mutex> lock(mDisplayIdleDelayMutex);
1250 
1251     int64_t maxDelayNanos = 0;
1252     mDisplayIdleTimerNanos[toUnderlying(requester)] = delayNanos;
1253     for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
1254         if (mDisplayIdleTimerNanos[i] > maxDelayNanos) {
1255             maxDelayNanos = mDisplayIdleTimerNanos[i];
1256         }
1257     }
1258 
1259     if (mDisplayIdleDelayNanos == maxDelayNanos) {
1260         return NO_ERROR;
1261     }
1262 
1263     mDisplayIdleDelayNanos = maxDelayNanos;
1264 
1265     const int32_t displayIdleDelayMs = std::chrono::duration_cast<std::chrono::milliseconds>(
1266                                                std::chrono::nanoseconds(mDisplayIdleDelayNanos))
1267                                                .count();
1268     const std::string path = getPanelSysfsPath() + "idle_delay_ms";
1269     std::ofstream ofs(path);
1270     if (!ofs.is_open()) {
1271         ALOGW("%s() unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1272         return errno;
1273     } else {
1274         ofs << displayIdleDelayMs;
1275         ALOGI("%s() writes idle_delay_ms(%d) to the sysfs node (0x%x)", __func__,
1276               displayIdleDelayMs, ofs.rdstate());
1277         ofs.close();
1278     }
1279     return NO_ERROR;
1280 }
1281 
initDisplayHandleIdleExit()1282 void ExynosPrimaryDisplay::initDisplayHandleIdleExit() {
1283     if (bool support; getDisplayIdleTimerSupport(support) || support == false) {
1284         return;
1285     }
1286 
1287     const std::string path = getPanelSysfsPath() + "panel_need_handle_idle_exit";
1288     mDisplayNeedHandleIdleExitOfs.open(path, std::ofstream::out);
1289     if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
1290         ALOGI("%s() '%s' doesn't exist(%s)", __func__, path.c_str(), strerror(errno));
1291     }
1292 
1293     setDisplayNeedHandleIdleExit(false, true);
1294 }
1295 
setDisplayNeedHandleIdleExit(const bool needed,const bool force)1296 void ExynosPrimaryDisplay::setDisplayNeedHandleIdleExit(const bool needed, const bool force) {
1297     if (!mDisplayNeedHandleIdleExitOfs.is_open()) {
1298         return;
1299     }
1300 
1301     if (needed == mDisplayNeedHandleIdleExit && !force) {
1302         return;
1303     }
1304 
1305     mDisplayNeedHandleIdleExitOfs << needed;
1306     if (mDisplayNeedHandleIdleExitOfs.fail()) {
1307         ALOGW("%s() failed to write panel_need_handle_idle_exit(%d) to sysfs node %s", __func__,
1308               needed, strerror(errno));
1309         return;
1310     }
1311 
1312     mDisplayNeedHandleIdleExitOfs.flush();
1313     if (mDisplayNeedHandleIdleExitOfs.fail()) {
1314         ALOGW("%s() failed to flush panel_need_handle_idle_exit(%d) to sysfs node %s", __func__,
1315               needed, strerror(errno));
1316         return;
1317     }
1318 
1319     ALOGI("%s() writes panel_need_handle_idle_exit(%d) to sysfs node", __func__, needed);
1320     mDisplayNeedHandleIdleExit = needed;
1321 }
1322 
handleDisplayIdleEnter(const uint32_t idleTeRefreshRate)1323 void ExynosPrimaryDisplay::handleDisplayIdleEnter(const uint32_t idleTeRefreshRate) {
1324     bool needed = false;
1325     {
1326         Mutex::Autolock lock1(mDisplayMutex);
1327         uint32_t btsRefreshRate = getBtsRefreshRate();
1328         if (idleTeRefreshRate <= btsRefreshRate) {
1329             return;
1330         }
1331         Mutex::Autolock lock2(mDRMutex);
1332         for (size_t i = 0; i < mLayers.size(); i++) {
1333             if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
1334                 !mLayers[i]->checkBtsCap(idleTeRefreshRate)) {
1335                 needed = true;
1336                 break;
1337             }
1338         }
1339     }
1340 
1341     setDisplayNeedHandleIdleExit(needed, false);
1342 }
1343 
setFixedTe2Rate(const int targetTe2RateHz)1344 int32_t ExynosPrimaryDisplay::setFixedTe2Rate(const int targetTe2RateHz) {
1345     if (mDisplayTe2Manager) {
1346         return mDisplayTe2Manager->setFixedTe2Rate(targetTe2RateHz);
1347     } else {
1348         return HWC2_ERROR_UNSUPPORTED;
1349     }
1350 }
1351 
setDisplayTemperature(const int temperature)1352 int32_t ExynosPrimaryDisplay::setDisplayTemperature(const int temperature) {
1353     mDisplayTemperature = temperature;
1354     return HWC2_ERROR_UNSUPPORTED;
1355 }
1356 
onProximitySensorStateChanged(bool active)1357 void ExynosPrimaryDisplay::onProximitySensorStateChanged(bool active) {
1358     if (mProximitySensorStateChangeCallback) {
1359         ALOGI("ExynosPrimaryDisplay: %s: %d", __func__, active);
1360         ATRACE_NAME("onProximitySensorStateChanged(HAL)");
1361         mProximitySensorStateChangeCallback->onProximitySensorStateChanged(active);
1362     }
1363 }
1364 
setMinIdleRefreshRate(const int targetFps,const RrThrottleRequester requester)1365 int32_t ExynosPrimaryDisplay::setMinIdleRefreshRate(const int targetFps,
1366                                                     const RrThrottleRequester requester) {
1367     if (targetFps < 0) {
1368         return HWC2_ERROR_BAD_PARAMETER;
1369     }
1370     int fps = targetFps;
1371     if ((requester == RrThrottleRequester::BRIGHTNESS) &&
1372         (!mBrightnessBlockingZonesLookupTable.empty())) {
1373         std::unique_lock<std::mutex> lock(mPowerModeMutex);
1374         // Only check the BRIGHTNESS vote when the power is on.
1375         if (mPowerModeState.has_value() && (*mPowerModeState == HWC2_POWER_MODE_ON)) {
1376             auto res = mBrightnessController->getBrightnessNitsAndMode();
1377             if (res != std::nullopt) {
1378                 const auto it =
1379                         mBrightnessBlockingZonesLookupTable.upper_bound(std::get<0>(res.value()));
1380                 ALOGD("%s requester = BRIGHTNESS, brightness = %f nits, vote minimum refresh rate "
1381                       "to %d",
1382                       __func__, std::get<0>(res.value()), it->second);
1383                 fps = std::max(fps, it->second);
1384                 if (mDisplayConfigs.count(mActiveConfig)) {
1385                     if (fps > mDisplayConfigs[mActiveConfig].refreshRate) {
1386                         ALOGI("%s() The brightness blocking zone votes for the FPS = %d, which is "
1387                               "higher than the maximum refresh rate of the current configuration = "
1388                               "%d",
1389                               __func__, fps, mDisplayConfigs[mActiveConfig].refreshRate);
1390                         fps = mDisplayConfigs[mActiveConfig].refreshRate;
1391                     }
1392                 }
1393             }
1394         }
1395     }
1396 
1397     std::lock_guard<std::mutex> lock(mMinIdleRefreshRateMutex);
1398     if (fps == mRrThrottleFps[toUnderlying(requester)]) return NO_ERROR;
1399 
1400     ALOGD("%s requester %u, fps %d", __func__, toUnderlying(requester), fps);
1401     mRrThrottleFps[toUnderlying(requester)] = fps;
1402     int maxMinIdleFps = 0;
1403     for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1404         if (mRrThrottleFps[i] > maxMinIdleFps) {
1405             maxMinIdleFps = mRrThrottleFps[i];
1406         }
1407     }
1408 
1409     {
1410         std::lock_guard<std::mutex> lock(mPowerModeMutex);
1411         bool dozeMode = (mPowerModeState.has_value() &&
1412                          (*mPowerModeState == HWC2_POWER_MODE_DOZE ||
1413                           *mPowerModeState == HWC2_POWER_MODE_DOZE_SUSPEND));
1414         // Currently only proximity sensor will request the min refresh rate via this API with
1415         // PIXEL_DISP (or TEST for the debugging command). It will request a non-zero value,
1416         // e.g. 30Hz, if it's active, and request zero if it's inactive. So we can know its state
1417         // and update the TE2 option accordingly.
1418         if (mDisplayTe2Manager &&
1419             (requester == RrThrottleRequester::PIXEL_DISP ||
1420              requester == RrThrottleRequester::TEST)) {
1421             bool proximityActive = !!targetFps;
1422             ALOGD("%s: proximity state %s, min %dhz, doze mode %d", __func__,
1423                   proximityActive ? "active" : "inactive", targetFps, dozeMode);
1424             mDisplayTe2Manager->updateTe2OptionForProximity(proximityActive, targetFps, dozeMode);
1425             if (!dozeMode) {
1426                 mDisplayTe2Manager->handleProximitySensorStateChange(proximityActive);
1427             }
1428         }
1429 
1430         if (maxMinIdleFps == mMinIdleRefreshRate) return NO_ERROR;
1431 
1432         if (mVariableRefreshRateController) {
1433             if (dozeMode && maxMinIdleFps != kMinIdleRefreshRateForDozeMode) {
1434                 ALOGW("%s: setting %dhz in doze mode (expect %dhz)", __func__, maxMinIdleFps,
1435                       kMinIdleRefreshRateForDozeMode);
1436                 mMinIdleRefreshRate = maxMinIdleFps;
1437                 return NO_ERROR;
1438             }
1439 
1440             int ret = mVariableRefreshRateController
1441                               ->setFixedRefreshRateRange(maxMinIdleFps, mRefreshRateDelayNanos);
1442             if (ret >= 0) {
1443                 mMinIdleRefreshRate = maxMinIdleFps;
1444                 return NO_ERROR;
1445             }
1446             return ret;
1447         }
1448     }
1449 
1450     const std::string path = getPanelSysfsPath() + "min_vrefresh";
1451     std::ofstream ofs(path);
1452     if (!ofs.is_open()) {
1453         ALOGW("%s Unable to open node '%s', error = %s", __func__, path.c_str(), strerror(errno));
1454         return errno;
1455     } else {
1456         ofs << maxMinIdleFps;
1457         ofs.close();
1458         ALOGI("ExynosPrimaryDisplay::%s() writes min_vrefresh(%d) to the sysfs node", __func__,
1459               maxMinIdleFps);
1460     }
1461     mMinIdleRefreshRate = maxMinIdleFps;
1462     return NO_ERROR;
1463 }
1464 
setRefreshRateThrottleNanos(const int64_t delayNanos,const RrThrottleRequester requester)1465 int32_t ExynosPrimaryDisplay::setRefreshRateThrottleNanos(const int64_t delayNanos,
1466                                                           const RrThrottleRequester requester) {
1467     ATRACE_CALL();
1468     if (delayNanos < 0) {
1469         ALOGW("%s() set invalid delay(%" PRId64 ")", __func__, delayNanos);
1470         return BAD_VALUE;
1471     }
1472 
1473     int32_t ret = NO_ERROR;
1474     int64_t maxDelayNanos = 0;
1475     {
1476         std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1477         if (delayNanos == mRrThrottleNanos[toUnderlying(requester)]) return NO_ERROR;
1478 
1479         ALOGI("%s() requester(%u) set delay to %" PRId64 "ns", __func__, toUnderlying(requester),
1480               delayNanos);
1481         mRrThrottleNanos[toUnderlying(requester)] = delayNanos;
1482         uint32_t maxDelayRequester = toUnderlying(RrThrottleRequester::MAX);
1483         for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1484             if (mRrThrottleNanos[i] > maxDelayNanos) {
1485                 maxDelayRequester = i;
1486                 maxDelayNanos = mRrThrottleNanos[i];
1487             }
1488         }
1489 
1490         DISPLAY_ATRACE_INT("RefreshRateDelayRequester", maxDelayRequester);
1491         DISPLAY_ATRACE_INT64("RefreshRateDelay", ns2ms(maxDelayNanos));
1492         if (mRefreshRateDelayNanos == maxDelayNanos) {
1493             return NO_ERROR;
1494         }
1495 
1496         if (mVariableRefreshRateController) {
1497             int ret = mVariableRefreshRateController->setFixedRefreshRateRange(mMinIdleRefreshRate,
1498                                                                                maxDelayNanos);
1499             if (ret >= 0) {
1500                 mRefreshRateDelayNanos = maxDelayNanos;
1501                 return NO_ERROR;
1502             }
1503             return ret;
1504         }
1505 
1506         ret = setDisplayIdleDelayNanos(maxDelayNanos, DispIdleTimerRequester::RR_THROTTLE);
1507         if (ret == NO_ERROR) {
1508             mRefreshRateDelayNanos = maxDelayNanos;
1509         }
1510     }
1511 
1512     Mutex::Autolock lock(mDisplayMutex);
1513     if (ret == NO_ERROR) {
1514         recalculateTimelineLocked(maxDelayNanos);
1515     }
1516 
1517     return ret;
1518 }
1519 
dump(String8 & result,const std::vector<std::string> & args)1520 void ExynosPrimaryDisplay::dump(String8& result, const std::vector<std::string>& args) {
1521     ExynosDisplay::dump(result);
1522     result.appendFormat("Display idle timer: %s\n",
1523                         (mDisplayIdleTimerEnabled) ? "enabled" : "disabled");
1524     for (uint32_t i = 0; i < toUnderlying(DispIdleTimerRequester::MAX); i++) {
1525         result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mDisplayIdleTimerNanos[i]);
1526     }
1527 
1528     if (!mBrightnessBlockingZonesLookupTable.empty()) {
1529         int upperBound;
1530         int lowerBound = INT_MIN;
1531         result.appendFormat("Brightness blocking zone lookup table:\n");
1532         for (const auto& brightnessBlockingZone : mBrightnessBlockingZonesLookupTable) {
1533             upperBound = brightnessBlockingZone.first;
1534             result.appendFormat("\tBrightness blocking zone: range [%s %s) fps = %d\n",
1535                                 (lowerBound == INT_MIN ? "Min"
1536                                                        : std::to_string(lowerBound).c_str()),
1537                                 (upperBound == INT_MAX ? "Max"
1538                                                        : std::to_string(upperBound).c_str()),
1539                                 brightnessBlockingZone.second);
1540             lowerBound = upperBound;
1541         }
1542     } else {
1543         result.appendFormat("\n");
1544     }
1545 
1546     result.appendFormat("Min idle refresh rate: %d\n", mMinIdleRefreshRate);
1547     for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1548         result.appendFormat("\t[%u] vote to %d hz\n", i, mRrThrottleFps[i]);
1549     }
1550 
1551     result.appendFormat("Refresh rate delay: %" PRId64 " ns\n", mRefreshRateDelayNanos);
1552     for (uint32_t i = 0; i < toUnderlying(RrThrottleRequester::MAX); i++) {
1553         result.appendFormat("\t[%u] vote to %" PRId64 " ns\n", i, mRrThrottleNanos[i]);
1554     }
1555     if (mIsDisplayTempMonitorSupported) {
1556         result.appendFormat("Temperature : %d°C\n", mDisplayTemperature);
1557     }
1558     result.appendFormat("\n");
1559 
1560     DisplayType displayType = getDcDisplayType();
1561     std::string displayTypeIdentifier;
1562     if (displayType == DisplayType::DISPLAY_PRIMARY) {
1563         displayTypeIdentifier = "primarydisplay";
1564     } else if (displayType == DisplayType::DISPLAY_EXTERNAL) {
1565         displayTypeIdentifier = "externaldisplay";
1566     }
1567     if (!displayTypeIdentifier.empty()) {
1568         auto xrrVersion =
1569                 android::hardware::graphics::composer::getDisplayXrrVersion(displayTypeIdentifier);
1570         result.appendFormat("XRR version: %d.%d\n", xrrVersion.first, xrrVersion.second);
1571     }
1572     if (mVariableRefreshRateController) {
1573         mVariableRefreshRateController->dump(result, args);
1574     }
1575 }
1576 
calculateTimelineLocked(hwc2_config_t config,hwc_vsync_period_change_constraints_t * vsyncPeriodChangeConstraints,hwc_vsync_period_change_timeline_t * outTimeline)1577 void ExynosPrimaryDisplay::calculateTimelineLocked(
1578         hwc2_config_t config, hwc_vsync_period_change_constraints_t* vsyncPeriodChangeConstraints,
1579         hwc_vsync_period_change_timeline_t* outTimeline) {
1580     ATRACE_CALL();
1581     int64_t desiredUpdateTimeNanos = vsyncPeriodChangeConstraints->desiredTimeNanos;
1582     const int64_t origDesiredUpdateTimeNanos = desiredUpdateTimeNanos;
1583     int64_t threshold = 0;
1584     int64_t lastUpdateDelta = 0;
1585     int64_t actualChangeTime = 0;
1586     bool isDelayed = false;
1587 
1588     /* actualChangeTime includes transient duration */
1589     mDisplayInterface->getVsyncAppliedTime(config, &actualChangeTime);
1590 
1591     outTimeline->refreshRequired = true;
1592 
1593     /* When the refresh rate changes from high to low, check if RR throttle is needed */
1594     {
1595         std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1596         threshold = mRefreshRateDelayNanos;
1597         mRrUseDelayNanos = 0;
1598         mIsRrNeedCheckDelay = !mXrrSettings.versionInfo.needVrrParameters() &&
1599                 mDisplayConfigs[mActiveConfig].vsyncPeriod < mDisplayConfigs[config].vsyncPeriod;
1600         if (threshold != 0 && mLastRefreshRateAppliedNanos != 0 && mIsRrNeedCheckDelay) {
1601             lastUpdateDelta = desiredUpdateTimeNanos - mLastRefreshRateAppliedNanos;
1602             if (lastUpdateDelta < threshold) {
1603                 /* in this case, the active config change needs to be delayed */
1604                 isDelayed = true;
1605                 desiredUpdateTimeNanos += threshold - lastUpdateDelta;
1606                 mRrUseDelayNanos = threshold;
1607             }
1608         }
1609     }
1610 
1611     mVsyncPeriodChangeConstraints.desiredTimeNanos = desiredUpdateTimeNanos;
1612 
1613     getConfigAppliedTime(mVsyncPeriodChangeConstraints.desiredTimeNanos, actualChangeTime,
1614                          outTimeline->newVsyncAppliedTimeNanos, outTimeline->refreshTimeNanos);
1615 
1616     const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
1617     DISPLAY_LOGD_AND_ATRACE_NAME(eDebugDisplayConfig,
1618                                  "requested config : %d(%d)->%d(%d), isDelay:%d,"
1619                                  " delta %" PRId64 ", delay %" PRId64 ", threshold %" PRId64 ", "
1620                                  "now:%" PRId64 ", desired %" PRId64 "->%" PRId64
1621                                  ", newVsyncAppliedTimeNanos : %" PRId64
1622                                  ", refreshTimeNanos:%" PRId64
1623                                  ", mLastRefreshRateAppliedNanos:%" PRId64,
1624                                  mActiveConfig, mDisplayConfigs[mActiveConfig].vsyncPeriod, config,
1625                                  mDisplayConfigs[config].vsyncPeriod, isDelayed,
1626                                  ns2ms(lastUpdateDelta), ns2ms(threshold - lastUpdateDelta),
1627                                  ns2ms(threshold), ns2ms(now), ns2ms(origDesiredUpdateTimeNanos),
1628                                  ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos),
1629                                  ns2ms(outTimeline->newVsyncAppliedTimeNanos),
1630                                  ns2ms(outTimeline->refreshTimeNanos),
1631                                  ns2ms(mLastRefreshRateAppliedNanos));
1632 
1633     DISPLAY_ATRACE_INT64("TimeToApplyConfig",
1634                          ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - now));
1635 }
1636 
recalculateTimelineLocked(int64_t refreshRateDelayNanos)1637 void ExynosPrimaryDisplay::recalculateTimelineLocked(int64_t refreshRateDelayNanos) {
1638     ATRACE_CALL();
1639 
1640     if (mConfigRequestState != hwc_request_state_t::SET_CONFIG_STATE_PENDING) {
1641         return;
1642     }
1643 
1644     std::lock_guard<std::mutex> lock(mIdleRefreshRateThrottleMutex);
1645     if (!mIsRrNeedCheckDelay) {
1646         return;
1647     }
1648 
1649     int64_t desiredUpdateTimeNanos = mVsyncPeriodChangeConstraints.desiredTimeNanos;
1650     if (mRrUseDelayNanos) {
1651         desiredUpdateTimeNanos += (refreshRateDelayNanos - mRrUseDelayNanos);
1652     } else {
1653         int64_t lastUpdateDelta =
1654                 mVsyncPeriodChangeConstraints.desiredTimeNanos - mLastRefreshRateAppliedNanos;
1655         if (lastUpdateDelta < refreshRateDelayNanos) {
1656             desiredUpdateTimeNanos += (refreshRateDelayNanos - lastUpdateDelta);
1657         }
1658     }
1659     mRrUseDelayNanos = refreshRateDelayNanos;
1660 
1661     const nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
1662     if (desiredUpdateTimeNanos > now) {
1663         mVsyncPeriodChangeConstraints.desiredTimeNanos = desiredUpdateTimeNanos;
1664     } else {
1665         mVsyncPeriodChangeConstraints.desiredTimeNanos = now;
1666     }
1667 
1668     DISPLAY_ATRACE_INT64("TimeToApplyConfig",
1669                          ns2ms(mVsyncPeriodChangeConstraints.desiredTimeNanos - now));
1670 }
1671 
updateAppliedActiveConfig(const hwc2_config_t newConfig,const int64_t ts)1672 void ExynosPrimaryDisplay::updateAppliedActiveConfig(const hwc2_config_t newConfig,
1673                                                      const int64_t ts) {
1674     ATRACE_CALL();
1675     if (mAppliedActiveConfig == 0 ||
1676         getDisplayVsyncPeriodFromConfig(mAppliedActiveConfig) !=
1677                 getDisplayVsyncPeriodFromConfig(newConfig)) {
1678         DISPLAY_LOGD(eDebugDisplayConfig,
1679                      "%s mAppliedActiveConfig(%d->%d), mLastRefreshRateAppliedNanos(%" PRIu64
1680                      " -> %" PRIu64 ")",
1681                      __func__, mAppliedActiveConfig, newConfig, mLastRefreshRateAppliedNanos, ts);
1682         mLastRefreshRateAppliedNanos = ts;
1683         DISPLAY_ATRACE_INT64("LastRefreshRateAppliedMs", ns2ms(mLastRefreshRateAppliedNanos));
1684     }
1685 
1686     mAppliedActiveConfig = newConfig;
1687 }
1688 
checkBtsReassignResource(const int32_t vsyncPeriod,const int32_t btsVsyncPeriod)1689 void ExynosPrimaryDisplay::checkBtsReassignResource(const int32_t vsyncPeriod,
1690                                                     const int32_t btsVsyncPeriod) {
1691     ATRACE_CALL();
1692     uint32_t refreshRate = static_cast<uint32_t>(round(nsecsPerSec / vsyncPeriod * 0.1f) * 10);
1693 
1694     Mutex::Autolock lock(mDRMutex);
1695     if (vsyncPeriod < btsVsyncPeriod) {
1696         for (size_t i = 0; i < mLayers.size(); i++) {
1697             if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP == nullptr &&
1698                 !mLayers[i]->checkBtsCap(refreshRate)) {
1699                 mLayers[i]->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
1700                 break;
1701             }
1702         }
1703     } else if (vsyncPeriod > btsVsyncPeriod) {
1704         for (size_t i = 0; i < mLayers.size(); i++) {
1705             if (mLayers[i]->mOtfMPP && mLayers[i]->mM2mMPP) {
1706                 float srcWidth = mLayers[i]->mSourceCrop.right - mLayers[i]->mSourceCrop.left;
1707                 float srcHeight = mLayers[i]->mSourceCrop.bottom - mLayers[i]->mSourceCrop.top;
1708                 float resolution = srcWidth * srcHeight * refreshRate / 1000;
1709                 float ratioVertical = static_cast<float>(mLayers[i]->mDisplayFrame.bottom -
1710                                                          mLayers[i]->mDisplayFrame.top) /
1711                         mYres;
1712 
1713                 if (mLayers[i]->mOtfMPP->checkDownscaleCap(resolution, ratioVertical)) {
1714                     mLayers[i]->setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
1715                     break;
1716                 }
1717             }
1718         }
1719     }
1720 }
1721 
isDbmSupported()1722 bool ExynosPrimaryDisplay::isDbmSupported() {
1723     return mBrightnessController->isDbmSupported();
1724 }
1725 
setDbmState(bool enabled)1726 int32_t ExynosPrimaryDisplay::setDbmState(bool enabled) {
1727     mBrightnessController->processDimBrightness(enabled);
1728     return NO_ERROR;
1729 }
1730 
getRefreshListener()1731 RefreshListener* ExynosPrimaryDisplay::getRefreshListener() {
1732     if (mVariableRefreshRateController) {
1733         return mVariableRefreshRateController.get();
1734     }
1735     return nullptr;
1736 }
1737 
getVsyncListener()1738 VsyncListener* ExynosPrimaryDisplay::getVsyncListener() {
1739     if (mVariableRefreshRateController) {
1740         return mVariableRefreshRateController.get();
1741     }
1742     return nullptr;
1743 }
1744 
onConfigChange(int configId)1745 void ExynosPrimaryDisplay::onConfigChange(int configId) {
1746     if (mVariableRefreshRateController) {
1747         return mVariableRefreshRateController->setActiveVrrConfiguration(configId);
1748     }
1749 }
1750 
getPanelName()1751 const std::string& ExynosPrimaryDisplay::getPanelName() {
1752     if (!mPanelName.empty()) {
1753         return mPanelName;
1754     }
1755 
1756     const std::string& sysfs = getPanelSysfsPath();
1757     if (!sysfs.empty()) {
1758         std::string sysfs_rel("panel_name");
1759         if (readLineFromFile(sysfs + "/" + sysfs_rel, mPanelName, '\n') != OK) {
1760             ALOGE("failed reading %s/%s", sysfs.c_str(), sysfs_rel.c_str());
1761         }
1762     }
1763     return mPanelName;
1764 }
1765 
registerRefreshRateChangeListener(std::shared_ptr<RefreshRateChangeListener> listener)1766 int32_t ExynosPrimaryDisplay::registerRefreshRateChangeListener(
1767         std::shared_ptr<RefreshRateChangeListener> listener) {
1768     if (!mXrrSettings.versionInfo.hasVrrController()) return HWC2_ERROR_UNSUPPORTED;
1769 
1770     if (mVariableRefreshRateController) {
1771         mVariableRefreshRateController->registerRefreshRateChangeListener(listener);
1772         return NO_ERROR;
1773     } else {
1774         return -EINVAL;
1775     }
1776 }
1777 
1778 // TODO(b/355579338): to create a dedicated class DisplayTemperatureMonitor
initDisplayTempMonitor(const std::string & display)1779 bool ExynosPrimaryDisplay::initDisplayTempMonitor(const std::string& display) {
1780     mDisplayTempInterval = property_get_int32(kDisplayTempIntervalSec, 0);
1781 
1782     if (mDisplayTempInterval <= 0) {
1783         ALOGD("%s: Invalid display temperature interval: %d", __func__, mDisplayTempInterval);
1784         return false;
1785     }
1786 
1787     auto propertyName = getPropertyDisplayTemperatureStr(display);
1788 
1789     char value[PROPERTY_VALUE_MAX];
1790     auto ret = property_get(propertyName.c_str(), value, "");
1791 
1792     if (ret <= 0) {
1793         ALOGD("%s: Display temperature property values is empty", __func__);
1794         return false;
1795     }
1796 
1797     mDisplayTempSysfsNode = String8(value);
1798     return true;
1799 }
1800 
getDisplayTemperature()1801 int32_t ExynosPrimaryDisplay::getDisplayTemperature() {
1802     DISPLAY_ATRACE_CALL();
1803 
1804     if (mDisplayTempSysfsNode.empty()) {
1805         ALOGE("%s: Display temp sysfs node string is empty", __func__);
1806         return UINT_MAX;
1807     }
1808 
1809     int32_t temperature;
1810     std::ifstream ifs(mDisplayTempSysfsNode.c_str());
1811 
1812     if (!ifs.is_open()) {
1813         ALOGE("%s: Unable to open node '%s', error = %s", __func__, mDisplayTempSysfsNode.c_str(),
1814               strerror(errno));
1815         return UINT_MAX;
1816     }
1817 
1818     if (!(ifs >> temperature) || !ifs.good()) {
1819         ALOGE("%s: Unable to read node '%s', error = %s", __func__, mDisplayTempSysfsNode.c_str(),
1820               strerror(errno));
1821     }
1822 
1823     ifs.close();
1824     return temperature / 1000;
1825 }
1826 
isTemperatureMonitorThreadRunning()1827 bool ExynosPrimaryDisplay::isTemperatureMonitorThreadRunning() {
1828     android_atomic_acquire_load(&mTMThreadStatus);
1829     return (mTMThreadStatus > 0);
1830 }
1831 
checkTemperatureMonitorThread(bool shouldRun)1832 void ExynosPrimaryDisplay::checkTemperatureMonitorThread(bool shouldRun) {
1833     ATRACE_CALL();
1834     if (!mIsDisplayTempMonitorSupported) {
1835         return;
1836     }
1837 
1838     // If thread was destroyed, create thread and run.
1839     if (!isTemperatureMonitorThreadRunning()) {
1840         if (shouldRun) {
1841             temperatureMonitorThreadCreate();
1842             return;
1843         }
1844     } else {
1845         // if screen state changed make the thread suspend/resume.
1846         {
1847             std::lock_guard<std::mutex> lock(mThreadMutex);
1848             if (mTMLoopStatus != shouldRun) {
1849                 mTMLoopStatus = shouldRun;
1850                 mTMCondition.notify_one();
1851             }
1852         }
1853     }
1854 }
1855 
temperatureMonitorThreadCreate()1856 void ExynosPrimaryDisplay::temperatureMonitorThreadCreate() {
1857     mTMLoopStatus.store(false, std::memory_order_relaxed);
1858 
1859     ALOGI("Creating monitor display temperature thread");
1860     mTMLoopStatus.store(true, std::memory_order_relaxed);
1861     mTMThread = std::thread(&ExynosPrimaryDisplay::temperatureMonitorThreadLoop, this);
1862     mTMCondition.notify_one();
1863 }
1864 
temperatureMonitorThreadLoop()1865 void* ExynosPrimaryDisplay::temperatureMonitorThreadLoop() {
1866     android_atomic_inc(&mTMThreadStatus);
1867     while (true) {
1868         std::unique_lock<std::mutex> lock(mThreadMutex);
1869         mTMCondition.wait(lock, [this] { return mTMLoopStatus.load(std::memory_order_relaxed); });
1870 
1871         mDisplayTemperature = getDisplayTemperature();
1872         if (mDisplayTemperature == UINT_MAX) {
1873             ALOGE("%s: Failed to get display temperature", LOG_TAG);
1874         } else {
1875             ALOGI("Display Temperature : %d°C", mDisplayTemperature);
1876         }
1877 
1878         // Wait for the specified interval or until the thread is suspended
1879         mTMCondition.wait_for(lock, std::chrono::seconds(mDisplayTempInterval),
1880                               [this] { return !mTMLoopStatus.load(std::memory_order_relaxed); });
1881     }
1882     android_atomic_dec(&mTMThreadStatus);
1883     return NULL;
1884 }
1885