diff --git a/Android.bp b/Android.bp index cb3ac78c..541adbce 100644 --- a/Android.bp +++ b/Android.bp @@ -49,6 +49,8 @@ cc_defaults { "libsync", "libui", "libutils", + "libbinder", + "libhwcservice", ], include_dirs: ["vendor/intel/external/drm-hwcomposer"], @@ -68,6 +70,10 @@ cc_defaults { "-DHWC2_USE_CPP11", "-std=c++17", "-DUSE_IMAPPER4_METADATA_API", + "-Wno-unused-parameter", + "-Wno-unused-private-field", + "-Wno-unused-function", + "-frtti", ], product_variables: { @@ -111,6 +117,7 @@ filegroup { "hwc2_device/HwcDisplayConfigs.cpp", "hwc2_device/HwcLayer.cpp", "hwc2_device/hwc2_device.cpp", + "hwc2_device/hwcservice.cpp", ], } diff --git a/drm/DrmAtomicStateManager.cpp b/drm/DrmAtomicStateManager.cpp index 7e7870c0..2cb75293 100644 --- a/drm/DrmAtomicStateManager.cpp +++ b/drm/DrmAtomicStateManager.cpp @@ -675,4 +675,73 @@ auto DrmAtomicStateManager::SetColorBrightnessContrast(void) ->int{ return 0; } + +void DrmAtomicStateManager::SetHDCPState(HWCContentProtection state, + HWCContentType content_type) { + uint64_t value = 3; + uint64_t type = 3; + int ret =0; + + auto *connector = pipe_->connector->Get(); + + if (!connector->IsConnected()) + return; + + desired_protection_support_ = state; + + if (desired_protection_support_ == current_protection_support_) + return; + + if (pipe_->connector->Get()->GetHdcpTypeProperty().id() <= 0) { + ALOGE("Cannot set HDCP state as Type property is not supported \n"); + return; + } + + std::tie(ret, type) = pipe_->connector->Get()->GetHdcpTypeProperty().value(); + + if ((content_type < 2) && (content_type_ != content_type)) { + content_type_ = content_type; + + drmModeConnectorSetProperty(pipe_->device->GetFd(), + pipe_->connector->Get()->GetId(), + pipe_->connector->Get()->GetHdcpTypeProperty().id(), + content_type); + + } + + if (pipe_->connector->Get()->GetHdcpProperty().id() <= 0) { + ALOGE("Cannot set HDCP state as Connector property is not supported \n"); + return; + } + + std::tie(ret, value) = pipe_->connector->Get()->GetHdcpProperty().value(); + + if (value < 3) { + switch (value) { + case 0: + current_protection_support_ = hwcomposer::HWCContentProtection::kUnDesired; + break; + case 1: + current_protection_support_ = hwcomposer::HWCContentProtection::kDesired; + break; + default: + ALOGE("%s GetHDCPConnectorProperty default", __FUNCTION__); + break; + } + } + + if (desired_protection_support_ == HWCContentProtection::kUnSupported) { + desired_protection_support_ = current_protection_support_; + } + + current_protection_support_ = desired_protection_support_; + if (current_protection_support_ == kDesired) { + value = 1; + } + + drmModeConnectorSetProperty(pipe_->device->GetFd(), + pipe_->connector->Get()->GetId(), + pipe_->connector->Get()->GetHdcpProperty().id(), + value); +} } // namespace android diff --git a/drm/DrmAtomicStateManager.h b/drm/DrmAtomicStateManager.h index 2661df21..10bbe380 100644 --- a/drm/DrmAtomicStateManager.h +++ b/drm/DrmAtomicStateManager.h @@ -111,6 +111,8 @@ class DrmAtomicStateManager { uint32_t brightness_c) ->int; auto ApplyPendingLUT(struct drm_color_lut *lut, uint64_t lut_size) -> int; + void SetHDCPState(HWCContentProtection state, + HWCContentType content_type); private: auto CommitFrame(AtomicCommitArgs &args) -> int; @@ -156,6 +158,12 @@ class DrmAtomicStateManager { int frames_staged_{}; int frames_tracked_{}; bool hdr_mdata_set_ = false; + + hwcomposer::HWCContentProtection current_protection_support_ = + hwcomposer::HWCContentProtection::kUnSupported; + hwcomposer::HWCContentProtection desired_protection_support_ = + hwcomposer::HWCContentProtection::kUnSupported; + hwcomposer::HWCContentType content_type_ = hwcomposer::kCONTENT_TYPE0; }; } // namespace android diff --git a/drm/DrmConnector.cpp b/drm/DrmConnector.cpp index dc6f9310..32104efd 100644 --- a/drm/DrmConnector.cpp +++ b/drm/DrmConnector.cpp @@ -73,6 +73,14 @@ auto DrmConnector::CreateInstance(DrmDevice &dev, uint32_t connector_id, auto c = std::unique_ptr( new DrmConnector(std::move(conn), &dev, index)); + if (!GetConnectorProperty(dev, *c, "Content Protection", &c->hdcp_id_property_)) { + ALOGE("%s GetHDCPConnectorProperty check failed!", __FUNCTION__); + } + + if (!GetConnectorProperty(dev, *c, "HDCP Content Type", &c->hdcp_type_property_)) { + ALOGE("%s GetHDCPTypeProperty check failed!", __FUNCTION__); + } + if (!GetConnectorProperty(dev, *c, "DPMS", &c->dpms_property_) || !GetConnectorProperty(dev, *c, "CRTC_ID", &c->crtc_id_property_) || (dev.IsHdrSupportedDevice() && !GetConnectorProperty(dev, *c, "HDR_OUTPUT_METADATA", &c->hdr_op_metadata_prop_))) { diff --git a/drm/DrmConnector.h b/drm/DrmConnector.h index 456a879a..e7b600d9 100644 --- a/drm/DrmConnector.h +++ b/drm/DrmConnector.h @@ -31,6 +31,7 @@ #include "DrmUnique.h" #include "utils/hdr_metadata_defs.h" #include "utils/cta_hdr_defs.h" +#include "utils/hwcdefs.h" namespace android { @@ -114,6 +115,13 @@ class DrmConnector : public PipelineBindable { return hdr_metadata_; } + auto &GetHdcpProperty() const { + return hdcp_id_property_; + } + + auto &GetHdcpTypeProperty() const { + return hdcp_type_property_; + } auto IsConnected() const { return connector_->connection == DRM_MODE_CONNECTED; @@ -144,7 +152,8 @@ class DrmConnector : public PipelineBindable { void PrepareHdrMetadata(hdr_md *layer_hdr_metadata, struct hdr_output_metadata *final_hdr_metadata); - + void SetHDCPState(hwcomposer::HWCContentProtection state, + hwcomposer::HWCContentType content_type); const DrmProperty &link_status_property() const; private: DrmConnector(DrmModeConnectorUnique connector, DrmDevice *drm, uint32_t index) @@ -167,6 +176,8 @@ class DrmConnector : public PipelineBindable { DrmProperty writeback_fb_id_; DrmProperty writeback_out_fence_; DrmProperty link_status_property_; + DrmProperty hdcp_id_property_; + DrmProperty hdcp_type_property_; uint32_t preferred_mode_id_{}; //hdr_output_metadata property diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h index 61bc0e2a..d75aab66 100644 --- a/drm/DrmDevice.h +++ b/drm/DrmDevice.h @@ -26,6 +26,7 @@ #include "DrmEncoder.h" #include "DrmFbImporter.h" #include "utils/UniqueFd.h" +#include "utils/hwcdefs.h" #define DRM_FORMAT_NV12_Y_TILED_INTEL fourcc_code('9', '9', '9', '6') namespace android { diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp index 40bbd843..ef407312 100644 --- a/drm/ResourceManager.cpp +++ b/drm/ResourceManager.cpp @@ -22,6 +22,8 @@ #include #include +#include +#include #include "bufferinfo/BufferInfoGetter.h" #include "drm/DrmAtomicStateManager.h" @@ -177,10 +179,22 @@ void ResourceManager::Init() { }); UpdateFrontendDisplays(); - + pt_ = std::thread(&ResourceManager::HwcServiceThread, this); initialized_ = true; } +void ResourceManager::HwcServiceThread() { + this->hwcService_.Start((DrmHwcTwo*)frontend_interface_); + sp proc(ProcessState::self()); + if (!proc.get()) + { + ALOGE("Error: Fail to new ProcessState."); + return; + } + proc->startThreadPool(); + IPCThreadState::self()->joinThreadPool(); +} + void ResourceManager::DeInit() { if (!initialized_) { ALOGE("Not initialized"); diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h index c4450116..6f8f6937 100644 --- a/drm/ResourceManager.h +++ b/drm/ResourceManager.h @@ -23,6 +23,7 @@ #include "DrmDisplayPipeline.h" #include "DrmFbImporter.h" #include "UEventListener.h" +#include "hwc2_device/hwcservice.h" namespace android { class HwcDisplay; @@ -64,6 +65,7 @@ class ResourceManager { void UpdateFrontendDisplays(); void DetachAllFrontendDisplays(); void ReloadNode(); + void HwcServiceThread(); std::vector> drms_; @@ -81,6 +83,8 @@ class ResourceManager { bool initialized_{}; int card_num_ = 0; bool reloaded_{}; + android::HwcService hwcService_; + std::thread pt_; }; } // namespace android diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp index f51941dd..69e770c8 100644 --- a/hwc2_device/DrmHwcTwo.cpp +++ b/hwc2_device/DrmHwcTwo.cpp @@ -248,6 +248,53 @@ void DrmHwcTwo::SendHotplugEventToClient(hwc2_display_t displayid, } } +void DrmHwcTwo::EnableHDCPSessionForDisplay(uint32_t connector, + EHwcsContentType content_type) { + HWCContentType type = kCONTENT_TYPE0; + + if (content_type == HWCS_CP_CONTENT_TYPE1) { + type = kCONTENT_TYPE1; + } + + size_t size = displays_.size(); + for (size_t i = 0; i < size; i++) { + if (displays_[i]-> GetPipe().connector->Get()->GetId()== connector) { + displays_[i]->GetPipe().atomic_state_manager->SetHDCPState(HWCContentProtection::kDesired, type); + } + } +} + +void DrmHwcTwo::EnableHDCPSessionForAllDisplays(EHwcsContentType content_type) { + HWCContentType type = kCONTENT_TYPE0; + + if (content_type == HWCS_CP_CONTENT_TYPE1) { + type = kCONTENT_TYPE1; + } + + size_t size = displays_.size(); + for (size_t i = 0; i < size; i++) { + displays_[i]->GetPipe().atomic_state_manager->SetHDCPState(HWCContentProtection::kDesired, type); + } +} + +void DrmHwcTwo::DisableHDCPSessionForDisplay(uint32_t connector) { + size_t size = displays_.size(); + for (size_t i = 0; i < size; i++) { + if (displays_[i]->GetPipe().connector->Get()->GetId() == connector) { + displays_[i]->GetPipe().atomic_state_manager->SetHDCPState(HWCContentProtection::kUnDesired, + HWCContentType::kInvalid); + } + } +} + +void DrmHwcTwo::DisableHDCPSessionForAllDisplays() { + size_t size = displays_.size(); + for (size_t i = 0; i < size; i++) { + displays_[i]->GetPipe().atomic_state_manager->SetHDCPState(HWCContentProtection::kUnDesired, + HWCContentType::kInvalid); + } +} + void DrmHwcTwo::SendVsyncEventToClient( hwc2_display_t displayid, int64_t timestamp, [[maybe_unused]] uint32_t vsync_period) const { diff --git a/hwc2_device/DrmHwcTwo.h b/hwc2_device/DrmHwcTwo.h index a3e8d4b3..9b14f7c4 100644 --- a/hwc2_device/DrmHwcTwo.h +++ b/hwc2_device/DrmHwcTwo.h @@ -73,6 +73,14 @@ class DrmHwcTwo : public PipelineToFrontendBindingInterface { void SendVsyncPeriodTimingChangedEventToClient(hwc2_display_t displayid, int64_t timestamp) const; + void EnableHDCPSessionForDisplay(uint32_t connector, + EHwcsContentType content_type); + + void EnableHDCPSessionForAllDisplays(EHwcsContentType content_type); + + void DisableHDCPSessionForDisplay(uint32_t connector); + + void DisableHDCPSessionForAllDisplays(); private: void SendHotplugEventToClient(hwc2_display_t displayid, bool connected); diff --git a/hwc2_device/hwcservice.cpp b/hwc2_device/hwcservice.cpp new file mode 100644 index 00000000..efe36ea5 --- /dev/null +++ b/hwc2_device/hwcservice.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hwcservice.h" +#include +#include +#include +#include +#include "utils/hwcdefs.h" +#include "DrmHwcTwo.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#define LOG_TAG "hwc-service" +#endif +#define HWC_VERSION_STRING \ + "VERSION:HWC 2.0 GIT Branch & Latest Commit:" HWC_VERSION_GIT_BRANCH \ + " " HWC_VERSION_GIT_SHA " " __DATE__ " " __TIME__ + +namespace android { +using namespace hwcomposer; + +static HWCColorControl HWCS2HWC(EHwcsColorControl color) { + switch (color) { + case HWCS_COLOR_BRIGHTNESS: + return HWCColorControl::kColorBrightness; + case HWCS_COLOR_CONTRAST: + return HWCColorControl::kColorContrast; + case HWCS_COLOR_SATURATION: + return HWCColorControl::kColorSaturation; + case HWCS_COLOR_SHARP: + return HWCColorControl::kColorSharpness; + case HWCS_COLOR_HUE: + default: + return HWCColorControl::kColorHue; + } + return HWCColorControl::kColorHue; +} + +static HWCDeinterlaceControl HWCS2HWCDeinterlace(EHwcsDeinterlaceControl mode) { + switch (mode) { + case HWCS_DEINTERLACE_NONE: + return HWCDeinterlaceControl::kDeinterlaceNone; + case HWCS_DEINTERLACE_BOB: + return HWCDeinterlaceControl::kDeinterlaceBob; + case HWCS_DEINTERLACE_WEAVE: + return HWCDeinterlaceControl::kDeinterlaceWeave; + case HWCS_DEINTERLACE_MOTIONADAPTIVE: + return HWCDeinterlaceControl::kDeinterlaceMotionAdaptive; + case HWCS_DEINTERLACE_MOTIONCOMPENSATED: + default: + return HWCDeinterlaceControl::kDeinterlaceMotionCompensated; + } + return HWCDeinterlaceControl::kDeinterlaceNone; + ; +} + +HwcService::HwcService() : mpHwc(NULL), initialized_(false) { +} + +HwcService::~HwcService() { +} + +bool HwcService::Start(DrmHwcTwo *hwc) { + if (initialized_) + return true; + + mpHwc = hwc; + sp sm(defaultServiceManager()); + if (sm->addService(String16(IA_HWC_SERVICE_NAME), this, false)) { + ALOGE("Failed to start %s service", IA_HWC_SERVICE_NAME); + return false; + } + + initialized_ = true; + ALOGD("success to start %s service", IA_HWC_SERVICE_NAME); + return true; +} + +String8 HwcService::GetHwcVersion() { + return String8(""); +} + +status_t HwcService::SetOption(String8 option, String8 value) { + return OK; +} + +void HwcService::DumpOptions(void) { + // TO DO +} + +status_t HwcService::EnableLogviewToLogcat(bool enable) { + // TO DO + return OK; +} + +sp HwcService::GetDiagnostic() { + lock_.lock(); + ALOG_ASSERT(mpHwc); + if (mpDiagnostic == NULL) + mpDiagnostic = new Diagnostic(*mpHwc); + + lock_.unlock(); + + return mpDiagnostic; +} + +sp HwcService::GetControls() { + // TODO: Check the need for lock + ALOG_ASSERT(mpHwc); + return new Controls(*mpHwc, *this); +} + +status_t HwcService::Diagnostic::ReadLogParcel(Parcel *parcel) { + // TO DO + return OK; +} + +void HwcService::Diagnostic::EnableDisplay(uint32_t) { /* nothing */ +} +void HwcService::Diagnostic::DisableDisplay(uint32_t, bool) { /* nothing */ +} +void HwcService::Diagnostic::MaskLayer(uint32_t, uint32_t, bool) { /* nothing */ +} +void HwcService::Diagnostic::DumpFrames(uint32_t, int32_t, bool) { /* nothing */ +} + +HwcService::Controls::Controls(DrmHwcTwo &hwc, HwcService &hwcService) + : mHwc(hwc), + mHwcService(hwcService), + mbHaveSessionsEnabled(false), + mCurrentOptimizationMode(HWCS_OPTIMIZE_NORMAL) { +} + +HwcService::Controls::~Controls() { +} + +#define HWCS_ENTRY_FMT(fname, fmt, ...) \ + const char *___HWCS_FUNCTION = fname; \ + Log::add(fname " " fmt " -->", __VA_ARGS__) + +#define HWCS_ENTRY(fname) \ + const char *___HWCS_FUNCTION = fname; \ + Log::add(fname " -->") + +#define HWCS_ERROR(code) Log::add("%s ERROR %d <--", ___HWCS_FUNCTION, code) + +#define HWCS_EXIT_ERROR(code) \ + do { \ + int ___code = code; \ + HWCS_ERROR(___code); \ + return ___code; \ + } while (0) + +#define HWCS_OK_FMT(fmt, ...) \ + Log::add("%s OK " fmt " <--", ___HWCS_FUNCTION, __VA_ARGS__); + +#define HWCS_EXIT_OK_FMT(fmt, ...) \ + do { \ + HWCS_OK_FMT(fmt, __VA_ARGS__); \ + return OK; \ + } while (0) + +#define HWCS_EXIT_OK() \ + do { \ + Log::add("%s OK <--", ___HWCS_FUNCTION); \ + return OK; \ + } while (0) + +#define HWCS_EXIT_VAR(code) \ + do { \ + int ____code = code; \ + if (____code == OK) \ + HWCS_EXIT_OK(); \ + HWCS_EXIT_ERROR(____code); \ + } while (0) + +#define HWCS_EXIT_VAR_FMT(code, fmt, ...) \ + do { \ + int ____code = code; \ + if (____code == OK) \ + HWCS_EXIT_OK_FMT(fmt, __VA_ARGS__); \ + HWCS_EXIT_ERROR(____code); \ + } while (0) +status_t HwcService::Controls::DisplaySetOverscan(uint32_t display, + int32_t xoverscan, + int32_t yoverscan) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplayGetOverscan(uint32_t display, + int32_t *xoverscan, + int32_t *yoverscan) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplaySetScaling( + uint32_t display, EHwcsScalingMode eScalingMode) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplayGetScaling( + uint32_t display, EHwcsScalingMode *peScalingMode) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplayEnableBlank(uint32_t display, + bool blank) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplayRestoreDefaultColorParam( + uint32_t display, EHwcsColorControl color) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplayRestoreDefaultDeinterlaceParam( + uint32_t display) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplayGetColorParam(uint32_t display, + EHwcsColorControl color, + float *value, + float *startvalue, + float *endvalue) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplaySetColorParam(uint32_t display, + EHwcsColorControl color, + float value) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplaySetDeinterlaceParam( + uint32_t display, EHwcsDeinterlaceControl mode) { + // TO DO + return OK; +} + +std::vector +HwcService::Controls::DisplayModeGetAvailableModes(uint32_t display) { + std::vector modes; + // TO DO + return modes; +} + +status_t HwcService::Controls::DisplayModeGetMode(uint32_t display, + HwcsDisplayModeInfo *pMode) { + // TO DO + return OK; +} + +status_t HwcService::Controls::DisplayModeSetMode(uint32_t display, + const uint32_t config) { + // TO DO + return OK; +} + +status_t HwcService::Controls::EnableHDCPSessionForDisplay( + uint32_t connector, EHwcsContentType content_type) { + mHwc.EnableHDCPSessionForDisplay(connector, content_type); + return OK; +} + +status_t HwcService::Controls::EnableHDCPSessionForAllDisplays( + EHwcsContentType content_type) { + mHwc.EnableHDCPSessionForAllDisplays(content_type); + return OK; +} + +status_t HwcService::Controls::DisableHDCPSessionForDisplay( + uint32_t connector) { + mHwc.DisableHDCPSessionForDisplay(connector); + return OK; +} + +status_t HwcService::Controls::DisableHDCPSessionForAllDisplays() { + mHwc.DisableHDCPSessionForAllDisplays(); + return OK; +} + +status_t HwcService::Controls::SetHDCPSRMForAllDisplays(const int8_t *SRM, + uint32_t SRMLength) { + // TO DO + return OK; +} + +status_t HwcService::Controls::SetHDCPSRMForDisplay(uint32_t connector, + const int8_t *SRM, + uint32_t SRMLength) { + // TO DO + return OK; +} + +uint32_t HwcService::Controls::GetDisplayIDFromConnectorID( + uint32_t connector_id) { + // TO DO + return 0; +} + +bool HwcService::Controls::EnableDRMCommit(bool enable, uint32_t display_id) { + // TO DO + return true; +} + +bool HwcService::Controls::ResetDrmMaster(bool drop_master) { + // TO DO + return true; +} + +status_t HwcService::Controls::VideoEnableEncryptedSession( + uint32_t sessionID, uint32_t instanceID) { + // TO DO + return OK; +} + +status_t HwcService::Controls::VideoDisableAllEncryptedSessions( + uint32_t sessionID) { + // TO DO + return OK; +} + +status_t HwcService::Controls::VideoDisableAllEncryptedSessions() { + // TO DO + return OK; +} + +#ifdef ENABLE_PANORAMA +status_t HwcService::Controls::TriggerPanorama(uint32_t hotplug_simulation) { + mHwc.TriggerPanorama(hotplug_simulation); + return OK; +} + +status_t HwcService::Controls::ShutdownPanorama(uint32_t hotplug_simulation) { + mHwc.ShutdownPanorama(hotplug_simulation); + return OK; +} +#endif + +bool HwcService::Controls::VideoIsEncryptedSessionEnabled(uint32_t sessionID, + uint32_t instanceID) { + // TO DO + return OK; +} + +bool HwcService::Controls::needSetKeyFrameHint() { + // TO DO + return OK; +} + +status_t HwcService::Controls::VideoSetOptimizationMode( + EHwcsOptimizationMode mode) { + // TO DO + return OK; +} + +status_t HwcService::Controls::MdsUpdateVideoState(int64_t videoSessionID, + bool isPrepared) { + // TO DO + return OK; +} + +status_t HwcService::Controls::MdsUpdateVideoFPS(int64_t videoSessionID, + int32_t fps) { + // TO DO + return OK; +} + +status_t HwcService::Controls::MdsUpdateInputState(bool state) { + // TO DO + return OK; +} + +status_t HwcService::Controls::WidiGetSingleDisplay(bool *pEnabled) { + // TO DO + return OK; +} + +status_t HwcService::Controls::WidiSetSingleDisplay(bool enable) { + // TO DO + return OK; +} +void HwcService::RegisterListener(ENotification notify, + NotifyCallback *pCallback) { + // TO DO +} + +void HwcService::UnregisterListener(ENotification notify, + NotifyCallback *pCallback) { + // TO DO +} + +void HwcService::Notify(ENotification notify, int32_t paraCnt, int64_t para[]) { + // TO DO +} + +} // namespace android diff --git a/hwc2_device/hwcservice.h b/hwc2_device/hwcservice.h new file mode 100644 index 00000000..70badbcc --- /dev/null +++ b/hwc2_device/hwcservice.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_HWCSERVICE_H_ +#define OS_ANDROID_HWCSERVICE_H_ + +#include + +#include +#include +#include "libhwcservice/icontrols.h" +#include "libhwcservice/idiagnostic.h" +#include "libhwcservice/iservice.h" +#include "utils/spinlock.h" + +#define HWC_UNUSED(x) ((void)&(x)) +namespace android { +class DrmHwcTwo; +using namespace hwcomposer; + +class HwcService : public BnService { + public: + class Diagnostic : public BnDiagnostic { + public: + Diagnostic(DrmHwcTwo& DrmHwcTwo) : mHwc(DrmHwcTwo) { + HWC_UNUSED(mHwc); + } + + status_t ReadLogParcel(Parcel* parcel) override; + void EnableDisplay(uint32_t d) override; + void DisableDisplay(uint32_t d, bool bBlank) override; + void MaskLayer(uint32_t d, uint32_t layer, bool bHide) override; + void DumpFrames(uint32_t d, int32_t frames, bool bSync) override; + + private: + DrmHwcTwo& mHwc; + }; + + bool Start(DrmHwcTwo* hwc); + + sp GetDiagnostic(); + sp GetControls(); + + android::String8 GetHwcVersion(); + + void DumpOptions(void); + status_t SetOption(android::String8 option, android::String8 optionValue); + status_t EnableLogviewToLogcat(bool enable = true); + + class Controls : public BnControls { + public: + Controls(DrmHwcTwo& hwc, HwcService& hwcService); + virtual ~Controls(); + + status_t DisplaySetOverscan(uint32_t display, int32_t xoverscan, + int32_t yoverscan); + status_t DisplayGetOverscan(uint32_t display, int32_t* xoverscan, + int32_t* yoverscan); + status_t DisplaySetScaling(uint32_t display, EHwcsScalingMode eScalingMode); + status_t DisplayGetScaling(uint32_t display, + EHwcsScalingMode* eScalingMode); + status_t DisplayEnableBlank(uint32_t display, bool blank); + status_t DisplayRestoreDefaultColorParam(uint32_t display, + EHwcsColorControl color); + status_t DisplayRestoreDefaultDeinterlaceParam(uint32_t display); + status_t DisplayGetColorParam(uint32_t display, EHwcsColorControl color, + float* value, float* startvalue, + float* endvalue); + status_t DisplaySetColorParam(uint32_t display, EHwcsColorControl color, + float value); + status_t DisplaySetDeinterlaceParam(uint32_t display, + EHwcsDeinterlaceControl mode); + + std::vector DisplayModeGetAvailableModes( + uint32_t display); + status_t DisplayModeGetMode(uint32_t display, HwcsDisplayModeInfo* pMode); + status_t DisplayModeSetMode(uint32_t display, const uint32_t config); + + status_t EnableHDCPSessionForDisplay(uint32_t connector, + EHwcsContentType content_type); + + status_t EnableHDCPSessionForAllDisplays(EHwcsContentType content_type); + + status_t DisableHDCPSessionForDisplay(uint32_t connector); + + status_t DisableHDCPSessionForAllDisplays(); + +#ifdef ENABLE_PANORAMA + status_t TriggerPanorama(uint32_t hotplug_simulation); + status_t ShutdownPanorama(uint32_t hotplug_simulation); +#endif + + status_t SetHDCPSRMForAllDisplays(const int8_t* SRM, uint32_t SRMLength); + + status_t SetHDCPSRMForDisplay(uint32_t connector, const int8_t* SRM, + uint32_t SRMLength); + uint32_t GetDisplayIDFromConnectorID(uint32_t connector_id); + bool EnableDRMCommit(bool enable, uint32_t display_id); + bool ResetDrmMaster(bool drop_master); + status_t VideoEnableEncryptedSession(uint32_t sessionID, + uint32_t instanceID); + status_t VideoDisableAllEncryptedSessions(uint32_t sessionID); + status_t VideoDisableAllEncryptedSessions(); + bool VideoIsEncryptedSessionEnabled(uint32_t sessionID, + uint32_t instanceID); + bool needSetKeyFrameHint(); + status_t VideoSetOptimizationMode(EHwcsOptimizationMode mode); + status_t MdsUpdateVideoState(int64_t videoSessionID, bool isPrepared); + status_t MdsUpdateVideoFPS(int64_t videoSessionID, int32_t fps); + status_t MdsUpdateInputState(bool state); + status_t WidiGetSingleDisplay(bool* pEnabled); + status_t WidiSetSingleDisplay(bool enable); + + private: + DrmHwcTwo& mHwc; + HwcService& mHwcService; + bool mbHaveSessionsEnabled; + EHwcsOptimizationMode mCurrentOptimizationMode; + }; + + enum ENotification { + eInvalidNofiy = 0, + eOptimizationMode, + eMdsUpdateVideoState, + eMdsUpdateInputState, + eMdsUpdateVideoFps, + ePavpEnableEncryptedSession, + ePavpDisableEncryptedSession, + ePavpDisableAllEncryptedSessions, + ePavpIsEncryptedSessionEnabled, + eWidiGetSingleDisplay, + eWidiSetSingleDisplay, + eNeedSetKeyFrameHint, + }; + + class NotifyCallback { + public: + virtual ~NotifyCallback() { + } + virtual void notify(ENotification notify, int32_t paraCnt, + int64_t para[]) = 0; + }; + + void RegisterListener(ENotification notify, NotifyCallback* pCallback); + void UnregisterListener(ENotification notify, NotifyCallback* pCallback); + void Notify(ENotification notify, int32_t paraCnt, int64_t para[]); + HwcService(); + virtual ~HwcService(); + private: + friend class DrmHwcTwo; + + struct Notification { + Notification() : mWhat(eInvalidNofiy), mpCallback(NULL) { + } + Notification(ENotification what, NotifyCallback* pCallback) + : mWhat(what), mpCallback(pCallback) { + } + ENotification mWhat; + NotifyCallback* mpCallback; + }; + + SpinLock lock_; + DrmHwcTwo* mpHwc; + bool initialized_; + + sp mpDiagnostic; + + std::vector mNotifications; +}; +} // namespace android + +#endif // OS_ANDROID_HWCSERVICE_H_ diff --git a/libhwcservice/Android.bp b/libhwcservice/Android.bp new file mode 100644 index 00000000..decd1d9c --- /dev/null +++ b/libhwcservice/Android.bp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Obtain Android Version +ANDROID_VERSION = ["__builtin_func:word 1 __builtin_func:subst . <'PLATFORM_VERSION' unset>"] +cc_library_shared { + srcs: [ + "icontrols.cpp", + "idiagnostic.cpp", + "iservice.cpp", + "hwcserviceapi.cpp", + ], + name: "libhwcservice", + cflags: ["-fvisibility=default"] + ["-DENABLE_PANORAMA"], // ANDROIDMK TRANSLATION ERROR: unsupported conditional + + shared_libs: [ + "libutils", + "libbinder", + "liblog", + ], + compile_multilib: "both", + export_include_dirs: ["."], + proprietary: true, + header_libs: ["libcutils_headers"], + } diff --git a/libhwcservice/hwcserviceapi.cpp b/libhwcservice/hwcserviceapi.cpp new file mode 100644 index 00000000..6871ad75 --- /dev/null +++ b/libhwcservice/hwcserviceapi.cpp @@ -0,0 +1,441 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hwcserviceapi.h" + +#include "icontrols.h" +#include "iservice.h" + +#include +#include + +#include +#include + +using namespace std; +using namespace android; + +using namespace hwcomposer; + +extern "C" { +struct HwcsContext { + sp mHwcService; + sp mControls; +}; + +HWCSHANDLE HwcService_Connect() { + ProcessState::self() + ->startThreadPool(); // Required for starting binder threads + ALOGD("%s start",__FUNCTION__); + HwcsContext context; + context.mHwcService = interface_cast( + defaultServiceManager()->waitForService(String16(IA_HWC_SERVICE_NAME))); + if (context.mHwcService == NULL) { + printf("%d\n", __LINE__); + ALOGE("%s context.mHwcService == NULL",__FUNCTION__); + return NULL; + } + + ALOGD("%s IService ok",__FUNCTION__); + context.mControls = context.mHwcService->GetControls(); + ALOGD("%s context.mControls",__FUNCTION__); + if (context.mControls == NULL) { + printf("%d\n", __LINE__); + ALOGE("%s context.mControls == NULL",__FUNCTION__); + return NULL; + } + printf("%d\n", __LINE__); + ALOGD("HDcPD_ %s ok",__FUNCTION__); + return new HwcsContext(context); +} + +void HwcService_Disconnect(HWCSHANDLE hwcs) { + if (hwcs != NULL) { + delete static_cast(hwcs); + } +} + +const char* HwcService_GetHwcVersion(HWCSHANDLE hwcs) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return NULL; + } + + static String8 version = pContext->mHwcService->GetHwcVersion(); + if (version.length() == 0) { + return NULL; + } + return version; +} + +status_t HwcService_Display_SetOverscan(HWCSHANDLE hwcs, uint32_t display, + int32_t xoverscan, int32_t yoverscan) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplaySetOverscan(display, xoverscan, yoverscan); +} + +status_t HwcService_Display_GetOverscan(HWCSHANDLE hwcs, uint32_t display, + int32_t* xoverscan, + int32_t* yoverscan) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayGetOverscan(display, xoverscan, yoverscan); +} + +status_t HwcService_Display_SetScaling(HWCSHANDLE hwcs, uint32_t display, + EHwcsScalingMode eScalingMode) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplaySetScaling(display, eScalingMode); +} + +status_t HwcService_Display_GetScaling(HWCSHANDLE hwcs, uint32_t display, + EHwcsScalingMode* eScalingMode) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayGetScaling(display, eScalingMode); +} + +status_t HwcService_Display_EnableBlank(HWCSHANDLE hwcs, uint32_t display, + EHwcsBool blank) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayEnableBlank(display, blank); +} + +status_t HwcService_Display_RestoreDefaultColorParam(HWCSHANDLE hwcs, + uint32_t display, + EHwcsColorControl color) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayRestoreDefaultColorParam(display, color); +} + +status_t HwcService_Display_RestoreDefaultDeinterlaceParam(HWCSHANDLE hwcs, + uint32_t display) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayRestoreDefaultDeinterlaceParam(display); +} + +status_t HwcService_Display_GetColorParam(HWCSHANDLE hwcs, uint32_t display, + EHwcsColorControl color, float* value, + float* startvalue, float* endvalue) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayGetColorParam(display, color, value, + startvalue, endvalue); +} + +status_t HwcService_Display_SetColorParam(HWCSHANDLE hwcs, uint32_t display, + EHwcsColorControl color, + float value) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplaySetColorParam(display, color, value); +} + +status_t HwcService_Display_SetDeinterlaceParam(HWCSHANDLE hwcs, + uint32_t display, + uint32_t mode) { + EHwcsDeinterlaceControl de_mode; + + switch (mode) { + case 0: + de_mode = HWCS_DEINTERLACE_NONE; + break; + case 1: + de_mode = HWCS_DEINTERLACE_BOB; + break; + case 2: + de_mode = HWCS_DEINTERLACE_WEAVE; + break; + case 3: + de_mode = HWCS_DEINTERLACE_MOTIONADAPTIVE; + break; + case 4: + de_mode = HWCS_DEINTERLACE_MOTIONCOMPENSATED; + break; + default: + de_mode = HWCS_DEINTERLACE_NONE; + break; + } + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplaySetDeinterlaceParam(display, de_mode); +} + +status_t HwcService_DisplayMode_GetAvailableModes( + HWCSHANDLE hwcs, uint32_t display, + std::vector& pModeList) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + pModeList = pContext->mControls->DisplayModeGetAvailableModes(display); + return OK; +} + +status_t HwcService_DisplayMode_GetMode(HWCSHANDLE hwcs, uint32_t display, + HwcsDisplayModeInfo* pMode) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayModeGetMode(display, pMode); +} + +status_t HwcService_DisplayMode_SetMode(HWCSHANDLE hwcs, uint32_t display, + const uint32_t config) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->DisplayModeSetMode(display, config); +} + +status_t HwcService_Video_EnableHDCPSession_ForDisplay( + HWCSHANDLE hwcs, uint32_t connector, EHwcsContentType content_type) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->EnableHDCPSessionForDisplay(connector, + content_type); +} + +status_t HwcService_Video_EnableHDCPSession_AllDisplays( + HWCSHANDLE hwcs, EHwcsContentType content_type) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->EnableHDCPSessionForAllDisplays(content_type); +} + +status_t HwcService_Video_SetHDCPSRM_AllDisplays(HWCSHANDLE hwcs, + const int8_t* SRM, + uint32_t SRMLength) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->SetHDCPSRMForAllDisplays(SRM, SRMLength); +} + +status_t HwcService_Video_SetHDCPSRM_ForDisplay(HWCSHANDLE hwcs, + uint32_t connector, + const int8_t* SRM, + uint32_t SRMLength) { + HwcsContext* pContext = static_cast(hwcs); + + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->SetHDCPSRMForDisplay(connector, SRM, SRMLength); +} + +status_t HwcService_Video_DisableHDCPSession_ForDisplay(HWCSHANDLE hwcs, + uint32_t connector) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->DisableHDCPSessionForDisplay(connector); +} + +#ifdef ENABLE_PANORAMA +status_t HwcService_TriggerPanorama(HWCSHANDLE hwcs, + uint32_t hotplug_simulation) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->TriggerPanorama(hotplug_simulation); +} + +status_t HwcService_ShutdownPanorama(HWCSHANDLE hwcs, + uint32_t hotplug_simulation) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->ShutdownPanorama(hotplug_simulation); +} +#endif + +uint32_t HwcService_GetDisplayIDFromConnectorID(HWCSHANDLE hwcs, + uint32_t connector_id) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->GetDisplayIDFromConnectorID(connector_id); +} + +status_t HwcService_EnableDRMCommit(HWCSHANDLE hwcs, uint32_t enable, + uint32_t display_id) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->EnableDRMCommit(enable, display_id); +} + +status_t HwcService_ResetDrmMaster(HWCSHANDLE hwcs, uint32_t drop_master) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->ResetDrmMaster(drop_master); +} + +status_t HwcService_Video_DisableHDCPSession_AllDisplays(HWCSHANDLE hwcs) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + + return pContext->mControls->DisableHDCPSessionForAllDisplays(); +} + +status_t HwcService_Video_EnableEncryptedSession(HWCSHANDLE hwcs, + uint32_t sessionID, + uint32_t instanceID) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->VideoEnableEncryptedSession(sessionID, + instanceID); +} + +status_t HwcService_Video_DisableEncryptedSession(HWCSHANDLE hwcs, + uint32_t sessionID) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->VideoDisableAllEncryptedSessions(sessionID); +} + +status_t HwcService_Video_DisableAllEncryptedSessions(HWCSHANDLE hwcs) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->VideoDisableAllEncryptedSessions(); +} + +EHwcsBool HwcService_Video_IsEncryptedSessionEnabled(HWCSHANDLE hwcs, + uint32_t sessionID, + uint32_t instanceID) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return HWCS_FALSE; + } + return pContext->mControls->VideoIsEncryptedSessionEnabled(sessionID, + instanceID) + ? HWCS_TRUE + : HWCS_FALSE; +} + +status_t HwcService_Video_SetOptimizationMode(HWCSHANDLE hwcs, + EHwcsOptimizationMode mode) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->VideoSetOptimizationMode(mode); +} + +status_t HwcService_MDS_UpdateVideoState(HWCSHANDLE hwcs, + int64_t videoSessionID, + EHwcsBool isPrepared) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->MdsUpdateVideoState(videoSessionID, isPrepared); +} + +status_t HwcService_MDS_UpdateVideoFPS(HWCSHANDLE hwcs, int64_t videoSessionID, + int32_t fps) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->MdsUpdateVideoFPS(videoSessionID, fps); +} + +status_t HwcService_MDS_UpdateInputState(HWCSHANDLE hwcs, EHwcsBool state) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->MdsUpdateInputState(state); +} + +status_t HwcService_Widi_GetSingleDisplay(HWCSHANDLE hwcs, EHwcsBool* enable) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + if (!enable) { + return android::BAD_VALUE; + } + bool bEnabled = false; + status_t ret = pContext->mControls->WidiGetSingleDisplay(&bEnabled); + *enable = bEnabled ? HWCS_TRUE : HWCS_FALSE; + return ret; +} + +status_t HwcService_Widi_SetSingleDisplay(HWCSHANDLE hwcs, EHwcsBool enable) { + HwcsContext* pContext = static_cast(hwcs); + if (!pContext) { + return android::BAD_VALUE; + } + return pContext->mControls->WidiSetSingleDisplay(enable); +} +} diff --git a/libhwcservice/hwcserviceapi.h b/libhwcservice/hwcserviceapi.h new file mode 100644 index 00000000..511594dd --- /dev/null +++ b/libhwcservice/hwcserviceapi.h @@ -0,0 +1,298 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_HWC_HWCSERVICEAPI_H_ +#define OS_ANDROID_HWC_HWCSERVICEAPI_H_ + +#include + +#ifdef __cplusplus +#include +extern "C" { +#endif + +// Header file version. Please increment on any API additions. +// NOTE: Additions ONLY! No API modifications allowed (to maintain +// compatability). +#define HWCS_VERSION 1 + +typedef void *HWCSHANDLE; + +typedef enum _EHwcsBool { + HWCS_FALSE = 0, + HWCS_TRUE = 1, +} EHwcsBool; + +typedef int status_t; + +HWCSHANDLE HwcService_Connect(); +void HwcService_Disconnect(HWCSHANDLE hwcs); + +const char *HwcService_GetHwcVersion(HWCSHANDLE hwcs); + +// DisplayControl + +// Should these be hard coded in the API? +enum { + HWCS_MAX_OVERSCAN = 100, // The limit of the control parameters are + // +/-HWCS_MAX_OVERSCAN inclusive. + HWCS_OVERSCAN_RANGE = 15, // HWCS_OVERSCAN_RANGE describes the % of the + // display size a max control setting will adjust + // by. +}; + +/// Set overscan in the range +/-MAX_OVERSCAN inclusive. +// -ve : zoom/crop the image (increase display overscan). +// +ve : shrink the image (decrease display overscan). +status_t HwcService_Display_SetOverscan(HWCSHANDLE hwcs, uint32_t display, + int32_t xoverscan, int32_t yoverscan); +// Get last set overscan. +// Returns INVALID_OPERATION if overscan has not been set and +// xoverscan/yoverscan are untouched. +status_t HwcService_Display_GetOverscan(HWCSHANDLE hwcs, uint32_t display, + int32_t *xoverscan, int32_t *yoverscan); + +typedef enum _EHwcsScalingMode { + HWCS_SCALE_CENTRE = + 0, // Present the content centred at 1:1 source resolution. + HWCS_SCALE_STRETCH, // Do not preserve aspect ratio - scale to fill the + // display without cropping. + HWCS_SCALE_FIT, // Preserve aspect ratio - scale to closest edge (may be + // letterboxed or pillarboxed). + HWCS_SCALE_FILL, // Preserve aspect ratio - scale to fill the display (may + // crop the content). + HWCS_SCALE_MAX_ENUM // End of enum. +} EHwcsScalingMode; + +/// Set scaling to one of EScalingMode. +// Returns OK if succesful. +status_t HwcService_Display_SetScaling(HWCSHANDLE hwcs, uint32_t display, + EHwcsScalingMode eScalingMode); + +// Get last set scaling. +// Returns OK if succesful. +// Returns INVALID_OPERATION if scaling has not been set and eScalingMode is +// untouched. +status_t HwcService_Display_GetScaling(HWCSHANDLE hwcs, uint32_t display, + EHwcsScalingMode *eScalingMode); + +// Enable blank, true---blank, false---unblank +// Returns OK if succesful. +status_t HwcService_Display_EnableBlank(HWCSHANDLE hwcs, uint32_t display, + EHwcsBool blank); + +typedef enum _EHwcsColorControl { + HWCS_COLOR_BRIGHTNESS, + HWCS_COLOR_CONTRAST, + HWCS_COLOR_GAMMA, + HWCS_COLOR_SATURATION, + HWCS_COLOR_HUE, + HWCS_COLOR_SHARP, +} EHwcsColorControl; + +typedef enum _EHwcsDeinterlaceControl { + HWCS_DEINTERLACE_NONE, + HWCS_DEINTERLACE_BOB, + HWCS_DEINTERLACE_WEAVE, + HWCS_DEINTERLACE_MOTIONADAPTIVE, + HWCS_DEINTERLACE_MOTIONCOMPENSATED, +} EHwcsDeinterlaceControl; + +// Enumerations for content type. +typedef enum _EHwcsContentType { + HWCS_CP_CONTENT_TYPE0, // Can support any HDCP specifiction. + HWCS_CP_CONTENT_TYPE1, // Can support only HDCP 2.2 and higher specification. +} EHwcsContentType; + +status_t HwcService_Display_RestoreDefaultColorParam(HWCSHANDLE hwcs, + uint32_t display, + EHwcsColorControl color); +status_t HwcService_Display_RestoreDefaultDeinterlaceParam(HWCSHANDLE hwcs, + uint32_t display); +status_t HwcService_Display_GetColorParam(HWCSHANDLE hwcs, uint32_t display, + EHwcsColorControl color, float *value, + float *startvalue, float *endvalue); +status_t HwcService_Display_SetColorParam(HWCSHANDLE hwcs, uint32_t display, + EHwcsColorControl color, float value); +status_t HwcService_Display_SetDeinterlaceParam(HWCSHANDLE hwcs, + uint32_t display, + uint32_t mode); + +// DisplayModeControl + +typedef enum _EHwcsModeFlags { + HWCS_MODE_FLAG_NONE = 0, + HWCS_MODE_FLAG_PREFERRED = 1 << 0, + HWCS_MODE_FLAG_SECURE = 1 << 1, + HWCS_MODE_FLAG_INTERLACED = 1 << 2, + HWCS_MODE_FLAG_CURRENT = 1 << 4, +} EHwcsModeFlags; + +/// Enumerations for common aspect ratios +/// Any ratio can be supported, with the upper 16 bits containing one dimension, +/// the lower 16 bits contains the lower dimension +typedef enum _EHwcsModeAspectRatio { + HWCS_MODE_ASPECT_RATIO_ANY = 0x00000000, + HWCS_MODE_ASPECT_RATIO_4_3 = 0x00040003, + HWCS_MODE_ASPECT_RATIO_16_9 = 0x00100009, +} EHwcsModeAspectRatio; + +typedef struct _HwcsDisplayModeInfo { + uint32_t width; + uint32_t height; + uint32_t refresh; + uint32_t xdpi; + uint32_t ydpi; +} HwcsDisplayModeInfo; + +#ifdef __cplusplus +/// query all available modes +// If non-NULL: fills pModeList with up to modeCount modes. +// Returns the number of modes available. +status_t HwcService_DisplayMode_GetAvailableModes( + HWCSHANDLE hwcs, uint32_t display, + std::vector &pModeList); +#endif + +/// get current mode +status_t HwcService_DisplayMode_GetMode(HWCSHANDLE hwcs, uint32_t display, + HwcsDisplayModeInfo *pMode); + +/// set mode +status_t HwcService_DisplayMode_SetMode(HWCSHANDLE hwcs, uint32_t display, + const uint32_t config); + +// VideoControl + +// The control enables the usage of HDCP for all planes supporting this feature +// on display. Some displays can support latest HDCP specification and also +// have ability to fallback to older specifications i.e. HDCP 2.2 and 1.4 +// in case latest specification cannot be supported for some reason. Type +// of content can be set by content_type. +status_t HwcService_Video_EnableHDCPSession_ForDisplay( + HWCSHANDLE hwcs, uint32_t connector, EHwcsContentType content_type); + +// The control enables the usage of HDCP for all planes supporting this +// feature on all connected displays. Some displays can support latest HDCP +// specification and also have ability to fallback to older specifications +// i.e. HDCP 2.2 and 1.4 in case latest specification cannot be supported +// for some reason. Type of content can be set by content_type. +status_t HwcService_Video_EnableHDCPSession_AllDisplays( + HWCSHANDLE hwcs, EHwcsContentType content_type); + +// The control disables the usage of HDCP for all planes supporting this feature +// on display. +status_t HwcService_Video_DisableHDCPSession_ForDisplay(HWCSHANDLE hwcs, + uint32_t connector); + +// The control disables the usage of HDCP for all planes supporting this feature +// on all connected displays. +status_t HwcService_Video_DisableHDCPSession_AllDisplays(HWCSHANDLE hwcs); + +#ifdef ENABLE_PANORAMA +status_t HwcService_TriggerPanorama(HWCSHANDLE hwcs, + uint32_t hotplug_simulation); +status_t HwcService_ShutdownPanorama(HWCSHANDLE hwcs, + uint32_t hotplug_simulation); +#endif + +status_t HwcService_Video_SetHDCPSRM_ForDisplay(HWCSHANDLE hwcs, + uint32_t connector, + const int8_t *SRM, + uint32_t SRMLengh); + +status_t HwcService_Video_SetHDCPSRM_AllDisplays(HWCSHANDLE hwcs, + const int8_t *SRM, + uint32_t SRMLengh); + +uint32_t HwcService_GetDisplayIDFromConnectorID(HWCSHANDLE hwcs, + uint32_t connector_id); + +status_t HwcService_EnableDRMCommit(HWCSHANDLE hwcs, uint32_t enable, + uint32_t display_id); + +status_t HwcService_ResetDrmMaster(HWCSHANDLE hwcs, uint32_t drop_master); + +// The control enables a the protected video subsystem to control when to +// replace any +// encrypted content with a default bitmap (usually black). + +// Enable the display of encrypted buffers with the specified sessionID and +// instanceID. +// This will take effect from the next composed frame. +// Any previously enabled instanceID will be disabled (replaced by the default +// image) +status_t HwcService_Video_EnableEncryptedSession(HWCSHANDLE hwcs, + uint32_t sessionID, + uint32_t instanceID); + +// Disable specific encrypted session. +// This call will trigger the HWC to remove any encrypted buffers with the +// specified sessionID +// from the screen and replace with a default image. +// The function will block until the screen no longer contains any encrypted +// data with this session. +// This should be called by any subsystem that knows that a specific encrypted +// video session is about to +// become invalid. +status_t HwcService_Video_DisableEncryptedSession(HWCSHANDLE hwcs, + uint32_t sessionID); + +// Disable all protected sessions. +// This call will trigger the HWC to remove any encrypted buffers from the +// screen and replace +// with a default image. +// The function will block until the screen no longer contains any encrypted +// data with any session. +// This should be called by any subsystem that knows that all encrypted video +// sessions are about to +// become invalid. +status_t HwcService_Video_DisableAllEncryptedSessions(HWCSHANDLE hwcs); + +// Return whether or not the specified session/instance is enabled. +EHwcsBool HwcService_Video_IsEncryptedSessionEnabled(HWCSHANDLE hwcs, + uint32_t sessionID, + uint32_t instanceID); + +// Hint provided by the application about the global optimization mode for the +// driver +typedef enum _EHwcsOptimizationMode { + HWCS_OPTIMIZE_NORMAL, + HWCS_OPTIMIZE_VIDEO, + HWCS_OPTIMIZE_CAMERA, +} EHwcsOptimizationMode; +status_t HwcService_Video_SetOptimizationMode(HWCSHANDLE hwcs, + EHwcsOptimizationMode mode); + +// MDS +status_t HwcService_MDS_UpdateVideoState(HWCSHANDLE hwcs, + int64_t videoSessionID, + EHwcsBool isPrepared); + +status_t HwcService_MDS_UpdateVideoFPS(HWCSHANDLE hwcs, int64_t videoSessionID, + int32_t fps); + +status_t HwcService_MDS_UpdateInputState(HWCSHANDLE hwcs, EHwcsBool state); + +// Widi +status_t HwcService_Widi_GetSingleDisplay(HWCSHANDLE hwcs, EHwcsBool *enable); +status_t HwcService_Widi_SetSingleDisplay(HWCSHANDLE hwcs, EHwcsBool enable); + +#ifdef __cplusplus +} +#endif + +#endif // OS_ANDROID_HWC_HWCSERVICEAPI_H_ diff --git a/libhwcservice/hwcservicehelper.h b/libhwcservice/hwcservicehelper.h new file mode 100644 index 00000000..c1a05180 --- /dev/null +++ b/libhwcservice/hwcservicehelper.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_HWC_HWCSERVICEHELPER_H_ +#define OS_ANDROID_HWC_HWCSERVICEHELPER_H_ + +// Inline c++ helpers to augment HwcServiceApi.h + +#include + +#if __ANDROID__ +#include + +class HwcServiceConnection : public android::RefBase { + public: + HwcServiceConnection() { + mHwcs = HwcService_Connect(); + } + ~HwcServiceConnection() { + HwcService_Disconnect(mHwcs); + } + operator HWCSHANDLE() { + return mHwcs; + } + HWCSHANDLE handle() { + return mHwcs; + } + + private: + // Non-copyable. + HwcServiceConnection(HwcServiceConnection const &); + void operator=(HwcServiceConnection const &); + + HWCSHANDLE mHwcs; +}; + +#endif // __ANDROID__ + +#endif // OS_ANDROID_HWC_HWCSERVICEHELPER_H_ diff --git a/libhwcservice/icontrols.cpp b/libhwcservice/icontrols.cpp new file mode 100644 index 00000000..3e4f4dfe --- /dev/null +++ b/libhwcservice/icontrols.cpp @@ -0,0 +1,923 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "icontrols.h" +#include +#include + +// For AID_ROOT & AID_MEDIA - various vendor code and utils include this despite +// the path. +#include + +namespace hwcomposer { + +using namespace android; + +/** + */ +class BpControls : public BpInterface { + public: + BpControls(const sp &impl) : BpInterface(impl) { + } + + enum { + // ============================================== + // Public APIs - try not to reorder these + + TRANSACT_DISPLAY_SET_OVERSCAN = IBinder::FIRST_CALL_TRANSACTION, + TRANSACT_DISPLAY_GET_OVERSCAN, + TRANSACT_DISPLAY_SET_SCALING, + TRANSACT_DISPLAY_GET_SCALING, + TRANSACT_DISPLAY_ENABLE_BLANK, + TRANSACT_DISPLAY_RESTORE_DEFAULT_COLOR_PARAM, + TRANSACT_DISPLAY_GET_COLOR_PARAM, + TRANSACT_DISPLAY_SET_COLOR_PARAM, + TRANSACT_DISPLAY_SET_DEINTERLACE_PARAM, + TRANSACT_DISPLAY_RESTORE_DEFAULT_DEINTERLACE_PARAM, + TRANSACT_DISPLAYMODE_GET_AVAILABLE_MODES, + TRANSACT_DISPLAYMODE_GET_MODE, + TRANSACT_DISPLAYMODE_SET_MODE, + TRANSACT_VIDEO_ENABLE_HDCP_SESSION_FOR_DISPLAY, + TRANSACT_VIDEO_ENABLE_HDCP_SESSION_FOR_ALL_DISPLAYS, + TRANSACT_VIDEO_DISABLE_HDCP_SESSION_FOR_DISPLAY, + TRANSACT_VIDEO_DISABLE_HDCP_SESSION_FOR_ALL_DISPLAYS, + TRANSACT_VIDEO_SET_HDCP_SRM_FOR_ALL_DISPLAYS, + TRANSACT_VIDEO_SET_HDCP_SRM_FOR_DISPLAY, + TRANSACT_GET_DISPLAYID_FROM_CONNECTORID, + TRANSACT_ENABLE_DRM_COMMIT, + TRANSACT_RESET_DRM_MASTER, + TRANSACT_VIDEO_ENABLE_ENCRYPTED_SESSION, + TRANSACT_VIDEO_DISABLE_ENCRYPTED_SESSION, + TRANSACT_VIDEO_DISABLE_ALL_ENCRYPTED_SESSIONS, + TRANSACT_VIDEO_IS_ENCRYPTED_SESSION_ENABLED, + TRANSACT_VIDEO_SET_OPTIMIZATION_MODE, + TRANSACT_MDS_UPDATE_VIDEO_STATE, + TRANSACT_MDS_UPDATE_VIDEO_FPS, + TRANSACT_MDS_UPDATE_INPUT_STATE, + TRANSACT_WIDI_GET_SINGLE_DISPLAY, + TRANSACT_WIDI_SET_SINGLE_DISPLAY, +#ifdef ENABLE_PANORAMA + TRANSACT_TRIGGER_PANORAMA, + TRANSACT_SHUTDOWN_PANORAMA, +#endif + }; + + status_t DisplaySetOverscan(uint32_t display, int32_t xoverscan, + int32_t yoverscan) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32(xoverscan); + data.writeInt32(yoverscan); + status_t ret = + remote()->transact(TRANSACT_DISPLAY_SET_OVERSCAN, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisplayGetOverscan(uint32_t display, int32_t *xoverscan, + int32_t *yoverscan) override { + if (!xoverscan || !yoverscan) { + return android::BAD_VALUE; + } + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(display); + status_t ret = + remote()->transact(TRANSACT_DISPLAY_GET_OVERSCAN, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + status_t res = reply.readInt32(); + if (res != OK) + return res; + *xoverscan = reply.readInt32(); + *yoverscan = reply.readInt32(); + return OK; + } + +#ifdef ENABLE_PANORAMA + status_t TriggerPanorama(uint32_t hotplug_simulation) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(hotplug_simulation); + status_t ret = remote()->transact(TRANSACT_TRIGGER_PANORAMA, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + status_t ShutdownPanorama(uint32_t hotplug_simulation) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(hotplug_simulation); + status_t ret = remote()->transact(TRANSACT_SHUTDOWN_PANORAMA, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } +#endif + + status_t DisplaySetScaling(uint32_t display, + EHwcsScalingMode eScalingMode) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32((int32_t)eScalingMode); + status_t ret = + remote()->transact(TRANSACT_DISPLAY_SET_SCALING, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisplayGetScaling(uint32_t display, + EHwcsScalingMode *eScalingMode) override { + if (!eScalingMode) { + return android::BAD_VALUE; + } + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(display); + status_t ret = + remote()->transact(TRANSACT_DISPLAY_GET_SCALING, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + status_t res = reply.readInt32(); + if (res != OK) + return res; + *eScalingMode = (EHwcsScalingMode)reply.readInt32(); + return OK; + } + + status_t DisplayEnableBlank(uint32_t display, bool blank) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32((int32_t)blank); + status_t ret = + remote()->transact(TRANSACT_DISPLAY_ENABLE_BLANK, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisplayRestoreDefaultColorParam(uint32_t display, + EHwcsColorControl color) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32(color); + status_t ret = remote()->transact( + TRANSACT_DISPLAY_RESTORE_DEFAULT_COLOR_PARAM, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisplayRestoreDefaultDeinterlaceParam(uint32_t display) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + status_t ret = remote()->transact( + TRANSACT_DISPLAY_RESTORE_DEFAULT_DEINTERLACE_PARAM, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisplayGetColorParam(uint32_t display, EHwcsColorControl color, + float *value, float *startvalue, + float *endvalue) override { + if (!value || !startvalue || !endvalue) { + return android::BAD_VALUE; + } + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32(color); + status_t ret = + remote()->transact(TRANSACT_DISPLAY_GET_COLOR_PARAM, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + *value = reply.readFloat(); + *startvalue = reply.readFloat(); + *endvalue = reply.readFloat(); + return reply.readInt32(); + } + + status_t DisplaySetColorParam(uint32_t display, EHwcsColorControl color, + float value) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32(color); + data.writeFloat(value); + status_t ret = + remote()->transact(TRANSACT_DISPLAY_SET_COLOR_PARAM, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisplaySetDeinterlaceParam(uint32_t display, + EHwcsDeinterlaceControl mode) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32(mode); + status_t ret = remote()->transact(TRANSACT_DISPLAY_SET_DEINTERLACE_PARAM, + data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + std::vector DisplayModeGetAvailableModes( + uint32_t display) override { + std::vector vector; + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + status_t ret = remote()->transact(TRANSACT_DISPLAYMODE_GET_AVAILABLE_MODES, + data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return vector; + } + int32_t n = reply.readInt32(); + while (n--) { + HwcsDisplayModeInfo info; + info.width = reply.readInt32(); + info.height = reply.readInt32(); + info.refresh = reply.readInt32(); + info.xdpi = reply.readInt32(); + info.ydpi = reply.readInt32(); + vector.push_back(info); + } + return vector; + } + + status_t DisplayModeGetMode(uint32_t display, + HwcsDisplayModeInfo *pMode) override { + if (!pMode) { + return android::BAD_VALUE; + } + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + status_t ret = + remote()->transact(TRANSACT_DISPLAYMODE_GET_MODE, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + pMode->width = reply.readInt32(); + pMode->height = reply.readInt32(); + pMode->refresh = reply.readInt32(); + pMode->xdpi = reply.readInt32(); + pMode->ydpi = reply.readInt32(); + return reply.readInt32(); + } + + status_t DisplayModeSetMode(uint32_t display, + const uint32_t config) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + data.writeInt32(display); + data.writeInt32(config); + status_t ret = + remote()->transact(TRANSACT_DISPLAYMODE_SET_MODE, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t EnableHDCPSessionForDisplay(uint32_t connector, + EHwcsContentType content_type) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(connector); + data.writeInt32(content_type); + status_t ret = remote()->transact( + TRANSACT_VIDEO_ENABLE_HDCP_SESSION_FOR_DISPLAY, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t EnableHDCPSessionForAllDisplays( + EHwcsContentType content_type) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(content_type); + status_t ret = remote()->transact( + TRANSACT_VIDEO_ENABLE_HDCP_SESSION_FOR_ALL_DISPLAYS, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisableHDCPSessionForDisplay(uint32_t connector) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(connector); + status_t ret = remote()->transact( + TRANSACT_VIDEO_DISABLE_HDCP_SESSION_FOR_DISPLAY, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t DisableHDCPSessionForAllDisplays() override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + status_t ret = remote()->transact( + TRANSACT_VIDEO_DISABLE_HDCP_SESSION_FOR_ALL_DISPLAYS, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + status_t SetHDCPSRMForAllDisplays(const int8_t *SRM, + uint32_t SRMLength) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeByteArray(SRMLength, (const uint8_t *)SRM); + status_t ret = remote()->transact( + TRANSACT_VIDEO_SET_HDCP_SRM_FOR_ALL_DISPLAYS, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + status_t SetHDCPSRMForDisplay(uint32_t connector, const int8_t *SRM, + uint32_t SRMLength) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(connector); + data.writeByteArray(SRMLength, (const uint8_t *)SRM); + status_t ret = remote()->transact(TRANSACT_VIDEO_SET_HDCP_SRM_FOR_DISPLAY, + data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + uint32_t GetDisplayIDFromConnectorID(uint32_t connector_id) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(connector_id); + + status_t ret = remote()->transact(TRANSACT_GET_DISPLAYID_FROM_CONNECTORID, + data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return (uint32_t)(reply.readInt32()); + } + + bool EnableDRMCommit(bool enable, uint32_t display_id) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(enable); + data.writeInt32(display_id); + + status_t ret = remote()->transact(TRANSACT_ENABLE_DRM_COMMIT, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return (uint32_t)(reply.readInt32()); + } + + bool ResetDrmMaster(bool drop_master) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(drop_master); + + status_t ret = remote()->transact(TRANSACT_RESET_DRM_MASTER, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return (uint32_t)(reply.readInt32()); + } + + status_t VideoEnableEncryptedSession(uint32_t sessionID, + uint32_t instanceID) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(sessionID); + data.writeInt32(instanceID); + status_t ret = remote()->transact(TRANSACT_VIDEO_ENABLE_ENCRYPTED_SESSION, + data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t VideoDisableAllEncryptedSessions(uint32_t sessionID) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(sessionID); + status_t ret = remote()->transact(TRANSACT_VIDEO_DISABLE_ENCRYPTED_SESSION, + data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + status_t VideoDisableAllEncryptedSessions() override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + status_t ret = remote()->transact( + TRANSACT_VIDEO_DISABLE_ALL_ENCRYPTED_SESSIONS, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + bool VideoIsEncryptedSessionEnabled(uint32_t sessionID, + uint32_t instanceID) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(sessionID); + data.writeInt32(instanceID); + status_t ret = remote()->transact( + TRANSACT_VIDEO_IS_ENCRYPTED_SESSION_ENABLED, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return false; + } + return reply.readInt32(); + } + + status_t VideoSetOptimizationMode(EHwcsOptimizationMode mode) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(mode); + status_t ret = + remote()->transact(TRANSACT_VIDEO_SET_OPTIMIZATION_MODE, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t MdsUpdateVideoState(int64_t videoSessionID, + bool isPrepared) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt64(videoSessionID); + data.writeInt32(isPrepared); + status_t ret = + remote()->transact(TRANSACT_MDS_UPDATE_VIDEO_STATE, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + return reply.readInt32(); + } + + status_t MdsUpdateVideoFPS(int64_t videoSessionID, int32_t fps) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt64(videoSessionID); + data.writeInt32(fps); + status_t ret = + remote()->transact(TRANSACT_MDS_UPDATE_VIDEO_FPS, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + status_t MdsUpdateInputState(bool state) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(state); + status_t ret = + remote()->transact(TRANSACT_MDS_UPDATE_INPUT_STATE, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } + + status_t WidiGetSingleDisplay(bool *pEnabled) override { + if (!pEnabled) { + return android::BAD_VALUE; + } + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + status_t ret = + remote()->transact(TRANSACT_WIDI_GET_SINGLE_DISPLAY, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return ret; + } + *pEnabled = reply.readInt32(); + return reply.readInt32(); + } + + status_t WidiSetSingleDisplay(bool enable) override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(IControls::getInterfaceDescriptor()); + data.writeInt32(enable); + status_t ret = + remote()->transact(TRANSACT_WIDI_SET_SINGLE_DISPLAY, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return reply.readInt32(); + } +}; + +IMPLEMENT_META_INTERFACE(Controls, "iahwc.controls"); + +status_t BnControls::onTransact(uint32_t code, const Parcel &data, + Parcel *reply, uint32_t flags) { + switch (code) { + case BpControls::TRANSACT_DISPLAY_SET_OVERSCAN: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + int32_t xoverscan = data.readInt32(); + int32_t yoverscan = data.readInt32(); + status_t ret = this->DisplaySetOverscan(display, xoverscan, yoverscan); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_GET_OVERSCAN: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + int32_t xoverscan; + int32_t yoverscan; + status_t ret = this->DisplayGetOverscan(display, &xoverscan, &yoverscan); + reply->writeInt32(ret); + reply->writeInt32(xoverscan); + reply->writeInt32(yoverscan); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_SET_SCALING: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + EHwcsScalingMode scaling = (EHwcsScalingMode)data.readInt32(); + status_t ret = this->DisplaySetScaling(display, scaling); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_GET_SCALING: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + EHwcsScalingMode scaling; + status_t ret = this->DisplayGetScaling(display, &scaling); + reply->writeInt32(ret); + reply->writeInt32((int32_t)scaling); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_ENABLE_BLANK: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + bool blank = (bool)data.readInt32(); + status_t ret = this->DisplayEnableBlank(display, blank); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_RESTORE_DEFAULT_COLOR_PARAM: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + EHwcsColorControl color = (EHwcsColorControl)data.readInt32(); + status_t ret = this->DisplayRestoreDefaultColorParam(display, color); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_RESTORE_DEFAULT_DEINTERLACE_PARAM: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + status_t ret = this->DisplayRestoreDefaultDeinterlaceParam(display); + reply->writeInt32(ret); + return NO_ERROR; + } + + case BpControls::TRANSACT_DISPLAY_GET_COLOR_PARAM: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + EHwcsColorControl color = (EHwcsColorControl)data.readInt32(); + float value; + float startvalue; + float endvalue; + status_t ret = this->DisplayGetColorParam(display, color, &value, + &startvalue, &endvalue); + reply->writeFloat(value); + reply->writeFloat(startvalue); + reply->writeFloat(endvalue); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_SET_COLOR_PARAM: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + EHwcsColorControl color = (EHwcsColorControl)data.readInt32(); + float value = data.readFloat(); + status_t ret = this->DisplaySetColorParam(display, color, value); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAY_SET_DEINTERLACE_PARAM: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + EHwcsDeinterlaceControl mode = (EHwcsDeinterlaceControl)data.readInt32(); + status_t ret = this->DisplaySetDeinterlaceParam(display, mode); + reply->writeInt32(ret); + return NO_ERROR; + } + + case BpControls::TRANSACT_DISPLAYMODE_GET_AVAILABLE_MODES: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + + std::vector vector = + this->DisplayModeGetAvailableModes(display); + reply->writeInt32(vector.size()); + for (uint32_t i = 0; i < vector.size(); i++) { + reply->writeInt32(vector[i].width); + reply->writeInt32(vector[i].height); + reply->writeInt32(vector[i].refresh); + reply->writeInt32(vector[i].xdpi); + reply->writeInt32(vector[i].ydpi); + } + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAYMODE_GET_MODE: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + HwcsDisplayModeInfo info; + status_t ret = this->DisplayModeGetMode(display, &info); + reply->writeInt32(info.width); + reply->writeInt32(info.height); + reply->writeInt32(info.refresh); + reply->writeInt32(info.xdpi); + reply->writeInt32(info.ydpi); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_DISPLAYMODE_SET_MODE: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t display = data.readInt32(); + uint32_t config = data.readInt32(); + status_t ret = this->DisplayModeSetMode(display, config); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_ENABLE_HDCP_SESSION_FOR_DISPLAY: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t connector = data.readInt32(); + EHwcsContentType content_type = (EHwcsContentType)data.readInt32(); + status_t ret = this->EnableHDCPSessionForDisplay(connector, content_type); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_ENABLE_HDCP_SESSION_FOR_ALL_DISPLAYS: { + CHECK_INTERFACE(IControls, data, reply); + EHwcsContentType content_type = (EHwcsContentType)data.readInt32(); + status_t ret = this->EnableHDCPSessionForAllDisplays(content_type); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_DISABLE_HDCP_SESSION_FOR_DISPLAY: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t connector = data.readInt32(); + status_t ret = this->DisableHDCPSessionForDisplay(connector); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_DISABLE_HDCP_SESSION_FOR_ALL_DISPLAYS: { + CHECK_INTERFACE(IControls, data, reply); + status_t ret = this->DisableHDCPSessionForAllDisplays(); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_SET_HDCP_SRM_FOR_ALL_DISPLAYS: { + CHECK_INTERFACE(IControls, data, reply); + std::vector srmvec; + data.readByteVector(&srmvec); + status_t ret = this->SetHDCPSRMForAllDisplays( + (const int8_t *)(srmvec.data()), srmvec.size()); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_SET_HDCP_SRM_FOR_DISPLAY: { + CHECK_INTERFACE(IControls, data, reply); + std::vector srmvec; + uint32_t connector = data.readInt32(); + data.readByteVector(&srmvec); + status_t ret = this->SetHDCPSRMForDisplay( + connector, (const int8_t *)(srmvec.data()), srmvec.size()); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_GET_DISPLAYID_FROM_CONNECTORID: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t connector_id = data.readInt32(); + uint32_t display_id = this->GetDisplayIDFromConnectorID(connector_id); + reply->writeInt32(display_id); + return NO_ERROR; + } + case BpControls::TRANSACT_ENABLE_DRM_COMMIT: { + CHECK_INTERFACE(IControls, data, reply); + bool enable = data.readInt32(); + uint32_t display_id = data.readInt32(); + bool ret = this->EnableDRMCommit(enable, display_id); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_RESET_DRM_MASTER: { + CHECK_INTERFACE(IControls, data, reply); + bool drop_master = data.readInt32(); + bool ret = this->ResetDrmMaster(drop_master); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_ENABLE_ENCRYPTED_SESSION: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t sessionID = data.readInt32(); + uint32_t instanceID = data.readInt32(); + status_t ret = this->VideoEnableEncryptedSession(sessionID, instanceID); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_DISABLE_ENCRYPTED_SESSION: { + CHECK_INTERFACE(IControls, data, reply); + int32_t sessionID = data.readInt32(); + status_t ret = this->VideoDisableAllEncryptedSessions(sessionID); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_DISABLE_ALL_ENCRYPTED_SESSIONS: { + CHECK_INTERFACE(IControls, data, reply); + status_t ret = this->VideoDisableAllEncryptedSessions(); + reply->writeInt32(ret); + return NO_ERROR; + } +#ifdef ENABLE_PANORAMA + case BpControls::TRANSACT_TRIGGER_PANORAMA: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t hotplug_simulation = data.readInt32(); + status_t ret = this->TriggerPanorama(hotplug_simulation); + reply->writeInt32(ret); + return NO_ERROR; + } + + case BpControls::TRANSACT_SHUTDOWN_PANORAMA: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t hotplug_simulation = data.readInt32(); + status_t ret = this->ShutdownPanorama(hotplug_simulation); + reply->writeInt32(ret); + return NO_ERROR; + } +#endif + case BpControls::TRANSACT_VIDEO_IS_ENCRYPTED_SESSION_ENABLED: { + CHECK_INTERFACE(IControls, data, reply); + uint32_t sessionID = data.readInt32(); + uint32_t instanceID = data.readInt32(); + bool bEnabled = + this->VideoIsEncryptedSessionEnabled(sessionID, instanceID); + reply->writeInt32(bEnabled); + return NO_ERROR; + } + case BpControls::TRANSACT_VIDEO_SET_OPTIMIZATION_MODE: { + CHECK_INTERFACE(IControls, data, reply); + EHwcsOptimizationMode mode = (EHwcsOptimizationMode)data.readInt32(); + status_t ret = this->VideoSetOptimizationMode(mode); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_MDS_UPDATE_VIDEO_STATE: { + CHECK_INTERFACE(IControls, data, reply); + int64_t videoSessionID = data.readInt64(); + bool isPrepared = data.readInt32(); + status_t ret = this->MdsUpdateVideoState(videoSessionID, isPrepared); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_MDS_UPDATE_VIDEO_FPS: { + CHECK_INTERFACE(IControls, data, reply); + int64_t videoSessionID = data.readInt64(); + int32_t fps = data.readInt32(); + status_t ret = this->MdsUpdateVideoFPS(videoSessionID, fps); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_MDS_UPDATE_INPUT_STATE: { + CHECK_INTERFACE(IControls, data, reply); + bool state = data.readInt32(); + status_t ret = this->MdsUpdateInputState(state); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_WIDI_GET_SINGLE_DISPLAY: { + CHECK_INTERFACE(IControls, data, reply); + bool enable = false; + status_t ret = this->WidiGetSingleDisplay(&enable); + reply->writeInt32(enable); + reply->writeInt32(ret); + return NO_ERROR; + } + case BpControls::TRANSACT_WIDI_SET_SINGLE_DISPLAY: { + CHECK_INTERFACE(IControls, data, reply); + bool enable = data.readInt32(); + status_t ret = this->WidiSetSingleDisplay(enable); + reply->writeInt32(ret); + return NO_ERROR; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +} // namespace hwcomposer diff --git a/libhwcservice/icontrols.h b/libhwcservice/icontrols.h new file mode 100644 index 00000000..66f8c400 --- /dev/null +++ b/libhwcservice/icontrols.h @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_HWC_ICONTROLS_H_ +#define OS_ANDROID_HWC_ICONTROLS_H_ + +#include +#include +#include "hwcserviceapi.h" + +namespace hwcomposer { + +class IControls : public android::IInterface { + public: + DECLARE_META_INTERFACE(Controls); + + virtual status_t DisplaySetOverscan(uint32_t display, int32_t xoverscan, + int32_t yoverscan) = 0; + virtual status_t DisplayGetOverscan(uint32_t display, int32_t *xoverscan, + int32_t *yoverscan) = 0; + virtual status_t DisplaySetScaling(uint32_t display, + EHwcsScalingMode eScalingMode) = 0; + virtual status_t DisplayGetScaling(uint32_t display, + EHwcsScalingMode *eScalingMode) = 0; + virtual status_t DisplayEnableBlank(uint32_t display, bool blank) = 0; + virtual status_t DisplayRestoreDefaultColorParam(uint32_t display, + EHwcsColorControl color) = 0; + virtual status_t DisplayRestoreDefaultDeinterlaceParam(uint32_t display) = 0; + virtual status_t DisplayGetColorParam(uint32_t display, + EHwcsColorControl color, float *value, + float *startvalue, float *endvalue) = 0; + virtual status_t DisplaySetColorParam(uint32_t display, + EHwcsColorControl color, + float value) = 0; + virtual status_t DisplaySetDeinterlaceParam(uint32_t display, + EHwcsDeinterlaceControl mode) = 0; + + virtual std::vector DisplayModeGetAvailableModes( + uint32_t display) = 0; + virtual status_t DisplayModeGetMode(uint32_t display, + HwcsDisplayModeInfo *pMode) = 0; + virtual status_t DisplayModeSetMode(uint32_t display, + const uint32_t config) = 0; + + virtual status_t EnableHDCPSessionForDisplay( + uint32_t connector, EHwcsContentType content_type) = 0; + + virtual status_t EnableHDCPSessionForAllDisplays( + EHwcsContentType content_type) = 0; + + virtual status_t DisableHDCPSessionForDisplay(uint32_t connector) = 0; + + virtual status_t DisableHDCPSessionForAllDisplays() = 0; + +#ifdef ENABLE_PANORAMA + virtual status_t TriggerPanorama(uint32_t hotplug_simulation) = 0; + + virtual status_t ShutdownPanorama(uint32_t hotplug_simulation) = 0; +#endif + + virtual status_t SetHDCPSRMForAllDisplays(const int8_t *SRM, + uint32_t SRMLength) = 0; + + virtual status_t SetHDCPSRMForDisplay(uint32_t connector, const int8_t *SRM, + uint32_t SRMLength) = 0; + + virtual uint32_t GetDisplayIDFromConnectorID(uint32_t connector_id) = 0; + + virtual bool EnableDRMCommit(bool enable, uint32_t display_id) = 0; + + virtual bool ResetDrmMaster(bool drop_master) = 0; + + virtual status_t VideoEnableEncryptedSession(uint32_t sessionID, + uint32_t instanceID) = 0; + virtual status_t VideoDisableAllEncryptedSessions(uint32_t sessionID) = 0; + virtual status_t VideoDisableAllEncryptedSessions() = 0; + virtual bool VideoIsEncryptedSessionEnabled(uint32_t sessionID, + uint32_t instanceID) = 0; + virtual status_t VideoSetOptimizationMode(EHwcsOptimizationMode mode) = 0; + + virtual status_t MdsUpdateVideoState(int64_t videoSessionID, + bool isPrepared) = 0; + virtual status_t MdsUpdateVideoFPS(int64_t videoSessionID, int32_t fps) = 0; + virtual status_t MdsUpdateInputState(bool state) = 0; + + virtual status_t WidiGetSingleDisplay(bool *pEnabled) = 0; + virtual status_t WidiSetSingleDisplay(bool enable) = 0; +}; + +class BnControls : public android::BnInterface { + public: + status_t onTransact(uint32_t, const android::Parcel &, android::Parcel *, + uint32_t) override; +}; + +} // namespace hwcomposer + +#endif // OS_ANDROID_HWC_ICONTROLS_H_ diff --git a/libhwcservice/idiagnostic.cpp b/libhwcservice/idiagnostic.cpp new file mode 100644 index 00000000..56916c3e --- /dev/null +++ b/libhwcservice/idiagnostic.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "idiagnostic.h" +#include +#include +#include + +namespace hwcomposer { + +using namespace android; + +class BpDiagnostic : public BpInterface { + public: + BpDiagnostic(const sp& impl) + : BpInterface(impl), mReply(0) { + } + + enum { + TRANSACT_READ_LOG_PARCEL = IBinder::FIRST_CALL_TRANSACTION, + TRANSACT_ENABLE_DISPLAY, + TRANSACT_DISABLE_DISPLAY, + TRANSACT_MASK_LAYER, + TRANSACT_DUMP_FRAMES + }; + + virtual ~BpDiagnostic() { + if (mReply) + delete mReply; + } + + status_t ReadLogParcel(Parcel* reply) { + Parcel data; + data.writeInterfaceToken(IDiagnostic::getInterfaceDescriptor()); + status_t ret = remote()->transact(TRANSACT_READ_LOG_PARCEL, data, reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return ret; + } + + void EnableDisplay(uint32_t d) { + Parcel data, reply; + data.writeInterfaceToken(IDiagnostic::getInterfaceDescriptor()); + data.writeInt32(d); + status_t ret = remote()->transact(TRANSACT_ENABLE_DISPLAY, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return; + } + } + + void DisableDisplay(uint32_t d, bool bBlank) { + Parcel data, reply; + data.writeInterfaceToken(IDiagnostic::getInterfaceDescriptor()); + data.writeInt32(d); + data.writeInt32(bBlank); + status_t ret = remote()->transact(TRANSACT_DISABLE_DISPLAY, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return; + } + } + + void MaskLayer(uint32_t d, uint32_t layer, bool bHide) { + Parcel data, reply; + data.writeInterfaceToken(IDiagnostic::getInterfaceDescriptor()); + data.writeInt32(d); + data.writeInt32(layer); + data.writeInt32(bHide); + status_t ret = remote()->transact(TRANSACT_MASK_LAYER, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return; + } + } + + void DumpFrames(uint32_t d, int32_t frames, bool bSync) { + Parcel data, reply; + data.writeInterfaceToken(IDiagnostic::getInterfaceDescriptor()); + data.writeInt32(d); + data.writeInt32(frames); + data.writeInt32(bSync); + status_t ret = remote()->transact(TRANSACT_DUMP_FRAMES, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + return; + } + } + + private: + Parcel* mReply; +}; + +IMPLEMENT_META_INTERFACE(Diagnostic, "ia.hwc.diagnostic"); + +status_t BnDiagnostic::onTransact(uint32_t code, const Parcel& data, + Parcel* reply, uint32_t flags) { + switch (code) { + case BpDiagnostic::TRANSACT_READ_LOG_PARCEL: { + CHECK_INTERFACE(IDiagnostic, data, reply); + status_t err = ReadLogParcel(reply); + return err; + } + + case BpDiagnostic::TRANSACT_ENABLE_DISPLAY: { + CHECK_INTERFACE(IDiagnostic, data, reply); + uint32_t d = data.readInt32(); + EnableDisplay(d); + return NO_ERROR; + } + + case BpDiagnostic::TRANSACT_DISABLE_DISPLAY: { + CHECK_INTERFACE(IDiagnostic, data, reply); + uint32_t d = data.readInt32(); + bool bBlank = data.readInt32(); + DisableDisplay(d, bBlank); + return NO_ERROR; + } + + case BpDiagnostic::TRANSACT_MASK_LAYER: { + CHECK_INTERFACE(IDiagnostic, data, reply); + uint32_t d = data.readInt32(); + uint32_t layer = data.readInt32(); + bool bHide = data.readInt32(); + MaskLayer(d, layer, bHide); + return NO_ERROR; + } + + case BpDiagnostic::TRANSACT_DUMP_FRAMES: { + CHECK_INTERFACE(IDiagnostic, data, reply); + uint32_t d = data.readInt32(); + int32_t frames = data.readInt32(); + bool bSync = data.readInt32(); + DumpFrames(d, frames, bSync); + return NO_ERROR; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +} // namespace hwcomposer diff --git a/libhwcservice/idiagnostic.h b/libhwcservice/idiagnostic.h new file mode 100644 index 00000000..5bd8aa2c --- /dev/null +++ b/libhwcservice/idiagnostic.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_HWC_IDIAGNOSTIC_H +#define OS_ANDROID_HWC_IDIAGNOSTIC_H + +#include +#include + +namespace hwcomposer { + +using namespace android; + +class IDiagnostic : public IInterface { + public: + DECLARE_META_INTERFACE(Diagnostic); + + // This class is shared with the validation team. Take care when changing it + // that + // the validation tests understand how we have changed this. + enum { + eLogTruncated = + 101, // Status to indicate log entries have been overwritten + }; + + virtual status_t ReadLogParcel(android::Parcel* reply) = 0; + + // Debug API + virtual void EnableDisplay(uint32_t d) = 0; + virtual void DisableDisplay(uint32_t d, bool bBlank) = 0; + virtual void MaskLayer(uint32_t d, uint32_t layer, bool bHide) = 0; + virtual void DumpFrames(uint32_t d, int32_t frames, bool bSync) = 0; +}; + +class BnDiagnostic : public android::BnInterface { + public: + BnDiagnostic() { + } + + virtual ~BnDiagnostic() { + } + + status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t) override; +}; + +} // namespace hwcomposer + +#endif // OS_ANDROID_HWC_IDIAGNOSTIC_H diff --git a/libhwcservice/idisplayoverscancontrol.h b/libhwcservice/idisplayoverscancontrol.h new file mode 100644 index 00000000..8c1b8452 --- /dev/null +++ b/libhwcservice/idisplayoverscancontrol.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_IDISPLAY_OVERSCAN_CONTROL_H_ +#define OS_ANDROID_IDISPLAY_OVERSCAN_CONTROL_H_ + +#include +#include "hwcservicehelper.h" + +namespace hwcomposer { + +/** + * Allows control of HDMI overscan + */ +class IDisplayOverscanControl : public android::RefBase { + public: + IDisplayOverscanControl(uint32_t display) : mDisplay(display) { + } + + enum { + MAX_OVERSCAN = HWCS_MAX_OVERSCAN, // The limit of the control parameters + // are +/-MAX_OVERSCAN inclusive. + RANGE = HWCS_OVERSCAN_RANGE, // RANGE describes the % of the display size a + // max control setting will adjust by. + }; + + /// Set overscan in the range +/-MAX_OVERSCAN inclusive. + // -ve : zoom/crop the image (increase display overscan). + // +ve : shrink the image (decrease display overscan). + status_t setOverscan(int32_t xoverscan, int32_t yoverscan) { + return HwcService_Display_SetOverscan(mHwcConn, mDisplay, xoverscan, + yoverscan); + } + + // Get last set overscan. + // Returns INVALID_OPERATION if overscan has not been set and + // xoverscan/yoverscan are untouched. + status_t getOverscan(int32_t *xoverscan, int32_t *yoverscan) { + return HwcService_Display_GetOverscan(mHwcConn, mDisplay, xoverscan, + yoverscan); + } + + private: + HwcServiceConnection mHwcConn; + uint32_t mDisplay; +}; + +} // namespace hwcomposer + +#endif // OS_ANDROID_IDISPLAY_OVERSCAN_CONTROL_H_ diff --git a/libhwcservice/idisplayscalingcontrol.h b/libhwcservice/idisplayscalingcontrol.h new file mode 100644 index 00000000..a45db3a6 --- /dev/null +++ b/libhwcservice/idisplayscalingcontrol.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_IDISPLAY_SCALING_CONTROL_H_ +#define OS_ANDROID_IDISPLAY_SCALING_CONTROL_H_ + +#include +#include "hwcservicehelper.h" + +namespace hwcomposer { + +/** + * Allows control of HDMI scaling for content + * that does not match the native display resolution. + */ +class IDisplayScalingControl : public android::RefBase { + public: + IDisplayScalingControl(uint32_t display) : mDisplay(display) { + } + + enum EScalingMode { + SCALE_CENTRE = HWCS_SCALE_CENTRE, // Present the content centred at 1:1 + // source resolution. + SCALE_STRETCH = HWCS_SCALE_STRETCH, // Do not preserve aspect ratio - scale + // to fill the display without + // cropping. + SCALE_FIT = HWCS_SCALE_FIT, // Preserve aspect ratio - scale to closest + // edge (may be letterboxed or pillarboxed). + SCALE_FILL = HWCS_SCALE_FILL, // Preserve aspect ratio - scale to fill the + // display (may crop the content). + SCALE_MAX_ENUM = HWCS_SCALE_MAX_ENUM // End of enum. + }; + + /// Set scaling to one of EScalingMode. + // Returns OK if succesful. + status_t setScaling(EScalingMode eScalingMode) { + return HwcService_Display_SetScaling(mHwcConn, mDisplay, + (EHwcsScalingMode)eScalingMode); + } + + // Get last set scaling. + // Returns OK if succesful. + // Returns INVALID_OPERATION if scaling has not been set and eScalingMode is + // untouched. + status_t getScaling(EScalingMode *eScalingMode) { + return HwcService_Display_GetScaling(mHwcConn, mDisplay, + (EHwcsScalingMode *)eScalingMode); + } + + private: + HwcServiceConnection mHwcConn; + uint32_t mDisplay; +}; + +} // namespace hwcomposer + +#endif // OS_ANDROID_IDISPLAY_SCALING_CONTROL_H_ diff --git a/libhwcservice/iservice.cpp b/libhwcservice/iservice.cpp new file mode 100644 index 00000000..4df5d084 --- /dev/null +++ b/libhwcservice/iservice.cpp @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iservice.h" +#include "icontrols.h" +#include "idiagnostic.h" + +#include + +namespace hwcomposer { + +using namespace android; + +/** + */ +class BpService : public BpInterface { + public: + BpService(const sp& impl) : BpInterface(impl) { + } + + enum { + // ============================================== + // Public APIs - try not to reorder these + + GET_HWC_VERSION = IBinder::FIRST_CALL_TRANSACTION, + + // Dump options and current settings to logcat. + DUMP_OPTIONS, + + // Override an option. + SET_OPTION, + + // Disable hwc logviewer output to logcat + DISABLE_LOG_TO_LOGCAT = 98, + // Enable hwclogviewer output to logcat + ENABLE_LOG_TO_LOGCAT = 99, + + // accessor for IBinder interface functions + TRANSACT_GET_DIAGNOSTIC = 100, + TRANSACT_GET_CONTROLS, + }; + + String8 GetHwcVersion() override { + Parcel data, reply; + data.writeInterfaceToken(IService::getInterfaceDescriptor()); + remote()->transact(GET_HWC_VERSION, data, &reply); + String8 ret = reply.readString8(); + return ret; + } + + void DumpOptions(void) override { + Parcel data, reply; + remote()->transact(DUMP_OPTIONS, data, &reply); + } + + status_t SetOption(String8 option, String8 optionValue) override { + Parcel data, reply; + data.writeInterfaceToken(IService::getInterfaceDescriptor()); + data.writeString16(String16(option)); + data.writeString16(String16(optionValue)); + remote()->transact(SET_OPTION, data, &reply); + status_t ret = reply.readInt32(); + return ret; + } + + status_t EnableLogviewToLogcat(bool enable = true) override { + Parcel data, reply; + data.writeInterfaceToken(IService::getInterfaceDescriptor()); + if (enable) { + remote()->transact(ENABLE_LOG_TO_LOGCAT, data, &reply); + } else { + remote()->transact(DISABLE_LOG_TO_LOGCAT, data, &reply); + } + status_t ret = reply.readInt32(); + return ret; + } + + sp GetDiagnostic() override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + status_t ret = remote()->transact(TRANSACT_GET_DIAGNOSTIC, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return interface_cast(reply.readStrongBinder()); + } + + sp GetControls() override { + Parcel data; + Parcel reply; + data.writeInterfaceToken(getInterfaceDescriptor()); + status_t ret = remote()->transact(TRANSACT_GET_CONTROLS, data, &reply); + if (ret != NO_ERROR) { + ALOGW("%s() transact failed: %d", __FUNCTION__, ret); + } + return interface_cast(reply.readStrongBinder()); + } +}; + +IMPLEMENT_META_INTERFACE(Service, "ia.hwc.IService"); + +status_t BnService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { + switch (code) { + case BpService::GET_HWC_VERSION: { + CHECK_INTERFACE(IService, data, reply); + reply->writeString8(GetHwcVersion()); + return NO_ERROR; + } + + case BpService::SET_OPTION: { + CHECK_INTERFACE(IService, data, reply); + String16 option = data.readString16(); + String16 optionValue = data.readString16(); + status_t ret = SetOption(String8(option), String8(optionValue)); + reply->writeInt32(ret); + return NO_ERROR; + } + + case BpService::DUMP_OPTIONS: { + CHECK_INTERFACE(IService, data, reply); + DumpOptions(); + return NO_ERROR; + } + + case BpService::DISABLE_LOG_TO_LOGCAT: { + CHECK_INTERFACE(IService, data, reply); + status_t ret = EnableLogviewToLogcat(false); + reply->writeInt32(ret); + return NO_ERROR; + } + + case BpService::ENABLE_LOG_TO_LOGCAT: { + CHECK_INTERFACE(IService, data, reply); + status_t ret = EnableLogviewToLogcat(); + reply->writeInt32(ret); + return NO_ERROR; + } + + case BpService::TRANSACT_GET_DIAGNOSTIC: { + CHECK_INTERFACE(IService, data, reply); + sp b = IInterface::asBinder(this->GetDiagnostic()); + reply->writeStrongBinder(b); + return NO_ERROR; + } + + case BpService::TRANSACT_GET_CONTROLS: { + CHECK_INTERFACE(IService, data, reply); + sp b = IInterface::asBinder(this->GetControls()); + reply->writeStrongBinder(b); + return NO_ERROR; + } + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +} // namespace hwcomposer diff --git a/libhwcservice/iservice.h b/libhwcservice/iservice.h new file mode 100644 index 00000000..82e72db7 --- /dev/null +++ b/libhwcservice/iservice.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_ANDROID_ISERVICE_H_ +#define OS_ANDROID_ISERVICE_H_ + +#include +#include + +#define IA_HWC_SERVICE_NAME "hwc.info" + +namespace hwcomposer { + +class IControls; +class IDiagnostic; + +using namespace android; + +/** Maintenance interface to control HWC activity. + */ +class IService : public IInterface { + public: + DECLARE_META_INTERFACE(Service); + + virtual sp GetDiagnostic() = 0; + virtual sp GetControls() = 0; + + virtual String8 GetHwcVersion() = 0; + virtual void DumpOptions(void) = 0; + virtual status_t SetOption(String8 option, String8 optionValue) = 0; + virtual status_t EnableLogviewToLogcat(bool enable = true) = 0; +}; + +/** + */ +class BnService : public BnInterface { + public: + status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t) override; +}; + +} // namespace hwcomposer + +#endif // OS_ANDROID_ISERVICE_H_ diff --git a/libhwcservice/test/Android.mk b/libhwcservice/test/Android.mk new file mode 100644 index 00000000..e4f19fba --- /dev/null +++ b/libhwcservice/test/Android.mk @@ -0,0 +1,31 @@ +# Copyright (c) 2015 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH := $(call my-dir) + +ANDROID_VERSION := $(word 1, $(subst ., , $(PLATFORM_VERSION))) + +include $(CLEAR_VARS) +LOCAL_MODULE:= hwcservice_test +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../ +LOCAL_SRC_FILES:= hwcservice_test.cpp +LOCAL_SHARED_LIBRARIES := libutils libbinder liblog libhwcservice +LOCAL_PROPRIETARY_MODULE := true +ifeq ($(shell test $(ANDROID_VERSION) -ge 8; echo $$?), 0) +LOCAL_CFLAGS += -DUSE_PROCESS_STATE +endif +ifeq ($(strip $(ENABLE_HYPER_DMABUF_SHARING)), true) +LOCAL_CFLAGS += -DENABLE_PANORAMA +endif +include $(BUILD_EXECUTABLE) diff --git a/libhwcservice/test/hwcservice_test.cpp b/libhwcservice/test/hwcservice_test.cpp new file mode 100644 index 00000000..60b2190a --- /dev/null +++ b/libhwcservice/test/hwcservice_test.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "hwcserviceapi.h" +#include "iservice.h" + +using namespace android; +using namespace hwcomposer; + +static void usage() { + aout << "Usage: hwcservice_test \n" + "\t-g: Get current display mode\n" + "\t-h: Enable HDCP support for a given Display. \n" + "\t-i: Disable HDCP support for a given Display. \n" + "\t-j: Enable HDCP support for all displays. \n" + "\t-k: Disable HDCP support for all displays. \n" + "\t-s: Set display mode\n" + "\t-p: Print all available display modes\n" + "\t-u: Set Hue\n" + "\t-a: Set Saturation\n" + "\t-b: Set Brightness\n" + "\t-c: Set Contrast\n" + "\t-e: Set Sharpness\n" + "\t-d: Set deinterlace\n" + "\t-r: Restore all default video colors/deinterlace \n" +#ifdef ENABLE_PANORAMA + "\t-w: Trigger Panorama with option of hotplug simulation or not\n" + "\t-m: Shutdown Panorama with option of hotplug simulation or not\n"; +#else + ; +#endif + exit(-1); +} + +int main(int argc, char** argv) { + uint32_t display = 0; + uint32_t display_mode_index = 0; + bool print_mode = false; + bool get_mode = false; + bool set_mode = false; + bool set_hue = false; + bool set_saturation = false; + bool set_brightness = false; + bool set_contrast = false; + bool set_deinterlace = false; + bool set_sharpness = false; + bool set_hdcp_for_display = false; + bool set_hdcp_for_all_display = false; + bool disable_hdcp_for_display = false; + bool disable_hdcp_for_all_display = false; + bool restore = false; +#ifdef ENABLE_PANORAMA + bool trigger_panorama = false; + bool shutdown_panorama = false; +#endif + int ch; +#ifdef ENABLE_PANORAMA + while ((ch = getopt(argc, argv, "gsphijkurabcdemw")) != -1) { +#else + while ((ch = getopt(argc, argv, "gsphijkurabcde")) != -1) { +#endif + switch (ch) { + case 'g': + get_mode = true; + break; + case 's': + set_mode = true; + break; + case 'p': + print_mode = true; + break; + case 'u': + set_hue = true; + break; + case 'r': + restore = true; + break; + case 'a': + set_saturation = true; + break; + case 'b': + set_brightness = true; + break; + case 'c': + set_contrast = true; + break; + case 'e': + set_sharpness = true; + break; + + case 'd': + set_deinterlace = true; + break; + case 'h': + set_hdcp_for_display = true; + break; + case 'i': + disable_hdcp_for_display = true; + break; + case 'j': + set_hdcp_for_all_display = true; + break; + case 'k': + disable_hdcp_for_all_display = true; + break; +#ifdef ENABLE_PANORAMA + case 'w': + trigger_panorama = true; + break; + case 'm': + shutdown_panorama = true; + break; +#endif + default: + usage(); + } + } + argc -= optind; + argv += optind; + +#ifdef USE_PROCESS_STATE + // Initialize ProcessState with /dev/vndbinder as HwcService is + // in the vndbinder context + android::ProcessState::initWithDriver("/dev/vndbinder"); +#endif + + // Connect to HWC service + HWCSHANDLE hwcs = HwcService_Connect(); + if (hwcs == NULL) { + aout << "Could not connect to service\n"; + return -1; + } + + std::vector modes; + HwcService_DisplayMode_GetAvailableModes(hwcs, display, modes); + if (print_mode) { + aout << "Mode Width x Height\tRefreshRate\tXDpi\tYDpi\n"; + for (uint32_t i = 0; i < modes.size(); i++) { + aout << i << "\t" << modes[i].width << "\t" << modes[i].height << "\t" + << modes[i].refresh << "\t" << modes[i].xdpi << "\t" << modes[i].ydpi + << endl; + } + } + + if (get_mode) { + HwcsDisplayModeInfo mode; + HwcService_DisplayMode_GetMode(hwcs, display, &mode); + aout << "Width x Height\tRefreshRate\tXDpi\tYDpi\n"; + aout << mode.width << "\t" << mode.height << "\t" << mode.refresh << "\t" + << mode.xdpi << "\t" << mode.ydpi << endl; + } + + if (set_mode) { + status_t ret = + HwcService_DisplayMode_SetMode(hwcs, display, display_mode_index); + if (ret != OK) { + aout << "Mode set failed\n"; + HwcService_Disconnect(hwcs); + return 1; + } + } + + if (set_hue) { + aout << "Set Hue to: " << atoi(argv[0]) << endl; + HwcService_Display_SetColorParam(hwcs, display, HWCS_COLOR_HUE, + atoi(argv[0])); + } + + if (set_brightness) { + aout << "Set Brightness to: " << atoi(argv[0]) << endl; + HwcService_Display_SetColorParam(hwcs, display, HWCS_COLOR_BRIGHTNESS, + atoi(argv[0])); + } + + if (set_saturation) { + aout << "Set Saturation to: " << atoi(argv[0]) << endl; + HwcService_Display_SetColorParam(hwcs, display, HWCS_COLOR_SATURATION, + atoi(argv[0])); + } + + if (set_contrast) { + aout << "Set Contrast to: " << atoi(argv[0]) << endl; + HwcService_Display_SetColorParam(hwcs, display, HWCS_COLOR_CONTRAST, + atoi(argv[0])); + } + + if (set_sharpness) { + aout << "Set Sharpness to: " << atoi(argv[0]) << endl; + HwcService_Display_SetColorParam(hwcs, display, HWCS_COLOR_SHARP, + atoi(argv[0])); + } + + if (set_deinterlace) { + aout << "Set Deinterlace to: " << atoi(argv[0]) << endl; + HwcService_Display_SetDeinterlaceParam(hwcs, display, atoi(argv[0])); + } + + if (restore) { + aout << "Restore default colors\n"; + HwcService_Display_RestoreDefaultColorParam(hwcs, display, HWCS_COLOR_HUE); + HwcService_Display_RestoreDefaultColorParam(hwcs, display, + HWCS_COLOR_SATURATION); + HwcService_Display_RestoreDefaultColorParam(hwcs, display, + HWCS_COLOR_BRIGHTNESS); + HwcService_Display_RestoreDefaultColorParam(hwcs, display, + HWCS_COLOR_CONTRAST); + HwcService_Display_RestoreDefaultColorParam(hwcs, display, + HWCS_COLOR_SHARP); + HwcService_Display_RestoreDefaultDeinterlaceParam(hwcs, display); + } + + if (set_hdcp_for_display) { + aout << "Set HDCP For Display: " << atoi(argv[0]) << endl; + if (atoi(argv[0]) == 0) { + HwcService_Video_EnableHDCPSession_ForDisplay(hwcs, atoi(argv[0]), + HWCS_CP_CONTENT_TYPE0); + } else { + HwcService_Video_EnableHDCPSession_ForDisplay(hwcs, atoi(argv[0]), + HWCS_CP_CONTENT_TYPE1); + } + } + + if (disable_hdcp_for_display) { + aout << "Disabling HDCP For Display: " << atoi(argv[0]) << endl; + HwcService_Video_DisableHDCPSession_ForDisplay(hwcs, atoi(argv[0])); + } + + if (set_hdcp_for_all_display) { + aout << "Set HDCP For All Displays Using Fallback: " << atoi(argv[0]) + << endl; + if (atoi(argv[0]) == 0) { + HwcService_Video_EnableHDCPSession_AllDisplays(hwcs, + HWCS_CP_CONTENT_TYPE0); + } else { + HwcService_Video_EnableHDCPSession_AllDisplays(hwcs, + HWCS_CP_CONTENT_TYPE1); + } + } + + if (disable_hdcp_for_all_display) { + aout << "Disabling HDCP For All Displays. " << endl; + HwcService_Video_DisableHDCPSession_AllDisplays(hwcs); + } + +#ifdef ENABLE_PANORAMA + if (trigger_panorama) { + int simulation_hotplug = 0; + if (argc >= 1) { + simulation_hotplug = atoi(argv[0]); + } + aout << "Trigger Panorama view mode, simulation hotplug: " + << simulation_hotplug << endl; + + HwcService_TriggerPanorama(hwcs, simulation_hotplug); + } + + if (shutdown_panorama) { + int simulation_hotplug = 0; + if (argc >= 1) { + simulation_hotplug = atoi(argv[0]); + } + aout << "Shutdown Panorama view mode, simulation hotplug: " + << simulation_hotplug << endl; + HwcService_ShutdownPanorama(hwcs, simulation_hotplug); + } +#endif + + HwcService_Disconnect(hwcs); + return 0; +} diff --git a/utils/hwcdefs.h b/utils/hwcdefs.h new file mode 100644 index 00000000..1a72ac77 --- /dev/null +++ b/utils/hwcdefs.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PUBLIC_HWCDEFS_H_ +#define PUBLIC_HWCDEFS_H_ + +#include + +#ifdef __cplusplus +#include "hwcrect.h" + +#include +#include + +namespace hwcomposer { + +template +using HwcRect = Rect; + +typedef std::vector> HwcRegion; + +enum class HWCBlending : int32_t { + kBlendingNone = 0x0100, + kBlendingPremult = 0x0105, + kBlendingCoverage = 0x0405, +}; + +// Enumerations for content protection. +enum HWCContentProtection { + kUnSupported = 0, // Content Protection is not supported. + kUnDesired = 1, // Content Protection is not required. + kDesired = 2 // Content Protection is desired. +}; + +enum HWCContentType { + kCONTENT_TYPE0, // Can support any HDCP specifiction. + kCONTENT_TYPE1, // Can support only HDCP 2.2 and higher specification. + kInvalid, // Used when disabling HDCP. +}; + +enum HWCTransform : uint32_t { + kIdentity = 0, + kReflectX = 1 << 0, + kReflectY = 1 << 1, + kTransform90 = 1 << 2, + kTransform180 = 1 << 3, + kTransform270 = 1 << 4, + kTransform45 = kTransform90 | kReflectY, + kTransform135 = kTransform90 | kReflectX, + kMaxTransform = 8 +}; + +enum HWCRotation { + kRotateNone = 0, + kRotate90, + kRotate180, + kRotate270, + kMaxRotate +}; + +enum HWCLayerType { + kLayerNormal = 0, + kLayerCursor = 1, + kLayerProtected = 2, + kLayerVideo = 3, + kLayerSolidColor = 4, +}; + +enum class HWCDisplayAttribute : int32_t { + kWidth = 1, + kHeight = 2, + kRefreshRate = 3, + kDpiX = 4, + kDpiY = 5 +}; + +enum class DisplayType : int32_t { + kInternal = 0, + kExternal = 1, + kVirtual = 2, + kLogical = 3, + kMosaic = 4, +}; +#endif //__cplusplus + +enum DisplayPowerMode { + kOff = 0, // Display is off + kDoze = 1, // Display is off and used by the app during any inactivity + // when the device is on battery + kOn = 2, // Display is on + kDozeSuspend = 3 // Dispaly in low power mode and stop applying + // updates from the client +}; + +enum HWCColorTransform { + // Applies no transform to the output color + kIdentical = 0, + // Applies an arbitrary transform defined by a 4x4 affine matrix + kArbitraryMatrix = 1 +}; + +#ifdef __cplusplus +enum class HWCColorControl : int32_t { + kColorHue = 0, + kColorSaturation = 1, + kColorBrightness = 2, + kColorContrast = 3, + kColorSharpness = 4 +}; + +enum class HWCDeinterlaceFlag : int32_t { + kDeinterlaceFlagNone = 0, + kDeinterlaceFlagForce = 1, + kDeinterlaceFlagAuto = 2 +}; + +enum class HWCDeinterlaceControl : int32_t { + kDeinterlaceNone = 0, + kDeinterlaceBob = 1, + kDeinterlaceWeave = 2, + kDeinterlaceMotionAdaptive = 3, + kDeinterlaceMotionCompensated = 4 +}; + +enum class HWCScalingRunTimeSetting : int32_t { + kScalingModeNone = 0, // use default scaling mode. + kScalingModeFast = 1, // use fast scaling mode. + kScalingModeHighQuality = 2 // use high quality scaling mode. +}; + +enum class HWCDisplayCapability : uint32_t { + kDisplayCapabilityInvalid = 0, + kDisplayCapabilitySkipClientColorTransform = 1, + kDisplayCapabilityDoze = 2 +}; + +struct EnumClassHash { + template + std::size_t operator()(T t) const { + return static_cast(t); + } +}; + +struct HWCColorProp { + float value_ = 0.0; + bool use_default_ = true; +}; + +struct HWCDeinterlaceProp { + HWCDeinterlaceFlag flag_; + HWCDeinterlaceControl mode_; +}; + +using HWCColorMap = + std::unordered_map; + +} // namespace hwcomposer +#endif // __cplusplus + +#endif // PUBLIC_HWCDEFS_H_ diff --git a/utils/hwcrect.h b/utils/hwcrect.h new file mode 100644 index 00000000..5cea4686 --- /dev/null +++ b/utils/hwcrect.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** \file */ +#ifndef PUBLIC_HWCRECT_H_ +#define PUBLIC_HWCRECT_H_ + +#include + +#include + +namespace hwcomposer { + +// Some of the structs are adopted from drm_hwcomposer +template +struct Rect { + union { + struct { + TFloat left, top, right, bottom; + }; + TFloat bounds[4]; + }; + typedef TFloat TNum; + Rect() { + reset(); + } + Rect(TFloat left_, TFloat top_, TFloat right_, TFloat bottom_) + : left(left_), top(top_), right(right_), bottom(bottom_) { + } + template + Rect(const Rect &rhs) { + for (int i = 0; i < 4; i++) + bounds[i] = rhs.bounds[i]; + } + template + Rect &operator=(const Rect &rhs) { + for (int i = 0; i < 4; i++) + bounds[i] = rhs.bounds[i]; + return *this; + } + bool operator==(const Rect &rhs) const { + for (int i = 0; i < 4; i++) { + if (bounds[i] != rhs.bounds[i]) + return false; + } + return true; + } + + /** + * Check if bounds are unset + * + * @return True if all bounds are set to 0 + */ + bool empty() const { + for (int i = 0; i < 4; i++) { + if (bounds[i] != 0) + return false; + } + return true; + } + + /** + * Set bounds to 0 + */ + void reset() { + for (int i = 0; i < 4; i++) { + memset(&bounds, 0, sizeof(bounds)); + } + } +}; + +} // namespace hwcomposer + +#endif // PUBLIC_HWCRECT_H_ diff --git a/utils/spinlock.h b/utils/spinlock.h new file mode 100644 index 00000000..31e394e9 --- /dev/null +++ b/utils/spinlock.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PUBLIC_SPINLOCK_H_ +#define PUBLIC_SPINLOCK_H_ + +#include + +namespace hwcomposer { + +class SpinLock { + public: + void lock() { + while (atomic_lock_.test_and_set(std::memory_order_acquire)) { + } + } + + void unlock() { + atomic_lock_.clear(std::memory_order_release); + } + + private: + std::atomic_flag atomic_lock_ = ATOMIC_FLAG_INIT; +}; + +class ScopedSpinLock { + public: + explicit ScopedSpinLock(SpinLock& lock) : lock_(lock) { + lock_.lock(); + locked_ = true; + } + + ~ScopedSpinLock() { + if (locked_) { + lock_.unlock(); + locked_ = false; + } + } + + private: + SpinLock& lock_; + bool locked_; +}; + +class ScopedSpinLocks { + public: + ScopedSpinLocks(SpinLock& lock1, SpinLock& lock2) + : lock1_(lock1), lock2_(lock2) { + lock1_.lock(); + lock2_.lock(); + } + + ~ScopedSpinLocks() { + lock1_.unlock(); + lock2_.unlock(); + } + + private: + SpinLock& lock1_; + SpinLock& lock2_; +}; + +} // namespace hwcomposer +#endif // PUBLIC_SPINLOCK_H_ diff --git a/utils/utils_android.h b/utils/utils_android.h new file mode 100644 index 00000000..f9a2378d --- /dev/null +++ b/utils/utils_android.h @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OS_UTILS_ANDROID_H_ +#define OS_UTILS_ANDROID_H_ + +#include +#include + +#include +#include +#include +#include + +#include "platformdefines.h" + +#include +#include + +#include +#include "hwctrace.h" +#include "hwcutils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Conversion from HAL to fourcc-based DRM formats +static uint32_t GetDrmFormatFromHALFormat(int format) { + switch (format) { + case HAL_PIXEL_FORMAT_RGBA_8888: + return DRM_FORMAT_BGRA8888; + case HAL_PIXEL_FORMAT_RGBX_8888: + return DRM_FORMAT_BGRX8888; + case HAL_PIXEL_FORMAT_RGB_888: + return DRM_FORMAT_BGR888; + case HAL_PIXEL_FORMAT_RGB_565: + return DRM_FORMAT_BGR565; + case HAL_PIXEL_FORMAT_BGRA_8888: + return DRM_FORMAT_ARGB8888; + case HAL_PIXEL_FORMAT_YV12: + return DRM_FORMAT_YVU420; + case HAL_PIXEL_FORMAT_RGBA_FP16: + return DRM_FORMAT_XBGR161616; + case HAL_PIXEL_FORMAT_RGBA_1010102: + return DRM_FORMAT_ABGR2101010; + default: + break; + } + + return DRM_FORMAT_NONE; +} + +static uint32_t DrmFormatToHALFormat(int format) { + switch (format) { + case DRM_FORMAT_BGRA8888: + return HAL_PIXEL_FORMAT_RGBA_8888; + case DRM_FORMAT_BGRX8888: + return HAL_PIXEL_FORMAT_RGBX_8888; + case DRM_FORMAT_BGR888: + return HAL_PIXEL_FORMAT_RGB_888; + case DRM_FORMAT_BGR565: + return HAL_PIXEL_FORMAT_RGB_565; + case DRM_FORMAT_ARGB8888: + return HAL_PIXEL_FORMAT_BGRA_8888; + case DRM_FORMAT_YVU420: + return HAL_PIXEL_FORMAT_YV12; + case DRM_FORMAT_R8: + return HAL_PIXEL_FORMAT_BLOB; + case DRM_FORMAT_GR88: + case DRM_FORMAT_R16: + return HAL_PIXEL_FORMAT_Y16; + case DRM_FORMAT_ABGR8888: + return HAL_PIXEL_FORMAT_RGBA_8888; + case DRM_FORMAT_RGB332: //('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ + return 0; + case DRM_FORMAT_BGR233: //('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ + return 0; + + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRX4444: + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_BGRA4444: + return 0; + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: + return 0; + case DRM_FORMAT_RGB565: + return HAL_PIXEL_FORMAT_RGB_565; + case DRM_FORMAT_RGB888: + return HAL_PIXEL_FORMAT_RGB_888; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_RGBA8888: + return 0; + case DRM_FORMAT_ABGR2101010: + return HAL_PIXEL_FORMAT_RGBA_1010102; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: + return 0; + case DRM_FORMAT_YUYV: + return HAL_PIXEL_FORMAT_YCbCr_422_I; + case DRM_FORMAT_YVYU: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_AYUV: + ETRACE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_NV12: + return HAL_PIXEL_FORMAT_NV12; + case DRM_FORMAT_NV21: + return HAL_PIXEL_FORMAT_YCrCb_420_SP; + case DRM_FORMAT_NV16: + return HAL_PIXEL_FORMAT_YCbCr_422_SP; + case DRM_FORMAT_NV61: + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + case DRM_FORMAT_YUV411: + case DRM_FORMAT_YVU411: + ETRACE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_YUV420: + return HAL_PIXEL_FORMAT_YCbCr_420_888; + case DRM_FORMAT_YVU420_ANDROID: + return HAL_PIXEL_FORMAT_YV12; + case DRM_FORMAT_YUV422: + return HAL_PIXEL_FORMAT_YCbCr_422_888; + case DRM_FORMAT_YVU422: + ETRACE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_YUV444: + return HAL_PIXEL_FORMAT_YCbCr_444_888; + case DRM_FORMAT_YVU444: + ETRACE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_NV12_Y_TILED_INTEL: + return HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL; + case DRM_FORMAT_P010: + return HAL_PIXEL_FORMAT_P010_INTEL; + case DRM_FORMAT_XBGR161616: + return HAL_PIXEL_FORMAT_RGBA_FP16; + default: + return 0; + break; + } + + return DRM_FORMAT_NONE; +} + +static native_handle_t *dup_buffer_handle(buffer_handle_t handle) { + native_handle_t *new_handle = native_handle_clone(handle); + if (new_handle == NULL) + ETRACE("failed to duplicate the handle"); + return new_handle; +} + +static void free_buffer_handle(native_handle_t *handle) { + int ret = native_handle_close(handle); + if (ret) + ETRACE("Failed to close native handle %d", ret); + ret = native_handle_delete(handle); + if (ret) + ETRACE("Failed to delete native handle %d", ret); +} + +static void CopyBufferHandle(HWCNativeHandle source, HWCNativeHandle *target) { + struct gralloc_handle *temp = new struct gralloc_handle(); + temp->handle_ = source->handle_; + temp->gralloc1_buffer_descriptor_t_ = 0; + temp->imported_handle_ = dup_buffer_handle(source->handle_); + temp->hwc_buffer_ = false; + *target = temp; +} + +static void DestroyBufferHandle(HWCNativeHandle handle) { + if (handle->imported_handle_) + free_buffer_handle(handle->imported_handle_); + + delete handle; + handle = NULL; +} + +static bool ImportGraphicsBuffer(HWCNativeHandle handle, int fd) { + auto gr_handle = (struct cros_gralloc_handle *)handle->imported_handle_; + memset(&(handle->meta_data_), 0, sizeof(struct HwcMeta)); + handle->meta_data_.format_ = gr_handle->format; + handle->meta_data_.tiling_mode_ = gr_handle->tiling_mode; + handle->meta_data_.width_ = gr_handle->width; + handle->meta_data_.height_ = gr_handle->height; + handle->meta_data_.native_format_ = gr_handle->droid_format; + + if (gr_handle->is_interlaced > 0) { + handle->meta_data_.is_interlaced_ = true; + } else { + handle->meta_data_.is_interlaced_ = false; + } + + int32_t numplanes = gr_handle->base.numFds; + handle->meta_data_.num_planes_ = numplanes; + + for (int32_t p = 0; p < numplanes; p++) { + handle->meta_data_.offsets_[p] = gr_handle->offsets[p]; + handle->meta_data_.pitches_[p] = gr_handle->strides[p]; + handle->meta_data_.prime_fds_[p] = gr_handle->fds[p]; + if (drmPrimeFDToHandle(fd, gr_handle->fds[p], + &handle->meta_data_.gem_handles_[p])) { + ETRACE("drmPrimeFDToHandle failed. %s", PRINTERROR()); + return false; + } + + handle->meta_data_.fb_modifiers_[p] = gr_handle->format_modifiers[p]; + } + + if (gr_handle->consumer_usage & GRALLOC1_PRODUCER_USAGE_PROTECTED) { + handle->meta_data_.usage_ = hwcomposer::kLayerProtected; + } else if (gr_handle->consumer_usage & GRALLOC1_CONSUMER_USAGE_CURSOR) { + handle->meta_data_.usage_ = hwcomposer::kLayerCursor; + // We support DRM_FORMAT_ARGB8888 for cursor. + handle->meta_data_.format_ = DRM_FORMAT_ARGB8888; + } else if (hwcomposer::IsSupportedMediaFormat(handle->meta_data_.format_)) { + handle->meta_data_.usage_ = hwcomposer::kLayerVideo; + } else { + handle->meta_data_.usage_ = hwcomposer::kLayerNormal; + } + + // switch minigbm specific enum to a standard one + if (handle->meta_data_.format_ == DRM_FORMAT_YVU420_ANDROID) + handle->meta_data_.format_ = DRM_FORMAT_YVU420; + + return true; +} +#ifdef __cplusplus +} +#endif +#endif