summaryrefslogtreecommitdiff
path: root/sdm
diff options
context:
space:
mode:
authorRamkumar Radhakrishnan <ramkumar@codeaurora.org>2017-07-31 21:37:46 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-08-04 13:31:25 -0700
commit497b638a133add2e061e6b75796912d6de309697 (patch)
tree42b40571c3ad901d402104dd86e59e91fa969f3e /sdm
parent0c689d47be3e7ad80d69c183958d32c210196496 (diff)
downloaddisplay-497b638a133add2e061e6b75796912d6de309697.tar.gz
hwc2: Wait for RegisterCallback() from SF before sending events.
Surfaceflinger registers callback functions to be called from hwcomposer on specific events like hotplug, vsync and screen refresh. since surfaceflinger and hwcomposer are two different processes that can run asynchronously. This causes hwcomposer to send an event to surfaceflinger before surfaceflinger registers callback and results in undefined behavior. So wait for callbacks to get registered by surfaceflinger and send an event to surfacelinger. Change-Id: I288e4d7dde8179cb4a119cdedad2877344c06dae CRs-Fixed: 2085392
Diffstat (limited to 'sdm')
-rw-r--r--sdm/libs/hwc2/hwc_callbacks.cpp26
-rw-r--r--sdm/libs/hwc2/hwc_callbacks.h6
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp44
-rw-r--r--sdm/libs/hwc2/hwc_session.h4
-rw-r--r--sdm/libs/hwc2/hwc_session_services.cpp8
5 files changed, 58 insertions, 30 deletions
diff --git a/sdm/libs/hwc2/hwc_callbacks.cpp b/sdm/libs/hwc2/hwc_callbacks.cpp
index 48ae3981..3be3bf64 100644
--- a/sdm/libs/hwc2/hwc_callbacks.cpp
+++ b/sdm/libs/hwc2/hwc_callbacks.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -34,22 +34,28 @@
namespace sdm {
-void HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
- if (hotplug_) {
- hotplug_(hotplug_data_, display, INT32(state));
+HWC2::Error HWCCallbacks::Hotplug(hwc2_display_t display, HWC2::Connection state) {
+ if (!hotplug_) {
+ return HWC2::Error::NoResources;
}
+ hotplug_(hotplug_data_, display, INT32(state));
+ return HWC2::Error::None;
}
-void HWCCallbacks::Refresh(hwc2_display_t display) {
- if (refresh_) {
- refresh_(refresh_data_, display);
+HWC2::Error HWCCallbacks::Refresh(hwc2_display_t display) {
+ if (!refresh_) {
+ return HWC2::Error::NoResources;
}
+ refresh_(refresh_data_, display);
+ return HWC2::Error::None;
}
-void HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
- if (vsync_) {
- vsync_(vsync_data_, display, timestamp);
+HWC2::Error HWCCallbacks::Vsync(hwc2_display_t display, int64_t timestamp) {
+ if (!vsync_) {
+ return HWC2::Error::NoResources;
}
+ vsync_(vsync_data_, display, timestamp);
+ return HWC2::Error::None;
}
HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
diff --git a/sdm/libs/hwc2/hwc_callbacks.h b/sdm/libs/hwc2/hwc_callbacks.h
index 015bf5d5..d3f4e529 100644
--- a/sdm/libs/hwc2/hwc_callbacks.h
+++ b/sdm/libs/hwc2/hwc_callbacks.h
@@ -40,9 +40,9 @@ namespace sdm {
class HWCCallbacks {
public:
- void Hotplug(hwc2_display_t display, HWC2::Connection state);
- void Refresh(hwc2_display_t display);
- void Vsync(hwc2_display_t display, int64_t timestamp);
+ HWC2::Error Hotplug(hwc2_display_t display, HWC2::Connection state);
+ HWC2::Error Refresh(hwc2_display_t display);
+ HWC2::Error Vsync(hwc2_display_t display, int64_t timestamp);
HWC2::Error Register(HWC2::Callback, hwc2_callback_data_t callback_data,
hwc2_function_pointer_t pointer);
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 293ffce6..7e99f29a 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -502,16 +502,16 @@ int32_t HWCSession::RegisterCallback(hwc2_device_t *device, int32_t descriptor,
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
+ SCOPE_LOCK(hwc_session->callbacks_lock_);
auto desc = static_cast<HWC2::Callback>(descriptor);
auto error = hwc_session->callbacks_.Register(desc, callback_data, pointer);
DLOGD("Registering callback: %s", to_string(desc).c_str());
if (descriptor == HWC2_CALLBACK_HOTPLUG) {
- // If primary display (HDMI) is not created yet, wait for it to be hotplugged.
- if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY]) {
+ if (hwc_session->hwc_display_[HWC_DISPLAY_PRIMARY] && !hwc_session->hdmi_is_primary_) {
hwc_session->callbacks_.Hotplug(HWC_DISPLAY_PRIMARY, HWC2::Connection::Connected);
}
}
-
+ hwc_session->callbacks_lock_.Broadcast();
return INT32(error);
}
@@ -675,7 +675,7 @@ int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t displa
}
if (hwc_session->need_invalidate_) {
- hwc_session->callbacks_.Refresh(display);
+ hwc_session->Refresh(display);
}
if (hwc_session->color_mgr_) {
@@ -1248,7 +1248,7 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
switch (pending_action.action) {
case kInvalidating:
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
break;
case kEnterQDCMMode:
ret = color_mgr_->EnableQDCMMode(true, hwc_display_[HWC_DISPLAY_PRIMARY]);
@@ -1259,12 +1259,12 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
case kApplySolidFill:
ret =
color_mgr_->SetSolidFill(pending_action.params, true, hwc_display_[HWC_DISPLAY_PRIMARY]);
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
break;
case kDisableSolidFill:
ret =
color_mgr_->SetSolidFill(pending_action.params, false, hwc_display_[HWC_DISPLAY_PRIMARY]);
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
break;
case kSetPanelBrightness:
brightness_value = reinterpret_cast<int32_t *>(resp_payload.payload);
@@ -1278,7 +1278,7 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
case kEnableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params, true,
hwc_display_[HWC_DISPLAY_PRIMARY]);
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
break;
case kDisableFrameCapture:
ret = color_mgr_->SetFrameCapture(pending_action.params, false,
@@ -1287,7 +1287,7 @@ android::status_t HWCSession::QdcmCMDHandler(const android::Parcel *input_parcel
case kConfigureDetailedEnhancer:
ret = color_mgr_->SetDetailedEnhancer(pending_action.params,
hwc_display_[HWC_DISPLAY_PRIMARY]);
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
break;
case kNoAction:
break;
@@ -1319,7 +1319,7 @@ void HWCSession::UEventHandler(const char *uevent_data, int length) {
DLOGI("Uevent FB0 = %s", uevent_data);
int panel_reset = GetEventValue(uevent_data, length, "PANEL_ALIVE=");
if (panel_reset == 0) {
- callbacks_.Refresh(0);
+ Refresh(0);
reset_panel_ = true;
}
} else if (strcasestr(uevent_data, HWC_UEVENT_DRM_EXT_HOTPLUG)) {
@@ -1445,7 +1445,7 @@ int HWCSession::HotPlugHandler(bool connected) {
} while (0);
if (connected) {
- callbacks_.Refresh(0);
+ Refresh(0);
if (!hdmi_is_primary_) {
// wait for sufficient time to ensure sufficient resources are available to process new
@@ -1457,8 +1457,8 @@ int HWCSession::HotPlugHandler(bool connected) {
// notify client
if (notify_hotplug) {
- callbacks_.Hotplug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
- connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
+ HotPlug(hdmi_is_primary_ ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL,
+ connected ? HWC2::Connection::Connected : HWC2::Connection::Disconnected);
}
qservice_->onHdmiHotplug(INT(connected));
@@ -1507,4 +1507,22 @@ android::status_t HWCSession::GetVisibleDisplayRect(const android::Parcel *input
return android::NO_ERROR;
}
+void HWCSession::Refresh(hwc2_display_t display) {
+ SCOPE_LOCK(callbacks_lock_);
+ HWC2::Error err = callbacks_.Refresh(display);
+ while (err != HWC2::Error::None) {
+ callbacks_lock_.Wait();
+ err = callbacks_.Refresh(display);
+ }
+}
+
+void HWCSession::HotPlug(hwc2_display_t display, HWC2::Connection state) {
+ SCOPE_LOCK(callbacks_lock_);
+ HWC2::Error err = callbacks_.Hotplug(display, state);
+ while (err != HWC2::Error::None) {
+ callbacks_lock_.Wait();
+ err = callbacks_.Hotplug(display, state);
+ }
+}
+
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 7d2a30c5..288bbbab 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -211,6 +211,9 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
android::status_t SetColorModeById(const android::Parcel *input_parcel);
+ void Refresh(hwc2_display_t display);
+ void HotPlug(hwc2_display_t display, HWC2::Connection state);
+
static Locker locker_;
CoreInterface *core_intf_ = nullptr;
HWCDisplay *hwc_display_[HWC_NUM_DISPLAY_TYPES] = {nullptr};
@@ -227,6 +230,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
qService::QService *qservice_ = nullptr;
HWCSocketHandler socket_handler_;
bool hdmi_is_primary_ = false;
+ Locker callbacks_lock_;
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 5cb9cf71..383ec3bd 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -208,7 +208,7 @@ int32_t HWCSession::SetActiveConfigIndex(int disp_id, uint32_t config) {
if (hwc_display_[disp_id]) {
error = hwc_display_[disp_id]->SetActiveDisplayConfig(config);
if (!error) {
- callbacks_.Refresh(0);
+ Refresh(0);
}
}
@@ -312,7 +312,7 @@ Return<int32_t> HWCSession::minHdcpEncryptionLevelChanged(IDisplayConfig::Displa
Return<int32_t> HWCSession::refreshScreen() {
SCOPE_LOCK(locker_);
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
return 0;
}
@@ -349,7 +349,7 @@ int32_t HWCSession::ControlPartialUpdate(int disp_id, bool enable) {
}
// Todo(user): Unlock it before sending events to client. It may cause deadlocks in future.
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
// Wait until partial update control is complete
int32_t error = locker_.WaitFinite(kPartialUpdateControlTimeoutMs);
@@ -443,7 +443,7 @@ Return<int32_t> HWCSession::setCameraLaunchStatus(uint32_t on) {
HWBwModes mode = on > 0 ? kBwCamera : kBwDefault;
// trigger invalidate to apply new bw caps.
- callbacks_.Refresh(HWC_DISPLAY_PRIMARY);
+ Refresh(HWC_DISPLAY_PRIMARY);
if (core_intf_->SetMaxBandwidthMode(mode) != kErrorNone) {
return -EINVAL;