diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 46625f7..9e429e8 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp @@ -483,6 +483,29 @@ void HwcDisplay::SetVsyncCallbacksEnabled(bool enabled) { vsync_worker_->SetTimestampCallback(std::move(callback)); } +bool HwcDisplay::SetDisplayEnabled(bool enabled) { + if (IsInHeadlessMode()) { + return true; + } + if (enabled) { + /* + * Setting the display to active before we have a composition + * can break some drivers, so skip setting a_args.active to + * true, as the next composition frame will implicitly activate + * the display + */ + return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0; + }; + + // Disable the display. + AtomicCommitArgs a_args{}; + a_args.active = false; + + auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); + ALOGE_IF(err != 0, "Failed to apply the dpms composition err=%d", err); + return err == 0; +} + void HwcDisplay::SetPipeline(std::shared_ptr pipeline) { Deinit(); @@ -1108,50 +1131,6 @@ bool HwcDisplay::CtmByGpu() { return true; } -HWC2::Error HwcDisplay::SetPowerMode(int32_t mode_in) { - auto mode = static_cast(mode_in); - - AtomicCommitArgs a_args{}; - - switch (mode) { - case HWC2::PowerMode::Off: - a_args.active = false; - break; - case HWC2::PowerMode::On: - a_args.active = true; - break; - case HWC2::PowerMode::Doze: - case HWC2::PowerMode::DozeSuspend: - return HWC2::Error::Unsupported; - default: - ALOGE("Incorrect power mode value (%d)\n", mode_in); - return HWC2::Error::BadParameter; - } - - if (IsInHeadlessMode()) { - return HWC2::Error::None; - } - - if (a_args.active && *a_args.active) { - /* - * Setting the display to active before we have a composition - * can break some drivers, so skip setting a_args.active to - * true, as the next composition frame will implicitly activate - * the display - */ - return GetPipe().atomic_state_manager->ActivateDisplayUsingDPMS() == 0 - ? HWC2::Error::None - : HWC2::Error::BadParameter; - }; - - auto err = GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args); - if (err) { - ALOGE("Failed to apply the dpms composition err=%d", err); - return HWC2::Error::BadParameter; - } - return HWC2::Error::None; -} - std::vector HwcDisplay::GetOrderLayersByZPos() { std::vector ordered_layers; ordered_layers.reserve(layers_.size()); diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index a442da5..d96e34b 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h @@ -136,6 +136,9 @@ class HwcDisplay { // Enable or disable vsync callbacks. void SetVsyncCallbacksEnabled(bool enabled); + // Enable or disable the display. + bool SetDisplayEnabled(bool enabled); + auto GetFrontendPrivateData() -> std::shared_ptr { return frontend_private_data_; } @@ -167,7 +170,6 @@ class HwcDisplay { HWC2::Error ChosePreferredConfig(); HWC2::Error SetColorMode(int32_t mode); HWC2::Error SetColorTransform(const float *matrix, int32_t hint); - HWC2::Error SetPowerMode(int32_t mode); HwcLayer *get_layer(ILayerId layer) { auto it = layers_.find(layer); if (it == layers_.end()) diff --git a/hwc2_device/hwc2_device.cpp b/hwc2_device/hwc2_device.cpp index e1b3334..81d0c77 100644 --- a/hwc2_device/hwc2_device.cpp +++ b/hwc2_device/hwc2_device.cpp @@ -475,6 +475,34 @@ static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display, return static_cast(HWC2::Error::None); } +static int32_t SetPowerMode(hwc2_device_t *device, hwc2_display_t display, + int32_t mode) { + ALOGV("SetPowerMode"); + LOCK_COMPOSER(device); + GET_DISPLAY(display); + + switch (mode) { + // Supported modes. + case static_cast(HWC2::PowerMode::Off): + case static_cast(HWC2::PowerMode::On): + break; + // Unsupported modes. + case static_cast(HWC2::PowerMode::Doze): + case static_cast(HWC2::PowerMode::DozeSuspend): + return static_cast(HWC2::Error::Unsupported); + // Bad parameter. + default: + ALOGE("Incorrect power mode value (%d)\n", mode); + return static_cast(HWC2::Error::BadParameter); + } + + if (!idisplay->SetDisplayEnabled(mode == + static_cast(HWC2::PowerMode::On))) { + return static_cast(HWC2::Error::BadParameter); + } + return static_cast(HWC2::Error::None); +} + static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t enabled) { ALOGV("SetVsyncEnabled"); @@ -1037,9 +1065,7 @@ static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device * /*dev*/, case HWC2::FunctionDescriptor::SetOutputBuffer: return (hwc2_function_pointer_t)SetOutputBuffer; case HWC2::FunctionDescriptor::SetPowerMode: - return ToHook( - DisplayHook); + return (hwc2_function_pointer_t)SetPowerMode; case HWC2::FunctionDescriptor::SetVsyncEnabled: return (hwc2_function_pointer_t)SetVsyncEnabled; case HWC2::FunctionDescriptor::ValidateDisplay: diff --git a/hwc3/ComposerClient.cpp b/hwc3/ComposerClient.cpp index 2056bbd..2e00a85 100644 --- a/hwc3/ComposerClient.cpp +++ b/hwc3/ComposerClient.cpp @@ -1356,12 +1356,24 @@ ndk::ScopedAStatus ComposerClient::setPowerMode(int64_t display_id, return ToBinderStatus(hwc3::Error::kBadDisplay); } - if (mode == PowerMode::ON_SUSPEND) { - return ToBinderStatus(hwc3::Error::kUnsupported); + // Only OFF and ON are supported. VTS requires checking for invalid enum + // values. + switch (static_cast(mode)) { + case static_cast(PowerMode::OFF): + case static_cast(PowerMode::ON): + break; + case static_cast(PowerMode::DOZE): + case static_cast(PowerMode::DOZE_SUSPEND): + case static_cast(PowerMode::ON_SUSPEND): + return ToBinderStatus(hwc3::Error::kUnsupported); + default: + return ToBinderStatus(hwc3::Error::kBadParameter); } - auto error = display->SetPowerMode(Hwc3PowerModeToHwc2(mode)); - return ToBinderStatus(Hwc2toHwc3Error(error)); + if (!display->SetDisplayEnabled(mode == PowerMode::ON)) { + return ToBinderStatus(hwc3::Error::kBadParameter); + } + return ndk::ScopedAStatus::ok(); } ndk::ScopedAStatus ComposerClient::setReadbackBuffer( diff --git a/hwc3/Utils.h b/hwc3/Utils.h index 9b46da3..6079f13 100644 --- a/hwc3/Utils.h +++ b/hwc3/Utils.h @@ -100,17 +100,6 @@ inline int32_t Hwc3RenderIntentToHwc2(RenderIntent render_intent) { return static_cast(render_intent); } -// Values match up to DOZE_SUSPEND. -// https://android.googlesource.com/platform/hardware/interfaces/+/refs/heads/main/graphics/composer/aidl/android/hardware/graphics/composer3/PowerMode.aidl -// https://cs.android.com/android/platform/superproject/main/+/main:hardware/libhardware/include_all/hardware/hwcomposer2.h;l=348;drc=d783cabd4d9bddb4b83f2dd38300b7598bb58b24 -inline int32_t Hwc3PowerModeToHwc2(PowerMode power_mode) { - if (power_mode > PowerMode::DOZE_SUSPEND) { - ALOGE("Unsupported HWC2 power mode. Could not translate: %d", power_mode); - return HWC2_POWER_MODE_ON; - } - return static_cast(power_mode); -} - // Values appear to match. // https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Dataspace.aidl // https://cs.android.com/android/platform/superproject/main/+/main:system/core/libsystem/include/system/graphics-base-v1.0.h;l=43