diff options
-rw-r--r-- | config/display-product-system.mk | 19 | ||||
-rw-r--r-- | gralloc/Android.bp | 27 | ||||
-rw-r--r-- | gralloc/QtiGralloc.cpp | 469 | ||||
-rw-r--r-- | libqdmetadata/Android.bp | 26 | ||||
-rw-r--r-- | libqdmetadata/Makefile.am | 16 | ||||
-rwxr-xr-x | libqdmetadata/qdMetaData.cpp | 642 | ||||
-rw-r--r-- | libqdmetadata/qd_utils.cpp | 279 | ||||
-rw-r--r-- | services/config/src/Android.bp | 29 | ||||
-rw-r--r-- | services/config/src/client_impl.cpp | 1066 | ||||
-rw-r--r-- | services/config/src/client_impl.h | 139 | ||||
-rw-r--r-- | services/config/src/client_interface.cpp | 65 | ||||
-rw-r--r-- | services/config/src/device_impl.cpp | 1040 | ||||
-rw-r--r-- | services/config/src/device_impl.h | 153 | ||||
-rw-r--r-- | services/config/src/device_interface.cpp | 42 | ||||
-rw-r--r-- | services/config/src/opcode_types.h | 93 |
15 files changed, 4104 insertions, 1 deletions
diff --git a/config/display-product-system.mk b/config/display-product-system.mk index 55f3a429..19e3fe6c 100644 --- a/config/display-product-system.mk +++ b/config/display-product-system.mk @@ -1,9 +1,19 @@ -PRODUCT_PACKAGES += vendor.display.config@1.0 \ +PRODUCT_PACKAGES += libdisplayconfig \ + libqdMetaData \ + libqdMetaData.system \ + libgralloc.qti \ + libdrm \ + vendor.display.config@1.0 \ vendor.display.config@1.1 \ vendor.display.config@1.2 \ vendor.display.config@1.3 \ vendor.display.config@1.4 \ vendor.display.config@1.5 \ + libsmomo.qti \ + liblayerext.qti \ + libsmomoconfig.qti \ + libcomposerextn.qti \ + libdisplayconfig.qti \ vendor.qti.hardware.display.config-V1-ndk_platform \ vendor.qti.hardware.display.config-V2-ndk_platform \ vendor.qti.hardware.display.config-V3-ndk_platform \ @@ -11,8 +21,15 @@ PRODUCT_PACKAGES += vendor.display.config@1.0 \ vendor.qti.hardware.display.config-V5-ndk_platform \ vendor.qti.hardware.display.config-V6-ndk_platform +SOONG_CONFIG_NAMESPACES += qtidisplaycommonsys SOONG_CONFIG_NAMESPACES += qtiunifeddraw # Soong Keys +SOONG_CONFIG_qtidisplaycommonsys := displayconfig_enabled SOONG_CONFIG_qtiunifeddraw := qtiunifeddraw_enabled # Soong Values +SOONG_CONFIG_qtidisplaycommonsys_displayconfig_enabled := false SOONG_CONFIG_qtiunifeddraw_qtiunifeddraw_enabled := true + +ifeq ($(call is-vendor-board-platform,QCOM),true) + SOONG_CONFIG_qtidisplaycommonsys_displayconfig_enabled := true +endif diff --git a/gralloc/Android.bp b/gralloc/Android.bp new file mode 100644 index 00000000..b256e522 --- /dev/null +++ b/gralloc/Android.bp @@ -0,0 +1,27 @@ +cc_library_shared { + name: "libgralloc.qti", + vendor_available: true, + system_ext_specific: true, + cflags: [ + "-Wno-sign-conversion", + "-DLOG_TAG=\"qtigralloc\"", + ], + export_include_dirs: ["."], + header_abi_checker: { + enabled: true, + }, + shared_libs: [ + "liblog", + "libcutils", + "libutils", + "libgralloctypes", + "libhidlbase", + "libhardware", + "android.hardware.graphics.mapper@4.0", + ], + + srcs: ["QtiGralloc.cpp"], + + header_libs: ["display_intf_headers"], +} + diff --git a/gralloc/QtiGralloc.cpp b/gralloc/QtiGralloc.cpp new file mode 100644 index 00000000..348e097a --- /dev/null +++ b/gralloc/QtiGralloc.cpp @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2020, 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 "QtiGralloc.h" + +#include <log/log.h> +namespace qtigralloc { + +using android::hardware::graphics::mapper::V4_0::IMapper; + +static sp<IMapper> getInstance() { + static sp<IMapper> mapper = IMapper::getService(); + return mapper; +} + +Error decodeMetadataState(hidl_vec<uint8_t> &in, bool *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(out, in.data(), METADATA_SET_SIZE); + return Error::NONE; +} + +Error encodeMetadataState(bool *in, hidl_vec<uint8_t> *out) { + if (!in || !out) { + return Error::BAD_VALUE; + } + out->resize(sizeof(bool) * METADATA_SET_SIZE); + memcpy(out->data(), in, sizeof(bool) * METADATA_SET_SIZE); + return Error::NONE; +} + +Error decodeColorMetadata(hidl_vec<uint8_t> &in, ColorMetaData *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(out, in.data(), sizeof(ColorMetaData)); + return Error::NONE; +} + +Error encodeColorMetadata(ColorMetaData &in, hidl_vec<uint8_t> *out) { + if (!out) { + return Error::BAD_VALUE; + } + out->resize(sizeof(ColorMetaData)); + memcpy(out->data(), &in, sizeof(ColorMetaData)); + return Error::NONE; +} + +// decode the raw graphics metadata from bytestream and store it in 'data' member of +// GraphicsMetadata struct during mapper->set call, 'size' member is unused. +Error decodeGraphicsMetadata(hidl_vec<uint8_t> &in, GraphicsMetadata *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(&(out->data), in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES); + return Error::NONE; +} + +// encode only 'data' member of GraphicsMetadata struct for retrieval of +// graphics metadata during mapper->get call +Error encodeGraphicsMetadata(GraphicsMetadata &in, hidl_vec<uint8_t> *out) { + if (!out) { + return Error::BAD_VALUE; + } + out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES); + memcpy(out->data(), &(in.data), GRAPHICS_METADATA_SIZE_IN_BYTES); + return Error::NONE; +} + +// decode the raw graphics metadata from bytestream before presenting it to caller +Error decodeGraphicsMetadataRaw(hidl_vec<uint8_t> &in, void *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(out, in.data(), GRAPHICS_METADATA_SIZE_IN_BYTES); + return Error::NONE; +} + +// encode the raw graphics metadata in bytestream before calling mapper->set +Error encodeGraphicsMetadataRaw(void *in, hidl_vec<uint8_t> *out) { + if (!in || !out) { + return Error::BAD_VALUE; + } + out->resize(GRAPHICS_METADATA_SIZE_IN_BYTES); + memcpy(out->data(), in, GRAPHICS_METADATA_SIZE_IN_BYTES); + return Error::NONE; +} + +Error decodeUBWCStats(hidl_vec<uint8_t> &in, UBWCStats *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(out, in.data(), UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats)); + return Error::NONE; +} + +Error encodeUBWCStats(UBWCStats *in, hidl_vec<uint8_t> *out) { + if (!in || !out) { + return Error::BAD_VALUE; + } + out->resize(UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats)); + memcpy(out->data(), in, UBWC_STATS_ARRAY_SIZE * sizeof(UBWCStats)); + return Error::NONE; +} + +Error decodeCVPMetadata(hidl_vec<uint8_t> &in, CVPMetadata *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(out, in.data(), sizeof(CVPMetadata)); + return Error::NONE; +} + +Error encodeCVPMetadata(CVPMetadata &in, hidl_vec<uint8_t> *out) { + if (!out) { + return Error::BAD_VALUE; + } + out->resize(sizeof(CVPMetadata)); + memcpy(out->data(), &in, sizeof(CVPMetadata)); + return Error::NONE; +} + +Error decodeVideoHistogramMetadata(hidl_vec<uint8_t> &in, VideoHistogramMetadata *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(out, in.data(), sizeof(VideoHistogramMetadata)); + return Error::NONE; +} + +Error encodeVideoHistogramMetadata(VideoHistogramMetadata &in, hidl_vec<uint8_t> *out) { + if (!out) { + return Error::BAD_VALUE; + } + out->resize(sizeof(VideoHistogramMetadata)); + memcpy(out->data(), &in, sizeof(VideoHistogramMetadata)); + return Error::NONE; +} + +Error decodeVideoTimestampInfo(hidl_vec<uint8_t> &in, VideoTimestampInfo *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + memcpy(out, in.data(), sizeof(VideoTimestampInfo)); + return Error::NONE; +} + +Error encodeVideoTimestampInfo(VideoTimestampInfo &in, hidl_vec<uint8_t> *out) { + if (!out) { + return Error::BAD_VALUE; + } + out->resize(sizeof(VideoTimestampInfo)); + memcpy(out->data(), &in, sizeof(VideoTimestampInfo)); + return Error::NONE; +} + +Error decodeYUVPlaneInfoMetadata(hidl_vec<uint8_t> &in, qti_ycbcr *out) { + if (!in.size() || !out) { + return Error::BAD_VALUE; + } + qti_ycbcr *p = reinterpret_cast<qti_ycbcr *>(in.data()); + memcpy(out, in.data(), (YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr))); + return Error::NONE; +} + +Error encodeYUVPlaneInfoMetadata(qti_ycbcr *in, hidl_vec<uint8_t> *out) { + if (!out) { + return Error::BAD_VALUE; + } + out->resize(YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr)); + memcpy(out->data(), in, YCBCR_LAYOUT_ARRAY_SIZE * sizeof(qti_ycbcr)); + return Error::NONE; +} + +MetadataType getMetadataType(uint32_t in) { + switch (in) { + case QTI_VT_TIMESTAMP: + return MetadataType_VTTimestamp; + case QTI_VIDEO_PERF_MODE: + return MetadataType_VideoPerfMode; + case QTI_LINEAR_FORMAT: + return MetadataType_LinearFormat; + case QTI_SINGLE_BUFFER_MODE: + return MetadataType_SingleBufferMode; + case QTI_PP_PARAM_INTERLACED: + return MetadataType_PPParamInterlaced; + case QTI_MAP_SECURE_BUFFER: + return MetadataType_MapSecureBuffer; + case QTI_COLOR_METADATA: + return MetadataType_ColorMetadata; + case QTI_GRAPHICS_METADATA: + return MetadataType_GraphicsMetadata; + case QTI_UBWC_CR_STATS_INFO: + return MetadataType_UBWCCRStatsInfo; + case QTI_REFRESH_RATE: + return MetadataType_RefreshRate; + case QTI_CVP_METADATA: + return MetadataType_CVPMetadata; + case QTI_VIDEO_HISTOGRAM_STATS: + return MetadataType_VideoHistogramStats; + case QTI_VIDEO_TS_INFO: + return MetadataType_VideoTimestampInfo; + case QTI_FD: + return MetadataType_FD; + case QTI_PRIVATE_FLAGS: + return MetadataType_PrivateFlags; + case QTI_ALIGNED_WIDTH_IN_PIXELS: + return MetadataType_AlignedWidthInPixels; + case QTI_ALIGNED_HEIGHT_IN_PIXELS: + return MetadataType_AlignedHeightInPixels; + case QTI_STANDARD_METADATA_STATUS: + return MetadataType_StandardMetadataStatus; + case QTI_VENDOR_METADATA_STATUS: + return MetadataType_VendorMetadataStatus; + case QTI_BUFFER_TYPE: + return MetadataType_BufferType; + case QTI_CUSTOM_DIMENSIONS_STRIDE: + return MetadataType_CustomDimensionsStride; + case QTI_CUSTOM_DIMENSIONS_HEIGHT: + return MetadataType_CustomDimensionsHeight; + case QTI_RGB_DATA_ADDRESS: + return MetadataType_RgbDataAddress; + case QTI_COLORSPACE: + return MetadataType_ColorSpace; + case QTI_YUV_PLANE_INFO: + return MetadataType_YuvPlaneInfo; + default: + return MetadataType_Invalid; + } +} + +Error get(void *buffer, uint32_t type, void *param) { + hidl_vec<uint8_t> bytestream; + sp<IMapper> mapper = getInstance(); + + MetadataType metadata_type = getMetadataType(type); + if (metadata_type == MetadataType_Invalid) { + param = nullptr; + return Error::UNSUPPORTED; + } + + auto err = Error::UNSUPPORTED; + mapper->get(buffer, metadata_type, [&](const auto &tmpError, const auto &tmpByteStream) { + err = tmpError; + bytestream = tmpByteStream; + }); + + if (err != Error::NONE) { + return err; + } + + switch (type) { + case QTI_VT_TIMESTAMP: + err = static_cast<Error>(android::gralloc4::decodeUint64(qtigralloc::MetadataType_VTTimestamp, + bytestream, (uint64_t *)param)); + break; + case QTI_VIDEO_PERF_MODE: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_VideoPerfMode, bytestream, (uint32_t *)param)); + break; + case QTI_LINEAR_FORMAT: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_LinearFormat, bytestream, (uint32_t *)param)); + break; + case QTI_SINGLE_BUFFER_MODE: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_SingleBufferMode, bytestream, (uint32_t *)param)); + break; + case QTI_PP_PARAM_INTERLACED: + err = static_cast<Error>(android::gralloc4::decodeInt32( + qtigralloc::MetadataType_PPParamInterlaced, bytestream, (int32_t *)param)); + break; + case QTI_MAP_SECURE_BUFFER: + err = static_cast<Error>(android::gralloc4::decodeInt32( + qtigralloc::MetadataType_MapSecureBuffer, bytestream, (int32_t *)param)); + break; + case QTI_COLOR_METADATA: + err = decodeColorMetadata(bytestream, (ColorMetaData *)param); + break; + case QTI_GRAPHICS_METADATA: + err = decodeGraphicsMetadataRaw(bytestream, param); + break; + case QTI_UBWC_CR_STATS_INFO: + err = decodeUBWCStats(bytestream, (UBWCStats *)param); + break; + case QTI_REFRESH_RATE: + err = static_cast<Error>(android::gralloc4::decodeFloat(qtigralloc::MetadataType_RefreshRate, + bytestream, (float *)param)); + break; + case QTI_CVP_METADATA: + err = decodeCVPMetadata(bytestream, (CVPMetadata *)param); + break; + case QTI_VIDEO_HISTOGRAM_STATS: + err = decodeVideoHistogramMetadata(bytestream, (VideoHistogramMetadata *)param); + break; + case QTI_VIDEO_TS_INFO: + err = decodeVideoTimestampInfo(bytestream, (VideoTimestampInfo *)param); + break; + case QTI_FD: + err = static_cast<Error>(android::gralloc4::decodeInt32(qtigralloc::MetadataType_FD, + bytestream, (int32_t *)param)); + break; + case QTI_PRIVATE_FLAGS: + err = static_cast<Error>(android::gralloc4::decodeInt32(qtigralloc::MetadataType_PrivateFlags, + bytestream, (int32_t *)param)); + break; + case QTI_ALIGNED_WIDTH_IN_PIXELS: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_AlignedWidthInPixels, bytestream, (uint32_t *)param)); + break; + case QTI_ALIGNED_HEIGHT_IN_PIXELS: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_AlignedHeightInPixels, bytestream, (uint32_t *)param)); + break; + case QTI_STANDARD_METADATA_STATUS: + case QTI_VENDOR_METADATA_STATUS: + err = decodeMetadataState(bytestream, (bool *)param); + break; + case QTI_BUFFER_TYPE: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_BufferType, bytestream, (uint32_t *)param)); + break; + case QTI_CUSTOM_DIMENSIONS_STRIDE: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_CustomDimensionsStride, bytestream, (uint32_t *)param)); + break; + case QTI_CUSTOM_DIMENSIONS_HEIGHT: + err = static_cast<Error>(android::gralloc4::decodeUint32( + qtigralloc::MetadataType_CustomDimensionsHeight, bytestream, (uint32_t *)param)); + break; + case QTI_RGB_DATA_ADDRESS: + err = static_cast<Error>(android::gralloc4::decodeUint64( + qtigralloc::MetadataType_RgbDataAddress, bytestream, (uint64_t *)param)); + break; + case QTI_COLORSPACE: + err = static_cast<Error>(android::gralloc4::decodeUint32(qtigralloc::MetadataType_ColorSpace, + bytestream, (uint32_t *)param)); + break; + case QTI_YUV_PLANE_INFO: + err = decodeYUVPlaneInfoMetadata(bytestream, (qti_ycbcr *)param); + break; + default: + param = nullptr; + return Error::UNSUPPORTED; + } + + return err; +} + +Error set(void *buffer, uint32_t type, void *param) { + hidl_vec<uint8_t> bytestream; + sp<IMapper> mapper = getInstance(); + + Error err = Error::UNSUPPORTED; + MetadataType metadata_type = getMetadataType(type); + if (metadata_type == MetadataType_Invalid) { + return err; + } + + switch (type) { + case QTI_VT_TIMESTAMP: + err = static_cast<Error>(android::gralloc4::encodeUint64(qtigralloc::MetadataType_VTTimestamp, + *(uint64_t *)param, &bytestream)); + break; + case QTI_VIDEO_PERF_MODE: + err = static_cast<Error>(android::gralloc4::encodeUint32( + qtigralloc::MetadataType_VideoPerfMode, *(uint32_t *)param, &bytestream)); + break; + case QTI_LINEAR_FORMAT: + err = static_cast<Error>(android::gralloc4::encodeUint32( + qtigralloc::MetadataType_LinearFormat, *(uint32_t *)param, &bytestream)); + break; + case QTI_SINGLE_BUFFER_MODE: + err = static_cast<Error>(android::gralloc4::encodeUint32( + qtigralloc::MetadataType_SingleBufferMode, *(uint32_t *)param, &bytestream)); + break; + case QTI_PP_PARAM_INTERLACED: + err = static_cast<Error>(android::gralloc4::encodeInt32( + qtigralloc::MetadataType_PPParamInterlaced, *(int32_t *)param, &bytestream)); + break; + case QTI_MAP_SECURE_BUFFER: + err = static_cast<Error>(android::gralloc4::encodeInt32( + qtigralloc::MetadataType_MapSecureBuffer, *(int32_t *)param, &bytestream)); + break; + case QTI_COLOR_METADATA: + err = encodeColorMetadata(*(ColorMetaData *)param, &bytestream); + break; + case QTI_GRAPHICS_METADATA: + err = encodeGraphicsMetadataRaw(param, &bytestream); + break; + case QTI_UBWC_CR_STATS_INFO: + err = encodeUBWCStats((UBWCStats *)param, &bytestream); + break; + case QTI_REFRESH_RATE: + err = static_cast<Error>(android::gralloc4::encodeFloat(qtigralloc::MetadataType_RefreshRate, + *(float *)param, &bytestream)); + break; + case QTI_CVP_METADATA: + err = encodeCVPMetadata(*(CVPMetadata *)param, &bytestream); + break; + case QTI_VIDEO_HISTOGRAM_STATS: + err = encodeVideoHistogramMetadata(*(VideoHistogramMetadata *)param, &bytestream); + break; + case QTI_VIDEO_TS_INFO: + err = encodeVideoTimestampInfo(*(VideoTimestampInfo *)param, &bytestream); + break; + default: + param = nullptr; + return Error::UNSUPPORTED; + } + + if (err != Error::NONE) { + return err; + } + + return mapper->set((void *)buffer, metadata_type, bytestream); +} + +int getMetadataState(void *buffer, uint32_t type) { + bool metadata_set[METADATA_SET_SIZE]; + Error err; + if (IS_VENDOR_METADATA_TYPE(type)) { + err = get(buffer, QTI_VENDOR_METADATA_STATUS, &metadata_set); + } else { + err = get(buffer, QTI_STANDARD_METADATA_STATUS, &metadata_set); + } + + if (err != Error::NONE) { + ALOGE("Unable to get metadata state"); + return -1; + } + + if (IS_VENDOR_METADATA_TYPE(type)) { + return metadata_set[GET_VENDOR_METADATA_STATUS_INDEX(type)]; + } else if (GET_STANDARD_METADATA_STATUS_INDEX(type) < METADATA_SET_SIZE) { + return metadata_set[GET_STANDARD_METADATA_STATUS_INDEX(type)]; + } else { + return -1; + } +} + +} // namespace qtigralloc diff --git a/libqdmetadata/Android.bp b/libqdmetadata/Android.bp new file mode 100644 index 00000000..282fbf69 --- /dev/null +++ b/libqdmetadata/Android.bp @@ -0,0 +1,26 @@ +cc_library_shared { + name: "libqdMetaData", + vendor_available: true, + system_ext_specific: true, + cflags: [ + "-Wno-sign-conversion", + "-DLOG_TAG=\"qdmetadata\"", + "-D__QTI_DISPLAY_GRALLOC__", + ], + shared_libs: [ + "liblog", + "libcutils", + "libutils", + "libhidlbase", + "libgralloc.qti", + "libgralloctypes", + ], + header_libs: ["libhardware_headers", "display_intf_headers"], + srcs: ["qdMetaData.cpp", "qd_utils.cpp"], + export_header_lib_headers: ["display_intf_headers"], + export_include_dirs: ["."], + header_abi_checker: { + enabled: true, + }, +} + diff --git a/libqdmetadata/Makefile.am b/libqdmetadata/Makefile.am new file mode 100644 index 00000000..1fa7e644 --- /dev/null +++ b/libqdmetadata/Makefile.am @@ -0,0 +1,16 @@ +h_sources = qdMetaData.h + +cpp_sources = qdMetaData.cpp + +AM_CPPFLAGS += -D__QTI_NO_GRALLOC4__ + +qdMetaData_includedir = $(pkgincludedir)/display +qdMetaData_include_HEADERS = $(h_sources) + +lib_LTLIBRARIES = libqdMetaData.la +libqdMetaData_la_CC = @CC@ +libqdMetaData_la_SOURCES = $(cpp_sources) +libqdMetaData_la_CFLAGS = $(AM_CFLAGS) -DLOG_TAG=\"DisplayMetaData\" +libqdMetaData_la_CPPFLAGS = $(AM_CPPFLAGS) +libqdMetaData_LDADD = -lcutils -llog +libqdMetaData_la_LDFLAGS = -shared -avoid-version
\ No newline at end of file diff --git a/libqdmetadata/qdMetaData.cpp b/libqdmetadata/qdMetaData.cpp new file mode 100755 index 00000000..228a634c --- /dev/null +++ b/libqdmetadata/qdMetaData.cpp @@ -0,0 +1,642 @@ +/* + * Copyright (c) 2012-2021, 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 "qdMetaData.h" + +#include <QtiGrallocPriv.h> +#include <errno.h> +#include <gralloc_priv.h> +#ifndef __QTI_NO_GRALLOC4__ +#include <gralloctypes/Gralloc4.h> +#endif +#include <log/log.h> +#include <string.h> +#include <sys/mman.h> + +#include <cinttypes> + +static int colorMetaDataToColorSpace(ColorMetaData in, ColorSpace_t *out) { + if (in.colorPrimaries == ColorPrimaries_BT601_6_525 || + in.colorPrimaries == ColorPrimaries_BT601_6_625) { + if (in.range == Range_Full) { + *out = ITU_R_601_FR; + } else { + *out = ITU_R_601; + } + } else if (in.colorPrimaries == ColorPrimaries_BT2020) { + if (in.range == Range_Full) { + *out = ITU_R_2020_FR; + } else { + *out = ITU_R_2020; + } + } else if (in.colorPrimaries == ColorPrimaries_BT709_5) { + if (in.range == Range_Full) { + *out = ITU_R_709_FR; + } else { + *out = ITU_R_709; + } + } else { + ALOGE( + "Cannot convert ColorMetaData to ColorSpace_t. " + "Primaries = %d, Range = %d", + in.colorPrimaries, in.range); + return -1; + } + + return 0; +} + +static int colorSpaceToColorMetadata(ColorSpace_t in, ColorMetaData *out) { + out->transfer = Transfer_sRGB; + switch (in) { + case ITU_R_601: + out->colorPrimaries = ColorPrimaries_BT601_6_525; + out->range = Range_Limited; + break; + case ITU_R_601_FR: + out->colorPrimaries = ColorPrimaries_BT601_6_525; + out->range = Range_Full; + break; + case ITU_R_709: + out->colorPrimaries = ColorPrimaries_BT709_5; + out->range = Range_Limited; + break; + case ITU_R_709_FR: + out->colorPrimaries = ColorPrimaries_BT709_5; + out->range = Range_Full; + break; + case ITU_R_2020: + out->colorPrimaries = ColorPrimaries_BT2020; + out->range = Range_Limited; + break; + case ITU_R_2020_FR: + out->colorPrimaries = ColorPrimaries_BT2020; + out->range = Range_Full; + break; + default: + ALOGE("Cannot convert ColorSpace_t %d to ColorMetaData", in); + return -1; + break; + } + + return 0; +} + +#ifndef __QTI_NO_GRALLOC4__ +static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) { + switch (paramType) { + case SET_VT_TIMESTAMP: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)]; + case COLOR_METADATA: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)]; + case PP_PARAM_INTERLACED: + return metadata + ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)]; + case SET_VIDEO_PERF_MODE: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)]; + case SET_GRAPHICS_METADATA: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)]; + case SET_UBWC_CR_STATS_INFO: + return metadata + ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)]; + case UPDATE_BUFFER_GEOMETRY: + return metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX( + ::android::gralloc4::MetadataType_Crop.value)]; + case UPDATE_REFRESH_RATE: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)]; + case UPDATE_COLOR_SPACE: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)]; + case MAP_SECURE_BUFFER: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)]; + case LINEAR_FORMAT: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)]; + case SET_SINGLE_BUFFER_MODE: + return metadata + ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)]; + case SET_CVP_METADATA: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)]; + case SET_VIDEO_HISTOGRAM_STATS: + return metadata + ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)]; + case SET_VIDEO_TS_INFO: + return metadata + ->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)]; + case GET_S3D_FORMAT: + return metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)]; + default: + ALOGE("paramType %d not supported", paramType); + return false; + } +} + +static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) { + switch (paramType) { + case SET_VT_TIMESTAMP: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VT_TIMESTAMP)] = isSet; + break; + case COLOR_METADATA: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet; + break; + case PP_PARAM_INTERLACED: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_PP_PARAM_INTERLACED)] = + isSet; + break; + case SET_VIDEO_PERF_MODE: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_PERF_MODE)] = isSet; + break; + case SET_GRAPHICS_METADATA: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_GRAPHICS_METADATA)] = + isSet; + break; + case SET_UBWC_CR_STATS_INFO: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_UBWC_CR_STATS_INFO)] = + isSet; + break; + case UPDATE_BUFFER_GEOMETRY: + metadata->isStandardMetadataSet[GET_STANDARD_METADATA_STATUS_INDEX( + ::android::gralloc4::MetadataType_Crop.value)] = isSet; + break; + case UPDATE_REFRESH_RATE: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_REFRESH_RATE)] = isSet; + break; + case UPDATE_COLOR_SPACE: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_COLOR_METADATA)] = isSet; + break; + case MAP_SECURE_BUFFER: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_MAP_SECURE_BUFFER)] = + isSet; + break; + case LINEAR_FORMAT: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_LINEAR_FORMAT)] = isSet; + break; + case SET_SINGLE_BUFFER_MODE: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_SINGLE_BUFFER_MODE)] = + isSet; + break; + case SET_CVP_METADATA: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_CVP_METADATA)] = isSet; + break; + case SET_VIDEO_HISTOGRAM_STATS: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_HISTOGRAM_STATS)] = + isSet; + break; + case SET_VIDEO_TS_INFO: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_VIDEO_TS_INFO)] = + isSet; + break; + case S3D_FORMAT: + metadata->isVendorMetadataSet[GET_VENDOR_METADATA_STATUS_INDEX(QTI_S3D_FORMAT)] = isSet; + break; + default: + ALOGE("paramType %d not supported in Gralloc4", paramType); + } +} +#else +static bool getGralloc4Array(MetaData_t *metadata, int32_t paramType) { + return true; +} + +static void setGralloc4Array(MetaData_t *metadata, int32_t paramType, bool isSet) { +} +#endif + + +unsigned long getMetaDataSize() { + return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t))); +} + +// Cannot add default argument to existing function +unsigned long getMetaDataSizeWithReservedRegion(uint64_t reserved_size) { + return static_cast<unsigned long>(ROUND_UP_PAGESIZE(sizeof(MetaData_t) + reserved_size)); +} + +static int validateAndMap(private_handle_t* handle) { + if (private_handle_t::validate(handle)) { + ALOGE("%s: Private handle is invalid - handle:%p", __func__, handle); + return -1; + } + if (handle->fd_metadata < 0) { + // Metadata cannot be used + return -1; + } + + if (!handle->base_metadata) { + auto size = getMetaDataSize(); + void *base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, + handle->fd_metadata, 0); + if (base == reinterpret_cast<void*>(MAP_FAILED)) { + ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", + __func__, handle, handle->fd_metadata, strerror(errno)); + return -1; + } + handle->base_metadata = (uintptr_t) base; + auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata); + if (metadata->reservedSize) { + auto reserved_size = metadata->reservedSize; + munmap(reinterpret_cast<void *>(handle->base_metadata), getMetaDataSize()); + handle->base_metadata = 0; + size = getMetaDataSizeWithReservedRegion(reserved_size); + void *new_base = + mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, handle->fd_metadata, 0); + if (new_base == reinterpret_cast<void *>(MAP_FAILED)) { + ALOGE("%s: metadata mmap failed - handle:%p fd: %d err: %s", __func__, handle, + handle->fd_metadata, strerror(errno)); + return -1; + } + handle->base_metadata = (uintptr_t)new_base; + } + } + return 0; +} + +static void unmapAndReset(private_handle_t *handle) { + if (private_handle_t::validate(handle) == 0 && handle->base_metadata) { + // If reservedSize is 0, the return value will be the same as getMetaDataSize + auto metadata = reinterpret_cast<MetaData_t *>(handle->base_metadata); + auto size = getMetaDataSizeWithReservedRegion(metadata->reservedSize); + munmap(reinterpret_cast<void *>(handle->base_metadata), size); + handle->base_metadata = 0; + } +} + +int setMetaData(private_handle_t *handle, DispParamType paramType, + void *param) { + auto err = validateAndMap(handle); + if (err != 0) + return err; + return setMetaDataVa(reinterpret_cast<MetaData_t*>(handle->base_metadata), + paramType, param); +} + +int setMetaDataVa(MetaData_t *data, DispParamType paramType, + void *param) { + if (data == nullptr) + return -EINVAL; + // If parameter is NULL reset the specific MetaData Key + if (!param) { + setGralloc4Array(data, paramType, false); + switch (paramType) { + case SET_VIDEO_PERF_MODE: + data->isVideoPerfMode = 0; + break; + case SET_CVP_METADATA: + data->cvpMetadata.size = 0; + break; + case SET_VIDEO_HISTOGRAM_STATS: + data->video_histogram_stats.stat_len = 0; + break; + default: + ALOGE("Unknown paramType %d", paramType); + break; + } + // param unset + return 0; + } + + setGralloc4Array(data, paramType, true); + switch (paramType) { + case PP_PARAM_INTERLACED: + data->interlaced = *((int32_t *)param); + break; + case UPDATE_BUFFER_GEOMETRY: { + BufferDim_t in = *((BufferDim_t *)param); + data->crop = {0, 0, in.sliceWidth, in.sliceHeight}; + break; + } + case UPDATE_REFRESH_RATE: + data->refreshrate = *((float *)param); + break; + case UPDATE_COLOR_SPACE: { + ColorMetaData color = {}; + if (!colorSpaceToColorMetadata(*((ColorSpace_t *)param), &color)) { + data->color = color; + break; + } + return -EINVAL; + } + case MAP_SECURE_BUFFER: + data->mapSecureBuffer = *((int32_t *)param); + break; + case S3D_FORMAT: + data->s3dFormat = *((uint32_t *)param); + break; + case LINEAR_FORMAT: + data->linearFormat = *((uint32_t *)param); + break; + case SET_SINGLE_BUFFER_MODE: + data->isSingleBufferMode = *((uint32_t *)param); + break; + case SET_VT_TIMESTAMP: + data->vtTimeStamp = *((uint64_t *)param); + break; + case COLOR_METADATA: + data->color = *((ColorMetaData *)param); + break; + case SET_UBWC_CR_STATS_INFO: { + struct UBWCStats *stats = (struct UBWCStats *)param; + int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats); + for (int i = 0; i < numelems; i++) { + data->ubwcCRStats[i] = stats[i]; + } + break; + } + case SET_VIDEO_PERF_MODE: + data->isVideoPerfMode = *((uint32_t *)param); + break; + case SET_GRAPHICS_METADATA: { + GraphicsMetadata payload = *((GraphicsMetadata*)(param)); + data->graphics_metadata.size = payload.size; + memcpy(data->graphics_metadata.data, payload.data, + sizeof(data->graphics_metadata.data)); + break; + } + case SET_CVP_METADATA: { + struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param; + if (cvpMetadata->size <= CVP_METADATA_SIZE) { + data->cvpMetadata.size = cvpMetadata->size; + memcpy(data->cvpMetadata.payload, cvpMetadata->payload, + cvpMetadata->size); + data->cvpMetadata.capture_frame_rate = cvpMetadata->capture_frame_rate; + data->cvpMetadata.cvp_frame_rate = cvpMetadata->cvp_frame_rate; + data->cvpMetadata.flags = cvpMetadata->flags; + memcpy(data->cvpMetadata.reserved, cvpMetadata->reserved, + (8 * sizeof(uint32_t))); + } else { + setGralloc4Array(data, paramType, false); + ALOGE("%s: cvp metadata length %d is more than max size %d", __func__, + cvpMetadata->size, CVP_METADATA_SIZE); + return -EINVAL; + } + break; + } + case SET_VIDEO_HISTOGRAM_STATS: { + struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param; + if (vidstats->stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) { + memcpy(data->video_histogram_stats.stats_info, + vidstats->stats_info, VIDEO_HISTOGRAM_STATS_SIZE); + data->video_histogram_stats.stat_len = vidstats->stat_len; + data->video_histogram_stats.frame_type = vidstats->frame_type; + data->video_histogram_stats.display_width = vidstats->display_width; + data->video_histogram_stats.display_height = vidstats->display_height; + data->video_histogram_stats.decode_width = vidstats->decode_width; + data->video_histogram_stats.decode_height = vidstats->decode_height; + } else { + setGralloc4Array(data, paramType, false); + ALOGE("%s: video stats length %u is more than max size %u", __func__, + vidstats->stat_len, VIDEO_HISTOGRAM_STATS_SIZE); + return -EINVAL; + } + break; + } + case SET_VIDEO_TS_INFO: + data->videoTsInfo = *((VideoTimestampInfo *)param); + break; + default: + ALOGE("Unknown paramType %d", paramType); + break; + } + return 0; +} + +int clearMetaData(private_handle_t *handle, DispParamType paramType) { + auto err = validateAndMap(handle); + if (err != 0) + return err; + return clearMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata), + paramType); +} + +int clearMetaDataVa(MetaData_t *data, DispParamType paramType) { + if (data == nullptr) + return -EINVAL; + data->operation &= ~paramType; + switch (paramType) { + case SET_VIDEO_PERF_MODE: + data->isVideoPerfMode = 0; + break; + case SET_CVP_METADATA: + data->cvpMetadata.size = 0; + break; + case SET_VIDEO_HISTOGRAM_STATS: + data->video_histogram_stats.stat_len = 0; + break; + default: + ALOGE("Unknown paramType %d", paramType); + break; + } + return 0; +} + +int getMetaData(private_handle_t *handle, DispFetchParamType paramType, + void *param) { + int ret = validateAndMap(handle); + if (ret != 0) + return ret; + return getMetaDataVa(reinterpret_cast<MetaData_t *>(handle->base_metadata), + paramType, param); +} + +int getMetaDataVa(MetaData_t *data, DispFetchParamType paramType, + void *param) { + // Make sure we send 0 only if the operation queried is present + int ret = -EINVAL; + if (data == nullptr) + return ret; + if (param == nullptr) + return ret; + + if (!getGralloc4Array(data, paramType)) { + return ret; + } + + ret = 0; + + switch (paramType) { + case GET_PP_PARAM_INTERLACED: + *((int32_t *)param) = data->interlaced; + break; + case GET_BUFFER_GEOMETRY: + *((BufferDim_t *)param) = {data->crop.right, data->crop.bottom}; + break; + case GET_REFRESH_RATE: + *((float *)param) = data->refreshrate; + break; + case GET_COLOR_SPACE: { + ColorSpace_t color_space; + if (!colorMetaDataToColorSpace(data->color, &color_space)) { + *((ColorSpace_t *)param) = color_space; + } else { + ret = -EINVAL; + } + break; + } + case GET_MAP_SECURE_BUFFER: + *((int32_t *)param) = data->mapSecureBuffer; + break; + case GET_S3D_FORMAT: + *((uint32_t *)param) = data->s3dFormat; + break; + case GET_LINEAR_FORMAT: + *((uint32_t *)param) = data->linearFormat; + break; + case GET_SINGLE_BUFFER_MODE: + *((uint32_t *)param) = data->isSingleBufferMode; + break; + case GET_VT_TIMESTAMP: + *((uint64_t *)param) = data->vtTimeStamp; + break; + case GET_COLOR_METADATA: + *((ColorMetaData *)param) = data->color; + break; + case GET_UBWC_CR_STATS_INFO: { + struct UBWCStats *stats = (struct UBWCStats *)param; + int numelems = sizeof(data->ubwcCRStats) / sizeof(struct UBWCStats); + for (int i = 0; i < numelems; i++) { + stats[i] = data->ubwcCRStats[i]; + } + break; + } + case GET_VIDEO_PERF_MODE: + *((uint32_t *)param) = data->isVideoPerfMode; + break; + case GET_GRAPHICS_METADATA: + memcpy(param, data->graphics_metadata.data, sizeof(data->graphics_metadata.data)); + break; + case GET_CVP_METADATA: { + struct CVPMetadata *cvpMetadata = (struct CVPMetadata *)param; + cvpMetadata->size = 0; + if (data->cvpMetadata.size <= CVP_METADATA_SIZE) { + cvpMetadata->size = data->cvpMetadata.size; + memcpy(cvpMetadata->payload, data->cvpMetadata.payload, data->cvpMetadata.size); + cvpMetadata->capture_frame_rate = data->cvpMetadata.capture_frame_rate; + cvpMetadata->cvp_frame_rate = data->cvpMetadata.cvp_frame_rate; + cvpMetadata->flags = data->cvpMetadata.flags; + memcpy(cvpMetadata->reserved, data->cvpMetadata.reserved, (8 * sizeof(uint32_t))); + } else { + ret = -EINVAL; + } + break; + } + case GET_VIDEO_HISTOGRAM_STATS: { + struct VideoHistogramMetadata *vidstats = (struct VideoHistogramMetadata *)param; + vidstats->stat_len = 0; + if (data->video_histogram_stats.stat_len <= VIDEO_HISTOGRAM_STATS_SIZE) { + memcpy(vidstats->stats_info, data->video_histogram_stats.stats_info, + VIDEO_HISTOGRAM_STATS_SIZE); + vidstats->stat_len = data->video_histogram_stats.stat_len; + vidstats->frame_type = data->video_histogram_stats.frame_type; + vidstats->display_width = data->video_histogram_stats.display_width; + vidstats->display_height = data->video_histogram_stats.display_height; + vidstats->decode_width = data->video_histogram_stats.decode_width; + vidstats->decode_height = data->video_histogram_stats.decode_height; + } else { + ret = -EINVAL; + } + break; + } + case GET_VIDEO_TS_INFO: + *((VideoTimestampInfo *)param) = data->videoTsInfo; + break; + default: + ALOGE("Unknown paramType %d", paramType); + ret = -EINVAL; + break; + } + return ret; +} + +int copyMetaData(struct private_handle_t *src, struct private_handle_t *dst) { + auto err = validateAndMap(src); + if (err != 0) + return err; + + err = validateAndMap(dst); + if (err != 0) + return err; + + MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata); + MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata); + *dst_data = *src_data; + return 0; +} + +int copyMetaDataVaToHandle(MetaData_t *src_data, struct private_handle_t *dst) { + int err = -EINVAL; + if (src_data == nullptr) + return err; + + err = validateAndMap(dst); + if (err != 0) + return err; + + MetaData_t *dst_data = reinterpret_cast <MetaData_t *>(dst->base_metadata); + *dst_data = *src_data; + return 0; +} + +int copyMetaDataHandleToVa(struct private_handle_t *src, MetaData_t *dst_data) { + int err = -EINVAL; + if (dst_data == nullptr) + return err; + + err = validateAndMap(src); + if (err != 0) + return err; + + MetaData_t *src_data = reinterpret_cast <MetaData_t *>(src->base_metadata); + *dst_data = *src_data; + return 0; +} + +int copyMetaDataVaToVa(MetaData_t *src_data, MetaData_t *dst_data) { + int err = -EINVAL; + if (src_data == nullptr) + return err; + + if (dst_data == nullptr) + return err; + + *dst_data = *src_data; + return 0; +} + +int setMetaDataAndUnmap(struct private_handle_t *handle, enum DispParamType paramType, + void *param) { + auto ret = setMetaData(handle, paramType, param); + unmapAndReset(handle); + return ret; +} + +int getMetaDataAndUnmap(struct private_handle_t *handle, + enum DispFetchParamType paramType, + void *param) { + auto ret = getMetaData(handle, paramType, param); + unmapAndReset(handle); + return ret; +} diff --git a/libqdmetadata/qd_utils.cpp b/libqdmetadata/qd_utils.cpp new file mode 100644 index 00000000..ac5d094b --- /dev/null +++ b/libqdmetadata/qd_utils.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2013, 2018, 2020 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 <unistd.h> +#include <gralloc_priv.h> +#include "qd_utils.h" + +static const int kFBNodeMax = 4; +namespace qdutils { + +static int parseLine(char *input, char *tokens[], const uint32_t maxToken, uint32_t *count) { + char *tmpToken = NULL; + char *tmpPtr; + uint32_t index = 0; + const char *delim = ", =\n"; + if (!input) { + return -1; + } + tmpToken = strtok_r(input, delim, &tmpPtr); + while (tmpToken && index < maxToken) { + tokens[index++] = tmpToken; + tmpToken = strtok_r(NULL, delim, &tmpPtr); + } + *count = index; + + return 0; +} + +static int getExternalNode(const char *type) { + FILE *displayDeviceFP = NULL; + char fbType[MAX_FRAME_BUFFER_NAME_SIZE]; + char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE]; + int j = 0; + + for(j = 0; j < kFBNodeMax; j++) { + snprintf (msmFbTypePath, sizeof(msmFbTypePath), + "/sys/devices/virtual/graphics/fb%d/msm_fb_type", j); + displayDeviceFP = fopen(msmFbTypePath, "r"); + if(displayDeviceFP) { + fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE, + displayDeviceFP); + if(strncmp(fbType, type, strlen(type)) == 0) { + ALOGD("%s: %s is at fb%d", __func__, type, j); + fclose(displayDeviceFP); + break; + } + fclose(displayDeviceFP); + } else { + ALOGE("%s: Failed to open fb node %s", __func__, msmFbTypePath); + } + } + + if (j < kFBNodeMax) + return j; + else + ALOGE("%s: Failed to find %s node", __func__, type); + + return -1; +} + +int getHDMINode(void) { + return getExternalNode("dtv panel"); +} + +int getEdidRawData(char *buffer) +{ + int size; + int edidFile; + char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE]; + int node_id = getHDMINode(); + + if (node_id < 0) { + ALOGE("%s no HDMI node found", __func__); + return 0; + } + + snprintf(msmFbTypePath, sizeof(msmFbTypePath), + "/sys/devices/virtual/graphics/fb%d/edid_raw_data", node_id); + + edidFile = open(msmFbTypePath, O_RDONLY, 0); + + if (edidFile < 0) { + ALOGE("%s no edid raw data found %s", __func__,msmFbTypePath); + return 0; + } + + size = (int)read(edidFile, (char*)buffer, EDID_RAW_DATA_SIZE); + close(edidFile); + return size; +} + +bool isDPConnected() { + char connectPath[MAX_FRAME_BUFFER_NAME_SIZE]; + FILE *connectFile = NULL; + size_t len = MAX_STRING_LENGTH; + char stringBuffer[MAX_STRING_LENGTH]; + char *line = stringBuffer; + + int nodeId = getExternalNode("dp panel"); + if (nodeId < 0) { + ALOGE("%s no DP node found", __func__); + return false; + } + + snprintf(connectPath, sizeof(connectPath), + "/sys/devices/virtual/graphics/fb%d/connected", nodeId); + + connectFile = fopen(connectPath, "rb"); + if (!connectFile) { + ALOGW("Failed to open connect node for device node %s", connectPath); + return false; + } + + if (getline(&line, &len, connectFile) < 0) { + fclose(connectFile); + return false; + } + + fclose(connectFile); + + return atoi(line); +} + +int getDPTestConfig(uint32_t *panelBpp, uint32_t *patternType) { + if (!panelBpp || !patternType) { + return -1; + } + + char configPath[MAX_FRAME_BUFFER_NAME_SIZE]; + FILE *configFile = NULL; + uint32_t tokenCount = 0; + const uint32_t maxCount = 10; + char *tokens[maxCount] = { NULL }; + size_t len = MAX_STRING_LENGTH; + char stringBuffer[MAX_STRING_LENGTH]; + char *line = stringBuffer; + + int nodeId = getExternalNode("dp panel"); + if (nodeId < 0) { + ALOGE("%s no DP node found", __func__); + return -EINVAL; + } + + snprintf(configPath, sizeof(configPath), + "/sys/devices/virtual/graphics/fb%d/config", nodeId); + + configFile = fopen(configPath, "rb"); + if (!configFile) { + ALOGW("Failed to open config node for device node %s", configPath); + return -EINVAL; + } + + while (getline(&line, &len, configFile) != -1) { + if (!parseLine(line, tokens, maxCount, &tokenCount)) { + if (tokens[0] != NULL) { + if (!strncmp(tokens[0], "bpp", strlen("bpp"))) { + *panelBpp = static_cast<uint32_t>(atoi(tokens[1])); + } else if (!strncmp(tokens[0], "pattern", strlen("pattern"))) { + *patternType = static_cast<uint32_t>(atoi(tokens[1])); + } + } + } + } + + fclose(configFile); + + return 0; +} + +DriverType getDriverType() { + const char *fb_caps = "/sys/devices/virtual/graphics/fb0/mdp/caps"; + // 0 - File exists + return access(fb_caps, F_OK) ? DriverType::DRM : DriverType::FB; +} + +const char *GetHALPixelFormatString(int format) { + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + return "RGBA_8888"; + case HAL_PIXEL_FORMAT_RGBX_8888: + return "RGBX_8888"; + case HAL_PIXEL_FORMAT_RGB_888: + return "RGB_888"; + case HAL_PIXEL_FORMAT_RGB_565: + return "RGB_565"; + case HAL_PIXEL_FORMAT_BGR_565: + return "BGR_565"; + case HAL_PIXEL_FORMAT_BGRA_8888: + return "BGRA_8888"; + case HAL_PIXEL_FORMAT_RGBA_5551: + return "RGBA_5551"; + case HAL_PIXEL_FORMAT_RGBA_4444: + return "RGBA_4444"; + case HAL_PIXEL_FORMAT_YV12: + return "YV12"; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + return "YCbCr_422_SP_NV16"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return "YCrCb_420_SP_NV21"; + case HAL_PIXEL_FORMAT_YCbCr_422_I: + return "YCbCr_422_I_YUY2"; + case HAL_PIXEL_FORMAT_YCrCb_422_I: + return "YCrCb_422_I_YVYU"; + case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: + return "NV12_ENCODEABLE"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + return "YCbCr_420_SP_TILED_TILE_4x2"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + return "YCbCr_420_SP"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: + return "YCrCb_420_SP_ADRENO"; + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + return "YCrCb_422_SP"; + case HAL_PIXEL_FORMAT_R_8: + return "R_8"; + case HAL_PIXEL_FORMAT_RG_88: + return "RG_88"; + case HAL_PIXEL_FORMAT_INTERLACE: + return "INTERLACE"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS: + return "YCbCr_420_SP_VENUS"; + case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS: + return "YCrCb_420_SP_VENUS"; + case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC: + return "YCbCr_420_SP_VENUS_UBWC"; + case HAL_PIXEL_FORMAT_RGBA_1010102: + return "RGBA_1010102"; + case HAL_PIXEL_FORMAT_ARGB_2101010: + return "ARGB_2101010"; + case HAL_PIXEL_FORMAT_RGBX_1010102: + return "RGBX_1010102"; + case HAL_PIXEL_FORMAT_XRGB_2101010: + return "XRGB_2101010"; + case HAL_PIXEL_FORMAT_BGRA_1010102: + return "BGRA_1010102"; + case HAL_PIXEL_FORMAT_ABGR_2101010: + return "ABGR_2101010"; + case HAL_PIXEL_FORMAT_BGRX_1010102: + return "BGRX_1010102"; + case HAL_PIXEL_FORMAT_XBGR_2101010: + return "XBGR_2101010"; + case HAL_PIXEL_FORMAT_YCbCr_420_P010: + return "YCbCr_420_P010"; + case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC: + return "YCbCr_420_TP10_UBWC"; + case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS: + return "YCbCr_420_P010_VENUS"; + default: + return "Unknown_format"; + } +} + +}; //namespace qdutils diff --git a/services/config/src/Android.bp b/services/config/src/Android.bp new file mode 100644 index 00000000..73fb5d42 --- /dev/null +++ b/services/config/src/Android.bp @@ -0,0 +1,29 @@ +cc_library_shared { + name: "libdisplayconfig.qti", + vendor_available: true, + system_ext_specific: true, + cflags: [ + "-Wno-sign-conversion", + "-Wno-unused-parameter", + "-DLOG_TAG=\"libdisplayconfigqti\"", + ], + shared_libs: [ + "liblog", + "libhidlbase", + "libutils", + "vendor.display.config@2.0" + ], + header_libs: ["libhardware_headers", "display_intf_headers"], + srcs: [ + "client_interface.cpp", + "client_impl.cpp", + "device_impl.cpp", + "device_interface.cpp", + ], + export_header_lib_headers: ["display_intf_headers"], + export_include_dirs: ["."], + header_abi_checker: { + enabled: true, + }, +} + diff --git a/services/config/src/client_impl.cpp b/services/config/src/client_impl.cpp new file mode 100644 index 00000000..ad0b1fb7 --- /dev/null +++ b/services/config/src/client_impl.cpp @@ -0,0 +1,1066 @@ +/* +* Copyright (c) 2020-2021 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 <string> +#include <vector> + +#include "client_impl.h" + +namespace DisplayConfig { + +int ClientImpl::Init(std::string client_name, ConfigCallback *callback) { + display_config_ = IDisplayConfig::getService(); + // Unable to find Display Config 2.0 service. Fail Init. + if (!display_config_) { + return -1; + } + int32_t error = 0; + uint64_t handle = 0; + auto hidl_callback = [&error, &handle] (int32_t err, uint64_t client_handle) { + error = err; + handle = client_handle; + }; + int pid = getpid(); + android::sp<ClientCallback> client_cb(new ClientCallback(callback)); + display_config_->registerClient(client_name + std::to_string(pid), client_cb, + hidl_callback); + client_handle_ = handle; + + return 0; +} + +void ClientImpl::DeInit() { + int32_t error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kDestroy, {}, {}, hidl_cb); + display_config_.clear(); + display_config_ = nullptr; +} + +int ClientImpl::IsDisplayConnected(DisplayType dpy, bool *connected) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsDisplayConnected, input_params, {}, hidl_cb); + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *connected = *output; + } + + return error; +} + +int ClientImpl::SetDisplayStatus(DisplayType dpy, ExternalStatus status) { + struct StatusParams input = {dpy, status}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct StatusParams)); + int error = 0; + + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetDisplayStatus, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::ConfigureDynRefreshRate(DynRefreshRateOp op, uint32_t refresh_rate) { + struct DynRefreshRateParams input = {op, refresh_rate}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), + sizeof(struct DynRefreshRateParams)); + int error = 0; + + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kConfigureDynRefreshRate, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::GetConfigCount(DisplayType dpy, uint32_t *count) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType)); + const uint32_t *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetConfigCount, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const uint32_t*>(data); + *count = *output; + + return error; +} + +int ClientImpl::GetActiveConfig(DisplayType dpy, uint32_t *config) { + if (!config) { + return -EINVAL; + } + + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType)); + const uint32_t *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + if (display_config_) { + display_config_->perform(client_handle_, kGetActiveConfig, input_params, {}, hidl_cb); + } + + if (!error) { + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const uint32_t*>(data); + *config = *output; + } + + return error; +} + +int ClientImpl::SetActiveConfig(DisplayType dpy, uint32_t config) { + struct ConfigParams input = {dpy, config}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct ConfigParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetActiveConfig, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::GetDisplayAttributes(uint32_t config_index, DisplayType dpy, + Attributes *attributes) { + struct AttributesParams input = {config_index, dpy}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct AttributesParams)); + const struct Attributes *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetDisplayAttributes, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const Attributes*>(data); + if (!error) { + *attributes = *output; + } + + return error; +} + +int ClientImpl::SetPanelBrightness(uint32_t level) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&level), sizeof(uint32_t)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetPanelBrightness, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::GetPanelBrightness(uint32_t *level) { + const uint32_t *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetPanelBrightness, {}, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const uint32_t*>(data); + if (!error) { + *level = *output; + } + + return error; +} + +int ClientImpl::MinHdcpEncryptionLevelChanged(DisplayType dpy, uint32_t min_enc_level) { + struct MinHdcpEncLevelChangedParams input = {dpy, min_enc_level}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), + sizeof(struct MinHdcpEncLevelChangedParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kMinHdcpEncryptionLevelChanged, + input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::RefreshScreen() { + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kRefreshScreen, {}, {}, hidl_cb); + + return error; +} + +int ClientImpl::ControlPartialUpdate(DisplayType dpy, bool enable) { + struct PartialUpdateParams input = {dpy, enable}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), + sizeof(struct PartialUpdateParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kControlPartialUpdate, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::ToggleScreenUpdate(bool on) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&on), sizeof(bool)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kToggleScreenUpdate, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::SetIdleTimeout(uint32_t value) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&value), sizeof(uint32_t)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetIdleTimeout, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::GetHDRCapabilities(DisplayType dpy, HDRCapsParams *caps) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&dpy), sizeof(DisplayType)); + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetHdrCapabilities, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + + if (!error) { + const int32_t *hdr_caps; + const float *lum; + size_t size = output_params.size(); + size_t hdr_caps_size = size - 3 * sizeof(float); + hdr_caps_size /= sizeof(int32_t); + hdr_caps = reinterpret_cast<const int32_t*>(data); + for (size_t i = 0; i < hdr_caps_size; i++) { + caps->supported_hdr_types.push_back(*hdr_caps); + hdr_caps++; + } + lum = reinterpret_cast<const float *>(hdr_caps); + caps->max_luminance = lum[0]; + caps->max_avg_luminance = lum[1]; + caps->min_luminance = lum[2]; + } + + return error; +} + +int ClientImpl::SetCameraLaunchStatus(uint32_t on) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&on), sizeof(uint32_t)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetCameraLaunchStatus, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::DisplayBWTransactionPending(bool *status) { + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kDisplayBwTransactionPending, {}, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + if (!error) { + *status = *output; + } + + return error; +} + +int ClientImpl::SetDisplayAnimating(uint64_t display_id, bool animating) { + struct AnimationParams input = {display_id, animating}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct AnimationParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetDisplayAnimating, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::ControlIdlePowerCollapse(bool enable, bool synchronous) { + struct IdlePcParams input = {enable, synchronous}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct IdlePcParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kControlIdlePowerCollapse, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::GetWriteBackCapabilities(bool *is_wb_ubwc_supported) { + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetWritebackCapabilities, {}, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + if (!error) { + *is_wb_ubwc_supported = *output; + } + + return error; +} + +int ClientImpl::SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start, + uint32_t h_end, uint32_t v_start, uint32_t v_end, + uint32_t factor_in, uint32_t factor_out) { + struct DppsAdRoiParams input = {display_id, h_start, h_end, v_start, v_end, + factor_in, factor_out}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct DppsAdRoiParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetDisplayDppsAdRoi, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::UpdateVSyncSourceOnPowerModeOff() { + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kUpdateVsyncSourceOnPowerModeOff, {}, {}, hidl_cb); + + return error; +} + +int ClientImpl::UpdateVSyncSourceOnPowerModeDoze() { + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kUpdateVsyncSourceOnPowerModeDoze, {}, {}, hidl_cb); + + return error; +} + +int ClientImpl::SetPowerMode(uint32_t disp_id, PowerMode power_mode) { + struct PowerModeParams input = {disp_id, power_mode}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct PowerModeParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetPowerMode, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::IsPowerModeOverrideSupported(uint32_t disp_id, bool *supported) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsPowerModeOverrideSupported, + input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *supported = *output; + } + + return error; +} + +int ClientImpl::IsHDRSupported(uint32_t disp_id, bool *supported) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsHdrSupported, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *supported = *output; + } + + return error; +} + +int ClientImpl::IsWCGSupported(uint32_t disp_id, bool *supported) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(int32_t)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsWcgSupported, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *supported = *output; + } + + return error; +} + +int ClientImpl::SetLayerAsMask(uint32_t disp_id, uint64_t layer_id) { + struct LayerMaskParams input = {disp_id, layer_id}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct LayerMaskParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetLayerAsMask, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::GetDebugProperty(const std::string prop_name, std::string *value) { + ByteStream input_params; + std::string prop(prop_name); + prop += '\0'; + uint8_t *data_input = reinterpret_cast<uint8_t*>(const_cast<char*>(prop.data())); + input_params.setToExternal(reinterpret_cast<uint8_t*>(data_input), + prop.size() * sizeof(char)); + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetDebugProperty, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + const char *name = reinterpret_cast<const char *>(data); + if (!error) { + std::string output(name); + *value = output; + } + + return error; +} + +int ClientImpl::GetActiveBuiltinDisplayAttributes(Attributes *attr) { + const struct Attributes *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetActiveBuiltinDisplayAttributes, {}, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const Attributes*>(data); + if (!error) { + *attr = *output; + } + + return error; +} + +int ClientImpl::SetPanelLuminanceAttributes(uint32_t disp_id, float min_lum, float max_lum) { + struct PanelLumAttrParams input = {disp_id, min_lum, max_lum}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct PanelLumAttrParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetPanelLuminanceAttributes, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::IsBuiltInDisplay(uint32_t disp_id, bool *is_builtin) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsBuiltinDisplay, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *is_builtin = *output; + } + + return error; +} + +int ClientImpl::SetCWBOutputBuffer(uint32_t disp_id, const Rect rect, bool post_processed, + const native_handle_t *buffer) { + struct CwbBufferParams input = {disp_id, rect, post_processed}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct CwbBufferParams)); + + hidl_handle handle = buffer; + std::vector<hidl_handle> handle_vector; + handle_vector.push_back(buffer); + HandleStream input_handles = handle_vector; + + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetCwbOutputBuffer, input_params, + input_handles, hidl_cb); + + return error; +} + +int ClientImpl::GetSupportedDSIBitClks(uint32_t disp_id, std::vector<uint64_t> *bit_clks) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t)); + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetSupportedDsiBitclks, input_params, {}, hidl_cb); + + if (!error) { + const uint8_t *data = output_params.data(); + const uint64_t *bit_clks_data = reinterpret_cast<const uint64_t *>(data); + int num_bit_clks = static_cast<int>(output_params.size() / sizeof(uint64_t)); + for (int i = 0; i < num_bit_clks; i++) { + bit_clks->push_back(bit_clks_data[i]); + } + } + + return error; +} + +int ClientImpl::GetDSIClk(uint32_t disp_id, uint64_t *bit_clk) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t)); + const uint64_t *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetDsiClk, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const uint64_t*>(data); + + if (!error) { + *bit_clk = *output; + } + + return error; +} + +int ClientImpl::SetDSIClk(uint32_t disp_id, uint64_t bit_clk) { + struct DsiClkParams input = {disp_id, bit_clk}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct DsiClkParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetDsiClk, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::SetQsyncMode(uint32_t disp_id, QsyncMode mode) { + struct QsyncModeParams input = {disp_id, mode}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct QsyncModeParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSetQsyncMode, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id, bool *is_smart) { + struct SmartPanelCfgParams input = {disp_id, config_id}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), + sizeof(struct SmartPanelCfgParams)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsSmartPanelConfig, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *is_smart = *output; + } + + return error; +} + +int ClientImpl::IsAsyncVDSCreationSupported(bool *supported) { + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsAsyncVdsSupported, {}, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *supported = *output; + } + + return error; +} + +int ClientImpl::CreateVirtualDisplay(uint32_t width, uint32_t height, int32_t format) { + struct VdsParams input = {width, height, format}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct VdsParams)); + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kCreateVirtualDisplay, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::IsRotatorSupportedFormat(int hal_format, bool ubwc, bool *supported) { + struct RotatorFormatParams input = {hal_format, ubwc}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), + sizeof(struct RotatorFormatParams)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsRotatorSupportedFormat, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + + if (!error) { + *supported = *output; + } + + return error; +} + +int ClientImpl::ControlQsyncCallback(bool enable) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&enable), sizeof(bool)); + int32_t error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kControlQsyncCallback, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::ControlIdleStatusCallback(bool enable) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&enable), sizeof(bool)); + int32_t error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kControlIdleStatusCallback, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::SendTUIEvent(DisplayType dpy, TUIEventType event_type) { + struct TUIEventParams input = {dpy, event_type}; + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), sizeof(struct TUIEventParams)); + int32_t error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + + display_config_->perform(client_handle_, kSendTUIEvent, input_params, {}, hidl_cb); + + return error; +} + +int ClientImpl::GetDisplayHwId(uint32_t disp_id, uint32_t *display_hw_id) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t)); + ByteStream output_params; + + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetDisplayHwId, input_params, {}, hidl_cb); + + const uint8_t *data = output_params.data(); + const uint32_t *output = reinterpret_cast<const uint32_t*>(data); + + if (!error) { + *display_hw_id = *output; + } + + return error; +} + +int ClientImpl::GetSupportedDisplayRefreshRates(DisplayType dpy, + std::vector<uint32_t> *supported_refresh_rates) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t *>(&dpy), sizeof(DisplayType)); + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params](int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kGetSupportedDisplayRefreshRates, input_params, {}, + hidl_cb); + + if (!error) { + const uint8_t *data = output_params.data(); + const uint32_t *refresh_rates_data = reinterpret_cast<const uint32_t *>(data); + int num_refresh_rates = static_cast<int>(output_params.size() / sizeof(uint32_t)); + for (int i = 0; i < num_refresh_rates; i++) { + supported_refresh_rates->push_back(refresh_rates_data[i]); + } + } + + return error; +} + +int ClientImpl::IsRCSupported(uint32_t disp_id, bool *supported) { + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_id), sizeof(uint32_t)); + const bool *output; + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + + display_config_->perform(client_handle_, kIsRCSupported, input_params, {}, hidl_cb); + + if (!error) { + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool*>(data); + *supported = *output; + } + + return error; +} + +int ClientImpl::DummyDisplayConfigAPI() { + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + display_config_->perform(client_handle_, kDummyOpcode, {}, {}, hidl_cb); + if (error) { + return -EINVAL; + } + return error; +} + +int ClientImpl::IsSupportedConfigSwitch(uint32_t disp_id, uint32_t config, bool *supported) { + struct SupportedModesParams input = {disp_id, config}; + ByteStream input_params; + ByteStream output_params; + const bool *output; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&input), + sizeof(struct SupportedModesParams)); + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + if (display_config_) { + display_config_->perform(client_handle_, kIsSupportedConfigSwitch, input_params, {}, hidl_cb); + } + + if (!error) { + const uint8_t *data = output_params.data(); + output = reinterpret_cast<const bool *>(data); + *supported = *output; + } + + return error; +} + +int ClientImpl::GetDisplayType(uint64_t physical_disp_id, DisplayType *disp_type) { + if (!disp_type) { + return -EINVAL; + } + ByteStream input_params; + input_params.setToExternal(reinterpret_cast<uint8_t*>(&physical_disp_id), sizeof(uint64_t)); + ByteStream output_params; + int error = 0; + auto hidl_cb = [&error, &output_params] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + output_params = params; + }; + if (display_config_) { + display_config_->perform(client_handle_, kGetDisplayType, input_params, {}, hidl_cb); + } + + if (!error) { + const uint8_t *data = output_params.data(); + const DisplayType *output = reinterpret_cast<const DisplayType*>(data); + *disp_type = *output; + } + return error; +} + +int ClientImpl::AllowIdleFallback() { + int error = 0; + auto hidl_cb = [&error] (int32_t err, ByteStream params, HandleStream handles) { + error = err; + }; + if (display_config_) { + display_config_->perform(client_handle_, kAllowIdleFallback, {}, {}, hidl_cb); + } + return error; +} + +void ClientCallback::ParseNotifyCWBBufferDone(const ByteStream &input_params, + const HandleStream &input_handles) { + const int *error; + + if (callback_ == nullptr || input_params.size() == 0 || input_handles.size() == 0) { + return; + } + + const uint8_t *data = input_params.data(); + error = reinterpret_cast<const int*>(data); + hidl_handle buffer = input_handles[0]; + callback_->NotifyCWBBufferDone(*error, buffer.getNativeHandle()); +} + +void ClientCallback::ParseNotifyQsyncChange(const ByteStream &input_params) { + const struct QsyncCallbackParams *qsync_data; + + if (callback_ == nullptr || input_params.size() == 0) { + return; + } + + const uint8_t *data = input_params.data(); + qsync_data = reinterpret_cast<const QsyncCallbackParams*>(data); + callback_->NotifyQsyncChange(qsync_data->qsync_enabled, qsync_data->refresh_rate, + qsync_data->qsync_refresh_rate); +} + +void ClientCallback::ParseNotifyIdleStatus(const ByteStream &input_params) { + const bool *is_idle; + if (callback_ == nullptr || input_params.size() == 0) { + return; + } + + const uint8_t *data = input_params.data(); + is_idle = reinterpret_cast<const bool*>(data); + callback_->NotifyIdleStatus(*is_idle); +} + +Return<void> ClientCallback::perform(uint32_t op_code, const ByteStream &input_params, + const HandleStream &input_handles) { + switch (op_code) { + case kSetCwbOutputBuffer: + ParseNotifyCWBBufferDone(input_params, input_handles); + break; + case kControlQsyncCallback: + ParseNotifyQsyncChange(input_params); + break; + case kControlIdleStatusCallback: + ParseNotifyIdleStatus(input_params); + break; + default: + break; + } + + return Void(); +} + +} // namespace DisplayConfig diff --git a/services/config/src/client_impl.h b/services/config/src/client_impl.h new file mode 100644 index 00000000..48b543af --- /dev/null +++ b/services/config/src/client_impl.h @@ -0,0 +1,139 @@ +/* +* Copyright (c) 2020-2021 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. +*/ + +#ifndef __CLIENT_IMPL_H__ +#define __CLIENT_IMPL_H__ + +#define VALIDATE_CONFIG_SWITCH 1 + +#include <vendor/display/config/2.0/IDisplayConfig.h> +#include <hidl/HidlSupport.h> +#include <log/log.h> +#include <config/client_interface.h> +#include <string> +#include <vector> + +#include "opcode_types.h" + +namespace DisplayConfig { + +using vendor::display::config::V2_0::IDisplayConfig; +using vendor::display::config::V2_0::IDisplayConfigCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_handle; +using ::android::hardware::hidl_vec; + +typedef hidl_vec<uint8_t> ByteStream; +typedef hidl_vec<hidl_handle> HandleStream; + +class ClientCallback: public IDisplayConfigCallback { + public: + ClientCallback(ConfigCallback *cb) { + callback_ = cb; + } + + private: + virtual Return<void> perform(uint32_t op_code, const ByteStream &input_params, + const HandleStream &input_handles); + void ParseNotifyCWBBufferDone(const ByteStream &input_params, const HandleStream &input_handles); + void ParseNotifyQsyncChange(const ByteStream &input_params); + void ParseNotifyIdleStatus(const ByteStream &input_params); + ConfigCallback *callback_ = nullptr; +}; + +class ClientImpl : public ClientInterface { + public: + int Init(std::string client_name, ConfigCallback *callback); + void DeInit(); + + virtual int IsDisplayConnected(DisplayType dpy, bool *connected); + virtual int SetDisplayStatus(DisplayType dpy, ExternalStatus status); + virtual int ConfigureDynRefreshRate(DynRefreshRateOp op, uint32_t refresh_rate); + virtual int GetConfigCount(DisplayType dpy, uint32_t *count); + virtual int GetActiveConfig(DisplayType dpy, uint32_t *config); + virtual int SetActiveConfig(DisplayType dpy, uint32_t config); + virtual int GetDisplayAttributes(uint32_t config_index, DisplayType dpy, Attributes *attributes); + virtual int SetPanelBrightness(uint32_t level); + virtual int GetPanelBrightness(uint32_t *level); + virtual int MinHdcpEncryptionLevelChanged(DisplayType dpy, uint32_t min_enc_level); + virtual int RefreshScreen(); + virtual int ControlPartialUpdate(DisplayType dpy, bool enable); + virtual int ToggleScreenUpdate(bool on); + virtual int SetIdleTimeout(uint32_t value); + virtual int GetHDRCapabilities(DisplayType dpy, HDRCapsParams *caps); + virtual int SetCameraLaunchStatus(uint32_t on); + virtual int DisplayBWTransactionPending(bool *status); + virtual int SetDisplayAnimating(uint64_t display_id, bool animating); + virtual int ControlIdlePowerCollapse(bool enable, bool synchronous); + virtual int GetWriteBackCapabilities(bool *is_wb_ubwc_supported); + virtual int SetDisplayDppsAdROI(uint32_t display_id, uint32_t h_start, uint32_t h_end, + uint32_t v_start, uint32_t v_end, uint32_t factor_in, + uint32_t factor_out); + virtual int UpdateVSyncSourceOnPowerModeOff(); + virtual int UpdateVSyncSourceOnPowerModeDoze(); + virtual int SetPowerMode(uint32_t disp_id, PowerMode power_mode); + virtual int IsPowerModeOverrideSupported(uint32_t disp_id, bool *supported); + virtual int IsHDRSupported(uint32_t disp_id, bool *supported); + virtual int IsWCGSupported(uint32_t disp_id, bool *supported); + virtual int SetLayerAsMask(uint32_t disp_id, uint64_t layer_id); + virtual int GetDebugProperty(const std::string prop_name, std::string *value); + virtual int GetActiveBuiltinDisplayAttributes(Attributes *attr); + virtual int SetPanelLuminanceAttributes(uint32_t disp_id, float min_lum, float max_lum); + virtual int IsBuiltInDisplay(uint32_t disp_id, bool *is_builtin); + virtual int IsAsyncVDSCreationSupported(bool *supported); + virtual int CreateVirtualDisplay(uint32_t width, uint32_t height, int format); + virtual int GetSupportedDSIBitClks(uint32_t disp_id, std::vector<uint64_t> *bit_clks); + virtual int GetDSIClk(uint32_t disp_id, uint64_t *bit_clk); + virtual int SetDSIClk(uint32_t disp_id, uint64_t bit_clk); + virtual int SetCWBOutputBuffer(uint32_t disp_id, const Rect rect, bool post_processed, + const native_handle_t *buffer); + virtual int SetQsyncMode(uint32_t disp_id, QsyncMode mode); + virtual int IsSmartPanelConfig(uint32_t disp_id, uint32_t config_id, bool *is_smart); + virtual int IsRotatorSupportedFormat(int hal_format, bool ubwc, bool *supported); + virtual int ControlQsyncCallback(bool enable); + virtual int SendTUIEvent(DisplayType dpy, TUIEventType event_type); + virtual int GetDisplayHwId(uint32_t disp_id, uint32_t *display_hw_id); + virtual int GetSupportedDisplayRefreshRates(DisplayType dpy, + std::vector<uint32_t> *supported_refresh_rates); + virtual int IsRCSupported(uint32_t disp_id, bool *supported); + virtual int ControlIdleStatusCallback(bool enable); + virtual int IsSupportedConfigSwitch(uint32_t disp_id, uint32_t config, bool *supported); + virtual int GetDisplayType(uint64_t physical_disp_id, DisplayType *disp_type); + virtual int AllowIdleFallback(); + virtual int DummyDisplayConfigAPI(); + + private: + android::sp<IDisplayConfig> display_config_ = nullptr; + uint64_t client_handle_ = 0; +}; + +} // namespace DisplayConfig + +#endif // __CLIENT_IMPL_H__ diff --git a/services/config/src/client_interface.cpp b/services/config/src/client_interface.cpp new file mode 100644 index 00000000..9c9ecd2b --- /dev/null +++ b/services/config/src/client_interface.cpp @@ -0,0 +1,65 @@ +/* +* Copyright (c) 2020 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 <string> + +#include "client_impl.h" + +namespace DisplayConfig { + +int ClientInterface::Create(std::string client_name, ConfigCallback *callback, + ClientInterface **intf) { + if (!intf) { + return -1; + } + + ClientImpl *impl = new ClientImpl(); + if (!impl) { + return -1; + } + + int ret = impl->Init(client_name, callback); + if (ret) { + delete impl; + return -1; + } + + *intf = impl; + return 0; +} + +void ClientInterface::Destroy(ClientInterface *intf) { + if (intf) { + ClientImpl *impl = static_cast<ClientImpl *>(intf); + impl->DeInit(); + delete impl; + } +} + +} // namespace DisplayConfig diff --git a/services/config/src/device_impl.cpp b/services/config/src/device_impl.cpp new file mode 100644 index 00000000..df4731fb --- /dev/null +++ b/services/config/src/device_impl.cpp @@ -0,0 +1,1040 @@ +/* +* Copyright (c) 2020-2021 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 <string> +#include <vector> + +#include "device_impl.h" + +namespace DisplayConfig { + +DeviceImpl *DeviceImpl::device_obj_ = nullptr; +std::mutex DeviceImpl::device_lock_; + +int DeviceImpl::CreateInstance(ClientContext *intf) { + std::lock_guard<std::mutex> lock(device_lock_); + if (!device_obj_) { + device_obj_ = new DeviceImpl(); + if (!device_obj_) { + return -1; + } + + android::status_t status = device_obj_->IDisplayConfig::registerAsService(); + // Unable to start Display Config 2.0 service. Fail Init. + if (status != android::OK) { + delete device_obj_; + device_obj_ = nullptr; + return -1; + } + device_obj_->intf_ = intf; + } + + return 0; +} + +Return<void> DeviceImpl::registerClient(const hidl_string &client_name, + const sp<IDisplayConfigCallback>& callback, + registerClient_cb _hidl_cb) { + ALOGI("Register client:%s", client_name.c_str()); + int32_t error = 0; + std::string client_name_str = client_name.c_str(); + if (client_name_str.empty()) { + error = -EINVAL; + _hidl_cb(error, 0); + return Void(); + } + + if (!callback) { + ALOGW("IDisplayConfigCallback provided is null"); + } + + uint64_t client_handle = static_cast<uint64_t>(client_id_++); + std::shared_ptr<DeviceClientContext> device_client(new DeviceClientContext(callback)); + if (callback) { + callback->linkToDeath(this, client_handle); + } + + if (!intf_) { + ALOGW("ConfigInterface is invalid"); + _hidl_cb(error, 0); + return Void(); + } + + if (!device_client) { + ALOGW("Failed to initialize device client:%s", client_name.c_str()); + _hidl_cb(error, 0); + return Void(); + } + + ConfigInterface *intf = nullptr; + error = intf_->RegisterClientContext(device_client, &intf); + + if (error) { + callback->unlinkToDeath(this); + return Void(); + } + + device_client->SetDeviceConfigIntf(intf); + + display_config_map_.emplace(std::make_pair(client_handle, device_client)); + _hidl_cb(error, client_handle); + return Void(); +} + +void DeviceImpl::serviceDied(uint64_t client_handle, + const android::wp<::android::hidl::base::V1_0::IBase>& callback) { + std::lock_guard<std::mutex> lock(death_service_mutex_); + auto itr = display_config_map_.find(client_handle); + std::shared_ptr<DeviceClientContext> client = itr->second; + if (client != NULL) { + ConfigInterface *intf = client->GetDeviceConfigIntf(); + intf_->UnRegisterClientContext(intf); + client.reset(); + display_config_map_.erase(itr); + } +} + +DeviceImpl::DeviceClientContext::DeviceClientContext( + const sp<IDisplayConfigCallback> callback) : callback_(callback) { } + +sp<IDisplayConfigCallback> DeviceImpl::DeviceClientContext::GetDeviceConfigCallback() { + return callback_; +} + +void DeviceImpl::DeviceClientContext::SetDeviceConfigIntf(ConfigInterface *intf) { + intf_ = intf; +} + +ConfigInterface* DeviceImpl::DeviceClientContext::GetDeviceConfigIntf() { + return intf_; +} + +void DeviceImpl::DeviceClientContext::NotifyCWBBufferDone(int32_t error, + const native_handle_t *buffer) { + ByteStream output_params; + HandleStream output_handles; + std::vector<hidl_handle> handles; + + output_params.setToExternal(reinterpret_cast<uint8_t*>(&error), sizeof(int)); + handles.push_back(buffer); + output_handles = handles; + + auto status = callback_->perform(kSetCwbOutputBuffer, output_params, output_handles); + if (status.isDeadObject()) { + return; + } +} + +void DeviceImpl::DeviceClientContext::NotifyQsyncChange(bool qsync_enabled, int32_t refresh_rate, + int32_t qsync_refresh_rate) { + struct QsyncCallbackParams data = {qsync_enabled, refresh_rate, qsync_refresh_rate}; + ByteStream output_params; + + output_params.setToExternal(reinterpret_cast<uint8_t*>(&data), sizeof(data)); + + auto status = callback_->perform(kControlQsyncCallback, output_params, {}); + if (status.isDeadObject()) { + return; + } +} + +void DeviceImpl::DeviceClientContext::NotifyIdleStatus(bool is_idle) { + bool data = {is_idle}; + ByteStream output_params; + + output_params.setToExternal(reinterpret_cast<uint8_t*>(&data), sizeof(data)); + + auto status = callback_->perform(kControlIdleStatusCallback, output_params, {}); + if (status.isDeadObject()) { + return; + } +} + +void DeviceImpl::DeviceClientContext::ParseIsDisplayConnected(const ByteStream &input_params, + perform_cb _hidl_cb) { + const DisplayType *dpy; + bool connected = false; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + dpy = reinterpret_cast<const DisplayType*>(data); + int32_t error = intf_->IsDisplayConnected(*dpy, &connected); + + output_params.setToExternal(reinterpret_cast<uint8_t*>(&connected), + sizeof(connected)); + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetDisplayStatus(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct StatusParams *display_status; + const uint8_t *data = input_params.data(); + display_status = reinterpret_cast<const StatusParams*>(data); + int32_t error = intf_->SetDisplayStatus(display_status->dpy, + display_status->status); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseConfigureDynRefreshRate(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct DynRefreshRateParams *dyn_refresh_data; + const uint8_t *data = input_params.data(); + dyn_refresh_data = reinterpret_cast<const DynRefreshRateParams*>(data); + int32_t error = intf_->ConfigureDynRefreshRate(dyn_refresh_data->op, + dyn_refresh_data->refresh_rate); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetConfigCount(const ByteStream &input_params, + perform_cb _hidl_cb) { + const DisplayType *dpy; + uint32_t count = 0; + ByteStream output_params; + + if (input_params.size() == 0) { + _hidl_cb(-ENODATA, {}, {}); + return; + } + + const uint8_t *data = input_params.data(); + dpy = reinterpret_cast<const DisplayType*>(data); + int32_t error = intf_->GetConfigCount(*dpy, &count); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&count), + sizeof(uint32_t)); + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetActiveConfig(const ByteStream &input_params, + perform_cb _hidl_cb) { + const DisplayType *dpy; + uint32_t config = 0; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + dpy = reinterpret_cast<const DisplayType*>(data); + int32_t error = intf_->GetActiveConfig(*dpy, &config); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&config), + sizeof(uint32_t)); + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetActiveConfig(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct ConfigParams *set_active_cfg_data; + + const uint8_t *data = input_params.data(); + set_active_cfg_data = reinterpret_cast<const ConfigParams*>(data); + int32_t error = intf_->SetActiveConfig(set_active_cfg_data->dpy, + set_active_cfg_data->config); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetDisplayAttributes(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct AttributesParams *get_disp_attr_data; + struct Attributes attributes = {}; + ByteStream output_params; + int32_t error = -EINVAL; + + const uint8_t *data = input_params.data(); + get_disp_attr_data = reinterpret_cast<const AttributesParams*>(data); + error = intf_->GetDisplayAttributes(get_disp_attr_data->config_index, get_disp_attr_data->dpy, + &attributes); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&attributes), + sizeof(struct Attributes)); + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetPanelBrightness(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint32_t *level; + int32_t error = 0; + + const uint8_t *data = input_params.data(); + level = reinterpret_cast<const uint32_t*>(data); + error = intf_->SetPanelBrightness(*level); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetPanelBrightness(perform_cb _hidl_cb) { + uint32_t level = 0; + ByteStream output_params; + int32_t error = -EINVAL; + + error = intf_->GetPanelBrightness(&level); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&level), + sizeof(uint32_t)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseMinHdcpEncryptionLevelChanged( + const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct MinHdcpEncLevelChangedParams *min_hdcp_enc_level_data; + int32_t error = 0; + + const uint8_t *data = input_params.data(); + min_hdcp_enc_level_data = reinterpret_cast<const MinHdcpEncLevelChangedParams*>(data); + error = intf_->MinHdcpEncryptionLevelChanged(min_hdcp_enc_level_data->dpy, + min_hdcp_enc_level_data->min_enc_level); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseRefreshScreen(perform_cb _hidl_cb) { + int32_t error = intf_->RefreshScreen(); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseControlPartialUpdate(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct PartialUpdateParams *partial_update_data; + int32_t error = 0; + + const uint8_t *data = input_params.data(); + partial_update_data = reinterpret_cast<const PartialUpdateParams*>(data); + error = intf_->ControlPartialUpdate(partial_update_data->dpy, partial_update_data->enable); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseToggleScreenUpdate(const ByteStream &input_params, + perform_cb _hidl_cb) { + const bool *on; + int32_t error = 0; + + const uint8_t *data = input_params.data(); + on = reinterpret_cast<const bool*>(data); + error = intf_->ToggleScreenUpdate(on); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetIdleTimeout(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint32_t *timeout_value; + + const uint8_t *data = input_params.data(); + timeout_value = reinterpret_cast<const uint32_t*>(data); + int32_t error = intf_->SetIdleTimeout(*timeout_value); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetHdrCapabilities(const ByteStream &input_params, + perform_cb _hidl_cb) { + const DisplayType *dpy; + ByteStream output_params; + struct HDRCapsParams hdr_caps; + int32_t *data_output; + int32_t error = -EINVAL; + + const uint8_t *data = input_params.data(); + dpy = reinterpret_cast<const DisplayType*>(data); + error = intf_->GetHDRCapabilities(*dpy, &hdr_caps); + + data_output = reinterpret_cast<int32_t *>(malloc(sizeof(int32_t) * + hdr_caps.supported_hdr_types.size() + 3 * sizeof(float))); + if (data_output != NULL) { + for (int i = 0; i < hdr_caps.supported_hdr_types.size(); i++) { + data_output[i] = hdr_caps.supported_hdr_types[i]; + } + float *lum = reinterpret_cast<float *>(&data_output[hdr_caps.supported_hdr_types.size()]); + *lum = hdr_caps.max_luminance; + lum++; + *lum = hdr_caps.max_avg_luminance; + lum++; + *lum = hdr_caps.min_luminance; + output_params.setToExternal(reinterpret_cast<uint8_t*>(data_output), sizeof(int32_t) * + hdr_caps.supported_hdr_types.size() + 3 * sizeof(float)); + _hidl_cb(error, output_params, {}); + } + else { + _hidl_cb(-EINVAL, {}, {}); + } +} + +void DeviceImpl::DeviceClientContext::ParseSetCameraLaunchStatus(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint32_t *launch_status_data; + + const uint8_t *data = input_params.data(); + launch_status_data = reinterpret_cast<const uint32_t*>(data); + + int32_t error = intf_->SetCameraLaunchStatus(*launch_status_data); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseDisplayBwTransactionPending(perform_cb _hidl_cb) { + bool status = true; + ByteStream output_params; + + int32_t error = intf_->DisplayBWTransactionPending(&status); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&status), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetDisplayAnimating(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct AnimationParams *display_animating_data; + + const uint8_t *data = input_params.data(); + display_animating_data = reinterpret_cast<const AnimationParams*>(data); + int32_t error = intf_->SetDisplayAnimating(display_animating_data->display_id, + display_animating_data->animating); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseControlIdlePowerCollapse(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct IdlePcParams *idle_pc_data; + + const uint8_t *data = input_params.data(); + idle_pc_data = reinterpret_cast<const IdlePcParams*>(data); + int32_t error = intf_->ControlIdlePowerCollapse(idle_pc_data->enable, idle_pc_data->synchronous); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetWritebackCapabilities(perform_cb _hidl_cb) { + bool is_wb_ubwc_supported = false; + int32_t error = intf_->GetWriteBackCapabilities(&is_wb_ubwc_supported); + ByteStream output_params; + output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_wb_ubwc_supported), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetDisplayDppsAdRoi(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct DppsAdRoiParams *ad_roi_data; + + const uint8_t *data = input_params.data(); + ad_roi_data = reinterpret_cast<const DppsAdRoiParams*>(data); + + int32_t error = intf_->SetDisplayDppsAdROI(ad_roi_data->display_id, ad_roi_data->h_start, + ad_roi_data->h_end, ad_roi_data->v_start, + ad_roi_data->v_end, ad_roi_data->factor_in, + ad_roi_data->factor_out); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseUpdateVsyncSourceOnPowerModeOff(perform_cb _hidl_cb) { + int32_t error = intf_->UpdateVSyncSourceOnPowerModeOff(); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseUpdateVsyncSourceOnPowerModeDoze(perform_cb _hidl_cb) { + int32_t error = intf_->UpdateVSyncSourceOnPowerModeDoze(); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetPowerMode(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct PowerModeParams *set_power_mode_data; + + const uint8_t *data = input_params.data(); + set_power_mode_data = reinterpret_cast<const PowerModeParams*>(data); + int32_t error = intf_->SetPowerMode(set_power_mode_data->disp_id, + set_power_mode_data->power_mode); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsPowerModeOverrideSupported( + const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint8_t *data = input_params.data(); + const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data); + bool supported = false; + int32_t error = intf_->IsPowerModeOverrideSupported(*disp_id, &supported); + ByteStream output_params; + output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsHdrSupported(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint8_t *data = input_params.data(); + const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data); + bool supported = false; + int32_t error = intf_->IsHDRSupported(*disp_id, &supported); + ByteStream output_params; + output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsWcgSupported(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint8_t *data = input_params.data(); + const int32_t *disp_id = reinterpret_cast<const int32_t*>(data); + bool supported = false; + int32_t error = intf_->IsWCGSupported(*disp_id, &supported); + ByteStream output_params; + output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetLayerAsMask(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct LayerMaskParams *layer_mask_data; + + const uint8_t *data = input_params.data(); + layer_mask_data = reinterpret_cast<const LayerMaskParams*>(data); + int32_t error = intf_->SetLayerAsMask(layer_mask_data->disp_id, layer_mask_data->layer_id); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetDebugProperty(const ByteStream &input_params, + perform_cb _hidl_cb) { + std::string value; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + const char *name = reinterpret_cast<const char *>(data); + std::string prop_name(name); + int32_t error = intf_->GetDebugProperty(prop_name, &value); + value += '\0'; + uint8_t *data_output = reinterpret_cast<uint8_t*>(value.data()); + output_params.setToExternal(reinterpret_cast<uint8_t*>(data_output), + value.size() * sizeof(char)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetActiveBuiltinDisplayAttributes(perform_cb _hidl_cb) { + struct Attributes attr; + ByteStream output_params; + + int32_t error = intf_->GetActiveBuiltinDisplayAttributes(&attr); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&attr), sizeof(Attributes)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetPanelLuminanceAttributes( + const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct PanelLumAttrParams *panel_lum_attr_data; + + const uint8_t *data = input_params.data(); + panel_lum_attr_data = reinterpret_cast<const PanelLumAttrParams*>(data); + int32_t error = intf_->SetPanelLuminanceAttributes(panel_lum_attr_data->disp_id, + panel_lum_attr_data->min_lum, + panel_lum_attr_data->max_lum); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsBuiltinDisplay(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint32_t *disp_id; + bool is_builtin = false; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + disp_id = reinterpret_cast<const uint32_t*>(data); + int32_t error = intf_->IsBuiltInDisplay(*disp_id, &is_builtin); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_builtin), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetCwbOutputBuffer(uint64_t clientHandle, + const ByteStream &input_params, + const HandleStream &input_handles, + perform_cb _hidl_cb) { + const struct CwbBufferParams *cwb_buffer_data; + + const uint8_t *data = input_params.data(); + cwb_buffer_data = reinterpret_cast<const CwbBufferParams*>(data); + hidl_handle buffer = input_handles[0]; + + if (!callback_ || !buffer.getNativeHandle()) { + _hidl_cb(-1, {}, {}); + return; + } + + int32_t error = intf_->SetCWBOutputBuffer(cwb_buffer_data->disp_id , cwb_buffer_data->rect, + cwb_buffer_data->post_processed, + buffer.getNativeHandle()); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetSupportedDsiBitclks(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint32_t *disp_id; + ByteStream output_params; + std::vector<uint64_t> bit_clks; + uint64_t *bit_clks_data; + + const uint8_t *data = input_params.data(); + disp_id = reinterpret_cast<const uint32_t*>(data); + int32_t error = intf_->GetSupportedDSIBitClks(*disp_id, &bit_clks); + + bit_clks_data = reinterpret_cast<uint64_t *>(malloc(sizeof(uint64_t) * bit_clks.size())); + if (bit_clks_data == NULL) { + _hidl_cb(-EINVAL, {}, {}); + return; + } + for (int i = 0; i < bit_clks.size(); i++) { + bit_clks_data[i] = bit_clks[i]; + } + output_params.setToExternal(reinterpret_cast<uint8_t*>(bit_clks_data), + sizeof(uint64_t) * bit_clks.size()); + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetDsiClk(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint32_t *disp_id; + uint64_t bit_clk = 0; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + disp_id = reinterpret_cast<const uint32_t*>(data); + int32_t error = intf_->GetDSIClk(*disp_id, &bit_clk); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&bit_clk), + sizeof(uint64_t)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetDsiClk(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct DsiClkParams *set_dsi_clk_data; + + const uint8_t *data = input_params.data(); + set_dsi_clk_data = reinterpret_cast<const DsiClkParams*>(data); + int32_t error = intf_->SetDSIClk(set_dsi_clk_data->disp_id, set_dsi_clk_data->bit_clk); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSetQsyncMode(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct QsyncModeParams *set_qsync_mode_data; + + const uint8_t *data = input_params.data(); + set_qsync_mode_data = reinterpret_cast<const QsyncModeParams*>(data); + int32_t error = intf_->SetQsyncMode(set_qsync_mode_data->disp_id, set_qsync_mode_data->mode); + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsSmartPanelConfig(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct SmartPanelCfgParams *smart_panel_cfg_data; + bool is_smart = false; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + smart_panel_cfg_data = reinterpret_cast<const SmartPanelCfgParams*>(data); + int32_t error = intf_->IsSmartPanelConfig(smart_panel_cfg_data->disp_id, + smart_panel_cfg_data->config_id, &is_smart); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_smart), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsAsyncVdsSupported(perform_cb _hidl_cb) { + bool is_supported = false; + int32_t error = intf_->IsAsyncVDSCreationSupported(&is_supported); + ByteStream output_params; + output_params.setToExternal(reinterpret_cast<uint8_t*>(&is_supported), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseCreateVirtualDisplay(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct VdsParams *vds_input_data; + + const uint8_t *data = input_params.data(); + vds_input_data = reinterpret_cast<const VdsParams*>(data); + + int32_t error = intf_->CreateVirtualDisplay(vds_input_data->width, vds_input_data->height, + vds_input_data->format); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsRotatorSupportedFormat(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct RotatorFormatParams *input_data; + bool supported = false; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + input_data = reinterpret_cast<const RotatorFormatParams*>(data); + int32_t error = intf_->IsRotatorSupportedFormat(input_data->hal_format, input_data->ubwc, + &supported); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), + sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseControlQsyncCallback(uint64_t client_handle, + const ByteStream &input_params, + perform_cb _hidl_cb) { + const bool *enable; + + const uint8_t *data = input_params.data(); + enable = reinterpret_cast<const bool*>(data); + + int32_t error = intf_->ControlQsyncCallback(*enable); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseControlIdleStatusCallback(uint64_t client_handle, + const ByteStream &input_params, + perform_cb _hidl_cb) { + const bool *enable; + + const uint8_t *data = input_params.data(); + enable = reinterpret_cast<const bool*>(data); + + int32_t error = intf_->ControlIdleStatusCallback(*enable); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseSendTUIEvent(const ByteStream &input_params, + perform_cb _hidl_cb) { + const struct TUIEventParams *input_data = + reinterpret_cast<const TUIEventParams*>(input_params.data()); + + int32_t error = intf_->SendTUIEvent(input_data->dpy, input_data->tui_event_type); + + _hidl_cb(error, {}, {}); +} + +void DeviceImpl::ParseDestroy(uint64_t client_handle, perform_cb _hidl_cb) { + auto itr = display_config_map_.find(client_handle); + if (itr == display_config_map_.end()) { + _hidl_cb(-EINVAL, {}, {}); + return; + } + + std::shared_ptr<DeviceClientContext> client = itr->second; + if (client != NULL) { + sp<IDisplayConfigCallback> callback = client->GetDeviceConfigCallback(); + callback->unlinkToDeath(this); + ConfigInterface *intf = client->GetDeviceConfigIntf(); + intf_->UnRegisterClientContext(intf); + client.reset(); + display_config_map_.erase(itr); + } + + _hidl_cb(0, {}, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetDisplayHwId(const ByteStream &input_params, + perform_cb _hidl_cb) { + uint32_t disp_hw_id = 0; + ByteStream output_params; + + const uint8_t *data = input_params.data(); + const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data); + int32_t error = intf_->GetDisplayHwId(*disp_id, &disp_hw_id); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_hw_id), sizeof(uint32_t)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetSupportedDisplayRefreshRates( + const ByteStream &input_params, perform_cb _hidl_cb) { + ByteStream output_params; + std::vector<uint32_t> refresh_rates; + + const uint8_t *data = input_params.data(); + const DisplayType *dpy = reinterpret_cast<const DisplayType *>(data); + int32_t error = intf_->GetSupportedDisplayRefreshRates(*dpy, &refresh_rates); + + uint32_t *refresh_rates_data = + reinterpret_cast<uint32_t *>(malloc(sizeof(uint32_t) * refresh_rates.size())); + if (refresh_rates_data) { + for (int i = 0; i < refresh_rates.size(); i++) { + refresh_rates_data[i] = refresh_rates[i]; + } + output_params.setToExternal(reinterpret_cast<uint8_t *>(refresh_rates_data), + sizeof(uint32_t) * refresh_rates.size()); + _hidl_cb(error, output_params, {}); + } else { + _hidl_cb(-EINVAL, {}, {}); + } +} + +void DeviceImpl::DeviceClientContext::ParseIsRCSupported(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint8_t *data = input_params.data(); + const uint32_t *disp_id = reinterpret_cast<const uint32_t*>(data); + bool supported = false; + int32_t error = intf_->IsRCSupported(*disp_id, &supported); + ByteStream output_params; + output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), sizeof(bool)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseIsSupportedConfigSwitch(const ByteStream &input_params, + perform_cb _hidl_cb) { + if (!intf_) { + _hidl_cb(-EINVAL, {}, {}); + return; + } + + const struct SupportedModesParams *supported_modes_data; + const uint8_t *data = input_params.data(); + bool supported = false; + ByteStream output_params; + supported_modes_data = reinterpret_cast<const SupportedModesParams*>(data); + + int32_t error = intf_->IsSupportedConfigSwitch(supported_modes_data->disp_id, + supported_modes_data->mode, &supported); + output_params.setToExternal(reinterpret_cast<uint8_t*>(&supported), sizeof(bool)); + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseGetDisplayType(const ByteStream &input_params, + perform_cb _hidl_cb) { + const uint8_t *data = input_params.data(); + const uint64_t *physical_disp_id = reinterpret_cast<const uint64_t*>(data); + DisplayType disp_type = DisplayConfig::DisplayType::kInvalid; + int32_t error = intf_->GetDisplayType(*physical_disp_id, &disp_type); + ByteStream output_params; + output_params.setToExternal(reinterpret_cast<uint8_t*>(&disp_type), sizeof(DisplayType)); + + _hidl_cb(error, output_params, {}); +} + +void DeviceImpl::DeviceClientContext::ParseAllowIdleFallback(perform_cb _hidl_cb) { + int32_t error = intf_->AllowIdleFallback(); + _hidl_cb(error, {}, {}); +} + +Return<void> DeviceImpl::perform(uint64_t client_handle, uint32_t op_code, + const ByteStream &input_params, const HandleStream &input_handles, + perform_cb _hidl_cb) { + int32_t error = 0; + auto itr = display_config_map_.find(client_handle); + if (itr == display_config_map_.end()) { + error = -EINVAL; + _hidl_cb(error, {}, {}); + return Void(); + } + + std::shared_ptr<DeviceClientContext> client = itr->second; + if (!client) { + error = -EINVAL; + _hidl_cb(error, {}, {}); + return Void(); + } + switch (op_code) { + case kIsDisplayConnected: + client->ParseIsDisplayConnected(input_params, _hidl_cb); + break; + case kSetDisplayStatus: + client->ParseSetDisplayStatus(input_params, _hidl_cb); + break; + case kConfigureDynRefreshRate: + client->ParseConfigureDynRefreshRate(input_params, _hidl_cb); + break; + case kGetConfigCount: + client->ParseGetConfigCount(input_params, _hidl_cb); + break; + case kGetActiveConfig: + client->ParseGetActiveConfig(input_params, _hidl_cb); + break; + case kSetActiveConfig: + client->ParseSetActiveConfig(input_params, _hidl_cb); + break; + case kGetDisplayAttributes: + client->ParseGetDisplayAttributes(input_params, _hidl_cb); + break; + case kSetPanelBrightness: + client->ParseSetPanelBrightness(input_params, _hidl_cb); + break; + case kGetPanelBrightness: + client->ParseGetPanelBrightness(_hidl_cb); + break; + case kMinHdcpEncryptionLevelChanged: + client->ParseMinHdcpEncryptionLevelChanged(input_params, _hidl_cb); + break; + case kRefreshScreen: + client->ParseRefreshScreen(_hidl_cb); + break; + case kControlPartialUpdate: + client->ParseControlPartialUpdate(input_params, _hidl_cb); + break; + case kToggleScreenUpdate: + client->ParseToggleScreenUpdate(input_params, _hidl_cb); + break; + case kSetIdleTimeout: + client->ParseSetIdleTimeout(input_params, _hidl_cb); + break; + case kGetHdrCapabilities: + client->ParseGetHdrCapabilities(input_params, _hidl_cb); + break; + case kSetCameraLaunchStatus: + client->ParseSetCameraLaunchStatus(input_params, _hidl_cb); + break; + case kDisplayBwTransactionPending: + client->ParseDisplayBwTransactionPending(_hidl_cb); + break; + case kSetDisplayAnimating: + client->ParseSetDisplayAnimating(input_params, _hidl_cb); + break; + case kControlIdlePowerCollapse: + client->ParseControlIdlePowerCollapse(input_params, _hidl_cb); + break; + case kGetWritebackCapabilities: + client->ParseGetWritebackCapabilities(_hidl_cb); + break; + case kSetDisplayDppsAdRoi: + client->ParseSetDisplayDppsAdRoi(input_params, _hidl_cb); + break; + case kUpdateVsyncSourceOnPowerModeOff: + client->ParseUpdateVsyncSourceOnPowerModeOff(_hidl_cb); + break; + case kUpdateVsyncSourceOnPowerModeDoze: + client->ParseUpdateVsyncSourceOnPowerModeDoze(_hidl_cb); + break; + case kSetPowerMode: + client->ParseSetPowerMode(input_params, _hidl_cb); + break; + case kIsPowerModeOverrideSupported: + client->ParseIsPowerModeOverrideSupported(input_params, _hidl_cb); + break; + case kIsHdrSupported: + client->ParseIsHdrSupported(input_params, _hidl_cb); + break; + case kIsWcgSupported: + client->ParseIsWcgSupported(input_params, _hidl_cb); + break; + case kSetLayerAsMask: + client->ParseSetLayerAsMask(input_params, _hidl_cb); + break; + case kGetDebugProperty: + client->ParseGetDebugProperty(input_params, _hidl_cb); + break; + case kGetActiveBuiltinDisplayAttributes: + client->ParseGetActiveBuiltinDisplayAttributes(_hidl_cb); + break; + case kSetPanelLuminanceAttributes: + client->ParseSetPanelLuminanceAttributes(input_params, _hidl_cb); + break; + case kIsBuiltinDisplay: + client->ParseIsBuiltinDisplay(input_params, _hidl_cb); + break; + case kSetCwbOutputBuffer: + client->ParseSetCwbOutputBuffer(client_handle, input_params, input_handles, _hidl_cb); + break; + case kGetSupportedDsiBitclks: + client->ParseGetSupportedDsiBitclks(input_params, _hidl_cb); + break; + case kGetDsiClk: + client->ParseGetDsiClk(input_params, _hidl_cb); + break; + case kSetDsiClk: + client->ParseSetDsiClk(input_params, _hidl_cb); + break; + case kSetQsyncMode: + client->ParseSetQsyncMode(input_params, _hidl_cb); + break; + case kIsSmartPanelConfig: + client->ParseIsSmartPanelConfig(input_params, _hidl_cb); + break; + case kIsAsyncVdsSupported: + client->ParseIsAsyncVdsSupported(_hidl_cb); + break; + case kCreateVirtualDisplay: + client->ParseCreateVirtualDisplay(input_params, _hidl_cb); + break; + case kIsRotatorSupportedFormat: + client->ParseIsRotatorSupportedFormat(input_params, _hidl_cb); + break; + case kControlQsyncCallback: + client->ParseControlQsyncCallback(client_handle, input_params, _hidl_cb); + break; + case kControlIdleStatusCallback: + client->ParseControlIdleStatusCallback(client_handle, input_params, _hidl_cb); + break; + case kSendTUIEvent: + client->ParseSendTUIEvent(input_params, _hidl_cb); + break; + case kDestroy: + ParseDestroy(client_handle, _hidl_cb); + break; + case kGetDisplayHwId: + client->ParseGetDisplayHwId(input_params, _hidl_cb); + break; + case kGetSupportedDisplayRefreshRates: + client->ParseGetSupportedDisplayRefreshRates(input_params, _hidl_cb); + break; + case kIsRCSupported: + client->ParseIsRCSupported(input_params, _hidl_cb); + break; + case kIsSupportedConfigSwitch: + client->ParseIsSupportedConfigSwitch(input_params, _hidl_cb); + break; + case kGetDisplayType: + client->ParseGetDisplayType(input_params, _hidl_cb); + break; + case kAllowIdleFallback: + client->ParseAllowIdleFallback(_hidl_cb); + break; + case kDummyOpcode: + _hidl_cb(-EINVAL, {}, {}); + break; + default: + _hidl_cb(-EINVAL, {}, {}); + break; + } + return Void(); +} + +} // namespace DisplayConfig diff --git a/services/config/src/device_impl.h b/services/config/src/device_impl.h new file mode 100644 index 00000000..4c22a47d --- /dev/null +++ b/services/config/src/device_impl.h @@ -0,0 +1,153 @@ +/* +* Copyright (c) 2021 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. +*/ + +#ifndef __DEVICE_IMPL_H__ +#define __DEVICE_IMPL_H__ + +#include <vendor/display/config/2.0/IDisplayConfig.h> +#include <hidl/HidlSupport.h> +#include <log/log.h> +#include <config/device_interface.h> +#include <map> +#include <utility> +#include <string> +#include <vector> + +#include "opcode_types.h" + +namespace DisplayConfig { + +using vendor::display::config::V2_0::IDisplayConfig; +using vendor::display::config::V2_0::IDisplayConfigCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_handle; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::sp; + +typedef hidl_vec<uint8_t> ByteStream; +typedef hidl_vec<hidl_handle> HandleStream; + +class DeviceImpl : public IDisplayConfig, public android::hardware::hidl_death_recipient { + public: + static int CreateInstance(ClientContext *intf); + + private: + class DeviceClientContext : public ConfigCallback { + public: + explicit DeviceClientContext(const sp<IDisplayConfigCallback> callback); + + void SetDeviceConfigIntf(ConfigInterface *intf); + ConfigInterface* GetDeviceConfigIntf(); + sp<IDisplayConfigCallback> GetDeviceConfigCallback(); + + virtual void NotifyCWBBufferDone(int32_t error, const native_handle_t *buffer); + virtual void NotifyQsyncChange(bool qsync_enabled, int32_t refresh_rate, + int32_t qsync_refresh_rate); + virtual void NotifyIdleStatus(bool is_idle); + + void ParseIsDisplayConnected(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetDisplayStatus(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseConfigureDynRefreshRate(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetConfigCount(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetActiveConfig(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetActiveConfig(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetDisplayAttributes(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetPanelBrightness(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetPanelBrightness(perform_cb _hidl_cb); + void ParseMinHdcpEncryptionLevelChanged(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseRefreshScreen(perform_cb _hidl_cb); + void ParseControlPartialUpdate(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseToggleScreenUpdate(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetIdleTimeout(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetHdrCapabilities(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetCameraLaunchStatus(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseDisplayBwTransactionPending(perform_cb _hidl_cb); + void ParseSetDisplayAnimating(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseControlIdlePowerCollapse(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetWritebackCapabilities(perform_cb _hidl_cb); + void ParseSetDisplayDppsAdRoi(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseUpdateVsyncSourceOnPowerModeOff(perform_cb _hidl_cb); + void ParseUpdateVsyncSourceOnPowerModeDoze(perform_cb _hidl_cb); + void ParseSetPowerMode(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsPowerModeOverrideSupported(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsHdrSupported(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsWcgSupported(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetLayerAsMask(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetDebugProperty(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetActiveBuiltinDisplayAttributes(perform_cb _hidl_cb); + void ParseSetPanelLuminanceAttributes(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsBuiltinDisplay(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetCwbOutputBuffer(uint64_t clientHandle, const ByteStream &input_params, + const HandleStream &inputHandles, perform_cb _hidl_cb); + void ParseGetSupportedDsiBitclks(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetDsiClk(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetDsiClk(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseSetQsyncMode(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsSmartPanelConfig(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsAsyncVdsSupported(perform_cb _hidl_cb); + void ParseCreateVirtualDisplay(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsRotatorSupportedFormat(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseControlQsyncCallback(uint64_t client_handle, const ByteStream &input_params, + perform_cb _hidl_cb); + void ParseSendTUIEvent(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetDisplayHwId(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetSupportedDisplayRefreshRates(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseIsRCSupported(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseControlIdleStatusCallback(uint64_t client_handle, const ByteStream &input_params, + perform_cb _hidl_cb); + void ParseIsSupportedConfigSwitch(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseGetDisplayType(const ByteStream &input_params, perform_cb _hidl_cb); + void ParseAllowIdleFallback(perform_cb _hidl_cb); + + private: + ConfigInterface *intf_ = nullptr; + const sp<IDisplayConfigCallback> callback_; + }; + + Return<void> registerClient(const hidl_string &client_name, const sp<IDisplayConfigCallback>& cb, + registerClient_cb _hidl_cb) override; + Return<void> perform(uint64_t client_handle, uint32_t op_code, const ByteStream &input_params, + const HandleStream &input_handles, perform_cb _hidl_cb) override; + void serviceDied(uint64_t client_handle, + const android::wp<::android::hidl::base::V1_0::IBase>& callback); + void ParseDestroy(uint64_t client_handle, perform_cb _hidl_cb); + + ClientContext *intf_ = nullptr; + std::map<uint64_t, std::shared_ptr<DeviceClientContext>> display_config_map_; + uint64_t client_id_ = 0; + std::mutex death_service_mutex_; + static DeviceImpl *device_obj_; + static std::mutex device_lock_; +}; + +} // namespace DisplayConfig + +#endif // __DEVICE_IMPL_H__ diff --git a/services/config/src/device_interface.cpp b/services/config/src/device_interface.cpp new file mode 100644 index 00000000..0c2d6b73 --- /dev/null +++ b/services/config/src/device_interface.cpp @@ -0,0 +1,42 @@ +/* +* Copyright (c) 2020 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 "device_impl.h" + +namespace DisplayConfig { + +int DeviceInterface::RegisterDevice(ClientContext *intf) { + if (!intf) { + return -1; + } + + return DeviceImpl::CreateInstance(intf); +} + +} // namespace DisplayConfig diff --git a/services/config/src/opcode_types.h b/services/config/src/opcode_types.h new file mode 100644 index 00000000..4813e47d --- /dev/null +++ b/services/config/src/opcode_types.h @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2020-2021 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. +*/ + +#ifndef __OPCODE_TYPES_H__ +#define __OPCODE_TYPES_H__ + +namespace DisplayConfig { + +enum OpCode { + kIsDisplayConnected = 0, + kSetDisplayStatus = 1, + kConfigureDynRefreshRate = 2, + kGetConfigCount = 3, + kGetActiveConfig = 4, + kSetActiveConfig = 5, + kGetDisplayAttributes = 6, + kSetPanelBrightness = 7, + kGetPanelBrightness = 8, + kMinHdcpEncryptionLevelChanged = 9, + kRefreshScreen = 10, + kControlPartialUpdate = 11, + kToggleScreenUpdate = 12, + kSetIdleTimeout = 13, + kGetHdrCapabilities = 14, + kSetCameraLaunchStatus = 15, + kDisplayBwTransactionPending = 16, + kSetDisplayAnimating = 17, + kControlIdlePowerCollapse = 18, + kGetWritebackCapabilities = 19, + kSetDisplayDppsAdRoi = 20, + kUpdateVsyncSourceOnPowerModeOff = 21, + kUpdateVsyncSourceOnPowerModeDoze = 22, + kSetPowerMode = 23, + kIsPowerModeOverrideSupported = 24, + kIsHdrSupported = 25, + kIsWcgSupported = 26, + kSetLayerAsMask = 27, + kGetDebugProperty = 28, + kGetActiveBuiltinDisplayAttributes = 29, + kSetPanelLuminanceAttributes = 30, + kIsBuiltinDisplay = 31, + kSetCwbOutputBuffer = 32, + kGetSupportedDsiBitclks = 33, + kGetDsiClk = 34, + kSetDsiClk = 35, + kSetQsyncMode = 36, + kIsSmartPanelConfig = 37, + kIsAsyncVdsSupported = 38, + kCreateVirtualDisplay = 39, + kIsRotatorSupportedFormat = 40, + kControlQsyncCallback = 41, + kSendTUIEvent = 42, + kGetDisplayHwId = 43, + kGetSupportedDisplayRefreshRates = 44, + kIsRCSupported = 45, + kControlIdleStatusCallback = 46, + kIsSupportedConfigSwitch = 47, + kGetDisplayType = 48, + kAllowIdleFallback = 49, + kDummyOpcode = 50, + + kDestroy = 0xFFFF, // Destroy sequence execution +}; + +} // namespace DisplayConfig + +#endif // __OPCODE_TYPES_H__ |