Fixes race on hwcomposer vsync thread.
Bug: 75402353
Test: local
Change-Id: I3ed6c8543b39e5ca119cc8db6c019a5f08dbdcf5
diff --git a/guest/hals/hwcomposer/hwcomposer.cpp b/guest/hals/hwcomposer/hwcomposer.cpp
index d510285..fdeef65 100644
--- a/guest/hals/hwcomposer/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/hwcomposer.cpp
@@ -94,6 +94,8 @@
int sent = 0;
int last_sent = 0;
static const int log_interval = 60;
+ void (*vsync_proc)(const struct hwc_procs*, int, int64_t) = nullptr;
+ bool log_no_procs = true, log_no_vsync = true;
while (true) {
struct timespec rt;
if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
@@ -115,13 +117,27 @@
}
}
- pdev->procs->vsync(const_cast<hwc_procs_t*>(pdev->procs), 0, timestamp);
+ // The vsync thread is started on device open, it may run before the
+ // registerProcs callback has a chance to be called, so we need to make sure
+ // procs is not NULL before dereferencing it.
+ if (pdev && pdev->procs) {
+ vsync_proc = pdev->procs->vsync;
+ } else if (log_no_procs) {
+ log_no_procs = false;
+ ALOGI("procs is not set yet, unable to deliver vsync event");
+ }
+ if (vsync_proc) {
+ vsync_proc(const_cast<hwc_procs_t*>(pdev->procs), 0, timestamp);
+ ++sent;
+ } else if (log_no_vsync) {
+ log_no_vsync = false;
+ ALOGE("vsync callback is null (but procs was already set)");
+ }
if (rt.tv_sec - last_logged > log_interval) {
ALOGI("Sent %d syncs in %ds", sent - last_sent, log_interval);
last_logged = rt.tv_sec;
last_sent = sent;
}
- ++sent;
}
return NULL;
diff --git a/guest/hals/hwcomposer/legacy/hwcomposer.cpp b/guest/hals/hwcomposer/legacy/hwcomposer.cpp
index 29e8f0f..33122eb 100644
--- a/guest/hals/hwcomposer/legacy/hwcomposer.cpp
+++ b/guest/hals/hwcomposer/legacy/hwcomposer.cpp
@@ -355,6 +355,8 @@
int sent = 0;
int last_sent = 0;
static const int log_interval = 60;
+ void (*vsync_proc)(const struct hwc_procs*, int, int64_t) = nullptr;
+ bool log_no_procs = true, log_no_vsync = true;
while (true) {
struct timespec rt;
if (clock_gettime(CLOCK_MONOTONIC, &rt) == -1) {
@@ -376,13 +378,27 @@
}
}
- pdev->procs->vsync(const_cast<hwc_procs_t*>(pdev->procs), 0, timestamp);
+ // The vsync thread is started on device open, it may run before the
+ // registerProcs callback has a chance to be called, so we need to make sure
+ // procs is not NULL before dereferencing it.
+ if (pdev && pdev->procs) {
+ vsync_proc = pdev->procs->vsync;
+ } else if (log_no_procs) {
+ log_no_procs = false;
+ ALOGI("procs is not set yet, unable to deliver vsync event");
+ }
+ if (vsync_proc) {
+ vsync_proc(const_cast<hwc_procs_t*>(pdev->procs), 0, timestamp);
+ ++sent;
+ } else if (log_no_vsync) {
+ log_no_vsync = false;
+ ALOGE("vsync callback is null (but procs was already set)");
+ }
if (rt.tv_sec - last_logged > log_interval) {
ALOGI("Sent %d syncs in %ds", sent - last_sent, log_interval);
last_logged = rt.tv_sec;
last_sent = sent;
}
- ++sent;
}
return NULL;