Use a separate hwcomposer hidl instance for vr flinger
Improve robustness of vr flinger <--> surface flinger switching by
having vr flinger use a separate hardware composer hidl instance instead
of sharing the instance with surface flinger. Sharing the hardware
composer instance has proven to be error prone, with situations where
both the vr flinger thread and surface flinger main thread would write
to the composer at the same time, causing hard to diagnose
crashes (b/62925812).
Instead of sharing the hardware composer instance, when switching to vr
flinger we now delete the existing instance, create a new instance
directed to the vr hardware composer shim, and vr flinger creates its
own composer instance connected to the real hardware composer. By
creating a separate composer instance for vr flinger, crashes like the
ones found in b/62925812 are no longer impossible.
Most of the changes in this commit are related to enabling surface
flinger to delete HWComposer instances cleanly. In particular:
- Previously the hardware composer callbacks (which come in on a
hwbinder thread) would land in HWC2::Device and bubble up to the
SurfaceFlinger object. But with the new behavior the HWC2::Device
might be dead or in the process of being destroyed, so instead we have
SurfaceFlinger receive the composer callbacks directly, and forward
them to HWComposer and HWC2::Device. We include a composer id field in
the callbacks so surface flinger can ignore stale callbacks from dead
composer instances.
- Object ownership for HWC2::Display and HWC2::Layer was shared by
passing around shared_ptrs to these objects. This was problematic
because they referenced and used the HWC2::Device, which can now be
destroyed when switching to vr flinger. Simplify the ownership model
by having HWC2::Device own (via unique_ptr<>) instances of
HWC2::Display, which owns (again via unique_ptr<>) instances of
HWC2::Layer. In cases where we previously passed std::shared_ptr<> to
HWC2::Display or HWC2::Layer, instead pass non-owning HWC2::Display*
and HWC2::Layer* pointers. This ensures clean composer instance
teardown with no stale references to the deleted HWC2::Device.
- When the hardware composer instance is destroyed and the HWC2::Layers
are removed, notify the android::Layer via a callback, so it can
remove the HWC2::Layer from its internal table of hardware composer
layers. This removes the burden to explicitly clear out all hardware
composer layers when switching to vr flinger, which has been a source
of bugs.
- We were missing an mStateLock lock in
SurfaceFlinger::setVsyncEnabled(), which was necessary to ensure we
were setting vsync on the correct hardware composer instance. Once
that lock was added, surface flinger would sometimes deadlock when
transitioning to vr flinger, because the surface flinger main thread
would acquire mStateLock and then EventControlThread::mMutex, whereas
the event control thread would acquire the locks in the opposite
order. The changes in EventControlThread.cpp are to ensure it doesn't
hold a lock on EventControlThread::mMutex while calling
setVsyncEnabled(), to avoid the deadlock.
I found that without a composer callback registered in vr flinger the
vsync_event file wasn't getting vsync timestamps written, so vr flinger
would get stuck in an infinite loop trying to parse a vsync
timestamp. Since we need to have a callback anyway I changed the code in
hardware_composer.cpp to get the vsync timestamp from the callback, as
surface flinger does. I confirmed the timestamps are the same with
either method, and this lets us remove some extra code for extracting
the vsync timestamp that (probably) wasn't compatible with all devices
we want to run on anyway. I also added a timeout to the vysnc wait so
we'll see an error message in the log if we fail to wait for vsync,
instead of looping forever.
Bug: 62925812
Test: - Confirmed surface flinger <--> vr flinger switching is robust by
switching devices on and off hundreds of times and observing no
hardware composer related issues, surface flinger crashes, or
hardware composer service crashes.
- Confirmed 2d in vr works as before by going through the OOBE flow on a
standalone. This also exercises virtual display creation and usage
through surface flinger.
- Added logs to confirm perfect layer/display cleanup when destroying
hardware composer instances.
- Tested normal 2d phone usage to confirm basic layer create/destroy
functionality works as before.
- Monitored surface flinger file descriptor usage across dozens of
surface flinger <--> vr flinger transitions and observed no file
descriptor leaks.
- Confirmed the HWC1 code path still compiles.
- Ran the surface flinger tests and confirmed there are no new test
failures.
- Ran the hardware composer hidl in passthrough mode on a Marlin and
confirmed it works.
- Ran CTS tests for virtual displays and confirmed they all pass.
- Tested Android Auto and confirmed basic graphics functionality still
works.
Change-Id: Ibf1dbdf3ec15ca66467697d711f8109dc9e46a47
Merged-In: I17dc0e060bfb5cb447ffbaa573b279fc6d2d8bd1
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,