From 6860b2b92ebaed1fd14e4c93b895470d28c33153 Mon Sep 17 00:00:00 2001 From: Dileep Marchya Date: Fri, 7 Apr 2017 15:56:47 +0530 Subject: hwc2: Implement IDisplayConfig HIDL service. - Add IDisplayConfig service in composer process. - Add DisplayConfig wrapper to abstract IDisplayConfig interfaces. CRs-Fixed: 2036340 Change-Id: I54535e7224ee842b761509268ebaa2e8425bc8d7 --- Android.mk | 2 +- common.mk | 2 +- libdisplayconfig/Android.mk | 12 + libdisplayconfig/DisplayConfig.cpp | 363 +++++++++++++++++++++++++ libdisplayconfig/DisplayConfig.h | 110 ++++++++ sdm/libs/hwc2/Android.mk | 5 +- sdm/libs/hwc2/hwc_display.cpp | 6 +- sdm/libs/hwc2/hwc_display.h | 20 +- sdm/libs/hwc2/hwc_session.cpp | 367 +++++++------------------ sdm/libs/hwc2/hwc_session.h | 68 +++-- sdm/libs/hwc2/hwc_session_services.cpp | 483 +++++++++++++++++++++++++++++++++ 11 files changed, 1122 insertions(+), 316 deletions(-) create mode 100644 libdisplayconfig/Android.mk create mode 100644 libdisplayconfig/DisplayConfig.cpp create mode 100644 libdisplayconfig/DisplayConfig.h create mode 100644 sdm/libs/hwc2/hwc_session_services.cpp diff --git a/Android.mk b/Android.mk index 226e8a0d..1a285bf7 100644 --- a/Android.mk +++ b/Android.mk @@ -3,7 +3,7 @@ display-hals := include libqservice libqdutils $(sdm-libs)/utils $(sdm-libs)/cor ifneq ($(TARGET_IS_HEADLESS), true) display-hals += libcopybit liblight libmemtrack hdmi_cec \ - $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper libdrmutils + $(sdm-libs)/hwc $(sdm-libs)/hwc2 gpu_tonemapper libdrmutils libdisplayconfig endif ifneq ($(TARGET_USES_GRALLOC1), true) diff --git a/common.mk b/common.mk index 88d1aee2..b253c80b 100644 --- a/common.mk +++ b/common.mk @@ -3,7 +3,7 @@ display_top := $(call my-dir) #Common C flags common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers -common_flags += -Wconversion -Wall -Werror -std=c++11 +common_flags += -Wconversion -Wall -Werror -std=c++14 ifeq ($(TARGET_IS_HEADLESS), true) common_flags += -DTARGET_HEADLESS LOCAL_CLANG := false diff --git a/libdisplayconfig/Android.mk b/libdisplayconfig/Android.mk new file mode 100644 index 00000000..fae7f85c --- /dev/null +++ b/libdisplayconfig/Android.mk @@ -0,0 +1,12 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := libdisplayconfig +LOCAL_MODULE_TAGS := optional +LOCAL_HEADER_LIBRARIES := display_headers +LOCAL_COPY_HEADERS := DisplayConfig.h +LOCAL_SRC_FILES := DisplayConfig.cpp +LOCAL_SHARED_LIBRARIES := libhidlbase libhidltransport libutils \ + vendor.display.config@1.0 android.hidl.base@1.0 + +include $(BUILD_SHARED_LIBRARY) diff --git a/libdisplayconfig/DisplayConfig.cpp b/libdisplayconfig/DisplayConfig.cpp new file mode 100644 index 00000000..c55715bd --- /dev/null +++ b/libdisplayconfig/DisplayConfig.cpp @@ -0,0 +1,363 @@ +/* +* Copyright (c) 2017 The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#include "DisplayConfig.h" + +namespace display { + +using vendor::display::config::V1_0::IDisplayConfig; + +//============================================================================= +// The functions below run in the client process and wherever necessary +// do a binder call to HWC to get/set data. + +IDisplayConfig::DisplayType MapDisplayType(int dpy) { + switch (dpy) { + case DISPLAY_PRIMARY: + return IDisplayConfig::DisplayType::DISPLAY_PRIMARY; + + case DISPLAY_EXTERNAL: + return IDisplayConfig::DisplayType::DISPLAY_EXTERNAL; + + case DISPLAY_VIRTUAL: + return IDisplayConfig::DisplayType::DISPLAY_VIRTUAL; + + default: + break; + } + + return IDisplayConfig::DisplayType::INVALID; +} + +IDisplayConfig::DisplayExternalStatus MapExternalStatus(uint32_t status) { + switch (status) { + case EXTERNAL_OFFLINE: + return IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE; + + case EXTERNAL_ONLINE: + return IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE; + + case EXTERNAL_PAUSE: + return IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE; + + case EXTERNAL_RESUME: + return IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME; + + default: + break; + } + + return IDisplayConfig::DisplayExternalStatus::INVALID; +} + +IDisplayConfig::DisplayDynRefreshRateOp MapDynRefreshRateOp(uint32_t op) { + switch (op) { + case DISABLE_METADATA_DYN_REFRESH_RATE: + return IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE; + + case ENABLE_METADATA_DYN_REFRESH_RATE: + return IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE; + + case SET_BINDER_DYN_REFRESH_RATE: + return IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE; + + default: + break; + } + + return IDisplayConfig::DisplayDynRefreshRateOp::INVALID; +} + +int MapDisplayPortType(IDisplayConfig::DisplayPortType panelType) { + switch (panelType) { + case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT: + return DISPLAY_PORT_DEFAULT; + + case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DSI: + return DISPLAY_PORT_DSI; + + case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DTV: + return DISPLAY_PORT_DTV; + + case IDisplayConfig::DisplayPortType::DISPLAY_PORT_WRITEBACK: + return DISPLAY_PORT_WRITEBACK; + + case IDisplayConfig::DisplayPortType::DISPLAY_PORT_LVDS: + return DISPLAY_PORT_LVDS; + + case IDisplayConfig::DisplayPortType::DISPLAY_PORT_EDP: + return DISPLAY_PORT_EDP; + + case IDisplayConfig::DisplayPortType::DISPLAY_PORT_DP: + return DISPLAY_PORT_DP; + + default: + break; + } + + return -1; +} + +int isExternalConnected() { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return 0; + } + + int connected = 0; + intf->isDisplayConnected(IDisplayConfig::DisplayType::DISPLAY_EXTERNAL, + [&](const auto &tmpError, const auto &tmpStatus) { + if (tmpError) { + return; + } + + connected = tmpStatus; + }); + + return connected; +} + +int setSecondayDisplayStatus(int dpy, uint32_t status) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->setSecondayDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status)); +} + +int configureDynRefeshRate(uint32_t op, uint32_t refreshRate) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->configureDynRefeshRate(MapDynRefreshRateOp(op), refreshRate); +} + +int getConfigCount(int dpy) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + int count = 0; + intf->getActiveConfig(MapDisplayType(dpy), + [&](const auto &tmpError, const auto &tmpCount) { + if (tmpError) { + return; + } + + count = tmpCount; + }); + + return count; +} + +int getActiveConfig(int dpy) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + int config = 0; + intf->getActiveConfig(MapDisplayType(dpy), + [&](const auto &tmpError, const auto &tmpConfig) { + if (tmpError) { + return; + } + + config = tmpConfig; + }); + + return config; +} + +int setActiveConfig(int dpy, uint32_t config) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->setActiveConfig(MapDisplayType(dpy), config); +} + +DisplayAttributes getDisplayAttributes(uint32_t configIndex, int dpy) { + DisplayAttributes attributes; + + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return attributes; + } + + intf->getDisplayAttributes(configIndex, MapDisplayType(dpy), + [&](const auto &tmpError, const auto &tmpAttributes) { + if (tmpError) { + return; + } + + attributes.vsync_period = tmpAttributes.vsyncPeriod; + attributes.xres = tmpAttributes.xRes; + attributes.yres = tmpAttributes.yRes; + attributes.xdpi = tmpAttributes.xDpi; + attributes.ydpi = tmpAttributes.yDpi; + attributes.panel_type = MapDisplayPortType(tmpAttributes.panelType); + attributes.is_yuv = tmpAttributes.isYuv; + }); + + return attributes; +} + +int setPanelBrightness(uint32_t level) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->setPanelBrightness(level); +} + +uint32_t getPanelBrightness() { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return 0; + } + + int level = 0; + intf->getPanelBrightness( + [&](const auto &tmpError, const auto &tmpLevel) { + if (tmpError) { + return; + } + + level = tmpLevel; + }); + + return level; +} + +int minHdcpEncryptionLevelChanged(int dpy, uint32_t min_enc_level) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->minHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level); +} + +int refreshScreen() { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->refreshScreen(); +} + +int controlPartialUpdate(int dpy, bool enable) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->controlPartialUpdate(MapDisplayType(dpy), enable); +} + +int toggleScreenUpdate(uint32_t on) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->toggleScreenUpdate(on == 1); +} + +int setIdleTimeout(uint32_t value) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->setIdleTimeout(value); +} + +int getHDRCapabilities(int dpy, DisplayHDRCapabilities *caps) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL || caps == NULL) { + return -1; + } + + int error = -1; + intf->getHDRCapabilities(MapDisplayType(dpy), + [&](const auto &tmpError, const auto &tmpCaps) { + error = tmpError; + if (error) { + return; + } + + caps->supported_hdr_types = tmpCaps.supportedHdrTypes; + caps->max_luminance = tmpCaps.maxLuminance; + caps->max_avg_luminance = tmpCaps.maxAvgLuminance; + caps->min_luminance = tmpCaps.minLuminance; + }); + + return error; +} + +int setCameraLaunchStatus(uint32_t on) { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return -1; + } + + return intf->setCameraLaunchStatus(on); +} + +bool displayBWTransactionPending() { + android::sp intf = IDisplayConfig::getService(); + if (intf == NULL) { + return 0; + } + + int status = 0; + intf->displayBWTransactionPending( + [&](const auto &tmpError, const auto &tmpStatus) { + if (tmpError) { + return; + } + + status = tmpStatus; + }); + + return status; +} + +} // namespace display diff --git a/libdisplayconfig/DisplayConfig.h b/libdisplayconfig/DisplayConfig.h new file mode 100644 index 00000000..69a542a3 --- /dev/null +++ b/libdisplayconfig/DisplayConfig.h @@ -0,0 +1,110 @@ +/* + * Copyight (c) 2017 The Linux Foundation. All ights reserved. + * + * Redistibution and use in souce and binary forms, with or without + * modification, ae pemitted provided that the following conditions are + * met: + * * Redistibutions of souce code must retain the above copyright + * notice, this list of conditions and the following disclaime. + * * Redistibutions in binay form must reproduce the above + * copyight notice, this list of conditions and the following + * disclaime in the documentation and/o other materials provided + * with the distibution. + * * Neither the name of The Linux Foundation. no the names of its + * contibutos may be used to endorse or promote products derived + * fom this softwae without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DISPLAY_CONFIG_H__ +#define __DISPLAY_CONFIG_H__ + +#include +#include + +// This header is for clients to use to set/get global display configuration. + +namespace display { + +enum { + DISPLAY_PRIMARY = 0, + DISPLAY_EXTERNAL, + DISPLAY_VIRTUAL, +}; + +enum { + EXTERNAL_OFFLINE = 0, + EXTERNAL_ONLINE, + EXTERNAL_PAUSE, + EXTERNAL_RESUME, +}; + +enum { + DISABLE_METADATA_DYN_REFRESH_RATE = 0, + ENABLE_METADATA_DYN_REFRESH_RATE, + SET_BINDER_DYN_REFRESH_RATE, +}; + +enum { + DISPLAY_PORT_DEFAULT = 0, + DISPLAY_PORT_DSI, + DISPLAY_PORT_DTV, + DISPLAY_PORT_WRITEBACK, + DISPLAY_PORT_LVDS, + DISPLAY_PORT_EDP, + DISPLAY_PORT_DP, +}; + +struct DisplayAttributes { + uint32_t vsync_period = 0; //nanoseconds + uint32_t xres = 0; + uint32_t yres = 0; + float xdpi = 0.0f; + float ydpi = 0.0f; + int panel_type = DISPLAY_PORT_DEFAULT; + bool is_yuv = false; +}; + +struct DisplayHDRCapabilities { + std::vector supported_hdr_types; + float max_luminance = 0.0f; + float max_avg_luminance = 0.0f; + float min_luminance = 0.0f; +}; + +//============================================================================= +// The functions below run in the client pocess and wherever necessary +// do a binder call to HWC to get/set data. + +int isExternalConnected(); +int setSecondayDisplayStatus(int dpy, uint32_t status); +int configureDynRefeshRate(uint32_t op, uint32_t refreshRate); +int getConfigCount(int dpy); +int getActiveConfig(int dpy); +int setActiveConfig(int dpy, uint32_t config); +DisplayAttributes getDisplayAttributes(uint32_t configIndex, int dpy); +int setPanelBrightness(uint32_t level); +uint32_t getPanelBrightness(); +int minHdcpEncryptionLevelChanged(int dpy, uint32_t min_enc_level); +int refreshScreen(); +int controlPartialUpdate(int dpy, bool enable); +int toggleScreenUpdate(uint32_t on); +int setIdleTimeout(uint32_t value); +int getHDRCapabilities(int dpy, DisplayHDRCapabilities *caps); +int setCameraLaunchStatus(uint32_t on); +bool displayBWTransactionPending(); + +} // namespace display + +#endif // __DISPLAY_CONFIG_H__ diff --git a/sdm/libs/hwc2/Android.mk b/sdm/libs/hwc2/Android.mk index 81271b0b..592dc027 100644 --- a/sdm/libs/hwc2/Android.mk +++ b/sdm/libs/hwc2/Android.mk @@ -19,14 +19,15 @@ LOCAL_CLANG := true LOCAL_SHARED_LIBRARIES := libsdmcore libqservice libbinder libhardware libhardware_legacy \ libutils libcutils libsync libqdutils libqdMetaData libdl \ - libsdmutils libc++ liblog libgrallocutils \ - libui libgpu_tonemapper + libsdmutils libc++ liblog libgrallocutils libui libgpu_tonemapper \ + libhidlbase libhidltransport vendor.display.config@1.0 ifneq ($(TARGET_USES_GRALLOC1), true) LOCAL_SHARED_LIBRARIES += libmemalloc endif LOCAL_SRC_FILES := hwc_session.cpp \ + hwc_session_services.cpp \ hwc_display.cpp \ hwc_display_primary.cpp \ hwc_display_external.cpp \ diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp index 4f623ce5..69b0acd8 100644 --- a/sdm/libs/hwc2/hwc_display.cpp +++ b/sdm/libs/hwc2/hwc_display.cpp @@ -1523,7 +1523,7 @@ void HWCDisplay::GetPanelResolution(uint32_t *x_pixels, uint32_t *y_pixels) { *y_pixels = display_config.y_pixels; } -int HWCDisplay::SetDisplayStatus(uint32_t display_status) { +int HWCDisplay::SetDisplayStatus(DisplayStatus display_status) { int status = 0; switch (display_status) { @@ -1726,8 +1726,8 @@ void HWCDisplay::SetSecureDisplay(bool secure_display_active) { return; } -int HWCDisplay::SetActiveDisplayConfig(int config) { - return display_intf_->SetActiveConfig(UINT32(config)) == kErrorNone ? 0 : -1; +int HWCDisplay::SetActiveDisplayConfig(uint32_t config) { + return display_intf_->SetActiveConfig(config) == kErrorNone ? 0 : -1; } int HWCDisplay::GetActiveDisplayConfig(uint32_t *config) { diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h index 1b04c849..9ee78112 100644 --- a/sdm/libs/hwc2/hwc_display.h +++ b/sdm/libs/hwc2/hwc_display.h @@ -20,6 +20,7 @@ #ifndef __HWC_DISPLAY_H__ #define __HWC_DISPLAY_H__ +#include #include #include #include @@ -92,6 +93,14 @@ class HWCColorMode { class HWCDisplay : public DisplayEventHandler { public: + enum DisplayStatus { + kDisplayStatusInvalid = -1, + kDisplayStatusOffline, + kDisplayStatusOnline, + kDisplayStatusPause, + kDisplayStatusResume, + }; + virtual ~HWCDisplay() {} virtual int Init(); virtual int Deinit(); @@ -106,7 +115,7 @@ class HWCDisplay : public DisplayEventHandler { virtual HWC2::PowerMode GetLastPowerMode(); virtual int SetFrameBufferResolution(uint32_t x_pixels, uint32_t y_pixels); virtual void GetFrameBufferResolution(uint32_t *x_pixels, uint32_t *y_pixels); - virtual int SetDisplayStatus(uint32_t display_status); + virtual int SetDisplayStatus(DisplayStatus display_status); virtual int OnMinHdcpEncryptionLevelChange(uint32_t min_enc_level); virtual int Perform(uint32_t operation, ...); virtual void SetSecureDisplay(bool secure_display_active); @@ -132,7 +141,7 @@ class HWCDisplay : public DisplayEventHandler { } // Display Configurations - virtual int SetActiveDisplayConfig(int config); + virtual int SetActiveDisplayConfig(uint32_t config); virtual int GetActiveDisplayConfig(uint32_t *config); virtual int GetDisplayConfigCount(uint32_t *count); virtual int GetDisplayAttributesForConfig(int config, @@ -211,13 +220,6 @@ class HWCDisplay : public DisplayEventHandler { float* out_min_luminance); protected: - enum DisplayStatus { - kDisplayStatusOffline = 0, - kDisplayStatusOnline, - kDisplayStatusPause, - kDisplayStatusResume, - }; - // Maximum number of layers supported by display manager. static const uint32_t kMaxLayerCount = 32; diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp index 7b68eb81..a6739b2a 100644 --- a/sdm/libs/hwc2/hwc_session.cpp +++ b/sdm/libs/hwc2/hwc_session.cpp @@ -94,6 +94,8 @@ int HWCSession::Init() { return -EINVAL; } + StartServices(); + buffer_allocator_ = new HWCBufferAllocator(); DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), buffer_allocator_, @@ -770,8 +772,6 @@ int HWCSession::DisconnectDisplay(int disp) { // Qclient methods android::status_t HWCSession::notifyCallback(uint32_t command, const android::Parcel *input_parcel, android::Parcel *output_parcel) { - SEQUENCE_WAIT_SCOPE_LOCK(locker_); - android::status_t status = 0; switch (command) { @@ -780,14 +780,11 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa break; case qService::IQService::SCREEN_REFRESH: - callbacks_.Refresh(HWC_DISPLAY_PRIMARY); + refreshScreen(); break; case qService::IQService::SET_IDLE_TIMEOUT: - if (hwc_display_[HWC_DISPLAY_PRIMARY]) { - uint32_t timeout = UINT32(input_parcel->readInt32()); - hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(timeout); - } + setIdleTimeout(UINT32(input_parcel->readInt32())); break; case qService::IQService::SET_FRAME_DUMP_CONFIG: @@ -802,8 +799,13 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa status = SetDisplayMode(input_parcel); break; - case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: - status = SetSecondaryDisplayStatus(input_parcel, output_parcel); + case qService::IQService::SET_SECONDARY_DISPLAY_STATUS: { + int disp_id = INT(input_parcel->readInt32()); + HWCDisplay::DisplayStatus disp_status = + static_cast(input_parcel->readInt32()); + status = SetSecondaryDisplayStatus(disp_id, disp_status); + output_parcel->writeInt32(status); + } break; case qService::IQService::CONFIGURE_DYN_REFRESH_RATE: @@ -813,56 +815,89 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa case qService::IQService::SET_VIEW_FRAME: break; - case qService::IQService::TOGGLE_SCREEN_UPDATES: - status = ToggleScreenUpdates(input_parcel, output_parcel); + case qService::IQService::TOGGLE_SCREEN_UPDATES: { + int32_t input = input_parcel->readInt32(); + status = toggleScreenUpdate(input == 1); + output_parcel->writeInt32(status); + } break; case qService::IQService::QDCM_SVC_CMDS: status = QdcmCMDHandler(input_parcel, output_parcel); break; - case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: - status = OnMinHdcpEncryptionLevelChange(input_parcel, output_parcel); + case qService::IQService::MIN_HDCP_ENCRYPTION_LEVEL_CHANGED: { + int disp_id = input_parcel->readInt32(); + uint32_t min_enc_level = UINT32(input_parcel->readInt32()); + status = MinHdcpEncryptionLevelChanged(disp_id, min_enc_level); + output_parcel->writeInt32(status); + } break; - case qService::IQService::CONTROL_PARTIAL_UPDATE: - status = ControlPartialUpdate(input_parcel, output_parcel); + case qService::IQService::CONTROL_PARTIAL_UPDATE: { + int disp_id = input_parcel->readInt32(); + uint32_t enable = UINT32(input_parcel->readInt32()); + status = ControlPartialUpdate(disp_id, enable == 1); + output_parcel->writeInt32(status); + } break; - case qService::IQService::SET_ACTIVE_CONFIG: - status = HandleSetActiveDisplayConfig(input_parcel, output_parcel); + case qService::IQService::SET_ACTIVE_CONFIG: { + uint32_t config = UINT32(input_parcel->readInt32()); + int disp_id = input_parcel->readInt32(); + status = SetActiveConfigIndex(disp_id, config); + } break; - case qService::IQService::GET_ACTIVE_CONFIG: - status = HandleGetActiveDisplayConfig(input_parcel, output_parcel); + case qService::IQService::GET_ACTIVE_CONFIG: { + int disp_id = input_parcel->readInt32(); + uint32_t config = 0; + status = GetActiveConfigIndex(disp_id, &config); + output_parcel->writeInt32(INT(config)); + } break; - case qService::IQService::GET_CONFIG_COUNT: - status = HandleGetDisplayConfigCount(input_parcel, output_parcel); + case qService::IQService::GET_CONFIG_COUNT: { + int disp_id = input_parcel->readInt32(); + uint32_t count = 0; + status = GetConfigCount(disp_id, &count); + output_parcel->writeInt32(INT(count)); + } break; case qService::IQService::GET_DISPLAY_ATTRIBUTES_FOR_CONFIG: status = HandleGetDisplayAttributesForConfig(input_parcel, output_parcel); break; - case qService::IQService::GET_PANEL_BRIGHTNESS: - status = GetPanelBrightness(input_parcel, output_parcel); + case qService::IQService::GET_PANEL_BRIGHTNESS: { + int level = 0; + status = GetPanelBrightness(&level); + output_parcel->writeInt32(level); + } break; - case qService::IQService::SET_PANEL_BRIGHTNESS: - status = SetPanelBrightness(input_parcel, output_parcel); + case qService::IQService::SET_PANEL_BRIGHTNESS: { + uint32_t level = UINT32(input_parcel->readInt32()); + status = setPanelBrightness(level); + output_parcel->writeInt32(status); + } break; case qService::IQService::GET_DISPLAY_VISIBLE_REGION: status = GetVisibleDisplayRect(input_parcel, output_parcel); break; - case qService::IQService::SET_CAMERA_STATUS: - status = SetDynamicBWForCamera(input_parcel, output_parcel); + case qService::IQService::SET_CAMERA_STATUS: { + uint32_t camera_status = UINT32(input_parcel->readInt32()); + status = setCameraLaunchStatus(camera_status); + } break; - case qService::IQService::GET_BW_TRANSACTION_STATUS: - status = GetBWTransactionStatus(input_parcel, output_parcel); + case qService::IQService::GET_BW_TRANSACTION_STATUS: { + bool state = true; + status = DisplayBWTransactionPending(&state); + output_parcel->writeInt32(state); + } break; case qService::IQService::SET_LAYER_MIXER_RESOLUTION: @@ -885,167 +920,11 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa return status; } -android::status_t HWCSession::ToggleScreenUpdates(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int input = input_parcel->readInt32(); - int error = android::BAD_VALUE; - - if (hwc_display_[HWC_DISPLAY_PRIMARY] && (input <= 1) && (input >= 0)) { - error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(input == 1); - if (error != 0) { - DLOGE("Failed to toggle screen updates = %d. Error = %d", input, error); - } - } - output_parcel->writeInt32(error); - - return error; -} - -android::status_t HWCSession::SetPanelBrightness(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int level = input_parcel->readInt32(); - int error = android::BAD_VALUE; - - if (hwc_display_[HWC_DISPLAY_PRIMARY]) { - error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(level); - if (error != 0) { - DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error); - } - } - output_parcel->writeInt32(error); - - return error; -} - -android::status_t HWCSession::GetPanelBrightness(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int error = android::BAD_VALUE; - int ret = error; - - if (hwc_display_[HWC_DISPLAY_PRIMARY]) { - error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(&ret); - if (error != 0) { - ret = error; - DLOGE("Failed to get the panel brightness. Error = %d", error); - } - } - output_parcel->writeInt32(ret); - - return error; -} - -android::status_t HWCSession::ControlPartialUpdate(const android::Parcel *input_parcel, - android::Parcel *out) { - DisplayError error = kErrorNone; - int ret = 0; - uint32_t disp_id = UINT32(input_parcel->readInt32()); - uint32_t enable = UINT32(input_parcel->readInt32()); - - if (disp_id != HWC_DISPLAY_PRIMARY) { - DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id); - ret = -EINVAL; - out->writeInt32(ret); - return ret; - } - - if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { - DLOGE("primary display object is not instantiated"); - ret = -EINVAL; - out->writeInt32(ret); - return ret; - } - - uint32_t pending = 0; - error = hwc_display_[HWC_DISPLAY_PRIMARY]->ControlPartialUpdate(enable, &pending); - - if (error == kErrorNone) { - if (!pending) { - out->writeInt32(ret); - return ret; - } - } else if (error == kErrorNotSupported) { - out->writeInt32(ret); - return ret; - } else { - ret = -EINVAL; - out->writeInt32(ret); - return ret; - } - - // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future. - callbacks_.Refresh(HWC_DISPLAY_PRIMARY); - - // Wait until partial update control is complete - ret = locker_.WaitFinite(kPartialUpdateControlTimeoutMs); - - out->writeInt32(ret); - - return ret; -} - -android::status_t HWCSession::HandleSetActiveDisplayConfig(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int config = input_parcel->readInt32(); - int dpy = input_parcel->readInt32(); - int error = android::BAD_VALUE; - - if (dpy > HWC_DISPLAY_VIRTUAL) { - return android::BAD_VALUE; - } - - if (hwc_display_[dpy]) { - error = hwc_display_[dpy]->SetActiveDisplayConfig(config); - if (error == 0) { - callbacks_.Refresh(0); - } - } - - return error; -} - -android::status_t HWCSession::HandleGetActiveDisplayConfig(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int dpy = input_parcel->readInt32(); - int error = android::BAD_VALUE; - - if (dpy > HWC_DISPLAY_VIRTUAL) { - return android::BAD_VALUE; - } - - if (hwc_display_[dpy]) { - uint32_t config = 0; - error = hwc_display_[dpy]->GetActiveDisplayConfig(&config); - if (error == 0) { - output_parcel->writeInt32(INT(config)); - } - } - - return error; -} - -android::status_t HWCSession::HandleGetDisplayConfigCount(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int dpy = input_parcel->readInt32(); - int error = android::BAD_VALUE; - - if (dpy > HWC_DISPLAY_VIRTUAL) { - return android::BAD_VALUE; - } - - uint32_t count = 0; - if (hwc_display_[dpy]) { - error = hwc_display_[dpy]->GetDisplayConfigCount(&count); - if (error == 0) { - output_parcel->writeInt32(INT(count)); - } - } - - return error; -} - android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel, android::Parcel *output_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + int config = input_parcel->readInt32(); int dpy = input_parcel->readInt32(); int error = android::BAD_VALUE; @@ -1070,44 +949,24 @@ android::status_t HWCSession::HandleGetDisplayAttributesForConfig(const android: return error; } -android::status_t HWCSession::SetSecondaryDisplayStatus(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int ret = -EINVAL; - - uint32_t display_id = UINT32(input_parcel->readInt32()); - uint32_t display_status = UINT32(input_parcel->readInt32()); - - DLOGI("Display = %d, Status = %d", display_id, display_status); - - if (display_id >= HWC_NUM_DISPLAY_TYPES) { - DLOGE("Invalid display_id"); - } else if (display_id == HWC_DISPLAY_PRIMARY) { - DLOGE("Not supported for this display"); - } else if (!hwc_display_[display_id]) { - DLOGW("Display is not connected"); - } else { - ret = hwc_display_[display_id]->SetDisplayStatus(display_status); - } - - output_parcel->writeInt32(ret); - - return ret; -} - android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + uint32_t operation = UINT32(input_parcel->readInt32()); + HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY]; + switch (operation) { case qdutils::DISABLE_METADATA_DYN_REFRESH_RATE: - return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( - HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false); + return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false); + case qdutils::ENABLE_METADATA_DYN_REFRESH_RATE: - return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( - HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true); + return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true); + case qdutils::SET_BINDER_DYN_REFRESH_RATE: { uint32_t refresh_rate = UINT32(input_parcel->readInt32()); - return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform( - HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate); + return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refresh_rate); } + default: DLOGW("Invalid operation %d", operation); return -EINVAL; @@ -1117,11 +976,15 @@ android::status_t HWCSession::ConfigureRefreshRate(const android::Parcel *input_ } android::status_t HWCSession::SetDisplayMode(const android::Parcel *input_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + uint32_t mode = UINT32(input_parcel->readInt32()); return hwc_display_[HWC_DISPLAY_PRIMARY]->Perform(HWCDisplayPrimary::SET_DISPLAY_MODE, mode); } android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + DisplayError error = kErrorNone; std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); uint32_t max_mixer_stages = UINT32(input_parcel->readInt32()); @@ -1156,42 +1019,9 @@ android::status_t HWCSession::SetMaxMixerStages(const android::Parcel *input_par return 0; } -android::status_t HWCSession::SetDynamicBWForCamera(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - DisplayError error = kErrorNone; - uint32_t camera_status = UINT32(input_parcel->readInt32()); - HWBwModes mode = camera_status > 0 ? kBwCamera : kBwDefault; - - // trigger invalidate to apply new bw caps. - callbacks_.Refresh(HWC_DISPLAY_PRIMARY); - - error = core_intf_->SetMaxBandwidthMode(mode); - if (error != kErrorNone) { - return -EINVAL; - } - - new_bw_mode_ = true; - need_invalidate_ = true; - - return 0; -} - -android::status_t HWCSession::GetBWTransactionStatus(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - bool state = true; - - if (hwc_display_[HWC_DISPLAY_PRIMARY]) { - if (sync_wait(bw_mode_release_fd_, 0) < 0) { - DLOGI("bw_transaction_release_fd is not yet signalled: err= %s", strerror(errno)); - state = false; - } - output_parcel->writeInt32(state); - } - - return 0; -} - void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + uint32_t frame_dump_count = UINT32(input_parcel->readInt32()); std::bitset<32> bit_mask_display_type = UINT32(input_parcel->readInt32()); uint32_t bit_mask_layer_type = UINT32(input_parcel->readInt32()); @@ -1216,6 +1046,8 @@ void HWCSession::SetFrameDumpConfig(const android::Parcel *input_parcel) { } android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + DisplayError error = kErrorNone; uint32_t dpy = UINT32(input_parcel->readInt32()); @@ -1241,6 +1073,8 @@ android::status_t HWCSession::SetMixerResolution(const android::Parcel *input_pa } android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + auto display = static_cast(input_parcel->readInt32()); auto mode = static_cast(input_parcel->readInt32()); auto device = static_cast(this); @@ -1261,6 +1095,8 @@ android::status_t HWCSession::SetColorModeById(const android::Parcel *input_parc } void HWCSession::DynamicDebug(const android::Parcel *input_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + int type = input_parcel->readInt32(); bool enable = (input_parcel->readInt32() > 0); DLOGI("type = %d enable = %d", type, enable); @@ -1301,6 +1137,8 @@ void HWCSession::DynamicDebug(const android::Parcel *input_parcel) { android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel, android::Parcel *output_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + int ret = 0; int32_t *brightness_value = NULL; uint32_t display_id(0); @@ -1392,29 +1230,6 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel return (ret ? -EINVAL : 0); } -android::status_t HWCSession::OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel, - android::Parcel *output_parcel) { - int ret = -EINVAL; - uint32_t display_id = UINT32(input_parcel->readInt32()); - uint32_t min_enc_level = UINT32(input_parcel->readInt32()); - - DLOGI("Display %d", display_id); - - if (display_id >= HWC_NUM_DISPLAY_TYPES) { - DLOGE("Invalid display_id"); - } else if (display_id != HWC_DISPLAY_EXTERNAL) { - DLOGE("Not supported for display"); - } else if (!hwc_display_[display_id]) { - DLOGW("Display is not connected"); - } else { - ret = hwc_display_[display_id]->OnMinHdcpEncryptionLevelChange(min_enc_level); - } - - output_parcel->writeInt32(ret); - - return ret; -} - void *HWCSession::HWCUeventThread(void *context) { if (context) { return reinterpret_cast(context)->HWCUeventThreadHandler(); @@ -1627,6 +1442,8 @@ int HWCSession::GetVsyncPeriod(int disp) { android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel, android::Parcel *output_parcel) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + int dpy = input_parcel->readInt32(); if (dpy < HWC_DISPLAY_PRIMARY || dpy > HWC_DISPLAY_VIRTUAL) { diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h index c4c38a59..be4494ee 100644 --- a/sdm/libs/hwc2/hwc_session.h +++ b/sdm/libs/hwc2/hwc_session.h @@ -20,6 +20,7 @@ #ifndef __HWC_SESSION_H__ #define __HWC_SESSION_H__ +#include #include #include @@ -34,7 +35,10 @@ namespace sdm { -class HWCSession : hwc2_device_t, public qClient::BnQClient { +using ::vendor::display::config::V1_0::IDisplayConfig; +using ::android::hardware::Return; + +class HWCSession : hwc2_device_t, public IDisplayConfig, public qClient::BnQClient { public: struct HWCModuleMethods : public hw_module_methods_t { HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; } @@ -125,6 +129,44 @@ class HWCSession : hwc2_device_t, public qClient::BnQClient { int32_t ConnectDisplay(int disp); int DisconnectDisplay(int disp); int GetVsyncPeriod(int disp); + int32_t GetConfigCount(int disp_id, uint32_t *count); + int32_t GetActiveConfigIndex(int disp_id, uint32_t *config); + int32_t SetActiveConfigIndex(int disp_id, uint32_t config); + int32_t ControlPartialUpdate(int dpy, bool enable); + int32_t DisplayBWTransactionPending(bool *status); + int32_t SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status); + int32_t GetPanelBrightness(int *level); + int32_t MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level); + + // service methods + void StartServices(); + + // Methods from ::android::hardware::display::config::V1_0::IDisplayConfig follow. + Return isDisplayConnected(IDisplayConfig::DisplayType dpy, + isDisplayConnected_cb _hidl_cb) override; + Return setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy, + IDisplayConfig::DisplayExternalStatus status) override; + Return configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op, + uint32_t refreshRate) override; + Return getConfigCount(IDisplayConfig::DisplayType dpy, + getConfigCount_cb _hidl_cb) override; + Return getActiveConfig(IDisplayConfig::DisplayType dpy, + getActiveConfig_cb _hidl_cb) override; + Return setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) override; + Return getDisplayAttributes(uint32_t configIndex, IDisplayConfig::DisplayType dpy, + getDisplayAttributes_cb _hidl_cb) override; + Return setPanelBrightness(uint32_t level) override; + Return getPanelBrightness(getPanelBrightness_cb _hidl_cb) override; + Return minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy, + uint32_t min_enc_level) override; + Return refreshScreen() override; + Return controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) override; + Return toggleScreenUpdate(bool on) override; + Return setIdleTimeout(uint32_t value) override; + Return getHDRCapabilities(IDisplayConfig::DisplayType dpy, + getHDRCapabilities_cb _hidl_cb) override; + Return setCameraLaunchStatus(uint32_t on) override; + Return displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) override; // QClient methods virtual android::status_t notifyCallback(uint32_t command, const android::Parcel *input_parcel, @@ -133,38 +175,14 @@ class HWCSession : hwc2_device_t, public qClient::BnQClient { void SetFrameDumpConfig(const android::Parcel *input_parcel); android::status_t SetMaxMixerStages(const android::Parcel *input_parcel); android::status_t SetDisplayMode(const android::Parcel *input_parcel); - android::status_t SetSecondaryDisplayStatus(const android::Parcel *input_parcel, - android::Parcel *output_parcel); - android::status_t ToggleScreenUpdates(const android::Parcel *input_parcel, - android::Parcel *output_parcel); android::status_t ConfigureRefreshRate(const android::Parcel *input_parcel); android::status_t QdcmCMDHandler(const android::Parcel *input_parcel, android::Parcel *output_parcel); - android::status_t ControlPartialUpdate(const android::Parcel *input_parcel, android::Parcel *out); - android::status_t OnMinHdcpEncryptionLevelChange(const android::Parcel *input_parcel, - android::Parcel *output_parcel); - android::status_t SetPanelBrightness(const android::Parcel *input_parcel, - android::Parcel *output_parcel); - android::status_t GetPanelBrightness(const android::Parcel *input_parcel, - android::Parcel *output_parcel); - // These functions return the actual display config info as opposed to FB - android::status_t HandleSetActiveDisplayConfig(const android::Parcel *input_parcel, - android::Parcel *output_parcel); - android::status_t HandleGetActiveDisplayConfig(const android::Parcel *input_parcel, - android::Parcel *output_parcel); - android::status_t HandleGetDisplayConfigCount(const android::Parcel *input_parcel, - android::Parcel *output_parcel); android::status_t HandleGetDisplayAttributesForConfig(const android::Parcel *input_parcel, android::Parcel *output_parcel); android::status_t GetVisibleDisplayRect(const android::Parcel *input_parcel, android::Parcel *output_parcel); - - android::status_t SetDynamicBWForCamera(const android::Parcel *input_parcel, - android::Parcel *output_parcel); - android::status_t GetBWTransactionStatus(const android::Parcel *input_parcel, - android::Parcel *output_parcel); android::status_t SetMixerResolution(const android::Parcel *input_parcel); - android::status_t SetColorModeOverride(const android::Parcel *input_parcel); android::status_t SetColorModeById(const android::Parcel *input_parcel); diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp new file mode 100644 index 00000000..4b5374f0 --- /dev/null +++ b/sdm/libs/hwc2/hwc_session_services.cpp @@ -0,0 +1,483 @@ +/* +* Copyright (c) 2017, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation. nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include + +#include "hwc_buffer_sync_handler.h" +#include "hwc_session.h" + +#define __CLASS__ "HWCSession" + +namespace sdm { + +using ::android::hardware::Void; + +void HWCSession::StartServices() { + status_t status = IDisplayConfig::registerAsService(); + if (status != OK) { + DLOGW("Could not register IDisplayConfig as service (%d).", status); + } else { + DLOGI("IDisplayConfig service registration completed."); + } +} + +int MapDisplayType(IDisplayConfig::DisplayType dpy) { + switch (dpy) { + case IDisplayConfig::DisplayType::DISPLAY_PRIMARY: + return HWC_DISPLAY_PRIMARY; + + case IDisplayConfig::DisplayType::DISPLAY_EXTERNAL: + return HWC_DISPLAY_EXTERNAL; + + case IDisplayConfig::DisplayType::DISPLAY_VIRTUAL: + return HWC_DISPLAY_VIRTUAL; + + default: + break; + } + + return -EINVAL; +} + +HWCDisplay::DisplayStatus MapExternalStatus(IDisplayConfig::DisplayExternalStatus status) { + switch (status) { + case IDisplayConfig::DisplayExternalStatus::EXTERNAL_OFFLINE: + return HWCDisplay::kDisplayStatusOffline; + + case IDisplayConfig::DisplayExternalStatus::EXTERNAL_ONLINE: + return HWCDisplay::kDisplayStatusOnline; + + case IDisplayConfig::DisplayExternalStatus::EXTERNAL_PAUSE: + return HWCDisplay::kDisplayStatusPause; + + case IDisplayConfig::DisplayExternalStatus::EXTERNAL_RESUME: + return HWCDisplay::kDisplayStatusResume; + + default: + break; + } + + return HWCDisplay::kDisplayStatusInvalid; +} + +// Methods from ::vendor::hardware::display::config::V1_0::IDisplayConfig follow. +Return HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy, + isDisplayConnected_cb _hidl_cb) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + int32_t error = -EINVAL; + bool connected = false; + + int disp_id = MapDisplayType(dpy); + if (disp_id >= 0) { + connected = hwc_display_[disp_id]; + error = 0; + } + + _hidl_cb(error, connected); + + return Void(); +} + +int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + if (disp_id < 0) { + return -EINVAL; + } + + DLOGI("Display = %d, Status = %d", disp_id, status); + + if (disp_id == HWC_DISPLAY_PRIMARY) { + DLOGE("Not supported for this display"); + } else if (!hwc_display_[disp_id]) { + DLOGW("Display is not connected"); + } else { + return hwc_display_[disp_id]->SetDisplayStatus(status); + } + + return -EINVAL; +} + +Return HWCSession::setSecondayDisplayStatus(IDisplayConfig::DisplayType dpy, + IDisplayConfig::DisplayExternalStatus status) { + return SetSecondaryDisplayStatus(MapDisplayType(dpy), MapExternalStatus(status)); +} + +Return HWCSession::configureDynRefeshRate(IDisplayConfig::DisplayDynRefreshRateOp op, + uint32_t refreshRate) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY]; + + switch (op) { + case IDisplayConfig::DisplayDynRefreshRateOp::DISABLE_METADATA_DYN_REFRESH_RATE: + return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, false); + + case IDisplayConfig::DisplayDynRefreshRateOp::ENABLE_METADATA_DYN_REFRESH_RATE: + return hwc_display->Perform(HWCDisplayPrimary::SET_METADATA_DYN_REFRESH_RATE, true); + + case IDisplayConfig::DisplayDynRefreshRateOp::SET_BINDER_DYN_REFRESH_RATE: + return hwc_display->Perform(HWCDisplayPrimary::SET_BINDER_DYN_REFRESH_RATE, refreshRate); + + default: + DLOGW("Invalid operation %d", op); + return -EINVAL; + } + + return 0; +} + +int32_t HWCSession::GetConfigCount(int disp_id, uint32_t *count) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + if (disp_id >= 0 && hwc_display_[disp_id]) { + return hwc_display_[disp_id]->GetDisplayConfigCount(count); + } + + return -EINVAL; +} + +Return HWCSession::getConfigCount(IDisplayConfig::DisplayType dpy, + getConfigCount_cb _hidl_cb) { + uint32_t count = 0; + int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &count); + + _hidl_cb(error, count); + + return Void(); +} + +int32_t HWCSession::GetActiveConfigIndex(int disp_id, uint32_t *config) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + if (disp_id >= 0 && hwc_display_[disp_id]) { + return hwc_display_[disp_id]->GetActiveDisplayConfig(config); + } + + return -EINVAL; +} + +Return HWCSession::getActiveConfig(IDisplayConfig::DisplayType dpy, + getActiveConfig_cb _hidl_cb) { + uint32_t config = 0; + int32_t error = GetActiveConfigIndex(MapDisplayType(dpy), &config); + + _hidl_cb(error, config); + + return Void(); +} + +int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + if (disp_id < 0) { + return -EINVAL; + } + + int32_t error = -EINVAL; + if (hwc_display_[disp_id]) { + error = hwc_display_[disp_id]->SetActiveDisplayConfig(config); + if (!error) { + callbacks_.Refresh(0); + } + } + + return error; +} + +Return HWCSession::setActiveConfig(IDisplayConfig::DisplayType dpy, uint32_t config) { + return SetActiveConfigIndex(MapDisplayType(dpy), config); +} + +Return HWCSession::getDisplayAttributes(uint32_t configIndex, + IDisplayConfig::DisplayType dpy, + getDisplayAttributes_cb _hidl_cb) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + int32_t error = -EINVAL; + IDisplayConfig::DisplayAttributes display_attributes = {}; + + int disp_id = MapDisplayType(dpy); + if (disp_id >= 0 && hwc_display_[disp_id]) { + DisplayConfigVariableInfo hwc_display_attributes; + error = hwc_display_[disp_id]->GetDisplayAttributesForConfig(static_cast(configIndex), + &hwc_display_attributes); + if (!error) { + display_attributes.vsyncPeriod = hwc_display_attributes.vsync_period_ns; + display_attributes.xRes = hwc_display_attributes.x_pixels; + display_attributes.yRes = hwc_display_attributes.y_pixels; + display_attributes.xDpi = hwc_display_attributes.x_dpi; + display_attributes.yDpi = hwc_display_attributes.y_dpi; + display_attributes.panelType = IDisplayConfig::DisplayPortType::DISPLAY_PORT_DEFAULT; + display_attributes.isYuv = hwc_display_attributes.is_yuv; + } + } + + return Void(); +} + +Return HWCSession::setPanelBrightness(uint32_t level) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + int32_t error = -EINVAL; + if (hwc_display_[HWC_DISPLAY_PRIMARY]) { + error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetPanelBrightness(static_cast(level)); + if (error) { + DLOGE("Failed to set the panel brightness = %d. Error = %d", level, error); + } + } + + return error; +} + +int32_t HWCSession::GetPanelBrightness(int *level) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + int32_t error = -EINVAL; + + if (hwc_display_[HWC_DISPLAY_PRIMARY]) { + error = hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelBrightness(level); + if (error) { + DLOGE("Failed to get the panel brightness. Error = %d", error); + } + } + + return error; +} + +Return HWCSession::getPanelBrightness(getPanelBrightness_cb _hidl_cb) { + int level = 0; + int32_t error = GetPanelBrightness(&level); + + _hidl_cb(error, static_cast(level)); + + return Void(); +} + +int32_t HWCSession::MinHdcpEncryptionLevelChanged(int disp_id, uint32_t min_enc_level) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + DLOGI("Display %d", disp_id); + + if (disp_id < 0) { + return -EINVAL; + } + + if (disp_id != HWC_DISPLAY_EXTERNAL) { + DLOGE("Not supported for display"); + } else if (!hwc_display_[disp_id]) { + DLOGW("Display is not connected"); + } else { + return hwc_display_[disp_id]->OnMinHdcpEncryptionLevelChange(min_enc_level); + } + + return -EINVAL; +} + +Return HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::DisplayType dpy, + uint32_t min_enc_level) { + return MinHdcpEncryptionLevelChanged(MapDisplayType(dpy), min_enc_level); +} + +Return HWCSession::refreshScreen() { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + callbacks_.Refresh(HWC_DISPLAY_PRIMARY); + + return 0; +} + +int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + if (disp_id < 0) { + return -EINVAL; + } + + if (disp_id != HWC_DISPLAY_PRIMARY) { + DLOGW("CONTROL_PARTIAL_UPDATE is not applicable for display = %d", disp_id); + return -EINVAL; + } + + HWCDisplay *hwc_display = hwc_display_[HWC_DISPLAY_PRIMARY]; + if (!hwc_display) { + DLOGE("primary display object is not instantiated"); + return -EINVAL; + } + + uint32_t pending = 0; + DisplayError hwc_error = hwc_display->ControlPartialUpdate(enable, &pending); + + if (hwc_error == kErrorNone) { + if (!pending) { + return 0; + } + } else if (hwc_error == kErrorNotSupported) { + return 0; + } else { + return -EINVAL; + } + + // Todo(user): Unlock it before sending events to client. It may cause deadlocks in future. + callbacks_.Refresh(HWC_DISPLAY_PRIMARY); + + // Wait until partial update control is complete + int32_t error = locker_.WaitFinite(kPartialUpdateControlTimeoutMs); + + return error; +} + +Return HWCSession::controlPartialUpdate(IDisplayConfig::DisplayType dpy, bool enable) { + return ControlPartialUpdate(MapDisplayType(dpy), enable); +} + +Return HWCSession::toggleScreenUpdate(bool on) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + int32_t error = -EINVAL; + if (hwc_display_[HWC_DISPLAY_PRIMARY]) { + error = hwc_display_[HWC_DISPLAY_PRIMARY]->ToggleScreenUpdates(on); + if (error) { + DLOGE("Failed to toggle screen updates = %d. Error = %d", on, error); + } + } + + return error; +} + +Return HWCSession::setIdleTimeout(uint32_t value) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + if (hwc_display_[HWC_DISPLAY_PRIMARY]) { + hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(value); + return 0; + } + + return -EINVAL; +} + +Return HWCSession::getHDRCapabilities(IDisplayConfig::DisplayType dpy, + getHDRCapabilities_cb _hidl_cb) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + int32_t error = -EINVAL; + IDisplayConfig::DisplayHDRCapabilities hdr_caps = {}; + + do { + int disp_id = MapDisplayType(dpy); + if (disp_id < 0) { + DLOGE("Invalid display id = %d", disp_id); + break; + } + + HWCDisplay *hwc_display = hwc_display_[disp_id]; + if (!hwc_display) { + DLOGE("Display = %d is not connected.", disp_id); + break; + } + + // query number of hdr types + uint32_t out_num_types = 0; + if (hwc_display->GetHdrCapabilities(&out_num_types, nullptr, nullptr, nullptr, nullptr) + != HWC2::Error::None) { + break; + } + + if (!out_num_types) { + error = 0; + break; + } + + // query hdr caps + hdr_caps.supportedHdrTypes.resize(out_num_types); + + float out_max_luminance = 0.0f; + float out_max_average_luminance = 0.0f; + float out_min_luminance = 0.0f; + if (hwc_display->GetHdrCapabilities(&out_num_types, hdr_caps.supportedHdrTypes.data(), + &out_max_luminance, &out_max_average_luminance, + &out_min_luminance) + == HWC2::Error::None) { + error = 0; + } + } while (false); + + _hidl_cb(error, hdr_caps); + + return Void(); +} + +Return HWCSession::setCameraLaunchStatus(uint32_t on) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + HWBwModes mode = on > 0 ? kBwCamera : kBwDefault; + + // trigger invalidate to apply new bw caps. + callbacks_.Refresh(HWC_DISPLAY_PRIMARY); + + if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) { + return -EINVAL; + } + + new_bw_mode_ = true; + need_invalidate_ = true; + + return 0; +} + +int32_t HWCSession::DisplayBWTransactionPending(bool *status) { + SEQUENCE_WAIT_SCOPE_LOCK(locker_); + + if (hwc_display_[HWC_DISPLAY_PRIMARY]) { + if (sync_wait(bw_mode_release_fd_, 0) < 0) { + DLOGI("bw_transaction_release_fd is not yet signaled: err= %s", strerror(errno)); + *status = false; + } + + return 0; + } + + return -EINVAL; +} + +Return HWCSession::displayBWTransactionPending(displayBWTransactionPending_cb _hidl_cb) { + bool status = true; + + int32_t error = DisplayBWTransactionPending(&status); + + _hidl_cb(error, status); + + return Void(); +} + +} // namespace sdm -- cgit v1.2.3