diff options
Diffstat (limited to 'composer/hwc_session.cpp')
-rw-r--r-- | composer/hwc_session.cpp | 150 |
1 files changed, 142 insertions, 8 deletions
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp index 26dbc0e1..cba02406 100644 --- a/composer/hwc_session.cpp +++ b/composer/hwc_session.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Not a Contribution. * * Copyright 2015 The Android Open Source Project @@ -735,6 +735,18 @@ void HWCSession::PerformQsyncCallback(hwc2_display_t display) { } } +void HWCSession::PerformIdleStatusCallback(hwc2_display_t display) { + std::shared_ptr<DisplayConfig::ConfigCallback> callback = idle_callback_.lock(); + if (!callback) { + return; + } + + if (hwc_display_[display]->IsDisplayIdle()) { + DTRACE_SCOPED(); + callback->NotifyIdleStatus(true); + } +} + int32_t HWCSession::PresentDisplay(hwc2_display_t display, shared_ptr<Fence> *out_retire_fence) { auto status = HWC2::Error::BadDisplay; DTRACE_SCOPED(); @@ -783,6 +795,7 @@ int32_t HWCSession::PresentDisplay(hwc2_display_t display, shared_ptr<Fence> *ou status = hwc_display_[target_display]->Present(out_retire_fence); if (status == HWC2::Error::None) { PerformQsyncCallback(target_display); + PerformIdleStatusCallback(target_display); } } } @@ -893,6 +906,14 @@ void HWCSession::RegisterCallback(int32_t descriptor, hwc2_callback_data_t callb // Notfify all displays. NotifyClientStatus(client_connected_); } + + // On SF stop, disable the idle time. + if (!pointer && is_idle_time_up_ && hwc_display_[HWC_DISPLAY_PRIMARY]) { // De-registering… + DLOGI("disable idle time"); + hwc_display_[HWC_DISPLAY_PRIMARY]->SetIdleTimeoutMs(0,0); + is_idle_time_up_ = false; + } + need_invalidate_ = false; } @@ -1090,7 +1111,26 @@ int32_t HWCSession::SetPowerMode(hwc2_display_t display, int32_t int_mode) { return HWC2_ERROR_UNSUPPORTED; } - bool override_mode = async_powermode_ && display_ready_.test(UINT32(display)); + // async_powermode supported for power on and off + bool override_mode = async_powermode_ && display_ready_.test(UINT32(display)) && + async_power_mode_triggered_; + HWC2::PowerMode last_power_mode = hwc_display_[display]->GetCurrentPowerMode(); + + if (last_power_mode == mode) { + return HWC2_ERROR_NONE; + } + + // 1. For power transition cases other than Off->On or On->Off, async power mode + // will not be used. Hence, set override_mode to false for them. + // 2. When SF requests Doze mode transition on panels where Doze mode is not supported + // (like video mode), HWComposer.cpp will override the request to "On". Handle such cases + // in main thread path. + if (!((last_power_mode == HWC2::PowerMode::Off && mode == HWC2::PowerMode::On) || + (last_power_mode == HWC2::PowerMode::On && mode == HWC2::PowerMode::Off)) || + (last_power_mode == HWC2::PowerMode::Off && mode == HWC2::PowerMode::On)) { + override_mode = false; + } + if (!override_mode) { auto error = CallDisplayFunction(display, &HWCDisplay::SetPowerMode, mode, false /* teardown */); @@ -1671,6 +1711,22 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa status = SetDisplayBrightnessScale(input_parcel); break; + case qService::IQService::SET_STAND_BY_MODE: + if (!input_parcel) { + DLOGE("QService command = %d: input_parcel needed.", command); + break; + } + status = SetStandByMode(input_parcel); + break; + + case qService::IQService::GET_PANEL_RESOLUTION: + if (!input_parcel || !output_parcel) { + DLOGE("QService command = %d: input_parcel and output_parcel needed.", command); + break; + } + status = GetPanelResolution(input_parcel, output_parcel); + break; + default: DLOGW("QService command = %d is not supported.", command); break; @@ -2448,6 +2504,24 @@ void HWCSession::Refresh(hwc2_display_t display) { callbacks_.Refresh(display); } +android::status_t HWCSession::GetPanelResolution(const android::Parcel *input_parcel, + android::Parcel *output_parcel) { + SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]); + + if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { + DLOGI("Primary display is not initialized"); + return -EINVAL; + } + auto panel_width = 0u; + auto panel_height = 0u; + + hwc_display_[HWC_DISPLAY_PRIMARY]->GetPanelResolution(&panel_width, &panel_height); + output_parcel->writeInt32(INT32(panel_width)); + output_parcel->writeInt32(INT32(panel_height)); + + return android::NO_ERROR; +} + android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input_parcel, android::Parcel *output_parcel) { int disp_idx = GetDisplayIndex(input_parcel->readInt32()); @@ -2475,6 +2549,26 @@ android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input return android::NO_ERROR; } +android::status_t HWCSession::SetStandByMode(const android::Parcel *input_parcel) { + SCOPE_LOCK(locker_[HWC_DISPLAY_PRIMARY]); + + bool enable = (input_parcel->readInt32() > 0); + bool is_twm = (input_parcel->readInt32() > 0); + + if (!hwc_display_[HWC_DISPLAY_PRIMARY]) { + DLOGI("Primary display is not initialized"); + return -EINVAL; + } + + DisplayError error = hwc_display_[HWC_DISPLAY_PRIMARY]->SetStandByMode(enable, is_twm); + if (error != kErrorNone) { + DLOGE("SetStandByMode failed. Error = %d", error); + return -EINVAL; + } + + return android::NO_ERROR; +} + int HWCSession::CreatePrimaryDisplay() { int status = -EINVAL; HWDisplaysInfo hw_displays_info = {}; @@ -2951,13 +3045,12 @@ HWC2::Error HWCSession::ValidateDisplayInternal(hwc2_display_t display, uint32_t callbacks_.Refresh(display); need_invalidate_ = false; } - - if (color_mgr_) { - color_mgr_->SetColorModeDetailEnhancer(hwc_display_[display]); - } } - return hwc_display->Validate(out_num_types, out_num_requests); + auto status = HWC2::Error::None; + status = hwc_display->Validate(out_num_types, out_num_requests); + SetCpuPerfHintLargeCompCycle(); + return status; } HWC2::Error HWCSession::PresentDisplayInternal(hwc2_display_t display) { @@ -3064,13 +3157,14 @@ void HWCSession::HandleSecureSession() { display < HWCCallbacks::kNumRealDisplays; display++) { Locker::ScopeLock lock_d(locker_[display]); HWCDisplay *hwc_display = hwc_display_[display]; - if (!hwc_display || hwc_display->GetDisplayClass() != DISPLAY_CLASS_BUILTIN) { + if (!hwc_display) { continue; } bool is_active_secure_display = false; // The first On/Doze/DozeSuspend built-in display is taken as the secure display. if (!found_active_secure_display && + hwc_display->GetDisplayClass() == DISPLAY_CLASS_BUILTIN && hwc_display->GetCurrentPowerMode() != HWC2::PowerMode::Off) { is_active_secure_display = true; found_active_secure_display = true; @@ -3094,6 +3188,8 @@ void HWCSession::HandlePendingPowerMode(hwc2_display_t disp_id, Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]); bool pending_power_mode = false; + std::bitset<kSecureMax> secure_sessions = 0; + hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions); for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1; display < HWCCallbacks::kNumDisplays; display++) { if (display != active_builtin_disp_id) { @@ -3106,6 +3202,9 @@ void HWCSession::HandlePendingPowerMode(hwc2_display_t disp_id, } if (!pending_power_mode) { + if (!secure_sessions.any()) { + secure_session_active_ = false; + } return; } @@ -3362,6 +3461,20 @@ int32_t HWCSession::GetDisplayConnectionType(hwc2_display_t display, return HWC2_ERROR_NONE; } +int32_t HWCSession::GetClientTargetProperty(hwc2_display_t display, + HwcClientTargetProperty *outClientTargetProperty) { + if (!outClientTargetProperty) { + return HWC2_ERROR_BAD_PARAMETER; + } + + if (display >= HWCCallbacks::kNumDisplays) { + return HWC2_ERROR_BAD_DISPLAY; + } + + return CallDisplayFunction(display, &HWCDisplay::GetClientTargetProperty, + outClientTargetProperty); +} + int32_t HWCSession::GetDisplayBrightnessSupport(hwc2_display_t display, bool *outSupport) { if (!outSupport) { return HWC2_ERROR_BAD_PARAMETER; @@ -3551,4 +3664,25 @@ int32_t HWCSession::SetActiveConfigWithConstraints( vsync_period_change_constraints, out_timeline); } +void HWCSession::SetCpuPerfHintLargeCompCycle() { + bool found_non_primary_active_display = false; + + // Check any non-primary display is active + for (hwc2_display_t display = HWC_DISPLAY_PRIMARY + 1; + display < HWCCallbacks::kNumDisplays; display++) { + if (hwc_display_[display] == NULL) { + continue; + } + if (hwc_display_[display]->GetCurrentPowerMode() != HWC2::PowerMode::Off) { + found_non_primary_active_display = true; + break; + } + } + + // send cpu hint for primary display + if (!found_non_primary_active_display) { + hwc_display_[HWC_DISPLAY_PRIMARY]->SetCpuPerfHintLargeCompCycle(); + } +} + } // namespace sdm |