Merge "composer: Reset TUI event if other display is off"
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 705e2d0..0717993 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -3398,6 +3398,9 @@
uint64_t handle_id = 0;
*release_fence = nullptr;
+ // If release fence is available, then try to get it first and keep it out of lock to avoid
+ // deadlock with GetOutputBufferAcquireFence call, and validate it later with handle id.
+ display_intf_->GetOutputBufferAcquireFence(release_fence);
{
std::unique_lock<std::mutex> lock(cwb_mutex_);
auto &cwb_resp = cwb_capture_status_map_[client];
@@ -3406,22 +3409,17 @@
// If this function is called after either PostCommitLayerStack or NotifyCwbDone call,
// then release fence can be successfully retrieved from cwb_capture_status_map_.
handle_id = cwb_resp.handle_id;
- if (cwb_resp.status == kCWBReleaseFenceNotChecked) {
- // if status is updated as kCWBReleaseFenceNotChecked, which means the commit is over
- // and status got updated in PostCommitLayerStack->HandleFrameOutput. It indicates
- // that release fence is available.
- display_intf_->GetOutputBufferAcquireFence(release_fence);
- } else {
+ if (cwb_resp.status != kCWBReleaseFenceNotChecked) {
*release_fence = cwb_resp.release_fence;
}
status = cwb_resp.status;
} else if (layer_stack_.output_buffer != nullptr) {
// If this function is called before both PostCommitLayerStack and NotifyCwbDone call,
- // then release fence may be retrieved directly from layer_stack_.output_buffer.
+ // then handle_id may be retrieved directly from layer_stack_.output_buffer corresponding
+ // to available release fence.
const auto map_cwb_buffer = cwb_buffer_map_.find(layer_stack_.output_buffer->handle_id);
if (map_cwb_buffer != cwb_buffer_map_.end() && client == map_cwb_buffer->second) {
handle_id = layer_stack_.output_buffer->handle_id;
- display_intf_->GetOutputBufferAcquireFence(release_fence);
status = kCWBReleaseFenceNotChecked;
}
} else {
@@ -3433,6 +3431,8 @@
break;
}
}
+ // Avoid to return old release fence, in case of too early call of this function.
+ *release_fence = nullptr;
}
if (*release_fence != nullptr) {
@@ -3481,7 +3481,7 @@
auto error = GetReadbackBufferFenceForClient(kCWBClientComposer, release_fence);
// if release fence is null pointer, then just return with error.
- if (release_fence && *release_fence == nullptr) {
+ if (!release_fence || *release_fence == nullptr) {
status = HWC2::Error::Unsupported;
DLOGW("Readback buffer fence is not available! CWBReleaseFenceError: %d", error);
}
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index 17e4c78..a5b1c1b 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -3234,10 +3234,6 @@
available_mixer_count = hwc_display_[active_builtin]->GetAvailableMixerCount();
}
- if (available_mixer_count < min_mixer_count) {
- return -EAGAIN;
- }
-
for (auto &iter : *hw_displays_info) {
auto &info = iter.second;
@@ -3256,6 +3252,12 @@
continue;
}
+ if (available_mixer_count < min_mixer_count) {
+ DLOGI("mixers not available: available: %d, min: %d",
+ available_mixer_count, min_mixer_count);
+ return -EAGAIN;
+ }
+
// Count active pluggable display slots and slots with no commits.
bool first_commit_pending = false;
std::for_each(map_info_pluggable_.begin(), map_info_pluggable_.end(),
@@ -3734,13 +3736,17 @@
return;
}
+ static constexpr uint32_t min_mixer_count = 2;
+ uint32_t available_mixer_count = 0;
std :: bitset < kSecureMax > secure_sessions = 0;
if (active_builtin_disp_id < HWCCallbacks::kNumDisplays) {
Locker::ScopeLock lock_d(locker_[active_builtin_disp_id]);
hwc_display_[active_builtin_disp_id]->GetActiveSecureSession(&secure_sessions);
+ available_mixer_count = hwc_display_[active_builtin_disp_id]->GetAvailableMixerCount();
}
- if (secure_sessions.any() || active_builtin_disp_id >= HWCCallbacks::kNumDisplays) {
+ if (secure_sessions.any() || active_builtin_disp_id >= HWCCallbacks::kNumDisplays ||
+ available_mixer_count < min_mixer_count) {
return;
}
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 0702267..96bd91c 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -434,7 +434,7 @@
};
struct DisplayCWBSession{
- std::deque<QueueNode *> queue;
+ std::deque<std::shared_ptr<QueueNode>> queue;
std::mutex lock;
std::condition_variable cv;
std::future<void> future;
@@ -443,7 +443,7 @@
static void AsyncTaskToProcessCWBStatus(CWB *cwb, hwc2_display_t display_type);
void ProcessCWBStatus(hwc2_display_t display_type);
- void NotifyCWBStatus(int status, QueueNode *cwb_node);
+ void NotifyCWBStatus(int status, std::shared_ptr<QueueNode> cwb_node);
std::map<hwc2_display_t, DisplayCWBSession> display_cwb_session_map_;
HWCSession *hwc_session_ = nullptr;
diff --git a/composer/hwc_session_services.cpp b/composer/hwc_session_services.cpp
index e507be3..12ad1ad 100644
--- a/composer/hwc_session_services.cpp
+++ b/composer/hwc_session_services.cpp
@@ -1149,7 +1149,7 @@
hwc2_display_t display_type) {
HWC2::Error error = HWC2::Error::None;
auto& session_map = display_cwb_session_map_[display_type];
- QueueNode *node = nullptr;
+ std::shared_ptr<QueueNode> node = nullptr;
uint64_t node_handle_id = 0;
void *hdl = const_cast<native_handle_t *>(buffer);
auto err = gralloc::GetMetaDataValue(hdl, (int64_t)StandardMetadataType::BUFFER_ID,
@@ -1160,15 +1160,29 @@
}
if (error == HWC2::Error::None) {
- node = new QueueNode(callback, cwb_config, buffer, display_type, node_handle_id);
+ node = std::make_shared<QueueNode>(callback, cwb_config, buffer, display_type, node_handle_id);
if (node) {
// Keep CWB request handling related resources in a requested display context.
std::unique_lock<std::mutex> lock(session_map.lock);
+
+ // Iterate over the queue to avoid duplicate node of same buffer, because that
+ // buffer is already present in queue.
+ for (auto& qnode : session_map.queue) {
+ if (qnode->handle_id == node_handle_id) {
+ error = HWC2::Error::BadParameter;
+ DLOGW("CWB Buffer with handle id %lu is already available in Queue for processing!",
+ node_handle_id);
+ break;
+ }
+ }
+
// Ensure that async task runs only until all queued CWB requests have been fulfilled.
// If cwb queue is empty, async task has not either started or async task has finished
// processing previously queued cwb requests. Start new async task on such a case as
// currently running async task will automatically desolve without processing more requests.
- session_map.queue.push_back(node);
+ if (error == HWC2::Error::None) {
+ session_map.queue.push_back(node);
+ }
} else {
error = HWC2::Error::BadParameter;
DLOGE("Unable to allocate node for CWB request(handle id: %lu)!", node_handle_id);
@@ -1242,8 +1256,10 @@
session_map.cv.notify_one();
return 0;
} else {
- //Just skip notifying to client on not matching handle_id.
- return -1;
+ // Continue to check on not matching handle_id, to update the status of any matching
+ // node, because if notification for particular handle_id skip, then it will not update
+ // again and notification thread will wait for skipped node forever.
+ continue;
}
}
}
@@ -1259,7 +1275,7 @@
void HWCSession::CWB::ProcessCWBStatus(hwc2_display_t display_type) {
auto& session_map = display_cwb_session_map_[display_type];
while(true) {
- QueueNode *cwb_node = nullptr;
+ std::shared_ptr<QueueNode> cwb_node = nullptr;
{
std::unique_lock<std::mutex> lock(session_map.lock);
// Exit thread in case of no pending CWB request in queue.
@@ -1276,6 +1292,13 @@
} else if (cwb_node->notified_status == kCwbNotifiedNone) {
// Wait for the signal for availability of CWB notified node.
session_map.cv.wait(lock);
+ if (cwb_node->notified_status == kCwbNotifiedNone) {
+ // If any other node notified before front node, then need to continue to wait
+ // for front node, such that further client notification will be done in sequential
+ // manner.
+ DLOGW("CWB request is notified out of sequence.");
+ continue;
+ }
}
session_map.queue.pop_front();
}
@@ -1283,9 +1306,10 @@
// Notify to client, when notification is received successfully for expected input buffer.
NotifyCWBStatus(cwb_node->notified_status , cwb_node);
}
+ DLOGI("CWB queue is empty. Display: %d", display_type);
}
-void HWCSession::CWB::NotifyCWBStatus(int status, QueueNode *cwb_node) {
+void HWCSession::CWB::NotifyCWBStatus(int status, std::shared_ptr<QueueNode> cwb_node) {
// Notify client about buffer status and erase the node from pending request queue.
std::shared_ptr<DisplayConfig::ConfigCallback> callback = cwb_node->callback.lock();
if (callback) {
@@ -1295,7 +1319,6 @@
native_handle_close(cwb_node->buffer);
native_handle_delete(const_cast<native_handle_t *>(cwb_node->buffer));
- delete cwb_node;
}
int HWCSession::NotifyCwbDone(hwc2_display_t display, int32_t status, uint64_t handle_id) {