summaryrefslogtreecommitdiff
path: root/composer/hwc_session.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'composer/hwc_session.cpp')
-rw-r--r--composer/hwc_session.cpp150
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