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 
17 #define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
18 
19 #include "ExynosDevice.h"
20 
21 #include <aidl/android/hardware/graphics/composer3/IComposerCallback.h>
22 #include <sync/sync.h>
23 #include <sys/mman.h>
24 #include <unistd.h>
25 
26 #include "BrightnessController.h"
27 #include "ExynosDeviceDrmInterface.h"
28 #include "ExynosDisplay.h"
29 #include "ExynosExternalDisplayModule.h"
30 #include "ExynosHWCDebug.h"
31 #include "ExynosHWCHelper.h"
32 #include "ExynosLayer.h"
33 #include "ExynosPrimaryDisplayModule.h"
34 #include "ExynosResourceManagerModule.h"
35 #include "ExynosVirtualDisplayModule.h"
36 #include "VendorGraphicBuffer.h"
37 
38 using namespace vendor::graphics;
39 using namespace SOC_VERSION;
40 using aidl::android::hardware::graphics::composer3::IComposerCallback;
41 
42 /**
43  * ExynosDevice implementation
44  */
45 
46 class ExynosDevice;
47 
48 extern void PixelDisplayInit(ExynosDisplay *exynos_display, const std::string_view instance_str);
49 
50 static const std::map<const uint32_t, const std::string_view> pixelDisplayIntfName =
51         {{getDisplayId(HWC_DISPLAY_PRIMARY, 0), "default"},
52 #ifdef USES_IDISPLAY_INTF_SEC
53          {getDisplayId(HWC_DISPLAY_PRIMARY, 1), "secondary"}
54 #endif
55 };
56 
57 int hwcDebug;
58 int hwcFenceDebug[FENCE_IP_ALL];
59 struct exynos_hwc_control exynosHWCControl;
60 struct update_time_info updateTimeInfo;
61 char fence_names[FENCE_MAX][32];
62 
getDeviceInterfaceType()63 uint32_t getDeviceInterfaceType()
64 {
65     if (access(DRM_DEVICE_PATH, F_OK) == NO_ERROR)
66         return INTERFACE_TYPE_DRM;
67     else
68         return INTERFACE_TYPE_FB;
69 }
70 
ExynosDevice(bool vrrApiSupported)71 ExynosDevice::ExynosDevice(bool vrrApiSupported)
72       : mGeometryChanged(0),
73         mVsyncFd(-1),
74         mExtVsyncFd(-1),
75         mVsyncDisplayId(getDisplayId(HWC_DISPLAY_PRIMARY, 0)),
76         mTimestamp(0),
77         mDisplayMode(0),
78         mInterfaceType(INTERFACE_TYPE_FB),
79         mIsInTUI(false),
80         mVrrApiSupported(vrrApiSupported) {
81     exynosHWCControl.forceGpu = false;
82     exynosHWCControl.windowUpdate = true;
83     exynosHWCControl.forcePanic = false;
84     exynosHWCControl.skipStaticLayers = true;
85     exynosHWCControl.skipM2mProcessing = true;
86     exynosHWCControl.skipResourceAssign = true;
87     exynosHWCControl.multiResolution = true;
88     exynosHWCControl.dumpMidBuf = false;
89     exynosHWCControl.displayMode = DISPLAY_MODE_NUM;
90     exynosHWCControl.setDDIScaler = false;
91     exynosHWCControl.skipWinConfig = false;
92     exynosHWCControl.skipValidate = true;
93     exynosHWCControl.doFenceFileDump = false;
94     exynosHWCControl.fenceTracer = 0;
95     exynosHWCControl.sysFenceLogging = false;
96     exynosHWCControl.useDynamicRecomp = false;
97 
98     hwcDebug = 0;
99 
100     mInterfaceType = getDeviceInterfaceType();
101     ALOGD("HWC2 : %s : interface type(%d)", __func__, mInterfaceType);
102 
103     /*
104      * This order should not be changed
105      * new ExynosResourceManager ->
106      * create displays and add them to the list ->
107      * initDeviceInterface() ->
108      * ExynosResourceManager::updateRestrictions()
109      */
110     mResourceManager = new ExynosResourceManagerModule(this);
111 
112     for (size_t i = 0; i < AVAILABLE_DISPLAY_UNITS.size(); i++) {
113         exynos_display_t display_t = AVAILABLE_DISPLAY_UNITS[i];
114         ExynosDisplay *exynos_display = NULL;
115         ALOGD("Create display[%zu] type: %d, index: %d", i, display_t.type, display_t.index);
116         switch(display_t.type) {
117             case HWC_DISPLAY_PRIMARY:
118                 exynos_display =
119                         (ExynosDisplay *)(new ExynosPrimaryDisplayModule(display_t.index, this,
120                                                                          display_t.display_name));
121                 if(display_t.index == 0) {
122                     exynos_display->mPlugState = true;
123                     ExynosMPP::mainDisplayWidth = exynos_display->mXres;
124                     if (ExynosMPP::mainDisplayWidth <= 0) {
125                         ExynosMPP::mainDisplayWidth = 1440;
126                     }
127                     ExynosMPP::mainDisplayHeight = exynos_display->mYres;
128                     if (ExynosMPP::mainDisplayHeight <= 0) {
129                         ExynosMPP::mainDisplayHeight = 2560;
130                     }
131                 }
132                 break;
133             case HWC_DISPLAY_EXTERNAL:
134                 exynos_display =
135                         (ExynosDisplay *)(new ExynosExternalDisplayModule(display_t.index, this,
136                                                                           display_t.display_name));
137                 break;
138             case HWC_DISPLAY_VIRTUAL:
139                 exynos_display =
140                         (ExynosDisplay *)(new ExynosVirtualDisplayModule(display_t.index, this,
141                                                                          display_t.display_name));
142                 mNumVirtualDisplay = 0;
143                 break;
144             default:
145                 ALOGE("Unsupported display type(%d)", display_t.type);
146                 break;
147         }
148         exynos_display->mDeconNodeName.appendFormat("%s", display_t.decon_node_name.c_str());
149         mDisplays.add(exynos_display);
150         mDisplayMap.insert(std::make_pair(exynos_display->mDisplayId, exynos_display));
151 
152 #ifndef FORCE_DISABLE_DR
153         if (exynos_display->mDRDefault) exynosHWCControl.useDynamicRecomp = true;
154 #endif
155     }
156 
157     memset(mCallbackInfos, 0, sizeof(mCallbackInfos));
158 
159     dynamicRecompositionThreadCreate();
160 
161     for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
162         hwcFenceDebug[i] = 0;
163 
164     for (uint32_t i = 0; i < FENCE_MAX; i++) {
165         memset(fence_names[i], 0, sizeof(fence_names[0]));
166         sprintf(fence_names[i], "_%2dh", i);
167     }
168 
169     for (auto it : mDisplays) {
170         std::string displayName = std::string(it->mDisplayName.c_str());
171         it->mErrLogFileWriter.setPrefixName(displayName + "_hwc_error_log");
172         it->mDebugDumpFileWriter.setPrefixName(displayName + "_hwc_debug");
173         it->mFenceFileWriter.setPrefixName(displayName + "_hwc_fence_state");
174         String8 saveString;
175         saveString.appendFormat("ExynosDisplay %s is initialized", it->mDisplayName.c_str());
176         saveErrorLog(saveString, it);
177     }
178 
179     if (mInterfaceType == INTERFACE_TYPE_DRM) {
180         setVBlankOffDelay(1);
181     }
182 
183     mDisplayOffAsync = property_get_bool("vendor.display.async_off.supported", false);
184     initDeviceInterface(mInterfaceType);
185 
186     // registerRestrictions();
187     mResourceManager->updateRestrictions();
188     mResourceManager->initDisplays(mDisplays, mDisplayMap);
189 
190     char value[PROPERTY_VALUE_MAX];
191     property_get("vendor.display.lbe.supported", value, "0");
192     const bool lbe_supported = atoi(value) ? true : false;
193 
194     mNumPrimaryDisplays = 0;
195     for (size_t i = 0; i < mDisplays.size(); i++) {
196         if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY) {
197             ++mNumPrimaryDisplays;
198             auto iter = pixelDisplayIntfName.find(getDisplayId(HWC_DISPLAY_PRIMARY, i));
199             if (iter != pixelDisplayIntfName.end()) {
200                 PixelDisplayInit(mDisplays[i], iter->second);
201                 if (lbe_supported) {
202                     mDisplays[i]->initLbe();
203                 }
204             }
205         }
206     }
207 }
208 
initDeviceInterface(uint32_t interfaceType)209 void ExynosDevice::initDeviceInterface(uint32_t interfaceType)
210 {
211     if (interfaceType == INTERFACE_TYPE_DRM) {
212         mDeviceInterface = std::make_unique<ExynosDeviceDrmInterface>(this);
213     } else {
214         LOG_ALWAYS_FATAL("%s::Unknown interface type(%d)",
215                 __func__, interfaceType);
216     }
217 
218     mDeviceInterface->init(this);
219 
220     /* Remove display when display interface is not valid */
221     for (uint32_t i = 0; i < mDisplays.size();) {
222         ExynosDisplay* display = mDisplays[i];
223         display->initDisplayInterface(interfaceType);
224         if (mDeviceInterface->initDisplayInterface(display->mDisplayInterface) != NO_ERROR) {
225             ALOGD("Remove display[%d], Failed to initialize display interface", i);
226             mDisplays.removeAt(i);
227             mDisplayMap.erase(display->mDisplayId);
228             delete display;
229         } else {
230             i++;
231         }
232     }
233 
234     // Call handleHotplug() to capture the initial coldplug state of each display.
235     // This is necessary because the hotplug uevent handler created in postInit()
236     // below does not get always triggered when HWC is restarting.
237     handleHotplug();
238     mDeviceInterface->postInit();
239 }
240 
~ExynosDevice()241 ExynosDevice::~ExynosDevice() {
242     mDRLoopStatus = false;
243     mDRThread.join();
244     for(auto& display : mDisplays) {
245         delete display;
246     }
247     mDisplays.clear();
248 }
249 
isFirstValidate()250 bool ExynosDevice::isFirstValidate()
251 {
252     for (uint32_t i = 0; i < mDisplays.size(); i++) {
253         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
254             (!mDisplays[i]->mPowerModeState.has_value() ||
255              (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
256             continue;
257         if ((mDisplays[i]->mPlugState == true) &&
258             ((mDisplays[i]->mRenderingState != RENDERING_STATE_NONE) &&
259              (mDisplays[i]->mRenderingState != RENDERING_STATE_PRESENTED)))
260             return false;
261     }
262 
263     return true;
264 }
265 
isLastValidate(ExynosDisplay * display)266 bool ExynosDevice::isLastValidate(ExynosDisplay *display)
267 {
268     for (uint32_t i = 0; i < mDisplays.size(); i++) {
269         if (mDisplays[i] == display)
270             continue;
271         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
272             (!mDisplays[i]->mPowerModeState.has_value() ||
273              (mDisplays[i]->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF)))
274             continue;
275         if ((mDisplays[i]->mPlugState == true) &&
276             (mDisplays[i]->mRenderingState != RENDERING_STATE_VALIDATED) &&
277             (mDisplays[i]->mRenderingState != RENDERING_STATE_ACCEPTED_CHANGE))
278             return false;
279     }
280     return true;
281 }
282 
hasOtherDisplayOn(ExynosDisplay * display)283 bool ExynosDevice::hasOtherDisplayOn(ExynosDisplay *display) {
284     for (uint32_t i = 0; i < mDisplays.size(); i++) {
285         if (mDisplays[i] == display) continue;
286         if ((mDisplays[i]->mType != HWC_DISPLAY_VIRTUAL) &&
287             mDisplays[i]->mPowerModeState.has_value() &&
288             (mDisplays[i]->mPowerModeState.value() != (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
289             return true;
290     }
291     return false;
292 }
293 
isDynamicRecompositionThreadAlive()294 bool ExynosDevice::isDynamicRecompositionThreadAlive()
295 {
296     android_atomic_acquire_load(&mDRThreadStatus);
297     return (mDRThreadStatus > 0);
298 }
299 
checkDynamicRecompositionThread()300 void ExynosDevice::checkDynamicRecompositionThread()
301 {
302     ATRACE_CALL();
303     // If thread was destroyed, create thread and run. (resume status)
304     if (isDynamicRecompositionThreadAlive() == false) {
305         for (uint32_t i = 0; i < mDisplays.size(); i++) {
306             if (mDisplays[i]->mDREnable) {
307                 dynamicRecompositionThreadCreate();
308                 return;
309             }
310         }
311     } else {
312     // If thread is running and all displays turnned off DR, destroy the thread.
313         for (uint32_t i = 0; i < mDisplays.size(); i++) {
314             if (mDisplays[i]->mDREnable)
315                 return;
316         }
317         ALOGI("Destroying dynamic recomposition thread");
318         mDRLoopStatus = false;
319         mDRWakeUpCondition.notify_one();
320         mDRThread.join();
321     }
322 }
323 
dynamicRecompositionThreadCreate()324 void ExynosDevice::dynamicRecompositionThreadCreate()
325 {
326     if (exynosHWCControl.useDynamicRecomp == true) {
327         ALOGI("Creating dynamic recomposition thread");
328         mDRLoopStatus = true;
329         mDRThread = std::thread(&dynamicRecompositionThreadLoop, this);
330     }
331 }
332 
dynamicRecompositionThreadLoop(void * data)333 void *ExynosDevice::dynamicRecompositionThreadLoop(void *data)
334 {
335     ExynosDevice *dev = (ExynosDevice *)data;
336     ExynosDisplay *display[dev->mDisplays.size()];
337     uint64_t event_cnt[dev->mDisplays.size()];
338 
339     for (uint32_t i = 0; i < dev->mDisplays.size(); i++) {
340         display[i] = dev->mDisplays[i];
341         event_cnt[i] = 0;
342     }
343     android_atomic_inc(&(dev->mDRThreadStatus));
344 
345     while (dev->mDRLoopStatus) {
346         for (uint32_t i = 0; i < dev->mDisplays.size(); i++)
347             event_cnt[i] = display[i]->mUpdateEventCnt;
348 
349         /*
350          * If there is no update for more than 5s, favor the client composition mode.
351          * If all other conditions are met, mode will be switched to client composition.
352          */
353         {
354             std::unique_lock<std::mutex> lock(dev->mDRWakeUpMutex);
355             dev->mDRWakeUpCondition.wait_for(lock, std::chrono::seconds(5));
356             if (!dev->mDRLoopStatus) {
357                 break;
358             }
359         }
360         for (uint32_t i = 0; i < dev->mDisplays.size(); i++) {
361             if (display[i]->mDREnable &&
362                 display[i]->mPlugState == true &&
363                 event_cnt[i] == display[i]->mUpdateEventCnt) {
364                 if (display[i]->checkDynamicReCompMode() == DEVICE_2_CLIENT) {
365                     display[i]->mUpdateEventCnt = 0;
366                     display[i]->setGeometryChanged(GEOMETRY_DISPLAY_DYNAMIC_RECOMPOSITION);
367                     dev->onRefresh(display[i]->mDisplayId);
368                 }
369             }
370         }
371     }
372 
373     android_atomic_dec(&(dev->mDRThreadStatus));
374 
375     return NULL;
376 }
377 
378 /**
379  * Device Functions for HWC 2.0
380  */
381 
createVirtualDisplay(uint32_t width,uint32_t height,int32_t * format,ExynosDisplay * display)382 int32_t ExynosDevice::createVirtualDisplay(
383         uint32_t width, uint32_t height, int32_t* /*android_pixel_format_t*/ format, ExynosDisplay* display) {
384     ((ExynosVirtualDisplay*)display)->createVirtualDisplay(width, height, format);
385     return 0;
386 }
387 
388 /**
389  * @param *display
390  * @return int32_t
391  */
destroyVirtualDisplay(ExynosDisplay * display)392 int32_t ExynosDevice::destroyVirtualDisplay(ExynosDisplay* display) {
393     ((ExynosVirtualDisplay *)display)->destroyVirtualDisplay();
394     return 0;
395 }
396 
dump(uint32_t * outSize,char * outBuffer)397 void ExynosDevice::dump(uint32_t *outSize, char *outBuffer) {
398     if (outSize == NULL) {
399         ALOGE("%s:: outSize is null", __func__);
400         return;
401     }
402 
403     String8 result;
404     dump(result);
405 
406     if (outBuffer == NULL) {
407         *outSize = static_cast<uint32_t>(result.length());
408     } else {
409         if (*outSize == 0) {
410             ALOGE("%s:: outSize is 0", __func__);
411             return;
412         }
413         size_t copySize = min(static_cast<size_t>(*outSize), result.size());
414         ALOGI("HWC dump:: resultSize(%zu), outSize(%d), copySize(%zu)", result.size(), *outSize,
415               copySize);
416         strlcpy(outBuffer, result.c_str(), copySize);
417     }
418 }
419 
dump(String8 & result,const std::vector<std::string> & args)420 void ExynosDevice::dump(String8& result, const std::vector<std::string>& args) {
421     result.append("\n\n");
422 
423     struct tm* localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastUeventTime.tv_sec);
424     result.appendFormat("lastUeventTime(%02d:%02d:%02d.%03lu) lastTimestamp(%" PRIu64 ")\n",
425             localTime->tm_hour, localTime->tm_min,
426             localTime->tm_sec, updateTimeInfo.lastUeventTime.tv_usec/1000, mTimestamp);
427 
428     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastEnableVsyncTime.tv_sec);
429     result.appendFormat("lastEnableVsyncTime(%02d:%02d:%02d.%03lu)\n",
430             localTime->tm_hour, localTime->tm_min,
431             localTime->tm_sec, updateTimeInfo.lastEnableVsyncTime.tv_usec/1000);
432 
433     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastDisableVsyncTime.tv_sec);
434     result.appendFormat("lastDisableVsyncTime(%02d:%02d:%02d.%03lu)\n",
435             localTime->tm_hour, localTime->tm_min,
436             localTime->tm_sec, updateTimeInfo.lastDisableVsyncTime.tv_usec/1000);
437 
438     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastValidateTime.tv_sec);
439     result.appendFormat("lastValidateTime(%02d:%02d:%02d.%03lu)\n",
440             localTime->tm_hour, localTime->tm_min,
441             localTime->tm_sec, updateTimeInfo.lastValidateTime.tv_usec/1000);
442 
443     localTime = (struct tm*)localtime((time_t*)&updateTimeInfo.lastPresentTime.tv_sec);
444     result.appendFormat("lastPresentTime(%02d:%02d:%02d.%03lu)\n",
445             localTime->tm_hour, localTime->tm_min,
446             localTime->tm_sec, updateTimeInfo.lastPresentTime.tv_usec/1000);
447 
448     result.appendFormat("\n");
449     mResourceManager->dump(result);
450 
451     result.appendFormat("special plane num: %d:\n", getSpecialPlaneNum());
452     for (uint32_t index = 0; index < getSpecialPlaneNum(); index++) {
453         result.appendFormat("\tindex: %d attribute 0x%" PRIx64 "\n", getSpecialPlaneId(index),
454                             getSpecialPlaneAttr(index));
455     }
456     result.append("\n");
457 
458     for (size_t i = 0; i < mDisplays.size(); i++) {
459         ExynosDisplay* display = mDisplays[i];
460         if (display->mPlugState == true) display->miniDump(result);
461     }
462 
463     for (size_t i = 0;i < mDisplays.size(); i++) {
464         ExynosDisplay *display = mDisplays[i];
465         if (display->mPlugState == true) display->dump(result, args);
466     }
467 }
468 
getMaxVirtualDisplayCount()469 uint32_t ExynosDevice::getMaxVirtualDisplayCount() {
470 #ifdef USES_VIRTUAL_DISPLAY
471     return 1;
472 #else
473     return 0;
474 #endif
475 }
476 
registerCallback(int32_t descriptor,hwc2_callback_data_t callbackData,hwc2_function_pointer_t point)477 int32_t ExynosDevice::registerCallback (
478         int32_t descriptor, hwc2_callback_data_t callbackData,
479         hwc2_function_pointer_t point) {
480     if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE)
481         return HWC2_ERROR_BAD_PARAMETER;
482 
483     Mutex::Autolock lock(mDeviceCallbackMutex);
484     mCallbackInfos[descriptor].callbackData = callbackData;
485     mCallbackInfos[descriptor].funcPointer = point;
486 
487     /* Call hotplug callback for primary display*/
488     if (descriptor == HWC2_CALLBACK_HOTPLUG) {
489         HWC2_PFN_HOTPLUG callbackFunc =
490                 reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[descriptor].funcPointer);
491         if (callbackFunc != nullptr) {
492             for (auto it : mDisplays) {
493                 if (it->mPlugState)
494                     callbackFunc(callbackData, getDisplayId(it->mType, it->mIndex),
495                             HWC2_CONNECTION_CONNECTED);
496             }
497         } else {
498             // unregistering callback can be used as a sign of ComposerClient's death
499             for (auto it : mDisplays) {
500                 it->cleanupAfterClientDeath();
501             }
502         }
503     }
504     /* TODO(b/265244856): called by register callback vsync. it's only hwc2. */
505     if (descriptor == HWC2_CALLBACK_VSYNC)
506         mResourceManager->doPreProcessing();
507 
508     return HWC2_ERROR_NONE;
509 }
510 
isCallbackRegisteredLocked(int32_t descriptor)511 bool ExynosDevice::isCallbackRegisteredLocked(int32_t descriptor) {
512     if (descriptor < 0 || descriptor > HWC2_CALLBACK_SEAMLESS_POSSIBLE) {
513         ALOGE("%s:: %d callback is unknown", __func__, descriptor);
514         return false;
515     }
516 
517     if (mCallbackInfos[descriptor].callbackData == nullptr ||
518         mCallbackInfos[descriptor].funcPointer == nullptr) {
519         ALOGE("%s:: %d callback is not registered", __func__, descriptor);
520         return false;
521     }
522 
523     return true;
524 }
525 
isCallbackAvailable(int32_t descriptor)526 bool ExynosDevice::isCallbackAvailable(int32_t descriptor) {
527     Mutex::Autolock lock(mDeviceCallbackMutex);
528     return isCallbackRegisteredLocked(descriptor);
529 }
530 
531 using DisplayHotplugEvent = aidl::android::hardware::graphics::common::DisplayHotplugEvent;
hotplug_event_to_aidl(bool connected,int hotplugErrorCode)532 DisplayHotplugEvent hotplug_event_to_aidl(bool connected, int hotplugErrorCode) {
533     switch (hotplugErrorCode) {
534         case 0:
535             return connected ? DisplayHotplugEvent::CONNECTED : DisplayHotplugEvent::DISCONNECTED;
536         case 1:
537             return DisplayHotplugEvent::ERROR_INCOMPATIBLE_CABLE;
538         default:
539             return DisplayHotplugEvent::ERROR_UNKNOWN;
540     }
541 }
542 
findPoweredOffPrimaryDisplay(ExynosDisplay * excludeDisplay)543 ExynosDisplay* ExynosDevice::findPoweredOffPrimaryDisplay(ExynosDisplay* excludeDisplay) {
544     for (auto disp : mDisplays) {
545         if (disp != excludeDisplay && disp->mType == HWC_DISPLAY_PRIMARY &&
546             disp->mPowerModeState == HWC_POWER_MODE_OFF)
547             return disp;
548     }
549     return nullptr;
550 }
551 
onHotPlug(uint32_t displayId,bool status,int hotplugErrorCode)552 void ExynosDevice::onHotPlug(uint32_t displayId, bool status, int hotplugErrorCode) {
553     Mutex::Autolock lock(mDeviceCallbackMutex);
554 
555     // If we detect a hotplug of an external display on a foldable device, and we have a
556     // primary/built-in display in a powered off state, we need to use the powered off display's
557     // crtc/decon for the external display, to ensure color management is working properly
558     // (color management is supported only on decon0/decon1). See b/329034082.
559     ExynosDisplay* hotpluggedDisplay = getDisplay(displayId);
560     if (mNumPrimaryDisplays >= 2 && hotpluggedDisplay &&
561         hotpluggedDisplay->mType == HWC_DISPLAY_EXTERNAL) {
562         ALOGD("%s: display %s pluggedIn=%d hotplugErrorCode=%d", __func__,
563               hotpluggedDisplay->mDisplayTraceName.c_str(), status, hotplugErrorCode);
564         auto hotpluggedDisplayIntf = hotpluggedDisplay->mDisplayInterface.get();
565         ExynosDisplay* borrowedCrtcFrom = hotpluggedDisplayIntf->borrowedCrtcFrom();
566         if (status && hotplugErrorCode == 0) {
567             // The external display has been connected successfully, check if we can find an
568             // available decon for it, before we start initializing it.
569             if (borrowedCrtcFrom) {
570                 ALOGW("%s: external display is already using decon of %s", __func__,
571                       borrowedCrtcFrom->mDisplayTraceName.c_str());
572                 // Restore the original decon of the external display before proceeding.
573                 hotpluggedDisplayIntf->swapCrtcs(borrowedCrtcFrom);
574             }
575             ExynosDisplay* poweredOffPrimaryDisplay = findPoweredOffPrimaryDisplay(nullptr);
576             if (poweredOffPrimaryDisplay) {
577                 hotpluggedDisplayIntf->swapCrtcs(poweredOffPrimaryDisplay);
578             } else {
579                 // There is no powered off primary display/available decon at the moment,
580                 // this means hotplug of external display happened while the foldable device
581                 // was in dual concurrent display mode. We will try to switch decon assignment
582                 // for the external display later, when one of primary displays is turned off.
583                 ALOGD("onHotPlug: No powered off primary displays found!");
584             }
585         } else {
586             // The external display has been unplugged, or plugged in, but ran into an error.
587             // Restore the original decon assigned to it, if we previously switched decons.
588             if (borrowedCrtcFrom) {
589                 hotpluggedDisplayIntf->swapCrtcs(borrowedCrtcFrom);
590             }
591         }
592     }
593 
594     // If the new HotplugEvent API is available, use it, otherwise fall back
595     // to the old V2 API with onVsync hack, if necessary.
596     const auto& hotplugEventCallback =
597             mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onHotplugEvent);
598     if (hotplugEventCallback != mHwc3CallbackInfos.end()) {
599         const auto& callbackInfo = hotplugEventCallback->second;
600         if (callbackInfo.funcPointer != nullptr && callbackInfo.callbackData != nullptr) {
601             auto callbackFunc = reinterpret_cast<
602                     void (*)(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
603                              aidl::android::hardware::graphics::common::DisplayHotplugEvent)>(
604                     callbackInfo.funcPointer);
605             callbackFunc(callbackInfo.callbackData, displayId,
606                          hotplug_event_to_aidl(status, hotplugErrorCode));
607             return;
608         }
609     }
610 
611     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_HOTPLUG)) return;
612 
613     if (hotplugErrorCode) {
614         // We need to pass the error code to SurfaceFlinger, but we cannot modify the HWC
615         // HAL interface, so for now we'll send the hotplug error via a onVsync callback with
616         // a negative time value indicating the hotplug error.
617         if (isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) {
618             ALOGD("%s: hotplugErrorCode=%d sending to SF via onVsync_2_4", __func__,
619                   hotplugErrorCode);
620             hwc2_callback_data_t vsyncCallbackData =
621                     mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData;
622             HWC2_PFN_VSYNC_2_4 vsyncCallbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(
623                     mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer);
624             vsyncCallbackFunc(vsyncCallbackData, displayId, -hotplugErrorCode, ~0);
625             return;
626         } else {
627             ALOGW("%s: onVsync_2_4 is not registered, ignoring hotplugErrorCode=%d", __func__,
628                   hotplugErrorCode);
629             return;
630         }
631     }
632 
633     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_HOTPLUG].callbackData;
634     HWC2_PFN_HOTPLUG callbackFunc =
635             reinterpret_cast<HWC2_PFN_HOTPLUG>(mCallbackInfos[HWC2_CALLBACK_HOTPLUG].funcPointer);
636     callbackFunc(callbackData, displayId,
637                  status ? HWC2_CONNECTION_CONNECTED : HWC2_CONNECTION_DISCONNECTED);
638 }
639 
onRefreshDisplays()640 void ExynosDevice::onRefreshDisplays() {
641     for (auto& display : mDisplays) {
642          onRefresh(display->mDisplayId);
643     }
644 }
645 
onRefresh(uint32_t displayId)646 void ExynosDevice::onRefresh(uint32_t displayId) {
647     Mutex::Autolock lock(mDeviceCallbackMutex);
648 
649     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_REFRESH)) return;
650 
651     if (!checkDisplayConnection(displayId)) return;
652 
653     ExynosDisplay *display = (ExynosDisplay *)getDisplay(displayId);
654 
655     if (!display->mPowerModeState.has_value() ||
656              (display->mPowerModeState.value() == (hwc2_power_mode_t)HWC_POWER_MODE_OFF))
657         return;
658 
659     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_REFRESH].callbackData;
660     HWC2_PFN_REFRESH callbackFunc =
661             reinterpret_cast<HWC2_PFN_REFRESH>(mCallbackInfos[HWC2_CALLBACK_REFRESH].funcPointer);
662     callbackFunc(callbackData, displayId);
663 }
664 
onVsync(uint32_t displayId,int64_t timestamp)665 void ExynosDevice::onVsync(uint32_t displayId, int64_t timestamp) {
666     Mutex::Autolock lock(mDeviceCallbackMutex);
667 
668     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC)) return;
669 
670     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC].callbackData;
671     HWC2_PFN_VSYNC callbackFunc =
672             reinterpret_cast<HWC2_PFN_VSYNC>(mCallbackInfos[HWC2_CALLBACK_VSYNC].funcPointer);
673     callbackFunc(callbackData, displayId, timestamp);
674 }
675 
onVsync_2_4(uint32_t displayId,int64_t timestamp,uint32_t vsyncPeriod)676 bool ExynosDevice::onVsync_2_4(uint32_t displayId, int64_t timestamp, uint32_t vsyncPeriod) {
677     Mutex::Autolock lock(mDeviceCallbackMutex);
678 
679     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) return false;
680 
681     hwc2_callback_data_t callbackData = mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData;
682     HWC2_PFN_VSYNC_2_4 callbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(
683             mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer);
684     callbackFunc(callbackData, displayId, timestamp, vsyncPeriod);
685 
686     return true;
687 }
688 
onVsyncPeriodTimingChanged(uint32_t displayId,hwc_vsync_period_change_timeline_t * timeline)689 void ExynosDevice::onVsyncPeriodTimingChanged(uint32_t displayId,
690                                               hwc_vsync_period_change_timeline_t *timeline) {
691     Mutex::Autolock lock(mDeviceCallbackMutex);
692 
693     if (!timeline) {
694         ALOGE("vsync period change timeline is null");
695         return;
696     }
697 
698     if (!isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED)) return;
699 
700     hwc2_callback_data_t callbackData =
701             mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].callbackData;
702     HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED callbackFunc =
703             reinterpret_cast<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED>(
704                     mCallbackInfos[HWC2_CALLBACK_VSYNC_PERIOD_TIMING_CHANGED].funcPointer);
705     callbackFunc(callbackData, displayId, timeline);
706 }
707 
onContentProtectionUpdated(uint32_t displayId,HdcpLevels hdcpLevels)708 void ExynosDevice::onContentProtectionUpdated(uint32_t displayId, HdcpLevels hdcpLevels) {
709     Mutex::Autolock lock(mDeviceCallbackMutex);
710 
711     // If the new HdcpLevelsChanged HAL API is available, use it, otherwise fall back
712     // to the old V2 API with onVsync hack, if necessary.
713     const auto& hdcpLevelsChangedCallback =
714             mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onHdcpLevelsChanged);
715     if (hdcpLevelsChangedCallback != mHwc3CallbackInfos.end()) {
716         const auto& callbackInfo = hdcpLevelsChangedCallback->second;
717         if (callbackInfo.funcPointer != nullptr && callbackInfo.callbackData != nullptr) {
718             auto callbackFunc = reinterpret_cast<
719                     void (*)(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
720                              aidl::android::hardware::drm::HdcpLevels)>(callbackInfo.funcPointer);
721             ALOGD("%s: displayId=%u hdcpLevels=%s sending to SF via v3 HAL", __func__, displayId,
722                   hdcpLevels.toString().c_str());
723             callbackFunc(callbackInfo.callbackData, displayId, hdcpLevels);
724             return;
725         }
726     }
727 
728     // Workaround to pass content protection updates to SurfaceFlinger
729     // without changing HWC HAL interface.
730     if (isCallbackRegisteredLocked(HWC2_CALLBACK_VSYNC_2_4)) {
731         ALOGI("%s: displayId=%u hdcpLevels=%s sending to SF via onVsync_2_4", __func__, displayId,
732               hdcpLevels.toString().c_str());
733         hwc2_callback_data_t vsyncCallbackData =
734                 mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].callbackData;
735         HWC2_PFN_VSYNC_2_4 vsyncCallbackFunc = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(
736                 mCallbackInfos[HWC2_CALLBACK_VSYNC_2_4].funcPointer);
737         int32_t connectedLevel = static_cast<int32_t>(hdcpLevels.connectedLevel);
738         int32_t maxLevel = static_cast<int32_t>(hdcpLevels.maxLevel);
739         int32_t timestampValue = (connectedLevel & 0xFF) | ((maxLevel & 0xFF) << 8);
740         vsyncCallbackFunc(vsyncCallbackData, displayId, -timestampValue, ~1);
741     } else
742         ALOGW("%s: onVsync_2_4 is not registered, ignoring onContentProtectionUpdated", __func__);
743 }
744 
setHWCDebug(unsigned int debug)745 void ExynosDevice::setHWCDebug(unsigned int debug)
746 {
747     hwcDebug = debug;
748 }
749 
getHWCDebug()750 uint32_t ExynosDevice::getHWCDebug()
751 {
752     return hwcDebug;
753 }
754 
setHWCFenceDebug(uint32_t typeNum,uint32_t ipNum,uint32_t mode)755 void ExynosDevice::setHWCFenceDebug(uint32_t typeNum, uint32_t ipNum, uint32_t mode)
756 {
757     if (typeNum > FENCE_TYPE_ALL || typeNum < 0 || ipNum > FENCE_IP_ALL || ipNum < 0
758             || mode > 1 || mode < 0) {
759         ALOGE("%s:: input is not valid type(%u), IP(%u), mode(%d)", __func__, typeNum, ipNum, mode);
760         return;
761     }
762 
763     uint32_t value = 0;
764 
765     if (typeNum == FENCE_TYPE_ALL)
766         value = (1 << FENCE_TYPE_ALL) - 1;
767     else
768         value = 1 << typeNum;
769 
770     if (ipNum == FENCE_IP_ALL) {
771         for (uint32_t i = 0; i < FENCE_IP_ALL; i++) {
772             if (mode)
773                 hwcFenceDebug[i] |= value;
774             else
775                 hwcFenceDebug[i] &= (~value);
776         }
777     } else {
778         if (mode)
779             hwcFenceDebug[ipNum] |= value;
780         else
781             hwcFenceDebug[ipNum] &= (~value);
782     }
783 
784 }
785 
getHWCFenceDebug()786 void ExynosDevice::getHWCFenceDebug()
787 {
788     for (uint32_t i = 0; i < FENCE_IP_ALL; i++)
789         ALOGE("[HWCFenceDebug] IP_Number(%d) : Debug(%x)", i, hwcFenceDebug[i]);
790 }
791 
setHWCControl(uint32_t displayId,uint32_t ctrl,int32_t val)792 void ExynosDevice::setHWCControl(uint32_t displayId, uint32_t ctrl, int32_t val) {
793     ExynosDisplay *exynosDisplay = NULL;
794     switch (ctrl) {
795         case HWC_CTL_FORCE_GPU:
796             ALOGI("%s::HWC_CTL_FORCE_GPU on/off=%d", __func__, val);
797             exynosHWCControl.forceGpu = (unsigned int)val;
798             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
799             onRefresh(displayId);
800             break;
801         case HWC_CTL_WINDOW_UPDATE:
802             ALOGI("%s::HWC_CTL_WINDOW_UPDATE on/off=%d", __func__, val);
803             exynosHWCControl.windowUpdate = (unsigned int)val;
804             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
805             onRefresh(displayId);
806             break;
807         case HWC_CTL_FORCE_PANIC:
808             ALOGI("%s::HWC_CTL_FORCE_PANIC on/off=%d", __func__, val);
809             exynosHWCControl.forcePanic = (unsigned int)val;
810             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
811             break;
812         case HWC_CTL_SKIP_STATIC:
813             ALOGI("%s::HWC_CTL_SKIP_STATIC on/off=%d", __func__, val);
814             exynosHWCControl.skipStaticLayers = (unsigned int)val;
815             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
816             break;
817         case HWC_CTL_SKIP_M2M_PROCESSING:
818             ALOGI("%s::HWC_CTL_SKIP_M2M_PROCESSING on/off=%d", __func__, val);
819             exynosHWCControl.skipM2mProcessing = (unsigned int)val;
820             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
821             break;
822         case HWC_CTL_SKIP_RESOURCE_ASSIGN:
823             ALOGI("%s::HWC_CTL_SKIP_RESOURCE_ASSIGN on/off=%d", __func__, val);
824             exynosHWCControl.skipResourceAssign = (unsigned int)val;
825             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
826             onRefreshDisplays();
827             break;
828         case HWC_CTL_SKIP_VALIDATE:
829             ALOGI("%s::HWC_CTL_SKIP_VALIDATE on/off=%d", __func__, val);
830             exynosHWCControl.skipValidate = (unsigned int)val;
831             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
832             onRefreshDisplays();
833             break;
834         case HWC_CTL_DUMP_MID_BUF:
835             ALOGI("%s::HWC_CTL_DUMP_MID_BUF on/off=%d", __func__, val);
836             exynosHWCControl.dumpMidBuf = (unsigned int)val;
837             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
838             onRefreshDisplays();
839             break;
840         case HWC_CTL_CAPTURE_READBACK:
841             captureScreenWithReadback(displayId);
842             break;
843         case HWC_CTL_DISPLAY_MODE:
844             ALOGI("%s::HWC_CTL_DISPLAY_MODE mode=%d", __func__, val);
845             setDisplayMode((uint32_t)val);
846             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
847             onRefreshDisplays();
848             break;
849         // Support DDI scalser {
850         case HWC_CTL_DDI_RESOLUTION_CHANGE:
851             ALOGI("%s::HWC_CTL_DDI_RESOLUTION_CHANGE mode=%d", __func__, val);
852             exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
853             uint32_t width, height;
854 
855             /* TODO: Add branch here for each resolution/index */
856             switch(val) {
857             case 1:
858             case 2:
859             case 3:
860             default:
861                 width = 1440; height = 2960;
862                 break;
863             }
864 
865             if (exynosDisplay == NULL) {
866                 for (uint32_t i = 0; i < mDisplays.size(); i++) {
867                     mDisplays[i]->setDDIScalerEnable(width, height);
868                 }
869             } else {
870                 exynosDisplay->setDDIScalerEnable(width, height);
871             }
872             setGeometryChanged(GEOMETRY_DISPLAY_RESOLUTION_CHANGED);
873             onRefreshDisplays();
874             break;
875         // } Support DDI scaler
876         case HWC_CTL_ENABLE_COMPOSITION_CROP:
877         case HWC_CTL_ENABLE_EXYNOSCOMPOSITION_OPT:
878         case HWC_CTL_ENABLE_CLIENTCOMPOSITION_OPT:
879         case HWC_CTL_USE_MAX_G2D_SRC:
880         case HWC_CTL_ENABLE_HANDLE_LOW_FPS:
881         case HWC_CTL_ENABLE_EARLY_START_MPP:
882             exynosDisplay = (ExynosDisplay *)getDisplay(displayId);
883             if (exynosDisplay == NULL) {
884                 for (uint32_t i = 0; i < mDisplays.size(); i++) {
885                     mDisplays[i]->setHWCControl(ctrl, val);
886                 }
887             } else {
888                 exynosDisplay->setHWCControl(ctrl, val);
889             }
890             setGeometryChanged(GEOMETRY_DEVICE_CONFIG_CHANGED);
891             onRefreshDisplays();
892             break;
893         case HWC_CTL_DYNAMIC_RECOMP:
894             ALOGI("%s::HWC_CTL_DYNAMIC_RECOMP on/off = %d", __func__, val);
895             setDynamicRecomposition(displayId, (unsigned int)val);
896             break;
897         case HWC_CTL_ENABLE_FENCE_TRACER:
898             ALOGI("%s::HWC_CTL_ENABLE_FENCE_TRACER on/off=%d", __func__, val);
899             exynosHWCControl.fenceTracer = (unsigned int)val;
900             break;
901         case HWC_CTL_SYS_FENCE_LOGGING:
902             ALOGI("%s::HWC_CTL_SYS_FENCE_LOGGING on/off=%d", __func__, val);
903             exynosHWCControl.sysFenceLogging = (unsigned int)val;
904             break;
905         case HWC_CTL_DO_FENCE_FILE_DUMP:
906             ALOGI("%s::HWC_CTL_DO_FENCE_FILE_DUMP on/off=%d", __func__, val);
907             exynosHWCControl.doFenceFileDump = (unsigned int)val;
908             break;
909         default:
910             ALOGE("%s: unsupported HWC_CTL (%d)", __func__, ctrl);
911             break;
912     }
913 }
914 
setDisplayMode(uint32_t displayMode)915 void ExynosDevice::setDisplayMode(uint32_t displayMode)
916 {
917     exynosHWCControl.displayMode = displayMode;
918 }
919 
setDynamicRecomposition(uint32_t displayId,unsigned int on)920 void ExynosDevice::setDynamicRecomposition(uint32_t displayId, unsigned int on) {
921     exynosHWCControl.useDynamicRecomp = on;
922     ExynosDisplay *display = getDisplay(displayId);
923     if (display) {
924         display->mDRDefault = on;
925         display->mDREnable = on;
926         onRefresh(displayId);
927     }
928 }
929 
checkDisplayConnection(uint32_t displayId)930 bool ExynosDevice::checkDisplayConnection(uint32_t displayId)
931 {
932 	ExynosDisplay *display = getDisplay(displayId);
933 
934     if (!display)
935         return false;
936     else
937         return display->mPlugState;
938 }
939 
checkNonInternalConnection()940 bool ExynosDevice::checkNonInternalConnection()
941 {
942     for (uint32_t i = 0; i < mDisplays.size(); i++) {
943         switch(mDisplays[i]->mType) {
944             case HWC_DISPLAY_PRIMARY:
945                 break;
946             case HWC_DISPLAY_EXTERNAL:
947             case HWC_DISPLAY_VIRTUAL:
948                 if (mDisplays[i]->mPlugState)
949                     return true;
950                 break;
951             default:
952                 break;
953         }
954     }
955     return false;
956 }
957 
getCapabilitiesLegacy(uint32_t * outCount,int32_t * outCapabilities)958 void ExynosDevice::getCapabilitiesLegacy(uint32_t *outCount, int32_t *outCapabilities) {
959     uint32_t capabilityNum = 0;
960 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
961     capabilityNum++;
962 #endif
963 #ifndef HWC_NO_SUPPORT_SKIP_VALIDATE
964     capabilityNum++;
965 #endif
966     if (outCapabilities == NULL) {
967         *outCount = capabilityNum;
968         return;
969     }
970     if (capabilityNum != *outCount) {
971         ALOGE("%s:: invalid outCount(%d), should be(%d)", __func__, *outCount, capabilityNum);
972         return;
973     }
974 #if defined(HWC_SUPPORT_COLOR_TRANSFORM) || !defined(HWC_NO_SUPPORT_SKIP_VALIDATE)
975     uint32_t index = 0;
976 #endif
977 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
978     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
979 #endif
980 #ifndef HWC_NO_SUPPORT_SKIP_VALIDATE
981     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_VALIDATE;
982 #endif
983     return;
984 }
985 
getCapabilities(uint32_t * outCount,int32_t * outCapabilities)986 void ExynosDevice::getCapabilities(uint32_t *outCount, int32_t *outCapabilities) {
987     uint32_t capabilityNum = 0;
988 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
989     capabilityNum++;
990 #endif
991     if (outCapabilities == NULL) {
992         *outCount = capabilityNum;
993         return;
994     }
995     if (capabilityNum != *outCount) {
996         ALOGE("%s:: invalid outCount(%d), should be(%d)", __func__, *outCount, capabilityNum);
997         return;
998     }
999 #if defined(HWC_SUPPORT_COLOR_TRANSFORM)
1000     uint32_t index = 0;
1001     outCapabilities[index++] = HWC2_CAPABILITY_SKIP_CLIENT_COLOR_TRANSFORM;
1002 #endif
1003     return;
1004 }
1005 
clearGeometryChanged()1006 void ExynosDevice::clearGeometryChanged()
1007 {
1008     mGeometryChanged = 0;
1009 }
1010 
canSkipValidate()1011 bool ExynosDevice::canSkipValidate()
1012 {
1013     /*
1014      * This should be called by presentDisplay()
1015      * when presentDisplay() is called without validateDisplay() call
1016      */
1017 
1018     int ret = 0;
1019     if (exynosHWCControl.skipValidate == false)
1020         return false;
1021 
1022     for (uint32_t i = 0; i < mDisplays.size(); i++) {
1023         /*
1024          * Check all displays.
1025          * Resource assignment can have problem if validateDisplay is skipped
1026          * on only some displays.
1027          * All display's validateDisplay should be skipped or all display's validateDisplay
1028          * should not be skipped.
1029          */
1030         if (mDisplays[i]->mPlugState && mDisplays[i]->mPowerModeState.has_value() &&
1031             mDisplays[i]->mPowerModeState.value() != HWC2_POWER_MODE_OFF) {
1032             /*
1033              * presentDisplay is called without validateDisplay.
1034              * Call functions that should be called in validateDiplay
1035              */
1036             mDisplays[i]->doPreProcessing();
1037             mDisplays[i]->checkLayerFps();
1038 
1039             if ((ret = mDisplays[i]->canSkipValidate()) != NO_ERROR) {
1040                 ALOGD_AND_ATRACE_NAME(eDebugSkipValidate,
1041                                       "Display[%d] can't skip validate (%d), renderingState(%d), "
1042                                       "geometryChanged(0x%" PRIx64 ")",
1043                                       mDisplays[i]->mDisplayId, ret, mDisplays[i]->mRenderingState,
1044                                       mGeometryChanged);
1045                 return false;
1046             } else {
1047                 HDEBUGLOGD(eDebugSkipValidate, "Display[%d] can skip validate (%d), renderingState(%d), geometryChanged(0x%" PRIx64 ")",
1048                         mDisplays[i]->mDisplayId, ret,
1049                         mDisplays[i]->mRenderingState, mGeometryChanged);
1050             }
1051         }
1052     }
1053     return true;
1054 }
1055 
validateFences(ExynosDisplay * display)1056 bool ExynosDevice::validateFences(ExynosDisplay *display) {
1057     return mFenceTracker.validateFences(display);
1058 }
1059 
compareVsyncPeriod()1060 void ExynosDevice::compareVsyncPeriod() {
1061     /* TODO(b/265244856): to clarify what purpose of the function */
1062     ExynosDisplay *primary_display = getDisplay(getDisplayId(HWC_DISPLAY_PRIMARY, 0));
1063     ExynosDisplay *external_display = getDisplay(getDisplayId(HWC_DISPLAY_EXTERNAL, 0));
1064 
1065     mVsyncDisplayId = getDisplayId(HWC_DISPLAY_PRIMARY, 0);
1066 
1067     if ((external_display == nullptr) ||
1068         (!external_display->mPowerModeState.has_value() ||
1069          (external_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF))) {
1070         return;
1071     } else if (!primary_display->mPowerModeState.has_value() ||
1072                (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_OFF)) {
1073         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
1074         return;
1075     } else if (primary_display->mPowerModeState.has_value() &&
1076                ((primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE) ||
1077                 (primary_display->mPowerModeState.value() == HWC2_POWER_MODE_DOZE_SUSPEND)) &&
1078                (external_display->mVsyncPeriod >= DOZE_VSYNC_PERIOD)) { /*30fps*/
1079         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
1080         return;
1081     } else if (primary_display->mVsyncPeriod <= external_display->mVsyncPeriod) {
1082         mVsyncDisplayId = getDisplayId(HWC_DISPLAY_EXTERNAL, 0);
1083         return;
1084     }
1085 
1086     return;
1087 }
1088 
captureReadbackClass(ExynosDevice * device)1089 ExynosDevice::captureReadbackClass::captureReadbackClass(
1090         ExynosDevice *device) :
1091     mDevice(device)
1092 {
1093     if (device == nullptr)
1094         return;
1095 }
1096 
~captureReadbackClass()1097 ExynosDevice::captureReadbackClass::~captureReadbackClass()
1098 {
1099     VendorGraphicBufferMapper& gMapper(VendorGraphicBufferMapper::get());
1100     if (mBuffer != nullptr)
1101         gMapper.freeBuffer(mBuffer);
1102 
1103     if (mDevice != nullptr)
1104         mDevice->clearWaitingReadbackReqDone();
1105 }
1106 
1107 
allocBuffer(uint32_t format,uint32_t w,uint32_t h)1108 int32_t ExynosDevice::captureReadbackClass::allocBuffer(
1109         uint32_t format, uint32_t w, uint32_t h)
1110 {
1111     VendorGraphicBufferAllocator& gAllocator(VendorGraphicBufferAllocator::get());
1112 
1113     uint32_t dstStride = 0;
1114     uint64_t usage = static_cast<uint64_t>(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER |
1115             GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN);
1116 
1117     status_t error = NO_ERROR;
1118     error = gAllocator.allocate(w, h, format, 1, usage, &mBuffer, &dstStride, "HWC");
1119     if ((error != NO_ERROR) || (mBuffer == nullptr)) {
1120         ALOGE("failed to allocate destination buffer(%dx%d): %d",
1121                 w, h, error);
1122         return static_cast<int32_t>(error);
1123     }
1124     return NO_ERROR;
1125 }
1126 
saveToFile(const String8 & fileName)1127 void  ExynosDevice::captureReadbackClass::saveToFile(const String8 &fileName)
1128 {
1129     if (mBuffer == nullptr) {
1130         ALOGE("%s:: buffer is null", __func__);
1131         return;
1132     }
1133 
1134     char filePath[MAX_DEV_NAME] = {0};
1135     VendorGraphicBufferMeta gmeta(mBuffer);
1136 
1137     snprintf(filePath, MAX_DEV_NAME,
1138             "%s/%s", WRITEBACK_CAPTURE_PATH, fileName.c_str());
1139     FILE *fp = fopen(filePath, "w");
1140     if (fp) {
1141         uint32_t writeSize =
1142             gmeta.stride * gmeta.vstride * formatToBpp(gmeta.format)/8;
1143         void *writebackData = mmap(0, writeSize,
1144                 PROT_READ|PROT_WRITE, MAP_SHARED, gmeta.fd, 0);
1145         if (writebackData != MAP_FAILED && writebackData != NULL) {
1146             size_t result = fwrite(writebackData, writeSize, 1, fp);
1147             munmap(writebackData, writeSize);
1148             ALOGD("Success to write %zu data, size(%d)", result, writeSize);
1149         } else {
1150             ALOGE("Fail to mmap");
1151         }
1152         fclose(fp);
1153     } else {
1154         ALOGE("Fail to open %s", filePath);
1155     }
1156 }
1157 
signalReadbackDone()1158 void ExynosDevice::signalReadbackDone()
1159 {
1160     if (mIsWaitingReadbackReqDone) {
1161         Mutex::Autolock lock(mCaptureMutex);
1162         mCaptureCondition.signal();
1163     }
1164 }
1165 
captureScreenWithReadback(uint32_t displayId)1166 void ExynosDevice::captureScreenWithReadback(uint32_t displayId) {
1167     ExynosDisplay *display = getDisplay(displayId);
1168     if (display == nullptr) {
1169         ALOGE("There is no display(%d)", displayId);
1170         return;
1171     }
1172 
1173     int32_t outFormat;
1174     int32_t outDataspace;
1175     int32_t ret = 0;
1176     if ((ret = display->getReadbackBufferAttributes(
1177                 &outFormat, &outDataspace)) != HWC2_ERROR_NONE) {
1178         ALOGE("getReadbackBufferAttributes fail, ret(%d)", ret);
1179         return;
1180     }
1181 
1182     captureReadbackClass captureClass(this);
1183     if ((ret = captureClass.allocBuffer(outFormat, display->mXres, display->mYres))
1184             != NO_ERROR) {
1185         return;
1186     }
1187 
1188     mIsWaitingReadbackReqDone = true;
1189 
1190     if (display->setReadbackBuffer(captureClass.getBuffer(), -1, true) != HWC2_ERROR_NONE) {
1191         ALOGE("setReadbackBuffer fail");
1192         return;
1193     }
1194 
1195     /* Update screen */
1196     onRefresh(displayId);
1197 
1198     /* Wait for handling readback */
1199     uint32_t waitPeriod = display->mVsyncPeriod * 3;
1200     {
1201         Mutex::Autolock lock(mCaptureMutex);
1202         status_t err = mCaptureCondition.waitRelative(
1203                 mCaptureMutex, us2ns(waitPeriod));
1204         if (err == TIMED_OUT) {
1205             ALOGE("timeout, readback is not requested");
1206             return;
1207         } else if (err != NO_ERROR) {
1208             ALOGE("error waiting for readback request: %s (%d)", strerror(-err), err);
1209             return;
1210         } else {
1211             ALOGD("readback request is done");
1212         }
1213     }
1214 
1215     int32_t fence = -1;
1216     if (display->getReadbackBufferFence(&fence) != HWC2_ERROR_NONE) {
1217         ALOGE("getReadbackBufferFence fail");
1218         return;
1219     }
1220     if (sync_wait(fence, 1000) < 0) {
1221         ALOGE("sync wait error, fence(%d)", fence);
1222     }
1223     hwcFdClose(fence);
1224 
1225     String8 fileName;
1226     time_t curTime = time(NULL);
1227     struct tm *tm = localtime(&curTime);
1228     fileName.appendFormat("capture_format%d_%dx%d_%04d-%02d-%02d_%02d_%02d_%02d.raw",
1229             outFormat, display->mXres, display->mYres,
1230             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
1231             tm->tm_hour, tm->tm_min, tm->tm_sec);
1232     captureClass.saveToFile(fileName);
1233 }
1234 
setDisplayDeviceMode(int32_t display_id,int32_t mode)1235 int32_t ExynosDevice::setDisplayDeviceMode(int32_t display_id, int32_t mode)
1236 {
1237     int32_t ret = HWC2_ERROR_NONE;
1238 
1239     for (size_t i = 0; i < mDisplays.size(); i++) {
1240         if (mDisplays[i]->mType == HWC_DISPLAY_PRIMARY && mDisplays[i]->mDisplayId == display_id) {
1241             if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::PAUSE) ||
1242                 mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME)) {
1243                 ret = mDisplays[i]->setPowerMode(mode);
1244                 if (mode == static_cast<int32_t>(ext_hwc2_power_mode_t::RESUME) &&
1245                     ret == HWC2_ERROR_NONE) {
1246                     onRefresh(display_id);
1247                 }
1248                 return ret;
1249             } else {
1250                 return HWC2_ERROR_UNSUPPORTED;
1251             }
1252         }
1253     }
1254     return HWC2_ERROR_UNSUPPORTED;
1255 }
1256 
setPanelGammaTableSource(int32_t display_id,int32_t type,int32_t source)1257 int32_t ExynosDevice::setPanelGammaTableSource(int32_t display_id, int32_t type, int32_t source) {
1258     if (display_id < HWC_DISPLAY_PRIMARY || display_id >= HWC_NUM_DISPLAY_TYPES) {
1259         ALOGE("invalid display %d", display_id);
1260         return HWC2_ERROR_BAD_DISPLAY;
1261     }
1262 
1263     if (type < static_cast<int32_t>(DisplayType::DISPLAY_PRIMARY) ||
1264         type >= static_cast<int32_t>(DisplayType::DISPLAY_MAX)) {
1265         ALOGE("invalid display type %d", type);
1266         return HWC2_ERROR_BAD_PARAMETER;
1267     }
1268 
1269     if (source < static_cast<int32_t>(PanelGammaSource::GAMMA_DEFAULT) ||
1270         source >= static_cast<int32_t>(PanelGammaSource::GAMMA_TYPES)) {
1271         ALOGE("invalid gamma source %d", source);
1272         return HWC2_ERROR_BAD_PARAMETER;
1273     }
1274 
1275     return mDisplays[display_id]->SetCurrentPanelGammaSource(static_cast<DisplayType>(type),
1276                                                              static_cast<PanelGammaSource>(source));
1277 }
1278 
getLayerGenericMetadataKey(uint32_t __unused keyIndex,uint32_t * outKeyLength,char * __unused outKey,bool * __unused outMandatory)1279 void ExynosDevice::getLayerGenericMetadataKey(uint32_t __unused keyIndex,
1280         uint32_t* outKeyLength, char* __unused outKey, bool* __unused outMandatory)
1281 {
1282     *outKeyLength = 0;
1283     return;
1284 }
1285 
setVBlankOffDelay(const int vblankOffDelay)1286 void ExynosDevice::setVBlankOffDelay(const int vblankOffDelay) {
1287     static constexpr const char *kVblankOffDelayPath = "/sys/module/drm/parameters/vblankoffdelay";
1288 
1289     writeIntToFile(kVblankOffDelayPath, vblankOffDelay);
1290 }
1291 
getWindowPlaneNum()1292 uint32_t ExynosDevice::getWindowPlaneNum()
1293 {
1294     /*
1295      * ExynosDevice supports DPU Window Composition.
1296      * The number of windows can be composited is depends on the number of DPP planes.
1297      */
1298     return mDeviceInterface->getNumDPPChs();
1299 }
1300 
getSpecialPlaneNum()1301 uint32_t ExynosDevice::getSpecialPlaneNum()
1302 {
1303     /*
1304      * ExynosDevice might support something special purpose planes.
1305      * These planes are different with DPP planes.
1306      */
1307     return mDeviceInterface->getNumSPPChs();
1308 }
1309 
getSpecialPlaneNum(uint32_t)1310 uint32_t ExynosDevice::getSpecialPlaneNum(uint32_t /*displayId*/) {
1311     /*
1312      * TODO: create the query function for each display
1313      */
1314     return mDeviceInterface->getNumSPPChs();
1315 }
1316 
getSpecialPlaneId(uint32_t index)1317 uint32_t ExynosDevice::getSpecialPlaneId(uint32_t index)
1318 {
1319     return mDeviceInterface->getSPPChId(index);
1320 }
1321 
getSpecialPlaneAttr(uint32_t index)1322 uint64_t ExynosDevice::getSpecialPlaneAttr(uint32_t index)
1323 {
1324     return mDeviceInterface->getSPPChAttr(index);
1325 }
1326 
registerHwc3Callback(uint32_t descriptor,hwc2_callback_data_t callbackData,hwc2_function_pointer_t point)1327 int32_t ExynosDevice::registerHwc3Callback(uint32_t descriptor, hwc2_callback_data_t callbackData,
1328                                            hwc2_function_pointer_t point) {
1329     Mutex::Autolock lock(mDeviceCallbackMutex);
1330     mHwc3CallbackInfos[descriptor].callbackData = callbackData;
1331     mHwc3CallbackInfos[descriptor].funcPointer = point;
1332 
1333     return HWC2_ERROR_NONE;
1334 }
1335 
onVsyncIdle(hwc2_display_t displayId)1336 void ExynosDevice::onVsyncIdle(hwc2_display_t displayId) {
1337     Mutex::Autolock lock(mDeviceCallbackMutex);
1338     const auto &idleCallback = mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onVsyncIdle);
1339 
1340     if (idleCallback == mHwc3CallbackInfos.end()) return;
1341 
1342     const auto &callbackInfo = idleCallback->second;
1343     if (callbackInfo.funcPointer == nullptr || callbackInfo.callbackData == nullptr) return;
1344 
1345     auto callbackFunc =
1346             reinterpret_cast<void (*)(hwc2_callback_data_t callbackData,
1347                                       hwc2_display_t hwcDisplay)>(callbackInfo.funcPointer);
1348     callbackFunc(callbackInfo.callbackData, displayId);
1349 }
1350 
handleHotplug()1351 void ExynosDevice::handleHotplug() {
1352     bool hpdStatus = false;
1353 
1354     for (size_t i = 0; i < mDisplays.size(); i++) {
1355         if (mDisplays[i] == nullptr) {
1356             continue;
1357         }
1358 
1359         // Lock mDisplayMutex during hotplug processing.
1360         // Must-have for unplug handling so that in-flight calls to
1361         // validateDisplay() and presentDisplay() don't race with
1362         // the display being removed.
1363         Mutex::Autolock lock(mDisplays[i]->mDisplayMutex);
1364 
1365         if (mDisplays[i]->checkHotplugEventUpdated(hpdStatus)) {
1366             mDisplays[i]->handleHotplugEvent(hpdStatus);
1367             mDisplays[i]->hotplug();
1368             mDisplays[i]->invalidate();
1369         }
1370     }
1371 }
1372 
onRefreshRateChangedDebug(hwc2_display_t displayId,uint32_t vsyncPeriod,uint32_t refreshPeriod)1373 void ExynosDevice::onRefreshRateChangedDebug(hwc2_display_t displayId, uint32_t vsyncPeriod,
1374                                              uint32_t refreshPeriod) {
1375     Mutex::Autolock lock(mDeviceCallbackMutex);
1376     const auto &refreshRateCallback =
1377             mHwc3CallbackInfos.find(IComposerCallback::TRANSACTION_onRefreshRateChangedDebug);
1378 
1379     if (refreshRateCallback == mHwc3CallbackInfos.end()) return;
1380 
1381     const auto &callbackInfo = refreshRateCallback->second;
1382     if (callbackInfo.funcPointer == nullptr || callbackInfo.callbackData == nullptr) return;
1383 
1384     ATRACE_INT("Refresh rate indicator callback",
1385                static_cast<int>(std::nano::den / (refreshPeriod ?: vsyncPeriod)));
1386 
1387     auto callbackFunc =
1388             reinterpret_cast<void (*)(hwc2_callback_data_t callbackData, hwc2_display_t hwcDisplay,
1389                                       hwc2_vsync_period_t, int32_t)>(callbackInfo.funcPointer);
1390     callbackFunc(callbackInfo.callbackData, displayId, vsyncPeriod, refreshPeriod ?: vsyncPeriod);
1391 }
1392