Merge "libgui: Prevent segfaulting in abandoned ConsumerBase" into nyc-dev
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index e01aa3f..facf300 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -53,6 +53,8 @@
const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
+const char* k_coreServiceCategory = "core_services";
+const char* k_coreServicesProp = "ro.atrace.core.services";
typedef enum { OPT, REQ } requiredness ;
@@ -100,6 +102,7 @@
{ "pm", "Package Manager", ATRACE_TAG_PACKAGE_MANAGER, { } },
{ "ss", "System Server", ATRACE_TAG_SYSTEM_SERVER, { } },
{ "database", "Database", ATRACE_TAG_DATABASE, { } },
+ { k_coreServiceCategory, "Core services", 0, { } },
{ "sched", "CPU Scheduling", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
@@ -331,6 +334,12 @@
// or /sys/ files.
static bool isCategorySupported(const TracingCategory& category)
{
+ if (strcmp(category.name, k_coreServiceCategory) == 0) {
+ char value[PROPERTY_VALUE_MAX];
+ property_get(k_coreServicesProp, value, "");
+ return strlen(value) != 0;
+ }
+
bool ok = category.tags != 0;
for (int i = 0; i < MAX_SYS_FILES; i++) {
const char* path = category.sysfiles[i].path;
@@ -727,7 +736,24 @@
}
}
ok &= setTagsProperty(tags);
- ok &= setAppCmdlineProperty(g_debugAppCmdLine);
+
+ bool coreServicesTagEnabled = false;
+ for (int i = 0; i < NELEM(k_categories); i++) {
+ if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
+ coreServicesTagEnabled = g_categoryEnables[i];
+ }
+ }
+
+ std::string packageList(g_debugAppCmdLine);
+ if (coreServicesTagEnabled) {
+ char value[PROPERTY_VALUE_MAX];
+ property_get(k_coreServicesProp, value, "");
+ if (!packageList.empty()) {
+ packageList += ",";
+ }
+ packageList += value;
+ }
+ ok &= setAppCmdlineProperty(packageList.data());
ok &= pokeBinderServices();
// Disable all the sysfs enables. This is done as a separate loop from
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 60118a8..90ef277 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -1022,16 +1022,15 @@
}
static fd_t open_profile_dir(const std::string& profile_dir) {
- struct stat buffer;
- if (TEMP_FAILURE_RETRY(lstat(profile_dir.c_str(), &buffer)) == -1) {
- PLOG(ERROR) << "Failed to lstat profile_dir: " << profile_dir;
- return -1;
- }
-
fd_t profile_dir_fd = TEMP_FAILURE_RETRY(open(profile_dir.c_str(),
O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW));
if (profile_dir_fd < 0) {
- PLOG(ERROR) << "Failed to open profile_dir: " << profile_dir;
+ // In a multi-user environment, these directories can be created at
+ // different points and it's possible we'll attempt to open a profile
+ // dir before it exists.
+ if (errno != ENOENT) {
+ PLOG(ERROR) << "Failed to open profile_dir: " << profile_dir;
+ }
}
return profile_dir_fd;
}
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 635020e..6e92a47 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -93,6 +93,12 @@
LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
endif
+ifeq ($(BOARD_ENABLE_GPU_PROTECTED_CONTENT),true)
+ LOCAL_CFLAGS += -DENABLE_GPU_PROTECTED_CONTENT=true
+else
+ LOCAL_CFLAGS += -DENABLE_GPU_PROTECTED_CONTENT=false
+endif
+
include $(BUILD_SHARED_LIBRARY)
ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 052de3d..ba34eb6 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -130,11 +130,18 @@
for (int s : mActiveBuffers) {
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
- result.appendFormat("%s%s[%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
- prefix, (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
- buffer.get(), mSlots[s].mBufferState.string(), buffer->handle,
- buffer->width, buffer->height, buffer->stride, buffer->format);
-
+ // A dequeued buffer might be null if it's still being allocated
+ if (buffer.get()) {
+ result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
+ "[%4ux%4u:%4u,%3X]\n", prefix,
+ (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
+ buffer.get(), mSlots[s].mBufferState.string(),
+ buffer->handle, buffer->width, buffer->height,
+ buffer->stride, buffer->format);
+ } else {
+ result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
+ buffer.get(), mSlots[s].mBufferState.string());
+ }
}
for (int s : mFreeBuffers) {
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index cebcc4e..a06c7b5 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -135,7 +135,8 @@
bool atEnd = (cropExtLen+1) < extsLen &&
!strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
- return equal || atStart || atEnd || inMiddle;
+ return ENABLE_GPU_PROTECTED_CONTENT &&
+ (equal || atStart || atEnd || inMiddle);
}
static bool hasEglProtectedContent() {
@@ -419,21 +420,6 @@
return err;
}
- // For investigating b/27674961
- if (mEglSlots[slot].mEglImage == nullptr) {
- ALOGE("If you see this message in a log please post the log to "
- "b/27674961");
- ALOGE("slot = %d, mCurrentTexture = %d, mCurrentTextureImage = %p",
- slot, mCurrentTexture, mCurrentTextureImage.get());
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- ALOGE("mEglSlots[%d].mEglImage = %p", i,
- mEglSlots[i].mEglImage.get());
- }
- String8 dump;
- dumpLocked(dump, "");
- ALOGE("%s", dump.string());
- }
-
// Ensure we have a valid EglImageKHR for the slot, creating an EglImage
// if nessessary, for the gralloc buffer currently in the slot in
// ConsumerBase.
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 918faa8..90f27d1 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -67,7 +67,8 @@
egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config,
EGLNativeWindowType win, EGLSurface surface,
egl_connection_t const* cnx) :
- egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx)
+ egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
+ connected(true)
{
if (win) {
getDisplay()->onWindowSurfaceCreated();
@@ -77,14 +78,27 @@
egl_surface_t::~egl_surface_t() {
ANativeWindow* const window = win.get();
if (window != NULL) {
+ disconnect();
+ getDisplay()->onWindowSurfaceDestroyed();
+ }
+}
+
+void egl_surface_t::disconnect() {
+ ANativeWindow* const window = win.get();
+ if (window != NULL && connected) {
native_window_set_buffers_format(window, 0);
if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
ALOGW("EGLNativeWindowType %p disconnect failed", window);
}
- getDisplay()->onWindowSurfaceDestroyed();
+ connected = false;
}
}
+void egl_surface_t::terminate() {
+ disconnect();
+ egl_object_t::terminate();
+}
+
// ----------------------------------------------------------------------------
egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index 17a8304..673b7da 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -45,6 +45,7 @@
protected:
virtual ~egl_object_t();
+ virtual void terminate();
public:
egl_object_t(egl_display_t* display);
@@ -55,7 +56,6 @@
inline egl_display_t* getDisplay() const { return display; }
private:
- void terminate();
static bool get(egl_display_t const* display, egl_object_t* object);
public:
@@ -127,6 +127,7 @@
class egl_surface_t : public egl_object_t {
protected:
~egl_surface_t();
+ void terminate() override;
public:
typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
@@ -138,6 +139,9 @@
EGLConfig config;
sp<ANativeWindow> win;
egl_connection_t const* cnx;
+private:
+ bool connected;
+ void disconnect();
};
class egl_context_t: public egl_object_t {
diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp
index dba7211..754b603 100644
--- a/services/sensorservice/RecentEventLogger.cpp
+++ b/services/sensorservice/RecentEventLogger.cpp
@@ -76,7 +76,8 @@
std::lock_guard<std::mutex> lk(mLock);
if (mRecentEvents.size()) {
- *event = mRecentEvents[mRecentEvents.size()-1].mEvent;
+ // Index 0 contains the latest event emplace()'ed
+ *event = mRecentEvents[0].mEvent;
return true;
} else {
return false;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index f7678e4..f898ada 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -96,6 +96,7 @@
mDestroyLayer(nullptr),
mGetActiveConfig(nullptr),
mGetChangedCompositionTypes(nullptr),
+ mGetColorModes(nullptr),
mGetDisplayAttribute(nullptr),
mGetDisplayConfigs(nullptr),
mGetDisplayName(nullptr),
@@ -107,6 +108,8 @@
mPresentDisplay(nullptr),
mSetActiveConfig(nullptr),
mSetClientTarget(nullptr),
+ mSetColorMode(nullptr),
+ mSetColorTransform(nullptr),
mSetOutputBuffer(nullptr),
mSetPowerMode(nullptr),
mSetVsyncEnabled(nullptr),
@@ -117,6 +120,7 @@
mSetLayerBlendMode(nullptr),
mSetLayerColor(nullptr),
mSetLayerCompositionType(nullptr),
+ mSetLayerDataspace(nullptr),
mSetLayerDisplayFrame(nullptr),
mSetLayerPlaneAlpha(nullptr),
mSetLayerSidebandStream(nullptr),
@@ -337,6 +341,8 @@
mGetActiveConfig)) return;
if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
mGetChangedCompositionTypes)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
+ mGetColorModes)) return;
if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
mGetDisplayAttribute)) return;
if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
@@ -359,6 +365,10 @@
mSetActiveConfig)) return;
if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
mSetClientTarget)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
+ mSetColorMode)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
+ mSetColorTransform)) return;
if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
mSetOutputBuffer)) return;
if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
@@ -381,6 +391,8 @@
mSetLayerColor)) return;
if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
mSetLayerCompositionType)) return;
+ if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
+ mSetLayerDataspace)) return;
if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
mSetLayerDisplayFrame)) return;
if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
@@ -551,6 +563,28 @@
return Error::None;
}
+Error Display::getColorModes(std::vector<int32_t>* outModes) const
+{
+ uint32_t numModes = 0;
+ int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
+ &numModes, nullptr);
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ return error;
+ }
+
+ std::vector<int32_t> modes(numModes);
+ intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
+ modes.data());
+ error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ return error;
+ }
+
+ std::swap(*outModes, modes);
+ return Error::None;
+}
+
std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const
{
std::vector<std::shared_ptr<const Config>> configs;
@@ -752,6 +786,20 @@
return static_cast<Error>(intError);
}
+Error Display::setColorMode(int32_t mode)
+{
+ int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
+ return static_cast<Error>(intError);
+}
+
+Error Display::setColorTransform(const android::mat4& matrix,
+ android_color_transform_t hint)
+{
+ int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
+ matrix.asArray(), static_cast<int32_t>(hint));
+ return static_cast<Error>(intError);
+}
+
Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer,
const sp<Fence>& releaseFence)
{
@@ -965,6 +1013,14 @@
return static_cast<Error>(intError);
}
+Error Layer::setDataspace(android_dataspace_t dataspace)
+{
+ auto intDataspace = static_cast<int32_t>(dataspace);
+ int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
+ mDisplayId, mId, intDataspace);
+ return static_cast<Error>(intError);
+}
+
Error Layer::setDisplayFrame(const Rect& frame)
{
hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 967add0..e40602f 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -24,6 +24,7 @@
#undef HWC2_USE_CPP11
#include <ui/HdrCapabilities.h>
+#include <ui/mat4.h>
#include <utils/Log.h>
#include <utils/StrongPointer.h>
@@ -143,6 +144,7 @@
HWC2_PFN_DESTROY_LAYER mDestroyLayer;
HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig;
HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes;
+ HWC2_PFN_GET_COLOR_MODES mGetColorModes;
HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute;
HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs;
HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName;
@@ -154,6 +156,8 @@
HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget;
+ HWC2_PFN_SET_COLOR_MODE mSetColorMode;
+ HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform;
HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer;
HWC2_PFN_SET_POWER_MODE mSetPowerMode;
HWC2_PFN_SET_VSYNC_ENABLED mSetVsyncEnabled;
@@ -166,6 +170,7 @@
HWC2_PFN_SET_LAYER_BLEND_MODE mSetLayerBlendMode;
HWC2_PFN_SET_LAYER_COLOR mSetLayerColor;
HWC2_PFN_SET_LAYER_COMPOSITION_TYPE mSetLayerCompositionType;
+ HWC2_PFN_SET_LAYER_DATASPACE mSetLayerDataspace;
HWC2_PFN_SET_LAYER_DISPLAY_FRAME mSetLayerDisplayFrame;
HWC2_PFN_SET_LAYER_PLANE_ALPHA mSetLayerPlaneAlpha;
HWC2_PFN_SET_LAYER_SIDEBAND_STREAM mSetLayerSidebandStream;
@@ -273,6 +278,8 @@
std::shared_ptr<const Config>* outConfig) const;
[[clang::warn_unused_result]] Error getChangedCompositionTypes(
std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
+ [[clang::warn_unused_result]] Error getColorModes(
+ std::vector<int32_t>* outModes) const;
// Doesn't call into the HWC2 device, so no errors are possible
std::vector<std::shared_ptr<const Config>> getConfigs() const;
@@ -297,6 +304,9 @@
buffer_handle_t target,
const android::sp<android::Fence>& acquireFence,
android_dataspace_t dataspace);
+ [[clang::warn_unused_result]] Error setColorMode(int32_t mode);
+ [[clang::warn_unused_result]] Error setColorTransform(
+ const android::mat4& matrix, android_color_transform_t hint);
[[clang::warn_unused_result]] Error setOutputBuffer(
const android::sp<android::GraphicBuffer>& buffer,
const android::sp<android::Fence>& releaseFence);
@@ -360,6 +370,8 @@
[[clang::warn_unused_result]] Error setBlendMode(BlendMode mode);
[[clang::warn_unused_result]] Error setColor(hwc_color_t color);
[[clang::warn_unused_result]] Error setCompositionType(Composition type);
+ [[clang::warn_unused_result]] Error setDataspace(
+ android_dataspace_t dataspace);
[[clang::warn_unused_result]] Error setDisplayFrame(
const android::Rect& frame);
[[clang::warn_unused_result]] Error setPlaneAlpha(float alpha);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 6ebcdfe..a90e074 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -75,6 +75,8 @@
using namespace HWC2;
+static constexpr Attribute ColorTransform = static_cast<Attribute>(6);
+
namespace android {
void HWC2On1Adapter::DisplayContentsDeleter::operator()(
@@ -214,6 +216,10 @@
displayHook<decltype(&Display::getChangedCompositionTypes),
&Display::getChangedCompositionTypes, uint32_t*,
hwc2_layer_t*, int32_t*>);
+ case FunctionDescriptor::GetColorModes:
+ return asFP<HWC2_PFN_GET_COLOR_MODES>(
+ displayHook<decltype(&Display::getColorModes),
+ &Display::getColorModes, uint32_t*, int32_t*>);
case FunctionDescriptor::GetDisplayAttribute:
return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
getDisplayAttributeHook);
@@ -261,6 +267,12 @@
displayHook<decltype(&Display::setClientTarget),
&Display::setClientTarget, buffer_handle_t, int32_t,
int32_t>);
+ case FunctionDescriptor::SetColorMode:
+ return asFP<HWC2_PFN_SET_COLOR_MODE>(
+ displayHook<decltype(&Display::setColorMode),
+ &Display::setColorMode, int32_t>);
+ case FunctionDescriptor::SetColorTransform:
+ return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
case FunctionDescriptor::SetOutputBuffer:
return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
displayHook<decltype(&Display::setOutputBuffer),
@@ -299,6 +311,8 @@
case FunctionDescriptor::SetLayerCompositionType:
return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
setLayerCompositionTypeHook);
+ case FunctionDescriptor::SetLayerDataspace:
+ return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook);
case FunctionDescriptor::SetLayerDisplayFrame:
return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
layerHook<decltype(&Layer::setDisplayFrame),
@@ -554,6 +568,7 @@
mVsyncEnabled(Vsync::Invalid),
mClientTarget(),
mOutputBuffer(),
+ mHasColorTransform(false),
mLayers(),
mHwc1LayerMap() {}
@@ -681,6 +696,22 @@
return Error::None;
}
+Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes,
+ int32_t* outModes)
+{
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ if (!outModes) {
+ *outNumModes = mColorModes.size();
+ return Error::None;
+ }
+ uint32_t numModes = std::min(*outNumModes,
+ static_cast<uint32_t>(mColorModes.size()));
+ std::copy_n(mColorModes.cbegin(), numModes, outModes);
+ *outNumModes = numModes;
+ return Error::None;
+}
+
Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs,
hwc2_config_t* outConfigs)
{
@@ -827,14 +858,27 @@
if (!config) {
return Error::BadConfig;
}
- mActiveConfig = config;
- if (mDevice.mHwc1MinorVersion >= 4) {
- int error = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
- mHwc1Id, static_cast<int>(configId));
- ALOGE_IF(error != 0,
- "setActiveConfig: Failed to set active config on HWC1 (%d)",
- error);
+ if (config == mActiveConfig) {
+ return Error::None;
}
+
+ if (mDevice.mHwc1MinorVersion >= 4) {
+ uint32_t hwc1Id = 0;
+ auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id);
+ if (error != Error::None) {
+ return error;
+ }
+
+ int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+ mHwc1Id, static_cast<int>(hwc1Id));
+ if (intError != 0) {
+ ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)",
+ intError);
+ return Error::BadConfig;
+ }
+ mActiveConfig = config;
+ }
+
return Error::None;
}
@@ -850,6 +894,48 @@
return Error::None;
}
+Error HWC2On1Adapter::Display::setColorMode(int32_t mode)
+{
+ std::unique_lock<std::recursive_mutex> lock (mStateMutex);
+
+ ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode);
+
+ if (mode == mActiveColorMode) {
+ return Error::None;
+ }
+ if (mColorModes.count(mode) == 0) {
+ ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode);
+ return Error::Unsupported;
+ }
+
+ uint32_t hwc1Config = 0;
+ auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
+ if (error != Error::None) {
+ return error;
+ }
+
+ ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
+ int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+ mHwc1Id, hwc1Config);
+ if (intError != 0) {
+ ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
+ return Error::Unsupported;
+ }
+
+ mActiveColorMode = mode;
+ return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint)
+{
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+ ALOGV("%" PRIu64 "] setColorTransform(%d)", mId,
+ static_cast<int32_t>(hint));
+ mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY);
+ return Error::None;
+}
+
Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer,
int32_t releaseFence)
{
@@ -1002,7 +1088,17 @@
return Error::None;
}
-static constexpr uint32_t ATTRIBUTES[] = {
+static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
+ HWC_DISPLAY_VSYNC_PERIOD,
+ HWC_DISPLAY_WIDTH,
+ HWC_DISPLAY_HEIGHT,
+ HWC_DISPLAY_DPI_X,
+ HWC_DISPLAY_DPI_Y,
+ HWC_DISPLAY_COLOR_TRANSFORM,
+ HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = {
HWC_DISPLAY_VSYNC_PERIOD,
HWC_DISPLAY_WIDTH,
HWC_DISPLAY_HEIGHT,
@@ -1010,9 +1106,23 @@
HWC_DISPLAY_DPI_Y,
HWC_DISPLAY_NO_ATTRIBUTE,
};
-static constexpr size_t NUM_ATTRIBUTES = sizeof(ATTRIBUTES) / sizeof(uint32_t);
-static constexpr uint32_t ATTRIBUTE_MAP[] = {
+static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR =
+ sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t);
+static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR),
+ "Attribute tables have unexpected sizes");
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = {
+ 6, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+ 0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+ 1, // HWC_DISPLAY_WIDTH = 2,
+ 2, // HWC_DISPLAY_HEIGHT = 3,
+ 3, // HWC_DISPLAY_DPI_X = 4,
+ 4, // HWC_DISPLAY_DPI_Y = 5,
+ 5, // HWC_DISPLAY_COLOR_TRANSFORM = 6,
+};
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = {
5, // HWC_DISPLAY_NO_ATTRIBUTE = 0
0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
1, // HWC_DISPLAY_WIDTH = 2,
@@ -1024,7 +1134,14 @@
template <uint32_t attribute>
static constexpr bool attributesMatch()
{
- return ATTRIBUTES[ATTRIBUTE_MAP[attribute]] == attribute;
+ bool match = (attribute ==
+ ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]);
+ if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) {
+ return match;
+ }
+
+ return match && (attribute ==
+ ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]);
}
static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(),
"Tables out of sync");
@@ -1032,6 +1149,8 @@
static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync");
static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync");
static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(),
+ "Tables out of sync");
void HWC2On1Adapter::Display::populateConfigs()
{
@@ -1052,52 +1171,74 @@
for (size_t c = 0; c < numConfigs; ++c) {
uint32_t hwc1ConfigId = configs[c];
- hwc2_config_t id = static_cast<hwc2_config_t>(mConfigs.size());
- mConfigs.emplace_back(
- std::make_shared<Config>(*this, id, hwc1ConfigId));
- auto& config = mConfigs[id];
+ auto newConfig = std::make_shared<Config>(*this);
- int32_t values[NUM_ATTRIBUTES] = {};
- mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device, mHwc1Id,
- hwc1ConfigId, ATTRIBUTES, values);
-
- config->setAttribute(Attribute::VsyncPeriod,
- values[ATTRIBUTE_MAP[HWC_DISPLAY_VSYNC_PERIOD]]);
- config->setAttribute(Attribute::Width,
- values[ATTRIBUTE_MAP[HWC_DISPLAY_WIDTH]]);
- config->setAttribute(Attribute::Height,
- values[ATTRIBUTE_MAP[HWC_DISPLAY_HEIGHT]]);
- config->setAttribute(Attribute::DpiX,
- values[ATTRIBUTE_MAP[HWC_DISPLAY_DPI_X]]);
- config->setAttribute(Attribute::DpiY,
- values[ATTRIBUTE_MAP[HWC_DISPLAY_DPI_Y]]);
-
- ALOGV("Found config: %s", config->toString().c_str());
- }
-
- ALOGV("Getting active config");
- if (mDevice.mHwc1Device->getActiveConfig != nullptr) {
- auto activeConfig = mDevice.mHwc1Device->getActiveConfig(
- mDevice.mHwc1Device, mHwc1Id);
- if (activeConfig >= 0) {
- ALOGV("Setting active config to %d", activeConfig);
- mActiveConfig = mConfigs[activeConfig];
+ int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {};
+ bool hasColor = true;
+ auto result = mDevice.mHwc1Device->getDisplayAttributes(
+ mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId,
+ ATTRIBUTES_WITH_COLOR, values);
+ if (result != 0) {
+ mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device,
+ mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values);
+ hasColor = false;
}
- } else {
- ALOGV("getActiveConfig is null, choosing config 0");
- mActiveConfig = mConfigs[0];
+
+ auto attributeMap = hasColor ?
+ ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR;
+
+ newConfig->setAttribute(Attribute::VsyncPeriod,
+ values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]);
+ newConfig->setAttribute(Attribute::Width,
+ values[attributeMap[HWC_DISPLAY_WIDTH]]);
+ newConfig->setAttribute(Attribute::Height,
+ values[attributeMap[HWC_DISPLAY_HEIGHT]]);
+ newConfig->setAttribute(Attribute::DpiX,
+ values[attributeMap[HWC_DISPLAY_DPI_X]]);
+ newConfig->setAttribute(Attribute::DpiY,
+ values[attributeMap[HWC_DISPLAY_DPI_Y]]);
+ if (hasColor) {
+ newConfig->setAttribute(ColorTransform,
+ values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
+ }
+
+ // We can only do this after attempting to read the color transform
+ newConfig->setHwc1Id(hwc1ConfigId);
+
+ for (auto& existingConfig : mConfigs) {
+ if (existingConfig->merge(*newConfig)) {
+ ALOGV("Merged config %d with existing config %u: %s",
+ hwc1ConfigId, existingConfig->getId(),
+ existingConfig->toString().c_str());
+ newConfig.reset();
+ break;
+ }
+ }
+
+ // If it wasn't merged with any existing config, add it to the end
+ if (newConfig) {
+ newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+ ALOGV("Found new config %u: %s", newConfig->getId(),
+ newConfig->toString().c_str());
+ mConfigs.emplace_back(std::move(newConfig));
+ }
}
+
+ initializeActiveConfig();
+ populateColorModes();
}
void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height)
{
std::unique_lock<std::recursive_mutex> lock(mStateMutex);
- mConfigs.emplace_back(std::make_shared<Config>(*this, 0, 0));
+ mConfigs.emplace_back(std::make_shared<Config>(*this));
auto& config = mConfigs[0];
config->setAttribute(Attribute::Width, static_cast<int32_t>(width));
config->setAttribute(Attribute::Height, static_cast<int32_t>(height));
+ config->setHwc1Id(0);
+ config->setId(0);
mActiveConfig = config;
}
@@ -1286,6 +1427,12 @@
}
}
+bool HWC2On1Adapter::Display::hasColorTransform() const
+{
+ std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+ return mHasColorTransform;
+}
+
static std::string hwc1CompositionString(int32_t type)
{
switch (type) {
@@ -1475,17 +1622,23 @@
output << "Power mode: " << to_string(mPowerMode) << " ";
output << "Vsync: " << to_string(mVsyncEnabled) << '\n';
- output << " " << mConfigs.size() << " Config" <<
- (mConfigs.size() == 1 ? "" : "s") << " (* Active)\n";
- for (const auto& config : mConfigs) {
- if (config == mActiveConfig) {
- output << " * " << config->toString();
+ output << " Color modes [active]:";
+ for (const auto& mode : mColorModes) {
+ if (mode == mActiveColorMode) {
+ output << " [" << mode << ']';
} else {
- output << " " << config->toString();
+ output << " " << mode;
}
}
output << '\n';
+ output << " " << mConfigs.size() << " Config" <<
+ (mConfigs.size() == 1 ? "" : "s") << " (* active)\n";
+ for (const auto& config : mConfigs) {
+ output << (config == mActiveConfig ? " * " : " ");
+ output << config->toString(true) << '\n';
+ }
+
output << " " << mLayers.size() << " Layer" <<
(mLayers.size() == 1 ? "" : "s") << '\n';
for (const auto& layer : mLayers) {
@@ -1523,15 +1676,85 @@
return mAttributes.at(attribute);
}
-std::string HWC2On1Adapter::Display::Config::toString() const
+void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id)
+{
+ int32_t colorTransform = getAttribute(ColorTransform);
+ mHwc1Ids.emplace(colorTransform, id);
+}
+
+bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const
+{
+ for (const auto& idPair : mHwc1Ids) {
+ if (id == idPair.second) {
+ return true;
+ }
+ }
+ return false;
+}
+
+int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+ uint32_t id) const
+{
+ for (const auto& idPair : mHwc1Ids) {
+ if (id == idPair.second) {
+ return idPair.first;
+ }
+ }
+ return -1;
+}
+
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode,
+ uint32_t* outId) const
+{
+ for (const auto& idPair : mHwc1Ids) {
+ if (mode == idPair.first) {
+ *outId = idPair.second;
+ return Error::None;
+ }
+ }
+ ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId);
+ return Error::BadParameter;
+}
+
+bool HWC2On1Adapter::Display::Config::merge(const Config& other)
+{
+ auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height,
+ HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX,
+ HWC2::Attribute::DpiY};
+ for (auto attribute : attributes) {
+ if (getAttribute(attribute) != other.getAttribute(attribute)) {
+ return false;
+ }
+ }
+ int32_t otherColorTransform = other.getAttribute(ColorTransform);
+ if (mHwc1Ids.count(otherColorTransform) != 0) {
+ ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
+ "identical", mHwc1Ids.at(otherColorTransform),
+ other.mHwc1Ids.at(otherColorTransform));
+ return false;
+ }
+ mHwc1Ids.emplace(otherColorTransform,
+ other.mHwc1Ids.at(otherColorTransform));
+ return true;
+}
+
+std::set<int32_t> HWC2On1Adapter::Display::Config::getColorTransforms() const
+{
+ std::set<int32_t> colorTransforms;
+ for (const auto& idPair : mHwc1Ids) {
+ colorTransforms.emplace(idPair.first);
+ }
+ return colorTransforms;
+}
+
+std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const
{
std::string output;
const size_t BUFFER_SIZE = 100;
char buffer[BUFFER_SIZE] = {};
auto writtenBytes = snprintf(buffer, BUFFER_SIZE,
- "[%u] %u x %u", mHwcId,
- mAttributes.at(HWC2::Attribute::Width),
+ "%u x %u", mAttributes.at(HWC2::Attribute::Width),
mAttributes.at(HWC2::Attribute::Height));
output.append(buffer, writtenBytes);
@@ -1552,6 +1775,31 @@
output.append(buffer, writtenBytes);
}
+ std::memset(buffer, 0, BUFFER_SIZE);
+ if (splitLine) {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ "\n HWC1 ID/Color transform:");
+ } else {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE,
+ ", HWC1 ID/Color transform:");
+ }
+ output.append(buffer, writtenBytes);
+
+
+ for (const auto& id : mHwc1Ids) {
+ int32_t colorTransform = id.first;
+ uint32_t hwc1Id = id.second;
+ std::memset(buffer, 0, BUFFER_SIZE);
+ if (colorTransform == mDisplay.mActiveColorMode) {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
+ colorTransform);
+ } else {
+ writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
+ colorTransform);
+ }
+ output.append(buffer, writtenBytes);
+ }
+
return output;
}
@@ -1564,6 +1812,49 @@
return mConfigs[configId];
}
+void HWC2On1Adapter::Display::populateColorModes()
+{
+ mColorModes = mConfigs[0]->getColorTransforms();
+ for (const auto& config : mConfigs) {
+ std::set<int32_t> intersection;
+ auto configModes = config->getColorTransforms();
+ std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
+ configModes.cbegin(), configModes.cend(),
+ std::inserter(intersection, intersection.begin()));
+ std::swap(intersection, mColorModes);
+ }
+}
+
+void HWC2On1Adapter::Display::initializeActiveConfig()
+{
+ if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
+ ALOGV("getActiveConfig is null, choosing config 0");
+ mActiveConfig = mConfigs[0];
+ mActiveColorMode = -1;
+ return;
+ }
+
+ auto activeConfig = mDevice.mHwc1Device->getActiveConfig(
+ mDevice.mHwc1Device, mHwc1Id);
+ if (activeConfig >= 0) {
+ for (const auto& config : mConfigs) {
+ if (config->hasHwc1Id(activeConfig)) {
+ ALOGV("Setting active config to %d for HWC1 config %u",
+ config->getId(), activeConfig);
+ mActiveConfig = config;
+ mActiveColorMode = config->getColorModeForHwc1Id(activeConfig);
+ break;
+ }
+ }
+ if (!mActiveConfig) {
+ ALOGV("Unable to find active HWC1 config %u, defaulting to "
+ "config 0", activeConfig);
+ mActiveConfig = mConfigs[0];
+ mActiveColorMode = -1;
+ }
+ }
+}
+
void HWC2On1Adapter::Display::reallocateHwc1Contents()
{
// Allocate an additional layer for the framebuffer target
@@ -1688,6 +1979,7 @@
mZ(0),
mReleaseFence(),
mHwc1Id(0),
+ mHasUnsupportedDataspace(false),
mHasUnsupportedPlaneAlpha(false) {}
bool HWC2On1Adapter::SortLayersByZ::operator()(
@@ -1748,6 +2040,12 @@
return Error::None;
}
+Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t dataspace)
+{
+ mHasUnsupportedDataspace = (dataspace != HAL_DATASPACE_UNKNOWN);
+ return Error::None;
+}
+
Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame)
{
mDisplayFrame.setPending(frame);
@@ -1976,7 +2274,11 @@
void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer,
bool applyAllState)
{
- if (mHasUnsupportedPlaneAlpha) {
+ // HWC1 never supports color transforms or dataspaces and only sometimes
+ // supports plane alpha (depending on the version). These require us to drop
+ // some or all layers to client composition.
+ if (mHasUnsupportedDataspace || mHasUnsupportedPlaneAlpha ||
+ mDisplay.hasColorTransform()) {
hwc1Layer.compositionType = HWC_FRAMEBUFFER;
hwc1Layer.flags = HWC_SKIP_LAYER;
return;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index 6fdb184..caeb188 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -191,6 +191,7 @@
HWC2::Attribute attribute, int32_t* outValue);
HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
hwc2_layer_t* outLayers, int32_t* outTypes);
+ HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
HWC2::Error getConfigs(uint32_t* outNumConfigs,
hwc2_config_t* outConfigIds);
HWC2::Error getDozeSupport(int32_t* outSupport);
@@ -208,6 +209,8 @@
HWC2::Error setActiveConfig(hwc2_config_t configId);
HWC2::Error setClientTarget(buffer_handle_t target,
int32_t acquireFence, int32_t dataspace);
+ HWC2::Error setColorMode(int32_t mode);
+ HWC2::Error setColorTransform(android_color_transform_t hint);
HWC2::Error setOutputBuffer(buffer_handle_t buffer,
int32_t releaseFence);
HWC2::Error setPowerMode(HWC2::PowerMode mode);
@@ -231,34 +234,50 @@
void addRetireFence(int fenceFd);
void addReleaseFences(const hwc_display_contents_1& hwcContents);
+ bool hasColorTransform() const;
+
std::string dump() const;
private:
class Config {
public:
- Config(Display& display, hwc2_config_t id, uint32_t hwcId)
+ Config(Display& display)
: mDisplay(display),
- mId(id),
- mHwcId(hwcId),
mAttributes() {}
bool isOnDisplay(const Display& display) const {
return display.getId() == mDisplay.getId();
}
- hwc2_config_t getId() const { return mId; }
- uint32_t getHwcId() const { return mHwcId; }
-
void setAttribute(HWC2::Attribute attribute, int32_t value);
int32_t getAttribute(HWC2::Attribute attribute) const;
- std::string toString() const;
+ void setHwc1Id(uint32_t id);
+ bool hasHwc1Id(uint32_t id) const;
+ int32_t getColorModeForHwc1Id(uint32_t id) const;
+ HWC2::Error getHwc1IdForColorMode(int32_t mode,
+ uint32_t* outId) const;
+
+ void setId(hwc2_config_t id) { mId = id; }
+ hwc2_config_t getId() const { return mId; }
+
+ // Attempts to merge two configs that differ only in color
+ // mode. Returns whether the merge was successful
+ bool merge(const Config& other);
+
+ std::set<int32_t> getColorTransforms() const;
+
+ // splitLine divides the output into two lines suitable for
+ // dumpsys SurfaceFlinger
+ std::string toString(bool splitLine = false) const;
private:
Display& mDisplay;
- const hwc2_config_t mId;
- const uint32_t mHwcId;
+ hwc2_config_t mId;
std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
+
+ // Maps from color transform to HWC1 config ID
+ std::unordered_map<int32_t, uint32_t> mHwc1Ids;
};
class Changes {
@@ -312,6 +331,9 @@
std::shared_ptr<const Config>
getConfig(hwc2_config_t configId) const;
+ void populateColorModes();
+ void initializeActiveConfig();
+
void reallocateHwc1Contents();
void assignHwc1LayerIds();
@@ -349,8 +371,11 @@
std::unique_ptr<Changes> mChanges;
int32_t mHwc1Id;
+
std::vector<std::shared_ptr<Config>> mConfigs;
std::shared_ptr<const Config> mActiveConfig;
+ std::set<int32_t> mColorModes;
+ int32_t mActiveColorMode;
std::string mName;
HWC2::DisplayType mType;
HWC2::PowerMode mPowerMode;
@@ -359,6 +384,8 @@
FencedBuffer mClientTarget;
FencedBuffer mOutputBuffer;
+ bool mHasColorTransform;
+
std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap;
};
@@ -390,6 +417,17 @@
config, attribute, outValue);
}
+ static int32_t setColorTransformHook(hwc2_device_t* device,
+ hwc2_display_t display, const float* /*matrix*/,
+ int32_t /*android_color_transform_t*/ intHint) {
+ // We intentionally throw away the matrix, because if the hint is
+ // anything other than IDENTITY, we have to fall back to client
+ // composition anyway
+ auto hint = static_cast<android_color_transform_t>(intHint);
+ return callDisplayFunction(device, display, &Display::setColorTransform,
+ hint);
+ }
+
static int32_t setPowerModeHook(hwc2_device_t* device,
hwc2_display_t display, int32_t intMode) {
auto mode = static_cast<HWC2::PowerMode>(intMode);
@@ -467,6 +505,7 @@
HWC2::Error setBlendMode(HWC2::BlendMode mode);
HWC2::Error setColor(hwc_color_t color);
HWC2::Error setCompositionType(HWC2::Composition type);
+ HWC2::Error setDataspace(android_dataspace_t dataspace);
HWC2::Error setDisplayFrame(hwc_rect_t frame);
HWC2::Error setPlaneAlpha(float alpha);
HWC2::Error setSidebandStream(const native_handle_t* stream);
@@ -523,6 +562,7 @@
DeferredFence mReleaseFence;
size_t mHwc1Id;
+ bool mHasUnsupportedDataspace;
bool mHasUnsupportedPlaneAlpha;
};
@@ -562,6 +602,13 @@
&Layer::setCompositionType, type);
}
+ static int32_t setLayerDataspaceHook(hwc2_device_t* device,
+ hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) {
+ auto dataspace = static_cast<android_dataspace_t>(intDataspace);
+ return callLayerFunction(device, display, layer, &Layer::setDataspace,
+ dataspace);
+ }
+
static int32_t setLayerTransformHook(hwc2_device_t* device,
hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) {
auto transform = static_cast<HWC2::Transform>(intTransform);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c640f58..96252f3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -178,6 +178,9 @@
for (auto& point : mRemoteSyncPoints) {
point->setTransactionApplied();
}
+ for (auto& point : mLocalSyncPoints) {
+ point->setFrameAvailable();
+ }
mFlinger->deleteTextureAsync(mTextureName);
mFrameTracker.logAndResetStats(mName);
}
@@ -1478,6 +1481,17 @@
(type >= Transform::SCALE));
}
+ // If the layer is hidden, signal and clear out all local sync points so
+ // that transactions for layers depending on this layer's frames becoming
+ // visible are not blocked
+ if (c.flags & layer_state_t::eLayerHidden) {
+ Mutex::Autolock lock(mLocalSyncPointMutex);
+ for (auto& point : mLocalSyncPoints) {
+ point->setFrameAvailable();
+ }
+ mLocalSyncPoints.clear();
+ }
+
// Commit the transaction
commitTransaction(c);
return flags;