libsurfaceflinger: fix screenshot permission check am: fc0b911090 am: fd630967bb
am: 9a13672e31
Change-Id: I87807674d52c35884a0b986db3e1b6102a526b83
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 34aec5b..74430e8 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -681,10 +681,10 @@
const flat_binder_object *fb = reply.readObject(false);
ASSERT_TRUE(fb != NULL);
- EXPECT_EQ(fb->hdr.type, BINDER_TYPE_HANDLE);
- EXPECT_EQ(ProcessState::self()->getStrongProxyForHandle(fb->handle), m_server);
- EXPECT_EQ(fb->cookie, (binder_uintptr_t)0);
- EXPECT_EQ(fb->binder >> 32, (binder_uintptr_t)0);
+ EXPECT_EQ(BINDER_TYPE_HANDLE, fb->hdr.type);
+ EXPECT_EQ(m_server, ProcessState::self()->getStrongProxyForHandle(fb->handle));
+ EXPECT_EQ((binder_uintptr_t)0, fb->cookie);
+ EXPECT_EQ((uint64_t)0, (uint64_t)fb->binder >> 32);
}
TEST_F(BinderLibTest, FreedBinder) {
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index 733edc6..f350762 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -40,10 +40,8 @@
DisplayService::DisplayService(Hwc2::Composer* hidl,
RequestDisplayCallback request_display_callback)
: BASE("DisplayService",
- Endpoint::Create(display::DisplayProtocol::kClientPath)),
- hardware_composer_(hidl, request_display_callback),
- request_display_callback_(request_display_callback) {
- hardware_composer_.Initialize();
+ Endpoint::Create(display::DisplayProtocol::kClientPath)) {
+ hardware_composer_.Initialize(hidl, request_display_callback);
}
bool DisplayService::IsInitialized() const {
@@ -398,10 +396,6 @@
return {0};
}
-void DisplayService::OnHardwareComposerRefresh() {
- hardware_composer_.OnHardwareComposerRefresh();
-}
-
void DisplayService::SetDisplayConfigurationUpdateNotifier(
DisplayConfigurationUpdateNotifier update_notifier) {
update_notifier_ = update_notifier;
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index 6efe264..55e33ab 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -72,8 +72,6 @@
void GrantDisplayOwnership() { hardware_composer_.Enable(); }
void SeizeDisplayOwnership() { hardware_composer_.Disable(); }
- void OnHardwareComposerRefresh();
-
private:
friend BASE;
friend DisplaySurface;
@@ -119,7 +117,6 @@
pdx::Status<void> HandleSurfaceMessage(pdx::Message& message);
HardwareComposer hardware_composer_;
- RequestDisplayCallback request_display_callback_;
EpollEventDispatcher dispatcher_;
DisplayConfigurationUpdateNotifier update_notifier_;
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 11c1370..f9a5dcd 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -28,6 +28,8 @@
#include <private/dvr/clock_ns.h>
#include <private/dvr/ion_buffer.h>
+using android::hardware::Return;
+using android::hardware::Void;
using android::pdx::LocalHandle;
using android::pdx::rpc::EmptyVariant;
using android::pdx::rpc::IfAnyOf;
@@ -42,9 +44,6 @@
const char kBacklightBrightnessSysFile[] =
"/sys/class/leds/lcd-backlight/brightness";
-const char kPrimaryDisplayVSyncEventFile[] =
- "/sys/class/graphics/fb0/vsync_event";
-
const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
const char kDvrPerformanceProperty[] = "sys.dvr.performance";
@@ -86,22 +85,11 @@
} // anonymous namespace
-// Layer static data.
-Hwc2::Composer* Layer::hwc2_hidl_;
-const HWCDisplayMetrics* Layer::display_metrics_;
-
// HardwareComposer static data;
constexpr size_t HardwareComposer::kMaxHardwareLayers;
HardwareComposer::HardwareComposer()
- : HardwareComposer(nullptr, RequestDisplayCallback()) {}
-
-HardwareComposer::HardwareComposer(
- Hwc2::Composer* hwc2_hidl, RequestDisplayCallback request_display_callback)
- : initialized_(false),
- hwc2_hidl_(hwc2_hidl),
- request_display_callback_(request_display_callback),
- callbacks_(new ComposerCallback) {}
+ : initialized_(false), request_display_callback_(nullptr) {}
HardwareComposer::~HardwareComposer(void) {
UpdatePostThreadState(PostThreadState::Quit, true);
@@ -109,16 +97,19 @@
post_thread_.join();
}
-bool HardwareComposer::Initialize() {
+bool HardwareComposer::Initialize(
+ Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
if (initialized_) {
ALOGE("HardwareComposer::Initialize: already initialized.");
return false;
}
+ request_display_callback_ = request_display_callback;
+
HWC::Error error = HWC::Error::None;
Hwc2::Config config;
- error = hwc2_hidl_->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+ error = hidl->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
if (error != HWC::Error::None) {
ALOGE("HardwareComposer: Failed to get current display config : %d",
@@ -126,8 +117,8 @@
return false;
}
- error =
- GetDisplayMetrics(HWC_DISPLAY_PRIMARY, config, &native_display_metrics_);
+ error = GetDisplayMetrics(hidl, HWC_DISPLAY_PRIMARY, config,
+ &native_display_metrics_);
if (error != HWC::Error::None) {
ALOGE(
@@ -149,9 +140,6 @@
display_transform_ = HWC_TRANSFORM_NONE;
display_metrics_ = native_display_metrics_;
- // Pass hwc instance and metrics to setup globals for Layer.
- Layer::InitializeGlobals(hwc2_hidl_, &native_display_metrics_);
-
post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
LOG_ALWAYS_FATAL_IF(
!post_thread_event_fd_,
@@ -210,15 +198,11 @@
}
void HardwareComposer::OnPostThreadResumed() {
- hwc2_hidl_->resetCommands();
+ hidl_.reset(new Hwc2::Composer("default"));
+ hidl_callback_ = new ComposerCallback;
+ hidl_->registerCallback(hidl_callback_);
- // HIDL HWC seems to have an internal race condition. If we submit a frame too
- // soon after turning on VSync we don't get any VSync signals. Give poor HWC
- // implementations a chance to enable VSync before we continue.
- EnableVsync(false);
- std::this_thread::sleep_for(100ms);
EnableVsync(true);
- std::this_thread::sleep_for(100ms);
// TODO(skiazyk): We need to do something about accessing this directly,
// supposedly there is a backlight service on the way.
@@ -240,9 +224,12 @@
}
active_layer_count_ = 0;
- EnableVsync(false);
+ if (hidl_) {
+ EnableVsync(false);
+ }
- hwc2_hidl_->resetCommands();
+ hidl_callback_ = nullptr;
+ hidl_.reset(nullptr);
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "idle");
@@ -252,21 +239,21 @@
uint32_t num_types;
uint32_t num_requests;
HWC::Error error =
- hwc2_hidl_->validateDisplay(display, &num_types, &num_requests);
+ hidl_->validateDisplay(display, &num_types, &num_requests);
if (error == HWC2_ERROR_HAS_CHANGES) {
// TODO(skiazyk): We might need to inspect the requested changes first, but
// so far it seems like we shouldn't ever hit a bad state.
// error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
// display);
- error = hwc2_hidl_->acceptDisplayChanges(display);
+ error = hidl_->acceptDisplayChanges(display);
}
return error;
}
-int32_t HardwareComposer::EnableVsync(bool enabled) {
- return (int32_t)hwc2_hidl_->setVsyncEnabled(
+HWC::Error HardwareComposer::EnableVsync(bool enabled) {
+ return hidl_->setVsyncEnabled(
HWC_DISPLAY_PRIMARY,
(Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
: HWC2_VSYNC_DISABLE));
@@ -274,7 +261,7 @@
HWC::Error HardwareComposer::Present(hwc2_display_t display) {
int32_t present_fence;
- HWC::Error error = hwc2_hidl_->presentDisplay(display, &present_fence);
+ HWC::Error error = hidl_->presentDisplay(display, &present_fence);
// According to the documentation, this fence is signaled at the time of
// vsync/DMA for physical displays.
@@ -288,20 +275,21 @@
return error;
}
-HWC::Error HardwareComposer::GetDisplayAttribute(hwc2_display_t display,
+HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* hidl,
+ hwc2_display_t display,
hwc2_config_t config,
hwc2_attribute_t attribute,
int32_t* out_value) const {
- return hwc2_hidl_->getDisplayAttribute(
+ return hidl->getDisplayAttribute(
display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
}
HWC::Error HardwareComposer::GetDisplayMetrics(
- hwc2_display_t display, hwc2_config_t config,
+ Hwc2::Composer* hidl, hwc2_display_t display, hwc2_config_t config,
HWCDisplayMetrics* out_metrics) const {
HWC::Error error;
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_WIDTH,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_WIDTH,
&out_metrics->width);
if (error != HWC::Error::None) {
ALOGE(
@@ -310,7 +298,7 @@
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_HEIGHT,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_HEIGHT,
&out_metrics->height);
if (error != HWC::Error::None) {
ALOGE(
@@ -319,7 +307,8 @@
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_VSYNC_PERIOD,
+ error = GetDisplayAttribute(hidl, display, config,
+ HWC2_ATTRIBUTE_VSYNC_PERIOD,
&out_metrics->vsync_period_ns);
if (error != HWC::Error::None) {
ALOGE(
@@ -328,7 +317,7 @@
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_X,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_X,
&out_metrics->dpi.x);
if (error != HWC::Error::None) {
ALOGE(
@@ -337,7 +326,7 @@
return error;
}
- error = GetDisplayAttribute(display, config, HWC2_ATTRIBUTE_DPI_Y,
+ error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_Y,
&out_metrics->dpi.y);
if (error != HWC::Error::None) {
ALOGE(
@@ -374,7 +363,7 @@
if (post_thread_resumed_) {
stream << "Hardware Composer Debug Info:" << std::endl;
- stream << hwc2_hidl_->dumpDebugInfo();
+ stream << hidl_->dumpDebugInfo();
}
return stream.str();
@@ -446,8 +435,8 @@
std::vector<Hwc2::Layer> out_layers;
std::vector<int> out_fences;
- error = hwc2_hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
- &out_fences);
+ error = hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+ &out_fences);
ALOGE_IF(error != HWC::Error::None,
"HardwareComposer::PostLayers: Failed to get release fences: %s",
error.to_string().c_str());
@@ -546,7 +535,7 @@
}
int HardwareComposer::PostThreadPollInterruptible(
- const pdx::LocalHandle& event_fd, int requested_events) {
+ const pdx::LocalHandle& event_fd, int requested_events, int timeout_ms) {
pollfd pfd[2] = {
{
.fd = event_fd.Get(),
@@ -561,7 +550,7 @@
};
int ret, error;
do {
- ret = poll(pfd, 2, -1);
+ ret = poll(pfd, 2, timeout_ms);
error = errno;
ALOGW_IF(ret < 0,
"HardwareComposer::PostThreadPollInterruptible: Error during "
@@ -571,6 +560,8 @@
if (ret < 0) {
return -error;
+ } else if (ret == 0) {
+ return -ETIMEDOUT;
} else if (pfd[0].revents != 0) {
return 0;
} else if (pfd[1].revents != 0) {
@@ -623,114 +614,17 @@
}
}
-// Reads the timestamp of the last vsync from the display driver.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::ReadVSyncTimestamp(int64_t* timestamp) {
- const int event_fd = primary_display_vsync_event_fd_.Get();
- int ret, error;
-
- // The driver returns data in the form "VSYNC=<timestamp ns>".
- std::array<char, 32> data;
- data.fill('\0');
-
- // Seek back to the beginning of the event file.
- ret = lseek(event_fd, 0, SEEK_SET);
- if (ret < 0) {
- error = errno;
- ALOGE(
- "HardwareComposer::ReadVSyncTimestamp: Failed to seek vsync event fd: "
- "%s",
- strerror(error));
- return -error;
- }
-
- // Read the vsync event timestamp.
- ret = read(event_fd, data.data(), data.size());
- if (ret < 0) {
- error = errno;
- ALOGE_IF(
- error != EAGAIN,
- "HardwareComposer::ReadVSyncTimestamp: Error while reading timestamp: "
- "%s",
- strerror(error));
- return -error;
- }
-
- ret = sscanf(data.data(), "VSYNC=%" PRIu64,
- reinterpret_cast<uint64_t*>(timestamp));
- if (ret < 0) {
- error = errno;
- ALOGE(
- "HardwareComposer::ReadVSyncTimestamp: Error while parsing timestamp: "
- "%s",
- strerror(error));
- return -error;
- }
-
- return 0;
-}
-
-// Blocks until the next vsync event is signaled by the display driver.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::BlockUntilVSync() {
- // Vsync is signaled by POLLPRI on the fb vsync node.
- return PostThreadPollInterruptible(primary_display_vsync_event_fd_, POLLPRI);
-}
-
// Waits for the next vsync and returns the timestamp of the vsync event. If
// vsync already passed since the last call, returns the latest vsync timestamp
-// instead of blocking. This method updates the last_vsync_timeout_ in the
-// process.
-//
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
+// instead of blocking.
int HardwareComposer::WaitForVSync(int64_t* timestamp) {
- int error;
-
- // Get the current timestamp and decide what to do.
- while (true) {
- int64_t current_vsync_timestamp;
- error = ReadVSyncTimestamp(¤t_vsync_timestamp);
- if (error < 0 && error != -EAGAIN)
- return error;
-
- if (error == -EAGAIN) {
- // Vsync was turned off, wait for the next vsync event.
- error = BlockUntilVSync();
- if (error < 0 || error == kPostThreadInterrupted)
- return error;
-
- // Try again to get the timestamp for this new vsync interval.
- continue;
- }
-
- // Check that we advanced to a later vsync interval.
- if (TimestampGT(current_vsync_timestamp, last_vsync_timestamp_)) {
- *timestamp = last_vsync_timestamp_ = current_vsync_timestamp;
- return 0;
- }
-
- // See how close we are to the next expected vsync. If we're within 1ms,
- // sleep for 1ms and try again.
- const int64_t ns_per_frame = display_metrics_.vsync_period_ns;
- const int64_t threshold_ns = 1000000; // 1ms
-
- const int64_t next_vsync_est = last_vsync_timestamp_ + ns_per_frame;
- const int64_t distance_to_vsync_est = next_vsync_est - GetSystemClockNs();
-
- if (distance_to_vsync_est > threshold_ns) {
- // Wait for vsync event notification.
- error = BlockUntilVSync();
- if (error < 0 || error == kPostThreadInterrupted)
- return error;
- } else {
- // Sleep for a short time (1 millisecond) before retrying.
- error = SleepUntil(GetSystemClockNs() + threshold_ns);
- if (error < 0 || error == kPostThreadInterrupted)
- return error;
- }
+ int error = PostThreadPollInterruptible(
+ hidl_callback_->GetVsyncEventFd(), POLLIN, /*timeout_ms*/ 1000);
+ if (error == kPostThreadInterrupted || error < 0) {
+ return error;
+ } else {
+ *timestamp = hidl_callback_->GetVsyncTime();
+ return 0;
}
}
@@ -749,7 +643,8 @@
return -error;
}
- return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN);
+ return PostThreadPollInterruptible(
+ vsync_sleep_timer_fd_, POLLIN, /*timeout_ms*/ -1);
}
void HardwareComposer::PostThread() {
@@ -772,15 +667,6 @@
strerror(errno));
#endif // ENABLE_BACKLIGHT_BRIGHTNESS
- // Open the vsync event node for the primary display.
- // TODO(eieio): Move this into a platform-specific class.
- primary_display_vsync_event_fd_ =
- LocalHandle(kPrimaryDisplayVSyncEventFile, O_RDONLY);
- ALOGE_IF(!primary_display_vsync_event_fd_,
- "HardwareComposer: Failed to open vsync event node for primary "
- "display: %s",
- strerror(errno));
-
// Open the wait pingpong status node for the primary display.
// TODO(eieio): Move this into a platform-specific class.
primary_display_wait_pp_fd_ =
@@ -951,7 +837,8 @@
// The bottom layer is opaque, other layers blend.
HWC::BlendMode blending =
layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
- layers_[layer_index].Setup(surfaces[layer_index], blending,
+ layers_[layer_index].Setup(surfaces[layer_index], native_display_metrics_,
+ hidl_.get(), blending,
display_transform_, HWC::Composition::Device,
layer_index);
display_surfaces_.push_back(surfaces[layer_index]);
@@ -979,30 +866,6 @@
vsync_callback_ = callback;
}
-void HardwareComposer::HwcRefresh(hwc2_callback_data_t /*data*/,
- hwc2_display_t /*display*/) {
- // TODO(eieio): implement invalidate callbacks.
-}
-
-void HardwareComposer::HwcVSync(hwc2_callback_data_t /*data*/,
- hwc2_display_t /*display*/,
- int64_t /*timestamp*/) {
- ATRACE_NAME(__PRETTY_FUNCTION__);
- // Intentionally empty. HWC may require a callback to be set to enable vsync
- // signals. We bypass this callback thread by monitoring the vsync event
- // directly, but signals still need to be enabled.
-}
-
-void HardwareComposer::HwcHotplug(hwc2_callback_data_t /*callbackData*/,
- hwc2_display_t /*display*/,
- hwc2_connection_t /*connected*/) {
- // TODO(eieio): implement display hotplug callbacks.
-}
-
-void HardwareComposer::OnHardwareComposerRefresh() {
- // TODO(steventhomas): Handle refresh.
-}
-
void HardwareComposer::SetBacklightBrightness(int brightness) {
if (backlight_brightness_fd_) {
std::array<char, 32> text;
@@ -1011,18 +874,59 @@
}
}
-void Layer::InitializeGlobals(Hwc2::Composer* hwc2_hidl,
- const HWCDisplayMetrics* metrics) {
- hwc2_hidl_ = hwc2_hidl;
- display_metrics_ = metrics;
+HardwareComposer::ComposerCallback::ComposerCallback() {
+ vsync_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
+ LOG_ALWAYS_FATAL_IF(
+ !vsync_event_fd_,
+ "Failed to create vsync event fd : %s",
+ strerror(errno));
+}
+
+Return<void> HardwareComposer::ComposerCallback::onHotplug(
+ Hwc2::Display /*display*/,
+ IComposerCallback::Connection /*conn*/) {
+ return Void();
+}
+
+Return<void> HardwareComposer::ComposerCallback::onRefresh(
+ Hwc2::Display /*display*/) {
+ return hardware::Void();
+}
+
+Return<void> HardwareComposer::ComposerCallback::onVsync(
+ Hwc2::Display display, int64_t timestamp) {
+ if (display == HWC_DISPLAY_PRIMARY) {
+ std::lock_guard<std::mutex> lock(vsync_mutex_);
+ vsync_time_ = timestamp;
+ int error = eventfd_write(vsync_event_fd_.Get(), 1);
+ LOG_ALWAYS_FATAL_IF(error != 0, "Failed writing to vsync event fd");
+ }
+ return Void();
+}
+
+const pdx::LocalHandle&
+HardwareComposer::ComposerCallback::GetVsyncEventFd() const {
+ return vsync_event_fd_;
+}
+
+int64_t HardwareComposer::ComposerCallback::GetVsyncTime() {
+ std::lock_guard<std::mutex> lock(vsync_mutex_);
+ eventfd_t event;
+ eventfd_read(vsync_event_fd_.Get(), &event);
+ LOG_ALWAYS_FATAL_IF(vsync_time_ < 0,
+ "Attempt to read vsync time before vsync event");
+ int64_t return_val = vsync_time_;
+ vsync_time_ = -1;
+ return return_val;
}
void Layer::Reset() {
- if (hwc2_hidl_ != nullptr && hardware_composer_layer_) {
- hwc2_hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+ if (hidl_ != nullptr && hardware_composer_layer_) {
+ hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
hardware_composer_layer_ = 0;
}
+ hidl_ = nullptr;
z_order_ = 0;
blending_ = HWC::BlendMode::None;
transform_ = HWC::Transform::None;
@@ -1034,29 +938,35 @@
}
void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_order) {
+ const HWCDisplayMetrics& display_metrics,
+ Hwc2::Composer* hidl, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order) {
Reset();
+ hidl_ = hidl;
z_order_ = z_order;
blending_ = blending;
transform_ = transform;
composition_type_ = HWC::Composition::Invalid;
target_composition_type_ = composition_type;
source_ = SourceSurface{surface};
- CommonLayerSetup();
+ CommonLayerSetup(display_metrics);
}
void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_order) {
+ const HWCDisplayMetrics& display_metrics,
+ Hwc2::Composer* hidl, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order) {
Reset();
+ hidl_ = hidl;
z_order_ = z_order;
blending_ = blending;
transform_ = transform;
composition_type_ = HWC::Composition::Invalid;
target_composition_type_ = composition_type;
source_ = SourceBuffer{buffer};
- CommonLayerSetup();
+ CommonLayerSetup(display_metrics);
}
void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
@@ -1076,7 +986,7 @@
return source_.Visit(Visitor{});
}
-void Layer::UpdateLayerSettings() {
+void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) {
if (!IsLayerSetup()) {
ALOGE(
"HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
@@ -1087,7 +997,7 @@
HWC::Error error;
hwc2_display_t display = HWC_DISPLAY_PRIMARY;
- error = hwc2_hidl_->setLayerCompositionType(
+ error = hidl_->setLayerCompositionType(
display, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
ALOGE_IF(
@@ -1095,7 +1005,7 @@
"Layer::UpdateLayerSettings: Error setting layer composition type: %s",
error.to_string().c_str());
- error = hwc2_hidl_->setLayerBlendMode(
+ error = hidl_->setLayerBlendMode(
display, hardware_composer_layer_,
blending_.cast<Hwc2::IComposerClient::BlendMode>());
ALOGE_IF(error != HWC::Error::None,
@@ -1104,41 +1014,39 @@
// TODO(eieio): Use surface attributes or some other mechanism to control
// the layer display frame.
- error = hwc2_hidl_->setLayerDisplayFrame(
+ error = hidl_->setLayerDisplayFrame(
display, hardware_composer_layer_,
- {0, 0, display_metrics_->width, display_metrics_->height});
+ {0, 0, display_metrics.width, display_metrics.height});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer display frame: %s",
error.to_string().c_str());
- error = hwc2_hidl_->setLayerVisibleRegion(
+ error = hidl_->setLayerVisibleRegion(
display, hardware_composer_layer_,
- {{0, 0, display_metrics_->width, display_metrics_->height}});
+ {{0, 0, display_metrics.width, display_metrics.height}});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer visible region: %s",
error.to_string().c_str());
- error =
- hwc2_hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+ error = hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
error.to_string().c_str());
- error =
- hwc2_hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+ error = hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting z_ order: %s",
error.to_string().c_str());
}
-void Layer::CommonLayerSetup() {
+void Layer::CommonLayerSetup(const HWCDisplayMetrics& display_metrics) {
HWC::Error error =
- hwc2_hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+ hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
ALOGE_IF(
error != HWC::Error::None,
"Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
error.to_string().c_str());
- UpdateLayerSettings();
+ UpdateLayerSettings(display_metrics);
}
void Layer::Prepare() {
@@ -1157,12 +1065,12 @@
if (!handle.get()) {
if (composition_type_ == HWC::Composition::Invalid) {
composition_type_ = HWC::Composition::SolidColor;
- hwc2_hidl_->setLayerCompositionType(
+ hidl_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
- hwc2_hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- layer_color);
+ hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ layer_color);
} else {
// The composition type is already set. Nothing else to do until a
// buffer arrives.
@@ -1170,15 +1078,15 @@
} else {
if (composition_type_ != target_composition_type_) {
composition_type_ = target_composition_type_;
- hwc2_hidl_->setLayerCompositionType(
+ hidl_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
}
HWC::Error error{HWC::Error::None};
- error = hwc2_hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_, 0, handle,
- acquire_fence_.Get());
+ error = hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_, 0, handle,
+ acquire_fence_.Get());
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer buffer: %s",
@@ -1187,9 +1095,9 @@
if (!surface_rect_functions_applied_) {
const float float_right = right;
const float float_bottom = bottom;
- error = hwc2_hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_,
- {0, 0, float_right, float_bottom});
+ error = hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_,
+ {0, 0, float_right, float_bottom});
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer source crop: %s",
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index a0c50e1..fc0efee 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -54,11 +54,6 @@
public:
Layer() {}
- // Sets up the global state used by all Layer instances. This must be called
- // before using any Layer methods.
- static void InitializeGlobals(Hwc2::Composer* hwc2_hidl,
- const HWCDisplayMetrics* metrics);
-
// Releases any shared pointers and fence handles held by this instance.
void Reset();
@@ -72,6 +67,7 @@
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
// |index| is the index of this surface in the DirectDisplaySurface array.
void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
+ const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
HWC::BlendMode blending, HWC::Transform transform,
HWC::Composition composition_type, size_t z_roder);
@@ -83,9 +79,10 @@
// |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
- void Setup(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order);
+ void Setup(const std::shared_ptr<IonBuffer>& buffer,
+ const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_order);
// Layers that use a direct IonBuffer should call this each frame to update
// which buffer will be used for the next PostLayers.
@@ -121,7 +118,7 @@
bool IsLayerSetup() const { return !source_.empty(); }
// Applies all of the settings to this layer using the hwc functions
- void UpdateLayerSettings();
+ void UpdateLayerSettings(const HWCDisplayMetrics& display_metrics);
int GetSurfaceId() const {
int surface_id = -1;
@@ -142,10 +139,9 @@
}
private:
- void CommonLayerSetup();
+ void CommonLayerSetup(const HWCDisplayMetrics& display_metrics);
- static Hwc2::Composer* hwc2_hidl_;
- static const HWCDisplayMetrics* display_metrics_;
+ Hwc2::Composer* hidl_ = nullptr;
// The hardware composer layer and metrics to use during the prepare cycle.
hwc2_layer_t hardware_composer_layer_ = 0;
@@ -263,11 +259,10 @@
static constexpr size_t kMaxHardwareLayers = 4;
HardwareComposer();
- HardwareComposer(Hwc2::Composer* hidl,
- RequestDisplayCallback request_display_callback);
~HardwareComposer();
- bool Initialize();
+ bool Initialize(Hwc2::Composer* hidl,
+ RequestDisplayCallback request_display_callback);
bool IsInitialized() const { return initialized_; }
@@ -281,11 +276,6 @@
// Get the HMD display metrics for the current display.
display::Metrics GetHmdDisplayMetrics() const;
- HWC::Error GetDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
- hwc2_attribute_t attributes,
- int32_t* out_value) const;
- HWC::Error GetDisplayMetrics(hwc2_display_t display, hwc2_config_t config,
- HWCDisplayMetrics* out_metrics) const;
std::string Dump();
void SetVSyncCallback(VSyncCallback callback);
@@ -308,34 +298,31 @@
int OnNewGlobalBuffer(DvrGlobalBufferKey key, IonBuffer& ion_buffer);
void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
- void OnHardwareComposerRefresh();
-
private:
- int32_t EnableVsync(bool enabled);
+ HWC::Error GetDisplayAttribute(Hwc2::Composer* hidl, hwc2_display_t display,
+ hwc2_config_t config,
+ hwc2_attribute_t attributes,
+ int32_t* out_value) const;
+ HWC::Error GetDisplayMetrics(Hwc2::Composer* hidl, hwc2_display_t display,
+ hwc2_config_t config,
+ HWCDisplayMetrics* out_metrics) const;
+
+ HWC::Error EnableVsync(bool enabled);
class ComposerCallback : public Hwc2::IComposerCallback {
public:
- ComposerCallback() {}
-
- hardware::Return<void> onHotplug(Hwc2::Display /*display*/,
- Connection /*connected*/) override {
- // TODO(skiazyk): depending on how the server is implemented, we might
- // have to set it up to synchronize with receiving this event, as it can
- // potentially be a critical event for setting up state within the
- // hwc2 module. That is, we (technically) should not call any other hwc
- // methods until this method has been called after registering the
- // callbacks.
- return hardware::Void();
- }
-
- hardware::Return<void> onRefresh(Hwc2::Display /*display*/) override {
- return hardware::Void();
- }
-
- hardware::Return<void> onVsync(Hwc2::Display /*display*/,
- int64_t /*timestamp*/) override {
- return hardware::Void();
- }
+ ComposerCallback();
+ hardware::Return<void> onHotplug(Hwc2::Display display,
+ Connection conn) override;
+ hardware::Return<void> onRefresh(Hwc2::Display display) override;
+ hardware::Return<void> onVsync(Hwc2::Display display,
+ int64_t timestamp) override;
+ const pdx::LocalHandle& GetVsyncEventFd() const;
+ int64_t GetVsyncTime();
+ private:
+ std::mutex vsync_mutex_;
+ pdx::LocalHandle vsync_event_fd_;
+ int64_t vsync_time_ = -1;
};
HWC::Error Validate(hwc2_display_t display);
@@ -364,17 +351,18 @@
void UpdatePostThreadState(uint32_t state, bool suspend);
// Blocks until either event_fd becomes readable, or we're interrupted by a
- // control thread. Any errors are returned as negative errno values. If we're
- // interrupted, kPostThreadInterrupted will be returned.
+ // control thread, or timeout_ms is reached before any events occur. Any
+ // errors are returned as negative errno values, with -ETIMEDOUT returned in
+ // the case of a timeout. If we're interrupted, kPostThreadInterrupted will be
+ // returned.
int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
- int requested_events);
+ int requested_events,
+ int timeout_ms);
- // BlockUntilVSync, WaitForVSync, and SleepUntil are all blocking calls made
- // on the post thread that can be interrupted by a control thread. If
- // interrupted, these calls return kPostThreadInterrupted.
+ // WaitForVSync and SleepUntil are blocking calls made on the post thread that
+ // can be interrupted by a control thread. If interrupted, these calls return
+ // kPostThreadInterrupted.
int ReadWaitPPState();
- int BlockUntilVSync();
- int ReadVSyncTimestamp(int64_t* timestamp);
int WaitForVSync(int64_t* timestamp);
int SleepUntil(int64_t wakeup_timestamp);
@@ -398,11 +386,9 @@
bool initialized_;
- // Hardware composer HAL device from SurfaceFlinger. VrFlinger does not own
- // this pointer.
- Hwc2::Composer* hwc2_hidl_;
+ std::unique_ptr<Hwc2::Composer> hidl_;
+ sp<ComposerCallback> hidl_callback_;
RequestDisplayCallback request_display_callback_;
- sp<ComposerCallback> callbacks_;
// Display metrics of the physical display.
HWCDisplayMetrics native_display_metrics_;
@@ -433,7 +419,8 @@
std::thread post_thread_;
// Post thread state machine and synchronization primitives.
- PostThreadStateType post_thread_state_{PostThreadState::Idle};
+ PostThreadStateType post_thread_state_{
+ PostThreadState::Idle | PostThreadState::Suspended};
std::atomic<bool> post_thread_quiescent_{true};
bool post_thread_resumed_{false};
pdx::LocalHandle post_thread_event_fd_;
@@ -444,9 +431,6 @@
// Backlight LED brightness sysfs node.
pdx::LocalHandle backlight_brightness_fd_;
- // Primary display vsync event sysfs node.
- pdx::LocalHandle primary_display_vsync_event_fd_;
-
// Primary display wait_pingpong state sysfs node.
pdx::LocalHandle primary_display_wait_pp_fd_;
@@ -478,12 +462,6 @@
static constexpr int kPostThreadInterrupted = 1;
- static void HwcRefresh(hwc2_callback_data_t data, hwc2_display_t display);
- static void HwcVSync(hwc2_callback_data_t data, hwc2_display_t display,
- int64_t timestamp);
- static void HwcHotplug(hwc2_callback_data_t callbackData,
- hwc2_display_t display, hwc2_connection_t connected);
-
HardwareComposer(const HardwareComposer&) = delete;
void operator=(const HardwareComposer&) = delete;
};
diff --git a/libs/vr/libvrflinger/include/dvr/vr_flinger.h b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
index e7f41a7..33cbc84 100644
--- a/libs/vr/libvrflinger/include/dvr/vr_flinger.h
+++ b/libs/vr/libvrflinger/include/dvr/vr_flinger.h
@@ -29,9 +29,6 @@
void GrantDisplayOwnership();
void SeizeDisplayOwnership();
- // Called on a binder thread.
- void OnHardwareComposerRefresh();
-
// dump all vr flinger state.
std::string Dump();
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index 56405de..fcf94f0 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -133,10 +133,6 @@
display_service_->SeizeDisplayOwnership();
}
-void VrFlinger::OnHardwareComposerRefresh() {
- display_service_->OnHardwareComposerRefresh();
-}
-
std::string VrFlinger::Dump() {
// TODO(karthikrs): Add more state information here.
return display_service_->DumpState(0/*unused*/);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 744dd50..248ef53 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -134,9 +134,11 @@
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (config == EGL_NO_CONFIG) {
#ifdef USE_HWC2
- config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
+ config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888,
+ /*logConfig*/ false);
#else
- config = RenderEngine::chooseEglConfig(display, format);
+ config = RenderEngine::chooseEglConfig(display, format,
+ /*logConfig*/ false);
#endif
}
eglSurface = eglCreateWindowSurface(display, config, window, NULL);
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 704b17e..433a224 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -215,6 +215,10 @@
}
}
+bool Composer::isRemote() {
+ return mClient->isRemote();
+}
+
void Composer::resetCommands() {
mWriter.reset();
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 40d2a4c..31a3c1d 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -143,6 +143,11 @@
void registerCallback(const sp<IComposerCallback>& callback);
+ // Returns true if the connected composer service is running in a remote
+ // process, false otherwise. This will return false if the service is
+ // configured in passthrough mode, for example.
+ bool isRemote();
+
// Reset all pending commands in the command buffer. Useful if you want to
// skip a frame but have already queued some commands.
void resetCommands();
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index b749ce6..78c0c85 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -33,45 +33,6 @@
#include <algorithm>
#include <inttypes.h>
-extern "C" {
- static void hotplug_hook(hwc2_callback_data_t callbackData,
- hwc2_display_t displayId, int32_t intConnected) {
- auto device = static_cast<HWC2::Device*>(callbackData);
- auto display = device->getDisplayById(displayId);
- if (display) {
- auto connected = static_cast<HWC2::Connection>(intConnected);
- device->callHotplug(std::move(display), connected);
- } else {
- ALOGE("Hotplug callback called with unknown display %" PRIu64,
- displayId);
- }
- }
-
- static void refresh_hook(hwc2_callback_data_t callbackData,
- hwc2_display_t displayId) {
- auto device = static_cast<HWC2::Device*>(callbackData);
- auto display = device->getDisplayById(displayId);
- if (display) {
- device->callRefresh(std::move(display));
- } else {
- ALOGE("Refresh callback called with unknown display %" PRIu64,
- displayId);
- }
- }
-
- static void vsync_hook(hwc2_callback_data_t callbackData,
- hwc2_display_t displayId, int64_t timestamp) {
- auto device = static_cast<HWC2::Device*>(callbackData);
- auto display = device->getDisplayById(displayId);
- if (display) {
- device->callVsync(std::move(display), timestamp);
- } else {
- ALOGE("Vsync callback called with unknown display %" PRIu64,
- displayId);
- }
- }
-}
-
using android::Fence;
using android::FloatRect;
using android::GraphicBuffer;
@@ -86,51 +47,78 @@
namespace Hwc2 = android::Hwc2;
+namespace {
+
+class ComposerCallbackBridge : public Hwc2::IComposerCallback {
+public:
+ ComposerCallbackBridge(ComposerCallback* callback, int32_t sequenceId)
+ : mCallback(callback), mSequenceId(sequenceId),
+ mHasPrimaryDisplay(false) {}
+
+ Return<void> onHotplug(Hwc2::Display display,
+ IComposerCallback::Connection conn) override
+ {
+ HWC2::Connection connection = static_cast<HWC2::Connection>(conn);
+ if (!mHasPrimaryDisplay) {
+ LOG_ALWAYS_FATAL_IF(connection != HWC2::Connection::Connected,
+ "Initial onHotplug callback should be "
+ "primary display connected");
+ mHasPrimaryDisplay = true;
+ mCallback->onHotplugReceived(mSequenceId, display,
+ connection, true);
+ } else {
+ mCallback->onHotplugReceived(mSequenceId, display,
+ connection, false);
+ }
+ return Void();
+ }
+
+ Return<void> onRefresh(Hwc2::Display display) override
+ {
+ mCallback->onRefreshReceived(mSequenceId, display);
+ return Void();
+ }
+
+ Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
+ {
+ mCallback->onVsyncReceived(mSequenceId, display, timestamp);
+ return Void();
+ }
+
+ bool HasPrimaryDisplay() { return mHasPrimaryDisplay; }
+
+private:
+ ComposerCallback* mCallback;
+ int32_t mSequenceId;
+ bool mHasPrimaryDisplay;
+};
+
+} // namespace anonymous
+
+
// Device methods
Device::Device(const std::string& serviceName)
: mComposer(std::make_unique<Hwc2::Composer>(serviceName)),
mCapabilities(),
mDisplays(),
- mHotplug(),
- mPendingHotplugs(),
- mRefresh(),
- mPendingRefreshes(),
- mVsync(),
- mPendingVsyncs()
+ mRegisteredCallback(false)
{
loadCapabilities();
- registerCallbacks();
}
-Device::~Device()
-{
- for (auto element : mDisplays) {
- auto display = element.second.lock();
- if (!display) {
- ALOGE("~Device: Found a display (%" PRId64 " that has already been"
- " destroyed", element.first);
- continue;
- }
-
- DisplayType displayType = HWC2::DisplayType::Invalid;
- auto error = display->getType(&displayType);
- if (error != Error::None) {
- ALOGE("~Device: Failed to determine type of display %" PRIu64
- ": %s (%d)", display->getId(), to_string(error).c_str(),
- static_cast<int32_t>(error));
- continue;
- }
-
- if (displayType == HWC2::DisplayType::Physical) {
- error = display->setVsyncEnabled(HWC2::Vsync::Disable);
- if (error != Error::None) {
- ALOGE("~Device: Failed to disable vsync for display %" PRIu64
- ": %s (%d)", display->getId(), to_string(error).c_str(),
- static_cast<int32_t>(error));
- }
- }
+void Device::registerCallback(ComposerCallback* callback, int32_t sequenceId) {
+ if (mRegisteredCallback) {
+ ALOGW("Callback already registered. Ignored extra registration "
+ "attempt.");
+ return;
}
+ mRegisteredCallback = true;
+ sp<ComposerCallbackBridge> callbackBridge(
+ new ComposerCallbackBridge(callback, sequenceId));
+ mComposer->registerCallback(callbackBridge);
+ LOG_ALWAYS_FATAL_IF(!callbackBridge->HasPrimaryDisplay(),
+ "Registered composer callback but didn't get primary display");
}
// Required by HWC2 device
@@ -146,7 +134,7 @@
}
Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
- android_pixel_format_t* format, std::shared_ptr<Display>* outDisplay)
+ android_pixel_format_t* format, Display** outDisplay)
{
ALOGI("Creating virtual display");
@@ -159,104 +147,66 @@
return error;
}
- ALOGI("Created virtual display");
+ auto display = std::make_unique<Display>(
+ *mComposer.get(), mCapabilities, displayId, DisplayType::Virtual);
+ *outDisplay = display.get();
*format = static_cast<android_pixel_format_t>(intFormat);
- *outDisplay = getDisplayById(displayId);
- if (!*outDisplay) {
- ALOGE("Failed to get display by id");
- return Error::BadDisplay;
- }
- (*outDisplay)->setConnected(true);
+ mDisplays.emplace(displayId, std::move(display));
+ ALOGI("Created virtual display");
return Error::None;
}
-void Device::registerHotplugCallback(HotplugCallback hotplug)
+void Device::destroyDisplay(hwc2_display_t displayId)
{
- ALOGV("registerHotplugCallback");
- mHotplug = hotplug;
- for (auto& pending : mPendingHotplugs) {
- auto& display = pending.first;
- auto connected = pending.second;
- ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(),
- to_string(connected).c_str());
- mHotplug(std::move(display), connected);
- }
+ ALOGI("Destroying display %" PRIu64, displayId);
+ mDisplays.erase(displayId);
}
-void Device::registerRefreshCallback(RefreshCallback refresh)
-{
- mRefresh = refresh;
- for (auto& pending : mPendingRefreshes) {
- mRefresh(std::move(pending));
- }
-}
+void Device::onHotplug(hwc2_display_t displayId, Connection connection) {
+ if (connection == Connection::Connected) {
+ auto display = getDisplayById(displayId);
+ if (display) {
+ if (display->isConnected()) {
+ ALOGW("Attempt to hotplug connect display %" PRIu64
+ " , which is already connected.", displayId);
+ } else {
+ display->setConnected(true);
+ }
+ } else {
+ DisplayType displayType;
+ auto intError = mComposer->getDisplayType(displayId,
+ reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(
+ &displayType));
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d). "
+ "Aborting hotplug attempt.",
+ displayId, to_string(error).c_str(), intError);
+ return;
+ }
-void Device::registerVsyncCallback(VsyncCallback vsync)
-{
- mVsync = vsync;
- for (auto& pending : mPendingVsyncs) {
- auto& display = pending.first;
- auto timestamp = pending.second;
- mVsync(std::move(display), timestamp);
- }
-}
-
-// For use by Device callbacks
-
-void Device::callHotplug(std::shared_ptr<Display> display, Connection connected)
-{
- if (connected == Connection::Connected) {
- if (!display->isConnected()) {
- mComposer->setClientTargetSlotCount(display->getId());
- display->loadConfigs();
- display->setConnected(true);
+ auto newDisplay = std::make_unique<Display>(
+ *mComposer.get(), mCapabilities, displayId, displayType);
+ mDisplays.emplace(displayId, std::move(newDisplay));
}
- } else {
- display->setConnected(false);
- mDisplays.erase(display->getId());
- }
-
- if (mHotplug) {
- mHotplug(std::move(display), connected);
- } else {
- ALOGV("callHotplug called, but no valid callback registered, storing");
- mPendingHotplugs.emplace_back(std::move(display), connected);
- }
-}
-
-void Device::callRefresh(std::shared_ptr<Display> display)
-{
- if (mRefresh) {
- mRefresh(std::move(display));
- } else {
- ALOGV("callRefresh called, but no valid callback registered, storing");
- mPendingRefreshes.emplace_back(std::move(display));
- }
-}
-
-void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp)
-{
- if (mVsync) {
- mVsync(std::move(display), timestamp);
- } else {
- ALOGV("callVsync called, but no valid callback registered, storing");
- mPendingVsyncs.emplace_back(std::move(display), timestamp);
+ } else if (connection == Connection::Disconnected) {
+ // The display will later be destroyed by a call to
+ // destroyDisplay(). For now we just mark it disconnected.
+ auto display = getDisplayById(displayId);
+ if (display) {
+ display->setConnected(false);
+ } else {
+ ALOGW("Attempted to disconnect unknown display %" PRIu64,
+ displayId);
+ }
}
}
// Other Device methods
-std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
- if (mDisplays.count(id) != 0) {
- auto strongDisplay = mDisplays[id].lock();
- ALOGE_IF(!strongDisplay, "Display %" PRId64 " is in mDisplays but is no"
- " longer alive", id);
- return strongDisplay;
- }
-
- auto display = std::make_shared<Display>(*this, id);
- mDisplays.emplace(id, display);
- return display;
+Display* Device::getDisplayById(hwc2_display_t id) {
+ auto iter = mDisplays.find(id);
+ return iter == mDisplays.end() ? nullptr : iter->second.get();
}
// Device initialization methods
@@ -271,84 +221,37 @@
}
}
-bool Device::hasCapability(HWC2::Capability capability) const
-{
- return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
- capability) != mCapabilities.cend();
-}
-
-namespace {
-class ComposerCallback : public Hwc2::IComposerCallback {
-public:
- ComposerCallback(Device* device) : mDevice(device) {}
-
- Return<void> onHotplug(Hwc2::Display display,
- Connection connected) override
- {
- hotplug_hook(mDevice, display, static_cast<int32_t>(connected));
- return Void();
- }
-
- Return<void> onRefresh(Hwc2::Display display) override
- {
- refresh_hook(mDevice, display);
- return Void();
- }
-
- Return<void> onVsync(Hwc2::Display display, int64_t timestamp) override
- {
- vsync_hook(mDevice, display, timestamp);
- return Void();
- }
-
-private:
- Device* mDevice;
-};
-} // namespace anonymous
-
-void Device::registerCallbacks()
-{
- sp<ComposerCallback> callback = new ComposerCallback(this);
- mComposer->registerCallback(callback);
-}
-
-
-// For use by Display
-
-void Device::destroyVirtualDisplay(hwc2_display_t display)
-{
- ALOGI("Destroying virtual display");
- auto intError = mComposer->destroyVirtualDisplay(display);
- auto error = static_cast<Error>(intError);
- ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
- " %s (%d)", display, to_string(error).c_str(), intError);
- mDisplays.erase(display);
-}
-
// Display methods
-Display::Display(Device& device, hwc2_display_t id)
- : mDevice(device),
+Display::Display(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t id, DisplayType type)
+ : mComposer(composer),
+ mCapabilities(capabilities),
mId(id),
mIsConnected(false),
- mType(DisplayType::Invalid)
+ mType(type)
{
ALOGV("Created display %" PRIu64, id);
-
- auto intError = mDevice.mComposer->getDisplayType(mId,
- reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
- id, to_string(error).c_str(), intError);
- }
+ setConnected(true);
}
-Display::~Display()
-{
- ALOGV("Destroyed display %" PRIu64, mId);
+Display::~Display() {
+ mLayers.clear();
+
if (mType == DisplayType::Virtual) {
- mDevice.destroyVirtualDisplay(mId);
+ ALOGV("Destroying virtual display");
+ auto intError = mComposer.destroyVirtualDisplay(mId);
+ auto error = static_cast<Error>(intError);
+ ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64
+ ") failed: %s (%d)", mId, to_string(error).c_str(), intError);
+ } else if (mType == DisplayType::Physical) {
+ auto error = setVsyncEnabled(HWC2::Vsync::Disable);
+ if (error != Error::None) {
+ ALOGE("~Display: Failed to disable vsync for display %" PRIu64
+ ": %s (%d)", mId, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ }
}
}
@@ -383,22 +286,35 @@
Error Display::acceptChanges()
{
- auto intError = mDevice.mComposer->acceptDisplayChanges(mId);
+ auto intError = mComposer.acceptDisplayChanges(mId);
return static_cast<Error>(intError);
}
-Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
+Error Display::createLayer(Layer** outLayer)
{
+ if (!outLayer) {
+ return Error::BadParameter;
+ }
hwc2_layer_t layerId = 0;
- auto intError = mDevice.mComposer->createLayer(mId, &layerId);
+ auto intError = mComposer.createLayer(mId, &layerId);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
}
- auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
- mLayers.emplace(layerId, layer);
- *outLayer = std::move(layer);
+ auto layer = std::make_unique<Layer>(
+ mComposer, mCapabilities, mId, layerId);
+ *outLayer = layer.get();
+ mLayers.emplace(layerId, std::move(layer));
+ return Error::None;
+}
+
+Error Display::destroyLayer(Layer* layer)
+{
+ if (!layer) {
+ return Error::BadParameter;
+ }
+ mLayers.erase(layer->getId());
return Error::None;
}
@@ -407,7 +323,7 @@
{
ALOGV("[%" PRIu64 "] getActiveConfig", mId);
hwc2_config_t configId = 0;
- auto intError = mDevice.mComposer->getActiveConfig(mId, &configId);
+ auto intError = mComposer.getActiveConfig(mId, &configId);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -430,12 +346,12 @@
}
Error Display::getChangedCompositionTypes(
- std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
+ std::unordered_map<Layer*, Composition>* outTypes)
{
std::vector<Hwc2::Layer> layerIds;
std::vector<Hwc2::IComposerClient::Composition> types;
- auto intError = mDevice.mComposer->getChangedCompositionTypes(mId,
- &layerIds, &types);
+ auto intError = mComposer.getChangedCompositionTypes(
+ mId, &layerIds, &types);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
error = static_cast<Error>(intError);
@@ -464,7 +380,7 @@
Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
{
std::vector<Hwc2::ColorMode> modes;
- auto intError = mDevice.mComposer->getColorModes(mId, &modes);
+ auto intError = mComposer.getColorModes(mId, &modes);
uint32_t numModes = modes.size();
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -489,19 +405,18 @@
Error Display::getName(std::string* outName) const
{
- auto intError = mDevice.mComposer->getDisplayName(mId, outName);
+ auto intError = mComposer.getDisplayName(mId, outName);
return static_cast<Error>(intError);
}
Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
- std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
- outLayerRequests)
+ std::unordered_map<Layer*, LayerRequest>* outLayerRequests)
{
uint32_t intDisplayRequests;
std::vector<Hwc2::Layer> layerIds;
std::vector<uint32_t> layerRequests;
- auto intError = mDevice.mComposer->getDisplayRequests(mId,
- &intDisplayRequests, &layerIds, &layerRequests);
+ auto intError = mComposer.getDisplayRequests(
+ mId, &intDisplayRequests, &layerIds, &layerRequests);
uint32_t numElements = layerIds.size();
auto error = static_cast<Error>(intError);
if (error != Error::None) {
@@ -535,7 +450,7 @@
Error Display::supportsDoze(bool* outSupport) const
{
bool intSupport = false;
- auto intError = mDevice.mComposer->getDozeSupport(mId, &intSupport);
+ auto intError = mComposer.getDozeSupport(mId, &intSupport);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -552,7 +467,7 @@
float maxAverageLuminance = -1.0f;
float minLuminance = -1.0f;
std::vector<Hwc2::Hdr> intTypes;
- auto intError = mDevice.mComposer->getHdrCapabilities(mId, &intTypes,
+ auto intError = mComposer.getHdrCapabilities(mId, &intTypes,
&maxLuminance, &maxAverageLuminance, &minLuminance);
auto error = static_cast<HWC2::Error>(intError);
@@ -571,25 +486,24 @@
}
Error Display::getReleaseFences(
- std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
+ std::unordered_map<Layer*, sp<Fence>>* outFences) const
{
std::vector<Hwc2::Layer> layerIds;
std::vector<int> fenceFds;
- auto intError = mDevice.mComposer->getReleaseFences(mId,
- &layerIds, &fenceFds);
+ auto intError = mComposer.getReleaseFences(mId, &layerIds, &fenceFds);
auto error = static_cast<Error>(intError);
uint32_t numElements = layerIds.size();
if (error != Error::None) {
return error;
}
- std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
+ std::unordered_map<Layer*, sp<Fence>> releaseFences;
releaseFences.reserve(numElements);
for (uint32_t element = 0; element < numElements; ++element) {
auto layer = getLayerById(layerIds[element]);
if (layer) {
sp<Fence> fence(new Fence(fenceFds[element]));
- releaseFences.emplace(std::move(layer), fence);
+ releaseFences.emplace(layer, fence);
} else {
ALOGE("getReleaseFences: invalid layer %" PRIu64
" found on display %" PRIu64, layerIds[element], mId);
@@ -607,7 +521,7 @@
Error Display::present(sp<Fence>* outPresentFence)
{
int32_t presentFenceFd = -1;
- auto intError = mDevice.mComposer->presentDisplay(mId, &presentFenceFd);
+ auto intError = mComposer.presentDisplay(mId, &presentFenceFd);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
return error;
@@ -625,7 +539,7 @@
config->getDisplayId(), mId);
return Error::BadConfig;
}
- auto intError = mDevice.mComposer->setActiveConfig(mId, config->getId());
+ auto intError = mComposer.setActiveConfig(mId, config->getId());
return static_cast<Error>(intError);
}
@@ -634,7 +548,7 @@
{
// TODO: Properly encode client target surface damage
int32_t fenceFd = acquireFence->dup();
- auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
+ auto intError = mComposer.setClientTarget(mId, slot, target,
fenceFd, static_cast<Hwc2::Dataspace>(dataspace),
std::vector<Hwc2::IComposerClient::Rect>());
return static_cast<Error>(intError);
@@ -642,15 +556,15 @@
Error Display::setColorMode(android_color_mode_t mode)
{
- auto intError = mDevice.mComposer->setColorMode(mId,
- static_cast<Hwc2::ColorMode>(mode));
+ auto intError = mComposer.setColorMode(
+ mId, static_cast<Hwc2::ColorMode>(mode));
return static_cast<Error>(intError);
}
Error Display::setColorTransform(const android::mat4& matrix,
android_color_transform_t hint)
{
- auto intError = mDevice.mComposer->setColorTransform(mId,
+ auto intError = mComposer.setColorTransform(mId,
matrix.asArray(), static_cast<Hwc2::ColorTransform>(hint));
return static_cast<Error>(intError);
}
@@ -660,7 +574,7 @@
{
int32_t fenceFd = releaseFence->dup();
auto handle = buffer->getNativeBuffer()->handle;
- auto intError = mDevice.mComposer->setOutputBuffer(mId, handle, fenceFd);
+ auto intError = mComposer.setOutputBuffer(mId, handle, fenceFd);
close(fenceFd);
return static_cast<Error>(intError);
}
@@ -668,14 +582,14 @@
Error Display::setPowerMode(PowerMode mode)
{
auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
- auto intError = mDevice.mComposer->setPowerMode(mId, intMode);
+ auto intError = mComposer.setPowerMode(mId, intMode);
return static_cast<Error>(intError);
}
Error Display::setVsyncEnabled(Vsync enabled)
{
auto intEnabled = static_cast<Hwc2::IComposerClient::Vsync>(enabled);
- auto intError = mDevice.mComposer->setVsyncEnabled(mId, intEnabled);
+ auto intError = mComposer.setVsyncEnabled(mId, intEnabled);
return static_cast<Error>(intError);
}
@@ -683,8 +597,7 @@
{
uint32_t numTypes = 0;
uint32_t numRequests = 0;
- auto intError = mDevice.mComposer->validateDisplay(mId,
- &numTypes, &numRequests);
+ auto intError = mComposer.validateDisplay(mId, &numTypes, &numRequests);
auto error = static_cast<Error>(intError);
if (error != Error::None && error != Error::HasChanges) {
return error;
@@ -701,7 +614,8 @@
uint32_t numTypes = 0;
uint32_t numRequests = 0;
int32_t presentFenceFd = -1;
- auto intError = mDevice.mComposer->presentOrValidateDisplay(mId, &numTypes, &numRequests, &presentFenceFd, state);
+ auto intError = mComposer.presentOrValidateDisplay(
+ mId, &numTypes, &numRequests, &presentFenceFd, state);
auto error = static_cast<Error>(intError);
if (error != Error::None && error != Error::HasChanges) {
return error;
@@ -720,15 +634,23 @@
void Display::discardCommands()
{
- mDevice.mComposer->resetCommands();
+ mComposer.resetCommands();
}
// For use by Device
+void Display::setConnected(bool connected) {
+ if (!mIsConnected && connected && mType == DisplayType::Physical) {
+ mComposer.setClientTargetSlotCount(mId);
+ loadConfigs();
+ }
+ mIsConnected = connected;
+}
+
int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
{
int32_t value = 0;
- auto intError = mDevice.mComposer->getDisplayAttribute(mId, configId,
+ auto intError = mComposer.getDisplayAttribute(mId, configId,
static_cast<Hwc2::IComposerClient::Attribute>(attribute),
&value);
auto error = static_cast<Error>(intError);
@@ -760,7 +682,7 @@
ALOGV("[%" PRIu64 "] loadConfigs", mId);
std::vector<Hwc2::Config> configIds;
- auto intError = mDevice.mComposer->getDisplayConfigs(mId, &configIds);
+ auto intError = mComposer.getDisplayConfigs(mId, &configIds);
auto error = static_cast<Error>(intError);
if (error != Error::None) {
ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
@@ -773,54 +695,51 @@
}
}
-// For use by Layer
-
-void Display::destroyLayer(hwc2_layer_t layerId)
-{
- auto intError =mDevice.mComposer->destroyLayer(mId, layerId);
- auto error = static_cast<Error>(intError);
- ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
- " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
- intError);
- mLayers.erase(layerId);
-}
-
// Other Display methods
-std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
+Layer* Display::getLayerById(hwc2_layer_t id) const
{
if (mLayers.count(id) == 0) {
return nullptr;
}
- auto layer = mLayers.at(id).lock();
- return layer;
+ return mLayers.at(id).get();
}
// Layer methods
-Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
- : mDisplay(display),
- mDisplayId(display->getId()),
- mDevice(display->getDevice()),
- mId(id)
+Layer::Layer(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t displayId, hwc2_layer_t layerId)
+ : mComposer(composer),
+ mCapabilities(capabilities),
+ mDisplayId(displayId),
+ mId(layerId)
{
- ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
- display->getId());
+ ALOGV("Created layer %" PRIu64 " on display %" PRIu64, layerId, displayId);
}
Layer::~Layer()
{
- auto display = mDisplay.lock();
- if (display) {
- display->destroyLayer(mId);
+ auto intError = mComposer.destroyLayer(mDisplayId, mId);
+ auto error = static_cast<Error>(intError);
+ ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
+ " failed: %s (%d)", mDisplayId, mId, to_string(error).c_str(),
+ intError);
+ if (mLayerDestroyedListener) {
+ mLayerDestroyedListener(this);
}
}
+void Layer::setLayerDestroyedListener(std::function<void(Layer*)> listener) {
+ LOG_ALWAYS_FATAL_IF(mLayerDestroyedListener && listener,
+ "Attempt to set layer destroyed listener multiple times");
+ mLayerDestroyedListener = listener;
+}
+
Error Layer::setCursorPosition(int32_t x, int32_t y)
{
- auto intError = mDevice.mComposer->setCursorPosition(mDisplayId,
- mId, x, y);
+ auto intError = mComposer.setCursorPosition(mDisplayId, mId, x, y);
return static_cast<Error>(intError);
}
@@ -828,8 +747,8 @@
const sp<Fence>& acquireFence)
{
int32_t fenceFd = acquireFence->dup();
- auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
- mId, slot, buffer, fenceFd);
+ auto intError = mComposer.setLayerBuffer(mDisplayId, mId, slot, buffer,
+ fenceFd);
return static_cast<Error>(intError);
}
@@ -839,7 +758,7 @@
// rects for HWC
Hwc2::Error intError = Hwc2::Error::NONE;
if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
- intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
+ intError = mComposer.setLayerSurfaceDamage(mDisplayId,
mId, std::vector<Hwc2::IComposerClient::Rect>());
} else {
size_t rectCount = 0;
@@ -851,8 +770,7 @@
rectArray[rect].right, rectArray[rect].bottom});
}
- intError = mDevice.mComposer->setLayerSurfaceDamage(mDisplayId,
- mId, hwcRects);
+ intError = mComposer.setLayerSurfaceDamage(mDisplayId, mId, hwcRects);
}
return static_cast<Error>(intError);
@@ -861,24 +779,22 @@
Error Layer::setBlendMode(BlendMode mode)
{
auto intMode = static_cast<Hwc2::IComposerClient::BlendMode>(mode);
- auto intError = mDevice.mComposer->setLayerBlendMode(mDisplayId,
- mId, intMode);
+ auto intError = mComposer.setLayerBlendMode(mDisplayId, mId, intMode);
return static_cast<Error>(intError);
}
Error Layer::setColor(hwc_color_t color)
{
Hwc2::IComposerClient::Color hwcColor{color.r, color.g, color.b, color.a};
- auto intError = mDevice.mComposer->setLayerColor(mDisplayId,
- mId, hwcColor);
+ auto intError = mComposer.setLayerColor(mDisplayId, mId, hwcColor);
return static_cast<Error>(intError);
}
Error Layer::setCompositionType(Composition type)
{
auto intType = static_cast<Hwc2::IComposerClient::Composition>(type);
- auto intError = mDevice.mComposer->setLayerCompositionType(mDisplayId,
- mId, intType);
+ auto intError = mComposer.setLayerCompositionType(
+ mDisplayId, mId, intType);
return static_cast<Error>(intError);
}
@@ -889,8 +805,7 @@
}
mDataSpace = dataspace;
auto intDataspace = static_cast<Hwc2::Dataspace>(dataspace);
- auto intError = mDevice.mComposer->setLayerDataspace(mDisplayId,
- mId, intDataspace);
+ auto intError = mComposer.setLayerDataspace(mDisplayId, mId, intDataspace);
return static_cast<Error>(intError);
}
@@ -898,27 +813,24 @@
{
Hwc2::IComposerClient::Rect hwcRect{frame.left, frame.top,
frame.right, frame.bottom};
- auto intError = mDevice.mComposer->setLayerDisplayFrame(mDisplayId,
- mId, hwcRect);
+ auto intError = mComposer.setLayerDisplayFrame(mDisplayId, mId, hwcRect);
return static_cast<Error>(intError);
}
Error Layer::setPlaneAlpha(float alpha)
{
- auto intError = mDevice.mComposer->setLayerPlaneAlpha(mDisplayId,
- mId, alpha);
+ auto intError = mComposer.setLayerPlaneAlpha(mDisplayId, mId, alpha);
return static_cast<Error>(intError);
}
Error Layer::setSidebandStream(const native_handle_t* stream)
{
- if (!mDevice.hasCapability(Capability::SidebandStream)) {
+ if (mCapabilities.count(Capability::SidebandStream) == 0) {
ALOGE("Attempted to call setSidebandStream without checking that the "
"device supports sideband streams");
return Error::Unsupported;
}
- auto intError = mDevice.mComposer->setLayerSidebandStream(mDisplayId,
- mId, stream);
+ auto intError = mComposer.setLayerSidebandStream(mDisplayId, mId, stream);
return static_cast<Error>(intError);
}
@@ -926,16 +838,14 @@
{
Hwc2::IComposerClient::FRect hwcRect{
crop.left, crop.top, crop.right, crop.bottom};
- auto intError = mDevice.mComposer->setLayerSourceCrop(mDisplayId,
- mId, hwcRect);
+ auto intError = mComposer.setLayerSourceCrop(mDisplayId, mId, hwcRect);
return static_cast<Error>(intError);
}
Error Layer::setTransform(Transform transform)
{
auto intTransform = static_cast<Hwc2::Transform>(transform);
- auto intError = mDevice.mComposer->setLayerTransform(mDisplayId,
- mId, intTransform);
+ auto intError = mComposer.setLayerTransform(mDisplayId, mId, intTransform);
return static_cast<Error>(intError);
}
@@ -950,20 +860,19 @@
rectArray[rect].right, rectArray[rect].bottom});
}
- auto intError = mDevice.mComposer->setLayerVisibleRegion(mDisplayId,
- mId, hwcRects);
+ auto intError = mComposer.setLayerVisibleRegion(mDisplayId, mId, hwcRects);
return static_cast<Error>(intError);
}
Error Layer::setZOrder(uint32_t z)
{
- auto intError = mDevice.mComposer->setLayerZOrder(mDisplayId, mId, z);
+ auto intError = mComposer.setLayerZOrder(mDisplayId, mId, z);
return static_cast<Error>(intError);
}
Error Layer::setInfo(uint32_t type, uint32_t appId)
{
- auto intError = mDevice.mComposer->setLayerInfo(mDisplayId, mId, type, appId);
+ auto intError = mComposer.setLayerInfo(mDisplayId, mId, type, appId);
return static_cast<Error>(intError);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 9bcda1e..fbe4c7e 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -53,10 +53,26 @@
class Display;
class Layer;
-typedef std::function<void(std::shared_ptr<Display>, Connection)>
- HotplugCallback;
-typedef std::function<void(std::shared_ptr<Display>)> RefreshCallback;
-typedef std::function<void(std::shared_ptr<Display>, nsecs_t)> VsyncCallback;
+// Implement this interface to receive hardware composer events.
+//
+// These callback functions will generally be called on a hwbinder thread, but
+// when first registering the callback the onHotplugReceived() function will
+// immediately be called on the thread calling registerCallback().
+//
+// All calls receive a sequenceId, which will be the value that was supplied to
+// HWC2::Device::registerCallback(). It's used to help differentiate callbacks
+// from different hardware composer instances.
+class ComposerCallback {
+ public:
+ virtual void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+ Connection connection,
+ bool primaryDisplay) = 0;
+ virtual void onRefreshReceived(int32_t sequenceId,
+ hwc2_display_t display) = 0;
+ virtual void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+ int64_t timestamp) = 0;
+ virtual ~ComposerCallback() = default;
+};
// C++ Wrapper around hwc2_device_t. Load all functions pointers
// and handle callback registration.
@@ -66,10 +82,8 @@
// Service name is expected to be 'default' or 'vr' for normal use.
// 'vr' will slightly modify the behavior of the mComposer.
Device(const std::string& serviceName);
- ~Device();
- friend class HWC2::Display;
- friend class HWC2::Layer;
+ void registerCallback(ComposerCallback* callback, int32_t sequenceId);
// Required by HWC2
@@ -81,27 +95,14 @@
uint32_t getMaxVirtualDisplayCount() const;
Error createVirtualDisplay(uint32_t width, uint32_t height,
- android_pixel_format_t* format,
- std::shared_ptr<Display>* outDisplay);
+ android_pixel_format_t* format, Display** outDisplay);
+ void destroyDisplay(hwc2_display_t displayId);
- void registerHotplugCallback(HotplugCallback hotplug);
- void registerRefreshCallback(RefreshCallback refresh);
- void registerVsyncCallback(VsyncCallback vsync);
-
- // For use by callbacks
-
- void callHotplug(std::shared_ptr<Display> display, Connection connected);
- void callRefresh(std::shared_ptr<Display> display);
- void callVsync(std::shared_ptr<Display> display, nsecs_t timestamp);
+ void onHotplug(hwc2_display_t displayId, Connection connection);
// Other Device methods
- // This will create a Display if one is not found, but it will not be marked
- // as connected. This Display may be null if the display has been torn down
- // but has not been removed from the map yet.
- std::shared_ptr<Display> getDisplayById(hwc2_display_t id);
-
- bool hasCapability(HWC2::Capability capability) const;
+ Display* getDisplayById(hwc2_display_t id);
android::Hwc2::Composer* getComposer() { return mComposer.get(); }
@@ -109,37 +110,23 @@
// Initialization methods
void loadCapabilities();
- void registerCallbacks();
-
- // For use by Display
-
- void destroyVirtualDisplay(hwc2_display_t display);
// Member variables
std::unique_ptr<android::Hwc2::Composer> mComposer;
-
std::unordered_set<Capability> mCapabilities;
- std::unordered_map<hwc2_display_t, std::weak_ptr<Display>> mDisplays;
-
- HotplugCallback mHotplug;
- std::vector<std::pair<std::shared_ptr<Display>, Connection>>
- mPendingHotplugs;
- RefreshCallback mRefresh;
- std::vector<std::shared_ptr<Display>> mPendingRefreshes;
- VsyncCallback mVsync;
- std::vector<std::pair<std::shared_ptr<Display>, nsecs_t>> mPendingVsyncs;
+ std::unordered_map<hwc2_display_t, std::unique_ptr<Display>> mDisplays;
+ bool mRegisteredCallback;
};
// Convenience C++ class to access hwc2_device_t Display functions directly.
-class Display : public std::enable_shared_from_this<Display>
+class Display
{
public:
- Display(Device& device, hwc2_display_t id);
+ Display(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t id, DisplayType type);
~Display();
- friend class HWC2::Device;
- friend class HWC2::Layer;
-
class Config
{
public:
@@ -212,12 +199,12 @@
// Required by HWC2
[[clang::warn_unused_result]] Error acceptChanges();
- [[clang::warn_unused_result]] Error createLayer(
- std::shared_ptr<Layer>* outLayer);
+ [[clang::warn_unused_result]] Error createLayer(Layer** outLayer);
+ [[clang::warn_unused_result]] Error destroyLayer(Layer* layer);
[[clang::warn_unused_result]] Error getActiveConfig(
std::shared_ptr<const Config>* outConfig) const;
[[clang::warn_unused_result]] Error getChangedCompositionTypes(
- std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
+ std::unordered_map<Layer*, Composition>* outTypes);
[[clang::warn_unused_result]] Error getColorModes(
std::vector<android_color_mode_t>* outModes) const;
@@ -227,14 +214,13 @@
[[clang::warn_unused_result]] Error getName(std::string* outName) const;
[[clang::warn_unused_result]] Error getRequests(
DisplayRequest* outDisplayRequests,
- std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
- outLayerRequests);
+ std::unordered_map<Layer*, LayerRequest>* outLayerRequests);
[[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
[[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
[[clang::warn_unused_result]] Error getHdrCapabilities(
std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
[[clang::warn_unused_result]] Error getReleaseFences(
- std::unordered_map<std::shared_ptr<Layer>,
+ std::unordered_map<Layer*,
android::sp<android::Fence>>* outFences) const;
[[clang::warn_unused_result]] Error present(
android::sp<android::Fence>* outPresentFence);
@@ -266,32 +252,31 @@
// Other Display methods
- Device& getDevice() const { return mDevice; }
hwc2_display_t getId() const { return mId; }
bool isConnected() const { return mIsConnected; }
+ void setConnected(bool connected); // For use by Device only
private:
- // For use by Device
-
- void setConnected(bool connected) { mIsConnected = connected; }
int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
void loadConfig(hwc2_config_t configId);
void loadConfigs();
- // For use by Layer
- void destroyLayer(hwc2_layer_t layerId);
-
// This may fail (and return a null pointer) if no layer with this ID exists
// on this display
- std::shared_ptr<Layer> getLayerById(hwc2_layer_t id) const;
+ Layer* getLayerById(hwc2_layer_t id) const;
// Member variables
- Device& mDevice;
+ // These are references to data owned by HWC2::Device, which will outlive
+ // this HWC2::Display, so these references are guaranteed to be valid for
+ // the lifetime of this object.
+ android::Hwc2::Composer& mComposer;
+ const std::unordered_set<Capability>& mCapabilities;
+
hwc2_display_t mId;
bool mIsConnected;
DisplayType mType;
- std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
+ std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
// The ordering in this map matters, for getConfigs(), when it is
// converted to a vector
std::map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
@@ -301,12 +286,18 @@
class Layer
{
public:
- Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id);
+ Layer(android::Hwc2::Composer& composer,
+ const std::unordered_set<Capability>& capabilities,
+ hwc2_display_t displayId, hwc2_layer_t layerId);
~Layer();
- bool isAbandoned() const { return mDisplay.expired(); }
hwc2_layer_t getId() const { return mId; }
+ // Register a listener to be notified when the layer is destroyed. When the
+ // listener function is called, the Layer will be in the process of being
+ // destroyed, so it's not safe to call methods on it.
+ void setLayerDestroyedListener(std::function<void(Layer*)> listener);
+
[[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
[[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
const android::sp<android::GraphicBuffer>& buffer,
@@ -333,11 +324,16 @@
[[clang::warn_unused_result]] Error setInfo(uint32_t type, uint32_t appId);
private:
- std::weak_ptr<Display> mDisplay;
+ // These are references to data owned by HWC2::Device, which will outlive
+ // this HWC2::Layer, so these references are guaranteed to be valid for
+ // the lifetime of this object.
+ android::Hwc2::Composer& mComposer;
+ const std::unordered_set<Capability>& mCapabilities;
+
hwc2_display_t mDisplayId;
- Device& mDevice;
hwc2_layer_t mId;
android_dataspace mDataSpace = HAL_DATASPACE_UNKNOWN;
+ std::function<void(Layer*)> mLayerDestroyedListener;
};
} // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index abf7dd1..b096a3a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -65,7 +65,6 @@
mFreeDisplaySlots(),
mHwcDisplaySlots(),
mCBContext(),
- mEventHandler(nullptr),
mVSyncCounts(),
mRemainingHwcVirtualDisplays(0)
{
@@ -74,41 +73,15 @@
mVSyncCounts[i] = 0;
}
- loadHwcModule(serviceName);
+ mHwcDevice = std::make_unique<HWC2::Device>(serviceName);
+ mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
}
HWComposer::~HWComposer() {}
-void HWComposer::setEventHandler(EventHandler* handler)
-{
- if (handler == nullptr) {
- ALOGE("setEventHandler: Rejected attempt to clear handler");
- return;
- }
-
- bool wasNull = (mEventHandler == nullptr);
- mEventHandler = handler;
-
- if (wasNull) {
- auto hotplugHook = std::bind(&HWComposer::hotplug, this,
- std::placeholders::_1, std::placeholders::_2);
- mHwcDevice->registerHotplugCallback(hotplugHook);
- auto invalidateHook = std::bind(&HWComposer::invalidate, this,
- std::placeholders::_1);
- mHwcDevice->registerRefreshCallback(invalidateHook);
- auto vsyncHook = std::bind(&HWComposer::vsync, this,
- std::placeholders::_1, std::placeholders::_2);
- mHwcDevice->registerVsyncCallback(vsyncHook);
- }
-}
-
-// Load and prepare the hardware composer module. Sets mHwc.
-void HWComposer::loadHwcModule(const std::string& serviceName)
-{
- ALOGV("loadHwcModule");
- mHwcDevice = std::make_unique<HWC2::Device>(serviceName);
-
- mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
+void HWComposer::registerCallback(HWC2::ComposerCallback* callback,
+ int32_t sequenceId) {
+ mHwcDevice->registerCallback(callback, sequenceId);
}
bool HWComposer::hasCapability(HWC2::Capability capability) const
@@ -146,54 +119,51 @@
}
}
-void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display,
- HWC2::Connection connected) {
- ALOGV("hotplug: %" PRIu64 ", %s", display->getId(),
- to_string(connected).c_str());
- int32_t disp = 0;
+void HWComposer::onHotplug(hwc2_display_t displayId,
+ HWC2::Connection connection) {
+ ALOGV("hotplug: %" PRIu64 ", %s", displayId,
+ to_string(connection).c_str());
+ mHwcDevice->onHotplug(displayId, connection);
if (!mDisplayData[0].hwcDisplay) {
- ALOGE_IF(connected != HWC2::Connection::Connected, "Assumed primary"
+ ALOGE_IF(connection != HWC2::Connection::Connected, "Assumed primary"
" display would be connected");
- mDisplayData[0].hwcDisplay = display;
- mHwcDisplaySlots[display->getId()] = 0;
- disp = DisplayDevice::DISPLAY_PRIMARY;
+ mDisplayData[0].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+ mHwcDisplaySlots[displayId] = 0;
} else {
// Disconnect is handled through HWComposer::disconnectDisplay via
// SurfaceFlinger's onHotplugReceived callback handling
- if (connected == HWC2::Connection::Connected) {
- mDisplayData[1].hwcDisplay = display;
- mHwcDisplaySlots[display->getId()] = 1;
+ if (connection == HWC2::Connection::Connected) {
+ mDisplayData[1].hwcDisplay = mHwcDevice->getDisplayById(displayId);
+ mHwcDisplaySlots[displayId] = 1;
}
- disp = DisplayDevice::DISPLAY_EXTERNAL;
}
- mEventHandler->onHotplugReceived(this, disp,
- connected == HWC2::Connection::Connected);
}
-void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) {
- mEventHandler->onInvalidateReceived(this);
-}
-
-void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
- int64_t timestamp) {
+bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp,
+ int32_t* outDisplay) {
+ auto display = mHwcDevice->getDisplayById(displayId);
+ if (!display) {
+ ALOGE("onVsync Failed to find display %" PRIu64, displayId);
+ return false;
+ }
auto displayType = HWC2::DisplayType::Invalid;
auto error = display->getType(&displayType);
if (error != HWC2::Error::None) {
- ALOGE("vsync: Failed to determine type of display %" PRIu64,
+ ALOGE("onVsync: Failed to determine type of display %" PRIu64,
display->getId());
- return;
+ return false;
}
if (displayType == HWC2::DisplayType::Virtual) {
ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
display->getId());
- return;
+ return false;
}
if (mHwcDisplaySlots.count(display->getId()) == 0) {
ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
display->getId());
- return;
+ return false;
}
int32_t disp = mHwcDisplaySlots[display->getId()];
@@ -207,17 +177,21 @@
if (timestamp == mLastHwVSync[disp]) {
ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
timestamp);
- return;
+ return false;
}
mLastHwVSync[disp] = timestamp;
}
+ if (outDisplay) {
+ *outDisplay = disp;
+ }
+
char tag[16];
snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
- mEventHandler->onVSyncReceived(this, disp, timestamp);
+ return true;
}
status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
@@ -236,7 +210,7 @@
return INVALID_OPERATION;
}
- std::shared_ptr<HWC2::Display> display;
+ HWC2::Display* display;
auto error = mHwcDevice->createVirtualDisplay(width, height, format,
&display);
if (error != HWC2::Error::None) {
@@ -265,13 +239,13 @@
return NO_ERROR;
}
-std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) {
+HWC2::Layer* HWComposer::createLayer(int32_t displayId) {
if (!isValidDisplay(displayId)) {
ALOGE("Failed to create layer on invalid display %d", displayId);
return nullptr;
}
auto display = mDisplayData[displayId].hwcDisplay;
- std::shared_ptr<HWC2::Layer> layer;
+ HWC2::Layer* layer;
auto error = display->createLayer(&layer);
if (error != HWC2::Error::None) {
ALOGE("Failed to create layer on display %d: %s (%d)", displayId,
@@ -281,6 +255,19 @@
return layer;
}
+void HWComposer::destroyLayer(int32_t displayId, HWC2::Layer* layer) {
+ if (!isValidDisplay(displayId)) {
+ ALOGE("Failed to destroy layer on invalid display %d", displayId);
+ return;
+ }
+ auto display = mDisplayData[displayId].hwcDisplay;
+ auto error = display->destroyLayer(layer);
+ if (error != HWC2::Error::None) {
+ ALOGE("Failed to destroy layer on display %d: %s (%d)", displayId,
+ to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+}
+
nsecs_t HWComposer::getRefreshTimestamp(int32_t displayId) const {
// this returns the last refresh timestamp.
// if the last one is not available, we estimate it based on
@@ -348,10 +335,8 @@
displayId);
return modes;
}
- const std::shared_ptr<HWC2::Display>& hwcDisplay =
- mDisplayData[displayId].hwcDisplay;
- auto error = hwcDisplay->getColorModes(&modes);
+ auto error = mDisplayData[displayId].hwcDisplay->getColorModes(&modes);
if (error != HWC2::Error::None) {
ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
@@ -471,7 +456,7 @@
return UNKNOWN_ERROR;
}
if (state == 1) { //Present Succeeded.
- std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+ std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
error = hwcDisplay->getReleaseFences(&releaseFences);
displayData.releaseFences = std::move(releaseFences);
displayData.lastPresentFence = outPresentFence;
@@ -490,8 +475,7 @@
return BAD_INDEX;
}
- std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::Composition>
- changedTypes;
+ std::unordered_map<HWC2::Layer*, HWC2::Composition> changedTypes;
changedTypes.reserve(numTypes);
error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
if (error != HWC2::Error::None) {
@@ -503,8 +487,7 @@
displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
- std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::LayerRequest>
- layerRequests;
+ std::unordered_map<HWC2::Layer*, HWC2::LayerRequest> layerRequests;
layerRequests.reserve(numRequests);
error = hwcDisplay->getRequests(&displayData.displayRequests,
&layerRequests);
@@ -598,7 +581,7 @@
}
sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId,
- const std::shared_ptr<HWC2::Layer>& layer) const {
+ HWC2::Layer* layer) const {
if (!isValidDisplay(displayId)) {
ALOGE("getLayerReleaseFence: Invalid display");
return Fence::NO_FENCE;
@@ -639,7 +622,7 @@
return UNKNOWN_ERROR;
}
- std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+ std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
error = hwcDisplay->getReleaseFences(&releaseFences);
if (error != HWC2::Error::None) {
ALOGE("presentAndGetReleaseFences: Failed to get release fences "
@@ -787,6 +770,8 @@
auto hwcId = displayData.hwcDisplay->getId();
mHwcDisplaySlots.erase(hwcId);
displayData.reset();
+
+ mHwcDevice->destroyDisplay(hwcId);
}
status_t HWComposer::setOutputBuffer(int32_t displayId,
@@ -885,7 +870,7 @@
HWComposer::DisplayData::DisplayData()
: hasClientComposition(false),
hasDeviceComposition(false),
- hwcDisplay(),
+ hwcDisplay(nullptr),
lastPresentFence(Fence::NO_FENCE),
outbufHandle(nullptr),
outbufAcquireFence(Fence::NO_FENCE),
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 3dfb65b..3640bb5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -65,23 +65,14 @@
class HWComposer
{
public:
- class EventHandler {
- friend class HWComposer;
- virtual void onVSyncReceived(
- HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
- virtual void onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) = 0;
- virtual void onInvalidateReceived(HWComposer* composer) = 0;
- protected:
- virtual ~EventHandler() {}
- };
-
// Uses the named composer service. Valid choices for normal use
// are 'default' and 'vr'.
HWComposer(const std::string& serviceName);
~HWComposer();
- void setEventHandler(EventHandler* handler);
+ void registerCallback(HWC2::ComposerCallback* callback,
+ int32_t sequenceId);
bool hasCapability(HWC2::Capability capability) const;
@@ -91,7 +82,9 @@
android_pixel_format_t* format, int32_t* outId);
// Attempts to create a new layer on this display
- std::shared_ptr<HWC2::Layer> createLayer(int32_t displayId);
+ HWC2::Layer* createLayer(int32_t displayId);
+ // Destroy a previously created layer
+ void destroyLayer(int32_t displayId, HWC2::Layer* layer);
// Asks the HAL what it can do
status_t prepare(DisplayDevice& displayDevice);
@@ -126,7 +119,7 @@
// Get last release fence for the given layer
sp<Fence> getLayerReleaseFence(int32_t displayId,
- const std::shared_ptr<HWC2::Layer>& layer) const;
+ HWC2::Layer* layer) const;
// Set the output buffer and acquire fence for a virtual display.
// Returns INVALID_OPERATION if displayId is not a virtual display.
@@ -142,6 +135,12 @@
// Events handling ---------------------------------------------------------
+ // Returns true if successful, false otherwise. The
+ // DisplayDevice::DisplayType of the display is returned as an output param.
+ bool onVsync(hwc2_display_t displayId, int64_t timestamp,
+ int32_t* outDisplay);
+ void onHotplug(hwc2_display_t displayId, HWC2::Connection connection);
+
void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
// Query display parameters. Pass in a display index (e.g.
@@ -169,19 +168,11 @@
private:
static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
- void loadHwcModule(const std::string& serviceName);
-
bool isValidDisplay(int32_t displayId) const;
static void validateChange(HWC2::Composition from, HWC2::Composition to);
struct cb_context;
- void invalidate(const std::shared_ptr<HWC2::Display>& display);
- void vsync(const std::shared_ptr<HWC2::Display>& display,
- int64_t timestamp);
- void hotplug(const std::shared_ptr<HWC2::Display>& display,
- HWC2::Connection connected);
-
struct DisplayData {
DisplayData();
~DisplayData();
@@ -189,11 +180,10 @@
bool hasClientComposition;
bool hasDeviceComposition;
- std::shared_ptr<HWC2::Display> hwcDisplay;
+ HWC2::Display* hwcDisplay;
HWC2::DisplayRequest displayRequests;
sp<Fence> lastPresentFence; // signals when the last set op retires
- std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>>
- releaseFences;
+ std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
buffer_handle_t outbufHandle;
sp<Fence> outbufAcquireFence;
mutable std::unordered_map<int32_t,
@@ -214,7 +204,6 @@
mutable Mutex mDisplayLock;
cb_context* mCBContext;
- EventHandler* mEventHandler;
size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
uint32_t mRemainingHwcVirtualDisplays;
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index ee6e886..052a959 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -31,34 +31,35 @@
}
bool EventControlThread::threadLoop() {
- Mutex::Autolock lock(mMutex);
-
- bool vsyncEnabled = mVsyncEnabled;
-
-#ifdef USE_HWC2
- mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
-#else
- mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
- mVsyncEnabled);
-#endif
+ enum class VsyncState {Unset, On, Off};
+ auto currentVsyncState = VsyncState::Unset;
while (true) {
- status_t err = mCond.wait(mMutex);
- if (err != NO_ERROR) {
- ALOGE("error waiting for new events: %s (%d)",
- strerror(-err), err);
- return false;
+ auto requestedVsyncState = VsyncState::On;
+ {
+ Mutex::Autolock lock(mMutex);
+ requestedVsyncState =
+ mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+ while (currentVsyncState == requestedVsyncState) {
+ status_t err = mCond.wait(mMutex);
+ if (err != NO_ERROR) {
+ ALOGE("error waiting for new events: %s (%d)",
+ strerror(-err), err);
+ return false;
+ }
+ requestedVsyncState =
+ mVsyncEnabled ? VsyncState::On : VsyncState::Off;
+ }
}
- if (vsyncEnabled != mVsyncEnabled) {
+ bool enable = requestedVsyncState == VsyncState::On;
#ifdef USE_HWC2
- mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
+ mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, enable);
#else
- mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
- SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
+ mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
+ SurfaceFlinger::EVENT_VSYNC, enable);
#endif
- vsyncEnabled = mVsyncEnabled;
- }
+ currentVsyncState = requestedVsyncState;
}
return false;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 3903a55..54d4cbd 100755
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -201,6 +201,12 @@
}
mFlinger->deleteTextureAsync(mTextureName);
mFrameTracker.logAndResetStats(mName);
+
+#ifdef USE_HWC2
+ ALOGE_IF(!mHwcLayers.empty(),
+ "Found stale hardware composer layers when destroying "
+ "surface flinger layer");
+#endif
}
// ---------------------------------------------------------------------------
@@ -303,7 +309,7 @@
mSurfaceFlingerConsumer->abandon();
#ifdef USE_HWC2
- clearHwcLayers();
+ destroyAllHwcLayers();
#endif
for (const auto& child : mCurrentChildren) {
@@ -364,6 +370,48 @@
// h/w composer set-up
// ---------------------------------------------------------------------------
+#ifdef USE_HWC2
+bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+ "Already have a layer for hwcId %d", hwcId);
+ HWC2::Layer* layer = hwc->createLayer(hwcId);
+ if (!layer) {
+ return false;
+ }
+ HWCInfo& hwcInfo = mHwcLayers[hwcId];
+ hwcInfo.hwc = hwc;
+ hwcInfo.layer = layer;
+ layer->setLayerDestroyedListener(
+ [this, hwcId] (HWC2::Layer* /*layer*/){mHwcLayers.erase(hwcId);});
+ return true;
+}
+
+void Layer::destroyHwcLayer(int32_t hwcId) {
+ if (mHwcLayers.count(hwcId) == 0) {
+ return;
+ }
+ auto& hwcInfo = mHwcLayers[hwcId];
+ LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr,
+ "Attempt to destroy null layer");
+ LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
+ hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
+ // The layer destroyed listener should have cleared the entry from
+ // mHwcLayers. Verify that.
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.count(hwcId) != 0,
+ "Stale layer entry in mHwcLayers");
+}
+
+void Layer::destroyAllHwcLayers() {
+ size_t numLayers = mHwcLayers.size();
+ for (size_t i = 0; i < numLayers; ++i) {
+ LOG_ALWAYS_FATAL_IF(mHwcLayers.empty(), "destroyAllHwcLayers failed");
+ destroyHwcLayer(mHwcLayers.begin()->first);
+ }
+ LOG_ALWAYS_FATAL_IF(!mHwcLayers.empty(),
+ "All hardware composer layers should have been destroyed");
+}
+#endif
+
Rect Layer::getContentCrop() const {
// this is the crop rectangle that applies to the buffer
// itself (as opposed to the window)
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8df8c49..1b7d075 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -447,37 +447,21 @@
#ifdef USE_HWC2
// -----------------------------------------------------------------------
+ bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
+ void destroyHwcLayer(int32_t hwcId);
+ void destroyAllHwcLayers();
+
bool hasHwcLayer(int32_t hwcId) {
- if (mHwcLayers.count(hwcId) == 0) {
- return false;
- }
- if (mHwcLayers[hwcId].layer->isAbandoned()) {
- ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
- mHwcLayers.erase(hwcId);
- return false;
- }
- return true;
+ return mHwcLayers.count(hwcId) > 0;
}
- std::shared_ptr<HWC2::Layer> getHwcLayer(int32_t hwcId) {
+ HWC2::Layer* getHwcLayer(int32_t hwcId) {
if (mHwcLayers.count(hwcId) == 0) {
return nullptr;
}
return mHwcLayers[hwcId].layer;
}
- void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
- if (layer) {
- mHwcLayers[hwcId].layer = layer;
- } else {
- mHwcLayers.erase(hwcId);
- }
- }
-
- void clearHwcLayers() {
- mHwcLayers.clear();
- }
-
#endif
// -----------------------------------------------------------------------
@@ -766,12 +750,14 @@
// HWC items, accessed from the main thread
struct HWCInfo {
HWCInfo()
- : layer(),
+ : hwc(nullptr),
+ layer(nullptr),
forceClientComposition(false),
compositionType(HWC2::Composition::Invalid),
clearClientTarget(false) {}
- std::shared_ptr<HWC2::Layer> layer;
+ HWComposer* hwc;
+ HWC2::Layer* layer;
bool forceClientComposition;
HWC2::Composition compositionType;
bool clearClientTarget;
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index ac2d8b2..57f468d 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -64,7 +64,7 @@
"EGL_ANDROIDX_no_config_context") &&
!findExtension(eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS),
"EGL_KHR_no_config_context")) {
- config = chooseEglConfig(display, hwcFormat);
+ config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
EGLint renderableType = 0;
@@ -108,7 +108,7 @@
EGLConfig dummyConfig = config;
if (dummyConfig == EGL_NO_CONFIG) {
- dummyConfig = chooseEglConfig(display, hwcFormat);
+ dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
}
EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE };
EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
@@ -406,7 +406,8 @@
return err;
}
-EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format) {
+EGLConfig RenderEngine::chooseEglConfig(EGLDisplay display, int format,
+ bool logConfig) {
status_t err;
EGLConfig config;
@@ -427,18 +428,20 @@
}
}
- // print some debugging info
- EGLint r,g,b,a;
- eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
- eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
- eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
- eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
- ALOGI("EGL information:");
- ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
- ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
- ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
- ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
- ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+ if (logConfig) {
+ // print some debugging info
+ EGLint r,g,b,a;
+ eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
+ eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
+ eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
+ eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
+ ALOGI("EGL information:");
+ ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
+ ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
+ ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
+ ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS)?:"Not Supported");
+ ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
+ }
return config;
}
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 56f5827..9544579 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -64,7 +64,7 @@
};
static RenderEngine* create(EGLDisplay display, int hwcFormat, uint32_t featureFlags);
- static EGLConfig chooseEglConfig(EGLDisplay display, int format);
+ static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
void primeCache() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 609b15b..0d93467 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -77,6 +77,7 @@
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
+#include "DisplayHardware/ComposerHal.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
@@ -101,10 +102,24 @@
namespace android {
-
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
+namespace {
+class ConditionalLock {
+public:
+ ConditionalLock(Mutex& mutex, bool lock) : mMutex(mutex), mLocked(lock) {
+ if (lock) {
+ mMutex.lock();
+ }
+ }
+ ~ConditionalLock() { if (mLocked) mMutex.unlock(); }
+private:
+ Mutex& mMutex;
+ bool mLocked;
+};
+} // namespace anonymous
+
// ---------------------------------------------------------------------------
const String16 sHardwareTest("android.permission.HARDWARE_TEST");
@@ -147,9 +162,6 @@
mLayersRemoved(false),
mLayersAdded(false),
mRepaintEverything(0),
- mHwc(nullptr),
- mRealHwc(nullptr),
- mVrHwc(nullptr),
mHwcServiceName(getHwcServiceName()),
mRenderEngine(nullptr),
mBootTime(systemTime()),
@@ -177,7 +189,9 @@
mTotalTime(0),
mLastSwapTime(0),
mNumLayers(0),
- mVrFlingerRequestsDisplay(false)
+ mVrFlingerRequestsDisplay(false),
+ mMainThreadId(std::this_thread::get_id()),
+ mComposerSequenceId(0)
{
ALOGI("SurfaceFlinger is starting");
@@ -583,48 +597,46 @@
ALOGI("Phase offset NS: %" PRId64 "", vsyncPhaseOffsetNs);
- { // Autolock scope
- Mutex::Autolock _l(mStateLock);
+ Mutex::Autolock _l(mStateLock);
- // initialize EGL for the default display
- mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(mEGLDisplay, NULL, NULL);
+ // initialize EGL for the default display
+ mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ eglInitialize(mEGLDisplay, NULL, NULL);
- // start the EventThread
- sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- vsyncPhaseOffsetNs, true, "app");
- mEventThread = new EventThread(vsyncSrc, *this, false);
- sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- sfVsyncPhaseOffsetNs, true, "sf");
- mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
- mEventQueue.setEventThread(mSFEventThread);
+ // start the EventThread
+ sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ vsyncPhaseOffsetNs, true, "app");
+ mEventThread = new EventThread(vsyncSrc, *this, false);
+ sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+ sfVsyncPhaseOffsetNs, true, "sf");
+ mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
+ mEventQueue.setEventThread(mSFEventThread);
- // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
- struct sched_param param = {0};
- param.sched_priority = 2;
- if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
- }
- if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO for EventThread");
- }
-
- // Get a RenderEngine for the given display / config (can't fail)
- mRenderEngine = RenderEngine::create(mEGLDisplay,
- HAL_PIXEL_FORMAT_RGBA_8888,
- hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
+ // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter
+ struct sched_param param = {0};
+ param.sched_priority = 2;
+ if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO for SFEventThread");
+ }
+ if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) {
+ ALOGE("Couldn't set SCHED_FIFO for EventThread");
}
- // Drop the state lock while we initialize the hardware composer. We drop
- // the lock because on creation, it will call back into SurfaceFlinger to
- // initialize the primary display.
- LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
- "Starting with vr flinger active is not currently supported.");
- mRealHwc = new HWComposer(mHwcServiceName);
- mHwc = mRealHwc;
- mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
+ // Get a RenderEngine for the given display / config (can't fail)
+ mRenderEngine = RenderEngine::create(mEGLDisplay,
+ HAL_PIXEL_FORMAT_RGBA_8888,
+ hasWideColorDisplay ? RenderEngine::WIDE_COLOR_SUPPORT : 0);
- Mutex::Autolock _l(mStateLock);
+ // retrieve the EGL context that was selected/created
+ mEGLContext = mRenderEngine->getEGLContext();
+
+ LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
+ "couldn't create EGLContext");
+
+ LOG_ALWAYS_FATAL_IF(mVrFlingerRequestsDisplay,
+ "Starting with vr flinger active is not currently supported.");
+ mHwc.reset(new HWComposer(mHwcServiceName));
+ mHwc->registerCallback(this, mComposerSequenceId);
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
@@ -639,16 +651,6 @@
}
}
- // retrieve the EGL context that was selected/created
- mEGLContext = mRenderEngine->getEGLContext();
-
- LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
- "couldn't create EGLContext");
-
- // make the GLContext current so that we can create textures when creating
- // Layers (which may happens before we render something)
- getDefaultDisplayDeviceLocked()->makeCurrent(mEGLDisplay, mEGLContext);
-
mEventControlThread = new EventControlThread(this);
mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
@@ -1218,11 +1220,16 @@
sLastResyncAttempted = now;
}
-void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
- nsecs_t timestamp) {
+void SurfaceFlinger::onVsyncReceived(int32_t sequenceId,
+ hwc2_display_t displayId, int64_t timestamp) {
Mutex::Autolock lock(mStateLock);
- // Ignore any vsyncs from the non-active hardware composer.
- if (composer != mHwc) {
+ // Ignore any vsyncs from a previous hardware composer.
+ if (sequenceId != mComposerSequenceId) {
+ return;
+ }
+
+ int32_t type;
+ if (!mHwc->onVsync(displayId, timestamp, &type)) {
return;
}
@@ -1230,7 +1237,7 @@
{ // Scope for the lock
Mutex::Autolock _l(mHWVsyncLock);
- if (type == 0 && mPrimaryHWVsyncEnabled) {
+ if (type == DisplayDevice::DISPLAY_PRIMARY && mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
}
@@ -1248,7 +1255,7 @@
}
void SurfaceFlinger::createDefaultDisplayDevice() {
- const int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+ const DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_PRIMARY;
wp<IBinder> token = mBuiltinDisplays[type];
// All non-virtual displays are currently considered secure.
@@ -1279,28 +1286,49 @@
mDisplays.add(token, hw);
setActiveColorModeInternal(hw, HAL_COLOR_MODE_NATIVE);
hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);
+
+ // Add the primary display token to mDrawingState so we don't try to
+ // recreate the DisplayDevice for the primary display.
+ mDrawingState.displays.add(token, DisplayDeviceState(type, true));
+
+ // make the GLContext current so that we can create textures when creating
+ // Layers (which may happens before we render something)
+ hw->makeCurrent(mEGLDisplay, mEGLContext);
}
-void SurfaceFlinger::onHotplugReceived(HWComposer* composer, int32_t disp, bool connected) {
- ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
+ hwc2_display_t display, HWC2::Connection connection,
+ bool primaryDisplay) {
+ ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)",
+ sequenceId, display,
+ connection == HWC2::Connection::Connected ?
+ "connected" : "disconnected",
+ primaryDisplay ? "primary" : "external");
- if (composer->isUsingVrComposer()) {
- // We handle initializing the primary display device for the VR
- // window manager hwc explicitly at the time of transition.
- if (disp != DisplayDevice::DISPLAY_PRIMARY) {
- ALOGE("External displays are not supported by the vr hardware composer.");
+ // Only lock if we're not on the main thread. This function is normally
+ // called on a hwbinder thread, but for the primary display it's called on
+ // the main thread with the state lock already held, so don't attempt to
+ // acquire it here.
+ ConditionalLock lock(mStateLock,
+ std::this_thread::get_id() != mMainThreadId);
+
+ if (primaryDisplay) {
+ mHwc->onHotplug(display, connection);
+ if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) {
+ createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
}
- return;
- }
-
- if (disp == DisplayDevice::DISPLAY_PRIMARY) {
- Mutex::Autolock lock(mStateLock);
- createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
createDefaultDisplayDevice();
} else {
+ if (sequenceId != mComposerSequenceId) {
+ return;
+ }
+ if (mHwc->isUsingVrComposer()) {
+ ALOGE("External displays are not supported by the vr hardware composer.");
+ return;
+ }
+ mHwc->onHotplug(display, connection);
auto type = DisplayDevice::DISPLAY_EXTERNAL;
- Mutex::Autolock _l(mStateLock);
- if (connected) {
+ if (connection == HWC2::Connection::Connected) {
createBuiltinDisplayLocked(type);
} else {
mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
@@ -1312,46 +1340,31 @@
}
}
-void SurfaceFlinger::onInvalidateReceived(HWComposer* composer) {
+void SurfaceFlinger::onRefreshReceived(int sequenceId,
+ hwc2_display_t /*display*/) {
Mutex::Autolock lock(mStateLock);
- if (composer == mHwc) {
- repaintEverything();
- } else {
- // This isn't from our current hardware composer. If it's a callback
- // from the real composer, forward the refresh request to vr
- // flinger. Otherwise ignore it.
- if (!composer->isUsingVrComposer()) {
- mVrFlinger->OnHardwareComposerRefresh();
- }
+ if (sequenceId != mComposerSequenceId) {
+ return;
}
+ repaintEverything();
}
void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
ATRACE_CALL();
+ Mutex::Autolock lock(mStateLock);
getHwComposer().setVsyncEnabled(disp,
enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
}
// Note: it is assumed the caller holds |mStateLock| when this is called
-void SurfaceFlinger::resetHwcLocked() {
+void SurfaceFlinger::resetDisplayState() {
disableHardwareVsync(true);
- clearHwcLayers(mDrawingState.layersSortedByZ);
- clearHwcLayers(mCurrentState.layersSortedByZ);
- for (size_t disp = 0; disp < mDisplays.size(); ++disp) {
- clearHwcLayers(mDisplays[disp]->getVisibleLayersSortedByZ());
- }
// Clear the drawing state so that the logic inside of
// handleTransactionLocked will fire. It will determine the delta between
// mCurrentState and mDrawingState and re-apply all changes when we make the
// transition.
mDrawingState.displays.clear();
- // Release virtual display hwcId during vr mode transition.
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
- if (displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL) {
- displayDevice->disconnect(getHwComposer());
- }
- }
+ eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
mDisplays.clear();
}
@@ -1363,57 +1376,54 @@
return;
}
- if (vrFlingerRequestsDisplay && !mVrHwc) {
- // Construct new HWComposer without holding any locks.
- mVrHwc = new HWComposer("vr");
-
- // Set up the event handlers. This step is neccessary to initialize the internal state of
- // the hardware composer object properly. Our callbacks are designed such that if they are
- // triggered between now and the point where the display is properly re-initialized, they
- // will not have any effect, so this is safe to do here, before the lock is aquired.
- mVrHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
- ALOGV("Vr HWC created");
+ if (vrFlingerRequestsDisplay && !mHwc->getComposer()->isRemote()) {
+ ALOGE("Vr flinger is only supported for remote hardware composer"
+ " service connections. Ignoring request to transition to vr"
+ " flinger.");
+ mVrFlingerRequestsDisplay = false;
+ return;
}
Mutex::Autolock _l(mStateLock);
- if (vrFlingerRequestsDisplay) {
- resetHwcLocked();
+ int currentDisplayPowerMode = getDisplayDeviceLocked(
+ mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode();
- mHwc = mVrHwc;
- mVrFlinger->GrantDisplayOwnership();
-
- } else {
+ if (!vrFlingerRequestsDisplay) {
mVrFlinger->SeizeDisplayOwnership();
+ }
- resetHwcLocked();
+ resetDisplayState();
+ mHwc.reset(); // Delete the current instance before creating the new one
+ mHwc.reset(new HWComposer(
+ vrFlingerRequestsDisplay ? "vr" : mHwcServiceName));
+ mHwc->registerCallback(this, ++mComposerSequenceId);
- mHwc = mRealHwc;
+ LOG_ALWAYS_FATAL_IF(!mHwc->getComposer()->isRemote(),
+ "Switched to non-remote hardware composer");
+
+ if (vrFlingerRequestsDisplay) {
+ mVrFlinger->GrantDisplayOwnership();
+ } else {
enableHardwareVsync();
}
mVisibleRegionsDirty = true;
invalidateHwcGeometry();
- // Explicitly re-initialize the primary display. This is because some other
- // parts of this class rely on the primary display always being available.
- createDefaultDisplayDevice();
-
// Re-enable default display.
- sp<LambdaMessage> requestMessage = new LambdaMessage([&]() {
- sp<DisplayDevice> hw(getDisplayDevice(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
- setPowerModeInternal(hw, HWC_POWER_MODE_NORMAL);
+ sp<DisplayDevice> hw(getDisplayDeviceLocked(
+ mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
+ setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true);
- // Reset the timing values to account for the period of the swapped in HWC
- const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
- const nsecs_t period = activeConfig->getVsyncPeriod();
- mAnimFrameTracker.setDisplayRefreshPeriod(period);
+ // Reset the timing values to account for the period of the swapped in HWC
+ const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+ const nsecs_t period = activeConfig->getVsyncPeriod();
+ mAnimFrameTracker.setDisplayRefreshPeriod(period);
- // Use phase of 0 since phase is not known.
- // Use latency of 0, which will snap to the ideal latency.
- setCompositorTimingSnapped(0, period, 0);
- });
- postMessageAsync(requestMessage);
+ // Use phase of 0 since phase is not known.
+ // Use latency of 0, which will snap to the ideal latency.
+ setCompositorTimingSnapped(0, period, 0);
android_atomic_or(1, &mRepaintEverything);
setTransactionFlags(eDisplayTransactionNeeded);
@@ -1749,15 +1759,14 @@
} else {
// Clear out the HWC layer if this layer was
// previously visible, but no longer is
- layer->setHwcLayer(displayDevice->getHwcDisplayId(),
- nullptr);
+ layer->destroyHwcLayer(
+ displayDevice->getHwcDisplayId());
}
} else {
// WM changes displayDevice->layerStack upon sleep/awake.
// Here we make sure we delete the HWC layers even if
// WM changed their layer stack.
- layer->setHwcLayer(displayDevice->getHwcDisplayId(),
- nullptr);
+ layer->destroyHwcLayer(displayDevice->getHwcDisplayId());
}
});
}
@@ -1872,10 +1881,7 @@
for (size_t i = 0; i < currentLayers.size(); i++) {
const auto& layer = currentLayers[i];
if (!layer->hasHwcLayer(hwcId)) {
- auto hwcLayer = mHwc->createLayer(hwcId);
- if (hwcLayer) {
- layer->setHwcLayer(hwcId, std::move(hwcLayer));
- } else {
+ if (!layer->createHwcLayer(mHwc.get(), hwcId)) {
layer->forceClientComposition(hwcId);
continue;
}
@@ -2161,7 +2167,7 @@
if (state.surface != NULL) {
// Allow VR composer to use virtual displays.
- if (mUseHwcVirtualDisplays || mHwc == mVrHwc) {
+ if (mUseHwcVirtualDisplays || mHwc->isUsingVrComposer()) {
int width = 0;
int status = state.surface->query(
NATIVE_WINDOW_WIDTH, &width);
@@ -3285,7 +3291,8 @@
d.height = 0;
displays.add(d);
setTransactionState(state, displays, 0);
- setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
+ setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL,
+ /*stateLockHeld*/ false);
const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
const nsecs_t period = activeConfig->getVsyncPeriod();
@@ -3311,7 +3318,7 @@
}
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
- int mode) {
+ int mode, bool stateLockHeld) {
ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
this);
int32_t type = hw->getDisplayType();
@@ -3328,7 +3335,7 @@
}
if (mInterceptor.isEnabled()) {
- Mutex::Autolock _l(mStateLock);
+ ConditionalLock lock(mStateLock, !stateLockHeld);
ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
if (idx < 0) {
ALOGW("Surface Interceptor SavePowerMode: invalid display token");
@@ -3414,7 +3421,8 @@
ALOGW("Attempt to set power mode = %d for virtual display",
mMode);
} else {
- mFlinger.setPowerModeInternal(hw, mMode);
+ mFlinger.setPowerModeInternal(
+ hw, mMode, /*stateLockHeld*/ false);
}
return true;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5123b58..058f4a1 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,13 +60,20 @@
#include "SurfaceInterceptor.h"
#include "StartPropertySetThread.h"
+#ifdef USE_HWC2
+#include "DisplayHardware/HWC2.h"
#include "DisplayHardware/HWComposer.h"
+#else
+#include "DisplayHardware/HWComposer_hwc1.h"
+#endif
+
#include "Effects/Daltonizer.h"
#include <map>
#include <mutex>
#include <queue>
#include <string>
+#include <thread>
#include <utility>
namespace android {
@@ -99,7 +106,11 @@
class SurfaceFlinger : public BnSurfaceComposer,
private IBinder::DeathRecipient,
+#ifdef USE_HWC2
+ private HWC2::ComposerCallback
+#else
private HWComposer::EventHandler
+#endif
{
public:
@@ -314,11 +325,20 @@
virtual void onFirstRef();
/* ------------------------------------------------------------------------
- * HWComposer::EventHandler interface
+ * HWC2::ComposerCallback / HWComposer::EventHandler interface
*/
- virtual void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp);
- virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected);
- virtual void onInvalidateReceived(HWComposer* composer);
+#ifdef USE_HWC2
+ void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+ int64_t timestamp) override;
+ void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+ HWC2::Connection connection,
+ bool primaryDisplay) override;
+ void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
+#else
+ void onVSyncReceived(HWComposer* composer, int type, nsecs_t timestamp) override;
+ void onHotplugReceived(HWComposer* composer, int disp, bool connected) override;
+ void onInvalidateReceived(HWComposer* composer) override;
+#endif
/* ------------------------------------------------------------------------
* Message handling
@@ -333,7 +353,12 @@
// called on the main thread in response to setActiveConfig()
void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode);
// called on the main thread in response to setPowerMode()
+#ifdef USE_HWC2
+ void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode,
+ bool stateLockHeld);
+#else
void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
+#endif
// Called on the main thread in response to setActiveColorMode()
void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
@@ -591,13 +616,7 @@
/* ------------------------------------------------------------------------
* VrFlinger
*/
- template<typename T>
- void clearHwcLayers(const T& layers) {
- for (size_t i = 0; i < layers.size(); ++i) {
- layers[i]->clearHwcLayers();
- }
- }
- void resetHwcLocked();
+ void resetDisplayState();
// Check to see if we should handoff to vr flinger.
void updateVrFlinger();
@@ -624,13 +643,14 @@
// access must be protected by mInvalidateLock
volatile int32_t mRepaintEverything;
- // current, real and vr hardware composers.
- HWComposer* mHwc;
+ // The current hardware composer interface. When switching into and out of
+ // vr, our HWComposer instance will be recreated.
+ std::unique_ptr<HWComposer> mHwc;
+
#ifdef USE_HWC2
- HWComposer* mRealHwc;
- HWComposer* mVrHwc;
const std::string mHwcServiceName; // "default" for real use, something else for testing.
#endif
+
// constant members (no synchronization needed for access)
RenderEngine* mRenderEngine;
nsecs_t mBootTime;
@@ -644,10 +664,6 @@
EGLDisplay mEGLDisplay;
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
-#ifdef USE_HWC2
- std::unique_ptr<dvr::VrFlinger> mVrFlinger;
-#endif
-
// Can only accessed from the main thread, these members
// don't need synchronization
State mDrawingState{LayerVector::StateSet::Drawing};
@@ -769,8 +785,14 @@
status_t CheckTransactCodeCredentials(uint32_t code);
#ifdef USE_HWC2
+ std::unique_ptr<dvr::VrFlinger> mVrFlinger;
std::atomic<bool> mVrFlingerRequestsDisplay;
static bool useVrFlinger;
+ std::thread::id mMainThreadId;
+ // The composer sequence id is a monotonically increasing integer that we
+ // use to differentiate callbacks from different hardware composer
+ // instances. Each hardware composer instance gets a different sequence id.
+ int32_t mComposerSequenceId;
#endif
float mSaturation = 1.0f;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 7aaa42a..78a04e0 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -535,8 +535,8 @@
// Initialize the H/W composer object. There may or may not be an
// actual hardware composer underneath.
- mHwc = new HWComposer(this,
- *static_cast<HWComposer::EventHandler *>(this));
+ mHwc.reset(new HWComposer(this,
+ *static_cast<HWComposer::EventHandler *>(this)));
// get a RenderEngine for the given display / config (can't fail)
mRenderEngine = RenderEngine::create(mEGLDisplay,