Merge "Add SurfaceInterceptor initial implementation"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index bf99017..4319dc2 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -35,6 +35,7 @@
#include <unistd.h>
#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
#include <cutils/properties.h>
#include "private/android_filesystem_config.h"
@@ -43,7 +44,6 @@
#include <cutils/log.h>
#include "dumpstate.h"
-#include "ScopedFd.h"
#include "ziparchive/zip_writer.h"
#include <openssl/sha.h>
@@ -629,8 +629,9 @@
}
bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
- ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
- if (fd.get() == -1) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK
+ | O_CLOEXEC)));
+ if (fd == -1) {
MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
return false;
}
@@ -1069,9 +1070,9 @@
}
static std::string SHA256_file_hash(std::string filepath) {
- ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
- | O_NOFOLLOW)));
- if (fd.get() == -1) {
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK
+ | O_CLOEXEC | O_NOFOLLOW)));
+ if (fd == -1) {
MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
return NULL;
}
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
index 7915fc2..881ab07 100644
--- a/cmds/servicemanager/binder.h
+++ b/cmds/servicemanager/binder.h
@@ -5,7 +5,7 @@
#define _BINDER_H_
#include <sys/ioctl.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
struct binder_state;
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 42ed148..a06fb4a 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -27,7 +27,7 @@
#include <utils/String16.h>
#include <utils/Vector.h>
#include <utils/Flattenable.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
#include <binder/IInterface.h>
#include <binder/Parcelable.h>
@@ -246,6 +246,7 @@
const char* readCString() const;
String8 readString8() const;
+ status_t readString8(String8* pArg) const;
String16 readString16() const;
status_t readString16(String16* pArg) const;
status_t readString16(std::unique_ptr<String16>* pArg) const;
@@ -586,10 +587,12 @@
if (ret == OK) {
*val = interface_cast<T>(tmp);
- if (val->get() == nullptr) {
- return UNKNOWN_ERROR;
+ if (val->get() == nullptr && tmp.get() != nullptr) {
+ ret = UNKNOWN_ERROR;
}
}
+
+ return ret;
}
template<typename T, typename U>
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index fe4b1fa..2bfb649 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -79,7 +79,8 @@
// needed gralloc buffers.
static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
- const sp<IGraphicBufferAlloc>& allocator = NULL);
+ const sp<IGraphicBufferAlloc>& allocator = NULL,
+ bool consumerIsSurfaceFlinger = false);
private:
BufferQueue(); // Create through createBufferQueue
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 838632c..d2bd32e 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -29,7 +29,7 @@
public:
friend class BufferQueue; // Needed to access binderDied
- BufferQueueProducer(const sp<BufferQueueCore>& core);
+ BufferQueueProducer(const sp<BufferQueueCore>& core, bool consumerIsSurfaceFlinger = false);
virtual ~BufferQueueProducer();
// requestBuffer returns the GraphicBuffer for slot N.
@@ -225,6 +225,10 @@
uint32_t mStickyTransform;
+ // This controls whether the GraphicBuffer pointer in the BufferItem is
+ // cleared after being queued
+ bool mConsumerIsSurfaceFlinger;
+
// This saves the fence from the last queueBuffer, such that the
// next queueBuffer call can throttle buffer production. The prior
// queueBuffer's fence is not nessessarily available elsewhere,
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index 1efcf3c..9b0d919 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -49,7 +49,8 @@
// previous frames are pending. Frames queued while in synchronous mode
// always trigger the callback. The item passed to the callback will contain
// all of the information about the queued frame except for its
- // GraphicBuffer pointer, which will always be null.
+ // GraphicBuffer pointer, which will always be null (except if the consumer
+ // is SurfaceFlinger).
//
// This is called without any lock held and can be called concurrently
// by multiple threads.
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index c62bc58..9353042 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -339,20 +339,19 @@
void setSurfaceDamage(const Region& damage) { surfaceDamage = damage; }
private:
- int64_t timestamp;
- int isAutoTimestamp;
- android_dataspace dataSpace;
+ int64_t timestamp{0};
+ int isAutoTimestamp{0};
+ android_dataspace dataSpace{HAL_DATASPACE_UNKNOWN};
Rect crop;
- int scalingMode;
- uint32_t transform;
- uint32_t stickyTransform;
+ int scalingMode{0};
+ uint32_t transform{0};
+ uint32_t stickyTransform{0};
sp<Fence> fence;
Region surfaceDamage;
};
// QueueBufferOutput must be a POD structure
struct __attribute__ ((__packed__)) QueueBufferOutput {
- inline QueueBufferOutput() { }
// outWidth - filled with default width applied to the buffer
// outHeight - filled with default height applied to the buffer
// outTransformHint - filled with default transform applied to the buffer
@@ -379,10 +378,10 @@
nextFrameNumber = inNextFrameNumber;
}
private:
- uint32_t width;
- uint32_t height;
- uint32_t transformHint;
- uint32_t numPendingBuffers;
+ uint32_t width{0};
+ uint32_t height{0};
+ uint32_t transformHint{0};
+ uint32_t numPendingBuffers{0};
uint64_t nextFrameNumber{0};
};
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index af26721..74a4123 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -137,6 +137,12 @@
* should be used */
virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
+ virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+ Vector<android_color_mode_t>* outColorModes) = 0;
+ virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) = 0;
+ virtual status_t setActiveColorMode(const sp<IBinder>& display,
+ android_color_mode_t colorMode) = 0;
+
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
*/
@@ -193,6 +199,9 @@
SET_POWER_MODE,
GET_DISPLAY_STATS,
GET_HDR_CAPABILITIES,
+ GET_DISPLAY_COLOR_MODES,
+ GET_ACTIVE_COLOR_MODE,
+ SET_ACTIVE_COLOR_MODE,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 95e8b70..b8ee331 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -83,6 +83,16 @@
// returned by getDisplayInfo
static status_t setActiveConfig(const sp<IBinder>& display, int id);
+ // Gets the list of supported color modes for the given display
+ static status_t getDisplayColorModes(const sp<IBinder>& display,
+ Vector<android_color_mode_t>* outColorModes);
+
+ // Gets the active color mode for the given display
+ static android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+
+ // Sets the active color mode for the given display
+ static status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
+
/* Triggers screen on/off or low power mode and waits for it to complete */
static void setDisplayPowerMode(const sp<IBinder>& display, int mode);
diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index eeacf43..bb974b3 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -516,6 +516,9 @@
* but must signal the event no more than 40ms after the first frame in the batch. The frames
* must be ordered by system timestamp inside and across batches.
*
+ * The component shall signal the render-timestamp of the very first frame (as well as the
+ * first frame after each flush) unbatched (with nData1 set to 1) within 5 msec.
+ *
* If component is doing frame-rate conversion, it must signal the render time of each
* converted frame, and must interpolate media timestamps for in-between frames.
*
@@ -753,15 +756,21 @@
When the command is "OMX_CommandStateSet" the component will queue a
state transition to the new state idenfied in nParam.
+ The component shall transition from executing to loaded state within 500 msec.
+
When the command is "OMX_CommandFlush", to flush a port's buffer queues,
the command will force the component to return all buffers NOT CURRENTLY
BEING PROCESSED to the application, in the order in which the buffers
were received.
+ The component shall finish flusing each port within 5 msec.
+
When the command is "OMX_CommandPortDisable" or
"OMX_CommandPortEnable", the component's port (given by the value of
nParam) will be stopped or restarted.
+ The component shall finish disabling/reenabling each port within 5 msec.
+
When the command "OMX_CommandMarkBuffer" is used to mark a buffer, the
pCmdData will point to a OMX_MARKTYPE structure containing the component
handle of the component to examine the buffer chain for the mark. nParam1
diff --git a/include/private/binder/binder_module.h b/include/private/binder/binder_module.h
index a8dd64f..2f11622 100644
--- a/include/private/binder/binder_module.h
+++ b/include/private/binder/binder_module.h
@@ -24,7 +24,7 @@
/* obtain structures and constants from the kernel header */
#include <sys/ioctl.h>
-#include <linux/binder.h>
+#include <linux/android/binder.h>
#ifdef __cplusplus
} // namespace android
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 4b3fcc6..292dd3b 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -74,10 +74,10 @@
status_t read(const Parcel& input);
struct matrix22_t {
- float dsdx;
- float dtdx;
- float dsdy;
- float dtdy;
+ float dsdx{0};
+ float dtdx{0};
+ float dsdy{0};
+ float dtdy{0};
};
sp<IBinder> surface;
uint32_t what;
diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h
index ad73ee7..842806e 100644
--- a/include/ui/DisplayInfo.h
+++ b/include/ui/DisplayInfo.h
@@ -26,17 +26,16 @@
namespace android {
struct DisplayInfo {
- uint32_t w;
- uint32_t h;
- float xdpi;
- float ydpi;
- float fps;
- float density;
- uint8_t orientation;
- bool secure;
- nsecs_t appVsyncOffset;
- nsecs_t presentationDeadline;
- int colorTransform;
+ uint32_t w{0};
+ uint32_t h{0};
+ float xdpi{0};
+ float ydpi{0};
+ float fps{0};
+ float density{0};
+ uint8_t orientation{0};
+ bool secure{false};
+ nsecs_t appVsyncOffset{0};
+ nsecs_t presentationDeadline{0};
};
/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
diff --git a/include/ui/DisplayStatInfo.h b/include/ui/DisplayStatInfo.h
index 0549a83..09543ec 100644
--- a/include/ui/DisplayStatInfo.h
+++ b/include/ui/DisplayStatInfo.h
@@ -22,8 +22,8 @@
namespace android {
struct DisplayStatInfo {
- nsecs_t vsyncTime;
- nsecs_t vsyncPeriod;
+ nsecs_t vsyncTime{0};
+ nsecs_t vsyncPeriod{0};
};
}; // namespace android
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index 74bad7a..b57b02a 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -44,20 +44,21 @@
LOCAL_PATH:= $(call my-dir)
+binder_cflags := -Wall -Wextra -Werror
+ifneq ($(TARGET_USES_64_BIT_BINDER),true)
+ifneq ($(TARGET_IS_64_BIT),true)
+binder_cflags += -DBINDER_IPC_32BIT=1
+endif
+endif
+
include $(CLEAR_VARS)
LOCAL_MODULE := libbinder
LOCAL_SHARED_LIBRARIES := libbase liblog libcutils libutils
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS := libbase libutils
-LOCAL_CLANG := true
LOCAL_SANITIZE := integer
LOCAL_SRC_FILES := $(sources)
-ifneq ($(TARGET_USES_64_BIT_BINDER),true)
-ifneq ($(TARGET_IS_64_BIT),true)
-LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
-endif
-endif
-LOCAL_CFLAGS += -Werror
+LOCAL_CFLAGS := $(binder_cflags)
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
@@ -65,10 +66,5 @@
LOCAL_STATIC_LIBRARIES := libbase libutils
LOCAL_EXPORT_STATIC_LIBRARY_HEADERS := libbase libutils
LOCAL_SRC_FILES := $(sources)
-ifneq ($(TARGET_USES_64_BIT_BINDER),true)
-ifneq ($(TARGET_IS_64_BIT),true)
-LOCAL_CFLAGS += -DBINDER_IPC_32BIT=1
-endif
-endif
-LOCAL_CFLAGS += -Werror
+LOCAL_CFLAGS := $(binder_cflags)
include $(BUILD_STATIC_LIBRARY)
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index c4d47ca..7ce2a31 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -237,6 +237,10 @@
// XXX can't add virtuals until binaries are updated.
//return shellCommand(in, out, err, args, resultReceiver);
+ (void)in;
+ (void)out;
+ (void)err;
+
if (resultReceiver != NULL) {
resultReceiver->send(INVALID_OPERATION);
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 5a2492e..d566456 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1842,13 +1842,37 @@
String8 Parcel::readString8() const
{
- int32_t size = readInt32();
- // watch for potential int overflow adding 1 for trailing NUL
- if (size > 0 && size < INT32_MAX) {
- const char* str = (const char*)readInplace(size+1);
- if (str) return String8(str, size);
+ String8 retString;
+ status_t status = readString8(&retString);
+ if (status != OK) {
+ // We don't care about errors here, so just return an empty string.
+ return String8();
}
- return String8();
+ return retString;
+}
+
+status_t Parcel::readString8(String8* pArg) const
+{
+ int32_t size;
+ status_t status = readInt32(&size);
+ if (status != OK) {
+ return status;
+ }
+ // watch for potential int overflow from size+1
+ if (size < 0 || size >= INT32_MAX) {
+ return BAD_VALUE;
+ }
+ // |writeString8| writes nothing for empty string.
+ if (size == 0) {
+ *pArg = String8();
+ return OK;
+ }
+ const char* str = (const char*)readInplace(size + 1);
+ if (str == NULL) {
+ return BAD_VALUE;
+ }
+ pArg->setTo(str, size);
+ return OK;
}
String16 Parcel::readString16() const
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index 5c5651c..e7078ba 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -420,7 +420,6 @@
RETURN_IF_FAILED(parcel->readInt32(&num_entries));
for (; num_entries > 0; --num_entries) {
- size_t start_pos = parcel->dataPosition();
String16 key;
int32_t value_type;
RETURN_IF_FAILED(parcel->readString16(&key));
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 5e3924a..2ffeb0d 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -66,6 +66,9 @@
addAligned(size, mIsDroppable);
addAligned(size, mAcquireCalled);
addAligned(size, mTransformToDisplayInverse);
+ addAligned(size, mAutoRefresh);
+ addAligned(size, mQueuedBuffer);
+ addAligned(size, mIsStale);
return size;
}
@@ -151,6 +154,9 @@
writeAligned(buffer, size, mIsDroppable);
writeAligned(buffer, size, mAcquireCalled);
writeAligned(buffer, size, mTransformToDisplayInverse);
+ writeAligned(buffer, size, mAutoRefresh);
+ writeAligned(buffer, size, mQueuedBuffer);
+ writeAligned(buffer, size, mIsStale);
return NO_ERROR;
}
@@ -207,6 +213,9 @@
readAligned(buffer, size, mIsDroppable);
readAligned(buffer, size, mAcquireCalled);
readAligned(buffer, size, mTransformToDisplayInverse);
+ readAligned(buffer, size, mAutoRefresh);
+ readAligned(buffer, size, mQueuedBuffer);
+ readAligned(buffer, size, mIsStale);
return NO_ERROR;
}
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 6de98f5..47f5eba 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -72,7 +72,8 @@
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
- const sp<IGraphicBufferAlloc>& allocator) {
+ const sp<IGraphicBufferAlloc>& allocator,
+ bool consumerIsSurfaceFlinger) {
LOG_ALWAYS_FATAL_IF(outProducer == NULL,
"BufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
@@ -82,7 +83,7 @@
LOG_ALWAYS_FATAL_IF(core == NULL,
"BufferQueue: failed to create BufferQueueCore");
- sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
+ sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
LOG_ALWAYS_FATAL_IF(producer == NULL,
"BufferQueue: failed to create BufferQueueProducer");
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index b574f9d..a9eac90 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -92,6 +92,7 @@
mSharedBufferSlot(INVALID_BUFFER_SLOT),
mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
HAL_DATASPACE_UNKNOWN),
+ mLastQueuedSlot(INVALID_BUFFER_SLOT),
mUniqueId(getUniqueId())
{
if (allocator == NULL) {
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index b7b56f0..3411dca 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -41,12 +41,15 @@
namespace android {
-BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core) :
+BufferQueueProducer::BufferQueueProducer(const sp<BufferQueueCore>& core,
+ bool consumerIsSurfaceFlinger) :
mCore(core),
mSlots(core->mSlots),
mConsumerName(),
mStickyTransform(0),
+ mConsumerIsSurfaceFlinger(consumerIsSurfaceFlinger),
mLastQueueBufferFence(Fence::NO_FENCE),
+ mLastQueuedTransform(0),
mCallbackMutex(),
mNextCallbackTicket(0),
mCurrentCallbackTicket(0),
@@ -912,9 +915,14 @@
VALIDATE_CONSISTENCY();
} // Autolock scope
- // Don't send the GraphicBuffer through the callback, and don't send
- // the slot number, since the consumer shouldn't need it
- item.mGraphicBuffer.clear();
+ // It is okay not to clear the GraphicBuffer when the consumer is SurfaceFlinger because
+ // it is guaranteed that the BufferQueue is inside SurfaceFlinger's process and
+ // there will be no Binder call
+ if (!mConsumerIsSurfaceFlinger) {
+ item.mGraphicBuffer.clear();
+ }
+
+ // Don't send the slot number through the callback since the consumer shouldn't need it
item.mSlot = BufferItem::INVALID_BUFFER_SLOT;
// Call back without the main BufferQueue lock held, but with the callback
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
index d4d4702..ac6ace6 100644
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ b/libs/gui/IGraphicBufferAlloc.cpp
@@ -101,7 +101,7 @@
uint32_t height = data.readUint32();
PixelFormat format = static_cast<PixelFormat>(data.readInt32());
uint32_t usage = data.readUint32();
- status_t error;
+ status_t error = NO_ERROR;
sp<GraphicBuffer> result =
createGraphicBuffer(width, height, format, usage, &error);
reply->writeInt32(error);
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 015945a..0a8e6a5 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -32,6 +32,8 @@
#include <private/gui/LayerState.h>
+#include <system/graphics.h>
+
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
#include <ui/HdrCapabilities.h>
@@ -269,6 +271,82 @@
return reply.readInt32();
}
+ virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+ Vector<android_color_mode_t>* outColorModes) {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayColorModes failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayColorModes failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_COLOR_MODES, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayColorModes failed to transact: %d", result);
+ return result;
+ }
+ result = static_cast<status_t>(reply.readInt32());
+ if (result == NO_ERROR) {
+ size_t numModes = reply.readUint32();
+ outColorModes->clear();
+ outColorModes->resize(numModes);
+ for (size_t i = 0; i < numModes; ++i) {
+ outColorModes->replaceAt(static_cast<android_color_mode_t>(reply.readInt32()), i);
+ }
+ }
+ return result;
+ }
+
+ virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display) {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("getActiveColorMode failed to writeInterfaceToken: %d", result);
+ return static_cast<android_color_mode_t>(result);
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("getActiveColorMode failed to writeStrongBinder: %d", result);
+ return static_cast<android_color_mode_t>(result);
+ }
+ result = remote()->transact(BnSurfaceComposer::GET_ACTIVE_COLOR_MODE, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("getActiveColorMode failed to transact: %d", result);
+ return static_cast<android_color_mode_t>(result);
+ }
+ return static_cast<android_color_mode_t>(reply.readInt32());
+ }
+
+ virtual status_t setActiveColorMode(const sp<IBinder>& display,
+ android_color_mode_t colorMode) {
+ Parcel data, reply;
+ status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ ALOGE("setActiveColorMode failed to writeInterfaceToken: %d", result);
+ return result;
+ }
+ result = data.writeStrongBinder(display);
+ if (result != NO_ERROR) {
+ ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result);
+ return result;
+ }
+ result = data.writeInt32(colorMode);
+ if (result != NO_ERROR) {
+ ALOGE("setActiveColorMode failed to writeInt32: %d", result);
+ return result;
+ }
+ result = remote()->transact(BnSurfaceComposer::SET_ACTIVE_COLOR_MODE, data, &reply);
+ if (result != NO_ERROR) {
+ ALOGE("setActiveColorMode failed to transact: %d", result);
+ return result;
+ }
+ return static_cast<status_t>(reply.readInt32());
+ }
+
virtual status_t clearAnimationFrameStats() {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -469,6 +547,56 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case GET_DISPLAY_COLOR_MODES: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ Vector<android_color_mode_t> colorModes;
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getDisplayColorModes failed to readStrongBinder: %d", result);
+ return result;
+ }
+ result = getDisplayColorModes(display, &colorModes);
+ reply->writeInt32(result);
+ if (result == NO_ERROR) {
+ reply->writeUint32(static_cast<uint32_t>(colorModes.size()));
+ for (size_t i = 0; i < colorModes.size(); ++i) {
+ reply->writeInt32(colorModes[i]);
+ }
+ }
+ return NO_ERROR;
+ }
+ case GET_ACTIVE_COLOR_MODE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
+ return result;
+ }
+ android_color_mode_t colorMode = getActiveColorMode(display);
+ result = reply->writeInt32(static_cast<int32_t>(colorMode));
+ return result;
+ }
+ case SET_ACTIVE_COLOR_MODE: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ sp<IBinder> display = nullptr;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
+ return result;
+ }
+ int32_t colorModeInt = 0;
+ result = data.readInt32(&colorModeInt);
+ if (result != NO_ERROR) {
+ ALOGE("setActiveColorMode failed to readInt32: %d", result);
+ return result;
+ }
+ result = setActiveColorMode(display,
+ static_cast<android_color_mode_t>(colorModeInt));
+ result = reply->writeInt32(result);
+ return result;
+ }
case CLEAR_ANIMATION_FRAME_STATS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
status_t result = clearAnimationFrameStats();
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 059223d..1c460e8 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -29,6 +29,8 @@
#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
+#include <system/graphics.h>
+
#include <ui/DisplayInfo.h>
#include <gui/CpuConsumer.h>
@@ -771,6 +773,20 @@
return ComposerService::getComposerService()->setActiveConfig(display, id);
}
+status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
+ Vector<android_color_mode_t>* outColorModes) {
+ return ComposerService::getComposerService()->getDisplayColorModes(display, outColorModes);
+}
+
+android_color_mode_t SurfaceComposerClient::getActiveColorMode(const sp<IBinder>& display) {
+ return ComposerService::getComposerService()->getActiveColorMode(display);
+}
+
+status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
+ android_color_mode_t colorMode) {
+ return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
+}
+
void SurfaceComposerClient::setDisplayPowerMode(const sp<IBinder>& token,
int mode) {
ComposerService::getComposerService()->setPowerMode(token, mode);
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 246346b..fb2b857 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -796,6 +796,11 @@
return NO_MEMORY;
}
+ if (numRects > (UINT32_MAX / sizeof(Rect))) {
+ android_errorWriteWithInfoLog(0x534e4554, "29983260", -1, NULL, 0);
+ return NO_MEMORY;
+ }
+
Region result;
result.mStorage.clear();
for (size_t r = 0; r < numRects; ++r) {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index a67b3ff..5c2c0ad 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -415,6 +415,17 @@
}
// ----------------------------------------------------------------------------
+#ifdef USE_HWC2
+void DisplayDevice::setActiveColorMode(android_color_mode_t mode) {
+ mActiveColorMode = mode;
+}
+
+android_color_mode_t DisplayDevice::getActiveColorMode() const {
+ return mActiveColorMode;
+}
+#endif
+
+// ----------------------------------------------------------------------------
void DisplayDevice::setLayerStack(uint32_t stack) {
mLayerStack = stack;
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index dd9b104..105e980 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -182,6 +182,11 @@
void setPowerMode(int mode);
bool isDisplayOn() const;
+#ifdef USE_HWC2
+ android_color_mode_t getActiveColorMode() const;
+ void setActiveColorMode(android_color_mode_t mode);
+#endif
+
/* ------------------------------------------------------------------------
* Display active config management.
*/
@@ -252,6 +257,10 @@
int mPowerMode;
// Current active config
int mActiveConfig;
+#ifdef USE_HWC2
+ // current active color mode
+ android_color_mode_t mActiveColorMode;
+#endif
};
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 87a0e9a..4fe3cfd 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -581,7 +581,7 @@
return Error::None;
}
-Error Display::getColorModes(std::vector<int32_t>* outModes) const
+Error Display::getColorModes(std::vector<android_color_mode_t>* outModes) const
{
uint32_t numModes = 0;
int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
@@ -599,7 +599,10 @@
return error;
}
- std::swap(*outModes, modes);
+ outModes->resize(numModes);
+ for (size_t i = 0; i < numModes; i++) {
+ (*outModes)[i] = static_cast<android_color_mode_t>(modes[i]);
+ }
return Error::None;
}
@@ -805,7 +808,7 @@
return static_cast<Error>(intError);
}
-Error Display::setColorMode(int32_t mode)
+Error Display::setColorMode(android_color_mode_t mode)
{
int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
return static_cast<Error>(intError);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index beb7bc6..fb04af8 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -282,7 +282,7 @@
[[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;
+ std::vector<android_color_mode_t>* outModes) const;
// Doesn't call into the HWC2 device, so no errors are possible
std::vector<std::shared_ptr<const Config>> getConfigs() const;
@@ -307,7 +307,7 @@
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 setColorMode(android_color_mode_t mode);
[[clang::warn_unused_result]] Error setColorTransform(
const android::mat4& matrix, android_color_transform_t hint);
[[clang::warn_unused_result]] Error setOutputBuffer(
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
index 0528d7b..7bca0f1 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -75,7 +75,7 @@
using namespace HWC2;
-static constexpr Attribute ColorTransform = static_cast<Attribute>(6);
+static constexpr Attribute ColorMode = static_cast<Attribute>(6);
namespace android {
@@ -268,9 +268,7 @@
&Display::setClientTarget, buffer_handle_t, int32_t,
int32_t, hwc_region_t>);
case FunctionDescriptor::SetColorMode:
- return asFP<HWC2_PFN_SET_COLOR_MODE>(
- displayHook<decltype(&Display::setColorMode),
- &Display::setColorMode, int32_t>);
+ return asFP<HWC2_PFN_SET_COLOR_MODE>(setColorModeHook);
case FunctionDescriptor::SetColorTransform:
return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
case FunctionDescriptor::SetOutputBuffer:
@@ -562,6 +560,7 @@
mHwc1Id(-1),
mConfigs(),
mActiveConfig(nullptr),
+ mActiveColorMode(static_cast<android_color_mode_t>(-1)),
mName(),
mType(type),
mPowerMode(PowerMode::Off),
@@ -894,7 +893,7 @@
return Error::None;
}
-Error HWC2On1Adapter::Display::setColorMode(int32_t mode)
+Error HWC2On1Adapter::Display::setColorMode(android_color_mode_t mode)
{
std::unique_lock<std::recursive_mutex> lock (mStateMutex);
@@ -1198,11 +1197,14 @@
newConfig->setAttribute(Attribute::DpiY,
values[attributeMap[HWC_DISPLAY_DPI_Y]]);
if (hasColor) {
- newConfig->setAttribute(ColorTransform,
+ // In HWC1, color modes are referred to as color transforms. To avoid confusion with
+ // the HWC2 concept of color transforms, we internally refer to them as color modes for
+ // both HWC1 and 2.
+ newConfig->setAttribute(ColorMode,
values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
}
- // We can only do this after attempting to read the color transform
+ // We can only do this after attempting to read the color mode
newConfig->setHwc1Id(hwc1ConfigId);
for (auto& existingConfig : mConfigs) {
@@ -1678,8 +1680,8 @@
void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id)
{
- int32_t colorTransform = getAttribute(ColorTransform);
- mHwc1Ids.emplace(colorTransform, id);
+ android_color_mode_t colorMode = static_cast<android_color_mode_t>(getAttribute(ColorMode));
+ mHwc1Ids.emplace(colorMode, id);
}
bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const
@@ -1692,18 +1694,20 @@
return false;
}
-int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
- uint32_t id) const
+Error HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+ uint32_t id, android_color_mode_t* outMode) const
{
for (const auto& idPair : mHwc1Ids) {
if (id == idPair.second) {
- return idPair.first;
+ *outMode = idPair.first;
+ return Error::None;
}
}
- return -1;
+ ALOGE("Unable to find color mode for HWC ID %" PRIu32 " on config %u", id, mId);
+ return Error::BadParameter;
}
-Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode,
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(android_color_mode_t mode,
uint32_t* outId) const
{
for (const auto& idPair : mHwc1Ids) {
@@ -1726,25 +1730,26 @@
return false;
}
}
- int32_t otherColorTransform = other.getAttribute(ColorTransform);
- if (mHwc1Ids.count(otherColorTransform) != 0) {
+ android_color_mode_t otherColorMode =
+ static_cast<android_color_mode_t>(other.getAttribute(ColorMode));
+ if (mHwc1Ids.count(otherColorMode) != 0) {
ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
- "identical", mHwc1Ids.at(otherColorTransform),
- other.mHwc1Ids.at(otherColorTransform));
+ "identical", mHwc1Ids.at(otherColorMode),
+ other.mHwc1Ids.at(otherColorMode));
return false;
}
- mHwc1Ids.emplace(otherColorTransform,
- other.mHwc1Ids.at(otherColorTransform));
+ mHwc1Ids.emplace(otherColorMode,
+ other.mHwc1Ids.at(otherColorMode));
return true;
}
-std::set<int32_t> HWC2On1Adapter::Display::Config::getColorTransforms() const
+std::set<android_color_mode_t> HWC2On1Adapter::Display::Config::getColorModes() const
{
- std::set<int32_t> colorTransforms;
+ std::set<android_color_mode_t> colorModes;
for (const auto& idPair : mHwc1Ids) {
- colorTransforms.emplace(idPair.first);
+ colorModes.emplace(idPair.first);
}
- return colorTransforms;
+ return colorModes;
}
std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const
@@ -1787,15 +1792,15 @@
for (const auto& id : mHwc1Ids) {
- int32_t colorTransform = id.first;
+ android_color_mode_t colorMode = id.first;
uint32_t hwc1Id = id.second;
std::memset(buffer, 0, BUFFER_SIZE);
- if (colorTransform == mDisplay.mActiveColorMode) {
+ if (colorMode == mDisplay.mActiveColorMode) {
writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
- colorTransform);
+ colorMode);
} else {
writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
- colorTransform);
+ colorMode);
}
output.append(buffer, writtenBytes);
}
@@ -1814,10 +1819,10 @@
void HWC2On1Adapter::Display::populateColorModes()
{
- mColorModes = mConfigs[0]->getColorTransforms();
+ mColorModes = mConfigs[0]->getColorModes();
for (const auto& config : mConfigs) {
- std::set<int32_t> intersection;
- auto configModes = config->getColorTransforms();
+ std::set<android_color_mode_t> intersection;
+ auto configModes = config->getColorModes();
std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
configModes.cbegin(), configModes.cend(),
std::inserter(intersection, intersection.begin()));
@@ -1830,7 +1835,7 @@
if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
ALOGV("getActiveConfig is null, choosing config 0");
mActiveConfig = mConfigs[0];
- mActiveColorMode = -1;
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
return;
}
@@ -1842,7 +1847,13 @@
ALOGV("Setting active config to %d for HWC1 config %u",
config->getId(), activeConfig);
mActiveConfig = config;
- mActiveColorMode = config->getColorModeForHwc1Id(activeConfig);
+ if (config->getColorModeForHwc1Id(activeConfig, &mActiveColorMode) != Error::None) {
+ // This should never happen since we checked for the config's presence before
+ // setting it as active.
+ ALOGE("Unable to find color mode for active HWC1 config %d",
+ config->getId());
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
+ }
break;
}
}
@@ -1850,7 +1861,7 @@
ALOGV("Unable to find active HWC1 config %u, defaulting to "
"config 0", activeConfig);
mActiveConfig = mConfigs[0];
- mActiveColorMode = -1;
+ mActiveColorMode = HAL_COLOR_MODE_NATIVE;
}
}
}
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
index dc7c355..e447c3c 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -213,7 +213,7 @@
HWC2::Error setClientTarget(buffer_handle_t target,
int32_t acquireFence, int32_t dataspace,
hwc_region_t damage);
- HWC2::Error setColorMode(int32_t mode);
+ HWC2::Error setColorMode(android_color_mode_t mode);
HWC2::Error setColorTransform(android_color_transform_t hint);
HWC2::Error setOutputBuffer(buffer_handle_t buffer,
int32_t releaseFence);
@@ -247,6 +247,7 @@
public:
Config(Display& display)
: mDisplay(display),
+ mId(0),
mAttributes() {}
bool isOnDisplay(const Display& display) const {
@@ -258,8 +259,9 @@
void setHwc1Id(uint32_t id);
bool hasHwc1Id(uint32_t id) const;
- int32_t getColorModeForHwc1Id(uint32_t id) const;
- HWC2::Error getHwc1IdForColorMode(int32_t mode,
+ HWC2::Error getColorModeForHwc1Id(uint32_t id,
+ android_color_mode_t *outMode) const;
+ HWC2::Error getHwc1IdForColorMode(android_color_mode_t mode,
uint32_t* outId) const;
void setId(hwc2_config_t id) { mId = id; }
@@ -269,7 +271,7 @@
// mode. Returns whether the merge was successful
bool merge(const Config& other);
- std::set<int32_t> getColorTransforms() const;
+ std::set<android_color_mode_t> getColorModes() const;
// splitLine divides the output into two lines suitable for
// dumpsys SurfaceFlinger
@@ -281,7 +283,7 @@
std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
// Maps from color transform to HWC1 config ID
- std::unordered_map<int32_t, uint32_t> mHwc1Ids;
+ std::unordered_map<android_color_mode_t, uint32_t> mHwc1Ids;
};
class Changes {
@@ -378,8 +380,8 @@
std::vector<std::shared_ptr<Config>> mConfigs;
std::shared_ptr<const Config> mActiveConfig;
- std::set<int32_t> mColorModes;
- int32_t mActiveColorMode;
+ std::set<android_color_mode_t> mColorModes;
+ android_color_mode_t mActiveColorMode;
std::string mName;
HWC2::DisplayType mType;
HWC2::PowerMode mPowerMode;
@@ -432,6 +434,12 @@
hint);
}
+ static int32_t setColorModeHook(hwc2_device_t* device,
+ hwc2_display_t display, int32_t /*android_color_mode_t*/ intMode) {
+ auto mode = static_cast<android_color_mode_t>(intMode);
+ return callDisplayFunction(device, display, &Display::setColorMode, mode);
+ }
+
static int32_t setPowerModeHook(hwc2_device_t* device,
hwc2_display_t display, int32_t intMode) {
auto mode = static_cast<HWC2::PowerMode>(intMode);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 199848f..4ac58c5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -364,8 +364,8 @@
return config;
}
-std::vector<int32_t> HWComposer::getColorModes(int32_t displayId) const {
- std::vector<int32_t> modes;
+std::vector<android_color_mode_t> HWComposer::getColorModes(int32_t displayId) const {
+ std::vector<android_color_mode_t> modes;
if (!isValidDisplay(displayId)) {
ALOGE("getColorModes: Attempted to access invalid display %d",
@@ -379,12 +379,31 @@
if (error != HWC2::Error::None) {
ALOGE("getColorModes failed for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
- return std::vector<int32_t>();
+ return std::vector<android_color_mode_t>();
}
return modes;
}
+status_t HWComposer::setActiveColorMode(int32_t displayId, android_color_mode_t mode) {
+ if (!isValidDisplay(displayId)) {
+ ALOGE("setActiveColorMode: Display %d is not valid", displayId);
+ return BAD_INDEX;
+ }
+
+ auto& displayData = mDisplayData[displayId];
+ auto error = displayData.hwcDisplay->setColorMode(mode);
+ if (error != HWC2::Error::None) {
+ ALOGE("setActiveConfig: Failed to set color mode %d on display %d: "
+ "%s (%d)", mode, displayId, to_string(error).c_str(),
+ static_cast<int32_t>(error));
+ return UNKNOWN_ERROR;
+ }
+
+ return NO_ERROR;
+}
+
+
void HWComposer::setVsyncEnabled(int32_t disp, HWC2::Vsync enabled) {
if (disp < 0 || disp >= HWC_DISPLAY_VIRTUAL) {
ALOGD("setVsyncEnabled: Ignoring for virtual display %d", disp);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 17676ae..41671f6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -154,7 +154,9 @@
std::shared_ptr<const HWC2::Display::Config>
getActiveConfig(int32_t displayId) const;
- std::vector<int32_t> getColorModes(int32_t displayId) const;
+ std::vector<android_color_mode_t> getColorModes(int32_t displayId) const;
+
+ status_t setActiveColorMode(int32_t displayId, android_color_mode_t mode);
// for debugging ----------------------------------------------------------
void dump(String8& out) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
index 9d92f61..2102457 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -42,6 +42,8 @@
#include <cutils/log.h>
#include <cutils/properties.h>
+#include <system/graphics.h>
+
#include "HWComposer.h"
#include "../Layer.h" // needed only for debugging
@@ -403,7 +405,7 @@
config.ydpi = values[i] / 1000.0f;
break;
case HWC_DISPLAY_COLOR_TRANSFORM:
- config.colorTransform = values[i];
+ config.colorMode = static_cast<android_color_mode_t>(values[i]);
break;
default:
ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
@@ -519,6 +521,11 @@
return mDisplayData[disp].configs[currentConfig].refresh;
}
+android_color_mode_t HWComposer::getColorMode(int disp) const {
+ size_t currentConfig = mDisplayData[disp].currentConfig;
+ return mDisplayData[disp].configs[currentConfig].colorMode;
+}
+
const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
return mDisplayData[disp].configs;
}
@@ -1182,10 +1189,10 @@
for (size_t c = 0; c < disp.configs.size(); ++c) {
const DisplayConfig& config(disp.configs[c]);
result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f"
- ", refresh=%" PRId64 ", colorTransform=%d\n",
+ ", refresh=%" PRId64 ", colorMode=%d\n",
c == disp.currentConfig ? "* " : "", c,
config.width, config.height, config.xdpi, config.ydpi,
- config.refresh, config.colorTransform);
+ config.refresh, config.colorMode);
}
if (disp.list) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
index c861817..170e382 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -22,6 +22,8 @@
#include <hardware/hwcomposer_defs.h>
+#include <system/graphics.h>
+
#include <ui/Fence.h>
#include <utils/BitSet.h>
@@ -257,7 +259,15 @@
float xdpi;
float ydpi;
nsecs_t refresh;
- int colorTransform;
+ android_color_mode_t colorMode;
+ bool operator==(const DisplayConfig& rhs) const {
+ return width == rhs.width &&
+ height == rhs.height &&
+ xdpi == rhs.xdpi &&
+ ydpi == rhs.ydpi &&
+ refresh == rhs.refresh &&
+ colorMode == rhs.colorMode;
+ }
};
// Query display parameters. Pass in a display index (e.g.
@@ -274,6 +284,7 @@
float getDpiX(int disp) const;
float getDpiY(int disp) const;
nsecs_t getRefreshPeriod(int disp) const;
+ android_color_mode_t getColorMode(int disp) const;
const Vector<DisplayConfig>& getConfigs(int disp) const;
size_t getCurrentConfig(int disp) const;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index dd88adb..bdd94e3 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -226,6 +226,7 @@
timestamp = mVSyncEvent[i].header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
+ mFlinger.mInterceptor.saveVSyncEvent(timestamp);
*event = mVSyncEvent[i];
mVSyncEvent[i].header.timestamp = 0;
vsyncCount = mVSyncEvent[i].vsync.count;
diff --git a/services/surfaceflinger/GpuService.cpp b/services/surfaceflinger/GpuService.cpp
index b981180..b993dfb 100644
--- a/services/surfaceflinger/GpuService.cpp
+++ b/services/surfaceflinger/GpuService.cpp
@@ -92,82 +92,27 @@
}
fprintf(outs,
"GPU Service commands:\n"
- " vkjson dump Vulkan device capabilities as JSON\n");
+ " vkjson dump Vulkan properties as JSON\n");
fclose(outs);
return NO_ERROR;
}
-VkResult vkjsonPrint(FILE* out, FILE* err) {
- VkResult result;
-
- const VkApplicationInfo app_info = {
- VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr,
- "vkjson", 1, /* app name, version */
- "", 0, /* engine name, version */
- VK_API_VERSION_1_0
- };
- const VkInstanceCreateInfo instance_info = {
- VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr,
- 0, /* flags */
- &app_info,
- 0, nullptr, /* layers */
- 0, nullptr, /* extensions */
- };
- VkInstance instance;
- result = vkCreateInstance(&instance_info, nullptr, &instance);
- if (result != VK_SUCCESS) {
- fprintf(err, "vkCreateInstance failed: %d\n", result);
- return result;
- }
-
- uint32_t ngpu = 0;
- result = vkEnumeratePhysicalDevices(instance, &ngpu, nullptr);
- if (result != VK_SUCCESS) {
- fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
- return result;
- }
- std::vector<VkPhysicalDevice> gpus(ngpu, VK_NULL_HANDLE);
- result = vkEnumeratePhysicalDevices(instance, &ngpu, gpus.data());
- if (result != VK_SUCCESS) {
- fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
- return result;
- }
-
- for (size_t i = 0, n = gpus.size(); i < n; i++) {
- auto props = VkJsonGetAllProperties(gpus[i]);
- std::string json = VkJsonAllPropertiesToJson(props);
- fwrite(json.data(), 1, json.size(), out);
- if (i < n - 1)
- fputc(',', out);
- fputc('\n', out);
- }
-
- vkDestroyInstance(instance, nullptr);
-
- return VK_SUCCESS;
+void vkjsonPrint(FILE* out) {
+ std::string json = VkJsonInstanceToJson(VkJsonGetInstance());
+ fwrite(json.data(), 1, json.size(), out);
+ fputc('\n', out);
}
-status_t cmd_vkjson(int out, int err) {
- int errnum;
+status_t cmd_vkjson(int out, int /*err*/) {
FILE* outs = fdopen(out, "w");
if (!outs) {
- errnum = errno;
+ int errnum = errno;
ALOGE("vkjson: failed to create output stream: %s", strerror(errnum));
return -errnum;
}
- FILE* errs = fdopen(err, "w");
- if (!errs) {
- errnum = errno;
- ALOGE("vkjson: failed to create error stream: %s", strerror(errnum));
- fclose(outs);
- return -errnum;
- }
- fprintf(outs, "[\n");
- VkResult result = vkjsonPrint(outs, errs);
- fprintf(outs, "]\n");
- fclose(errs);
+ vkjsonPrint(outs);
fclose(outs);
- return result >= 0 ? NO_ERROR : UNKNOWN_ERROR;
+ return NO_ERROR;
}
} // anonymous namespace
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6024fa9..d00791d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -51,6 +51,8 @@
#include "RenderEngine/RenderEngine.h"
+#include <mutex>
+
#define DEBUG_RESIZE 0
namespace android {
@@ -153,10 +155,9 @@
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer);
+ BufferQueue::createBufferQueue(&producer, &consumer, nullptr, true);
mProducer = new MonitoredProducer(producer, mFlinger);
- mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName,
- this);
+ mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mSurfaceFlingerConsumer->setContentsChangedListener(this);
mSurfaceFlingerConsumer->setName(mName);
@@ -210,7 +211,8 @@
// Add this buffer from our internal queue tracker
{ // Autolock scope
Mutex::Autolock lock(mQueueItemLock);
-
+ mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
+ item.mGraphicBuffer->getHeight(), item.mFrameNumber);
// Reset the frame number tracker when we receive the first buffer after
// a frame number reset
if (item.mFrameNumber == 1) {
@@ -310,22 +312,6 @@
return NO_ERROR;
}
-/*
- * The layer handle is just a BBinder object passed to the client
- * (remote process) -- we don't keep any reference on our side such that
- * the dtor is called when the remote side let go of its reference.
- *
- * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
- * this layer when the handle is destroyed.
- */
-class Layer::Handle : public BBinder, public LayerCleaner {
- public:
- Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
- : LayerCleaner(flinger, layer), owner(layer) {}
-
- wp<Layer> owner;
-};
-
sp<IBinder> Layer::getHandle() {
Mutex::Autolock _l(mLock);
@@ -1089,6 +1075,20 @@
return static_cast<uint32_t>(producerStickyTransform);
}
+bool Layer::latchUnsignaledBuffers() {
+ static bool propertyLoaded = false;
+ static bool latch = false;
+ static std::mutex mutex;
+ std::lock_guard<std::mutex> lock(mutex);
+ if (!propertyLoaded) {
+ char value[PROPERTY_VALUE_MAX] = {};
+ property_get("debug.sf.latch_unsignaled", value, "0");
+ latch = atoi(value);
+ propertyLoaded = true;
+ }
+ return latch;
+}
+
uint64_t Layer::getHeadFrameNumber() const {
Mutex::Autolock lock(mQueueItemLock);
if (!mQueueItems.empty()) {
@@ -1100,6 +1100,10 @@
bool Layer::headFenceHasSignaled() const {
#ifdef USE_HWC2
+ if (latchUnsignaledBuffers()) {
+ return true;
+ }
+
Mutex::Autolock lock(mQueueItemLock);
if (mQueueItems.empty()) {
return true;
@@ -2236,17 +2240,6 @@
// ---------------------------------------------------------------------------
-Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
- const sp<Layer>& layer)
- : mFlinger(flinger), mLayer(layer) {
-}
-
-Layer::LayerCleaner::~LayerCleaner() {
- // destroy client resources
- mFlinger->onLayerDestroyed(mLayer);
-}
-
-// ---------------------------------------------------------------------------
}; // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 78a8427..a63656e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -180,11 +180,6 @@
Rect computeBounds(const Region& activeTransparentRegion) const;
Rect computeBounds() const;
- class Handle;
- sp<IBinder> getHandle();
- sp<IGraphicBufferProducer> getProducer() const;
- const String8& getName() const;
-
int32_t getSequence() const { return sequence; }
// -----------------------------------------------------------------------
@@ -423,9 +418,6 @@
protected:
// constant
sp<SurfaceFlinger> mFlinger;
-
- virtual void onFirstRef();
-
/*
* Trivial class, used to ensure that mFlinger->onLayerDestroyed(mLayer)
* is called.
@@ -434,13 +426,24 @@
sp<SurfaceFlinger> mFlinger;
wp<Layer> mLayer;
protected:
- ~LayerCleaner();
+ ~LayerCleaner() {
+ // destroy client resources
+ mFlinger->onLayerDestroyed(mLayer);
+ }
public:
- LayerCleaner(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer);
+ LayerCleaner(const sp<SurfaceFlinger>& flinger,
+ const sp<Layer>& layer)
+ : mFlinger(flinger), mLayer(layer) {
+ }
};
+ virtual void onFirstRef();
+
+
+
private:
+ friend class SurfaceInterceptor;
// Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener
virtual void onFrameAvailable(const BufferItem& item) override;
virtual void onFrameReplaced(const BufferItem& item) override;
@@ -465,6 +468,9 @@
// Temporary - Used only for LEGACY camera mode.
uint32_t getProducerStickyTransform() const;
+ // Loads the corresponding system property once per process
+ static bool latchUnsignaledBuffers();
+
// -----------------------------------------------------------------------
class SyncPoint
@@ -524,6 +530,25 @@
// the Surface Controller) if set.
uint32_t getEffectiveScalingMode() const;
public:
+ /*
+ * The layer handle is just a BBinder object passed to the client
+ * (remote process) -- we don't keep any reference on our side such that
+ * the dtor is called when the remote side let go of its reference.
+ *
+ * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
+ * this layer when the handle is destroyed.
+ */
+ class Handle : public BBinder, public LayerCleaner {
+ public:
+ Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+ : LayerCleaner(flinger, layer), owner(layer) {}
+
+ wp<Layer> owner;
+ };
+
+ sp<IBinder> getHandle();
+ sp<IGraphicBufferProducer> getProducer() const;
+ const String8& getName() const;
void notifyAvailableFrames();
private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5583f0a..72ad53d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -162,6 +162,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mInterceptor(),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
@@ -192,6 +193,10 @@
}
ALOGI_IF(mDebugRegion, "showupdates enabled");
ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
+
+ property_get("debug.sf.disable_backpressure", value, "0");
+ mPropagateBackpressure = !atoi(value);
+ ALOGI_IF(!mPropagateBackpressure, "Disabling backpressure propagation");
}
void SurfaceFlinger::onFirstRef()
@@ -644,18 +649,7 @@
// All non-virtual displays are currently considered secure.
info.secure = true;
- // DisplayManager expects each color mode to be its own display
- // info record.
- std::vector<int32_t> modes = getHwComposer().getColorModes(type);
-
- if (modes.size() == 0) {
- info.colorTransform = 0;
- configs->push_back(info);
- }
- for (int32_t mode : modes) {
- info.colorTransform = mode;
- configs->push_back(info);
- }
+ configs->push_back(info);
}
return NO_ERROR;
@@ -717,6 +711,7 @@
if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
ALOGE("Attempt to set active config = %d for display with %zu configs",
mMode, configs.size());
+ return true;
}
sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
if (hw == NULL) {
@@ -735,6 +730,101 @@
postMessageSync(msg);
return NO_ERROR;
}
+status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
+ Vector<android_color_mode_t>* outColorModes) {
+ if ((outColorModes == nullptr) || (display.get() == nullptr)) {
+ return BAD_VALUE;
+ }
+
+ if (!display.get()) {
+ return NAME_NOT_FOUND;
+ }
+
+ int32_t type = NAME_NOT_FOUND;
+ for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
+ if (display == mBuiltinDisplays[i]) {
+ type = i;
+ break;
+ }
+ }
+
+ if (type < 0) {
+ return type;
+ }
+
+ std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+ outColorModes->clear();
+ std::copy(modes.cbegin(), modes.cend(), std::back_inserter(*outColorModes));
+
+ return NO_ERROR;
+}
+
+android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+ sp<DisplayDevice> device(getDisplayDevice(display));
+ if (device != nullptr) {
+ return device->getActiveColorMode();
+ }
+ return static_cast<android_color_mode_t>(BAD_VALUE);
+}
+
+void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
+ android_color_mode_t mode) {
+ ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
+ this);
+ int32_t type = hw->getDisplayType();
+ android_color_mode_t currentMode = hw->getActiveColorMode();
+
+ if (mode == currentMode) {
+ ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode);
+ return;
+ }
+
+ if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+ ALOGW("Trying to set config for virtual display");
+ return;
+ }
+
+ hw->setActiveColorMode(mode);
+ getHwComposer().setActiveColorMode(type, mode);
+}
+
+
+status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
+ android_color_mode_t colorMode) {
+ class MessageSetActiveColorMode: public MessageBase {
+ SurfaceFlinger& mFlinger;
+ sp<IBinder> mDisplay;
+ android_color_mode_t mMode;
+ public:
+ MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp<IBinder>& disp,
+ android_color_mode_t mode) :
+ mFlinger(flinger), mDisplay(disp) { mMode = mode; }
+ virtual bool handler() {
+ Vector<android_color_mode_t> modes;
+ mFlinger.getDisplayColorModes(mDisplay, &modes);
+ bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
+ if (mMode < 0 || !exists) {
+ ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode,
+ mDisplay.get());
+ return true;
+ }
+ sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+ if (hw == nullptr) {
+ ALOGE("Attempt to set active color mode = %d for null display %p",
+ mMode, mDisplay.get());
+ } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
+ ALOGW("Attempt to set active color mode= %d for virtual display",
+ mMode);
+ } else {
+ mFlinger.setActiveColorModeInternal(hw, mMode);
+ }
+ return true;
+ }
+ };
+ sp<MessageBase> msg = new MessageSetActiveColorMode(*this, display, colorMode);
+ postMessageSync(msg);
+ return NO_ERROR;
+}
status_t SurfaceFlinger::clearAnimationFrameStats() {
Mutex::Autolock _l(mStateLock);
@@ -937,7 +1027,7 @@
mPreviousPresentFence != Fence::NO_FENCE &&
mPreviousPresentFence->getSignalTime() == INT64_MAX;
ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
- if (frameMissed) {
+ if (mPropagateBackpressure && frameMissed) {
signalLayerUpdate();
break;
}
@@ -2213,6 +2303,8 @@
}
if (transactionFlags) {
+ mInterceptor.saveLayerUpdates(state, flags);
+
// this triggers the transaction
setTransactionFlags(transactionFlags);
@@ -2373,7 +2465,6 @@
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
{
- //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
@@ -2408,6 +2499,7 @@
if (result != NO_ERROR) {
return result;
}
+ mInterceptor.saveLayerCreate(layer);
setTransactionFlags(eTransactionNeeded);
return result;
@@ -2455,6 +2547,7 @@
status_t err = NO_ERROR;
sp<Layer> l(client->getLayerUser(handle));
if (l != NULL) {
+ mInterceptor.saveLayerDelete(l);
err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -3185,6 +3278,18 @@
mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
return NO_ERROR;
}
+ case 1020: { // Layer updates interceptor
+ n = data.readInt32();
+ if (n) {
+ ALOGV("Interceptor enabled");
+ mInterceptor.enable(mDrawingState.layersSortedByZ);
+ }
+ else{
+ ALOGV("Interceptor disabled");
+ mInterceptor.disable();
+ }
+ return NO_ERROR;
+ }
}
}
return err;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f063aaf..c38f688 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -46,6 +46,8 @@
#include <hardware/hwcomposer_defs.h>
+#include <system/graphics.h>
+
#include <private/gui/LayerState.h>
#include "Barrier.h"
@@ -54,6 +56,7 @@
#include "FenceTracker.h"
#include "FrameTracker.h"
#include "MessageQueue.h"
+#include "SurfaceInterceptor.h"
#include "DisplayHardware/HWComposer.h"
#include "Effects/Daltonizer.h"
@@ -146,6 +149,7 @@
private:
friend class Client;
friend class DisplayEventConnection;
+ friend class EventThread;
friend class Layer;
friend class MonitoredProducer;
@@ -222,6 +226,10 @@
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs);
virtual int getActiveConfig(const sp<IBinder>& display);
+ virtual status_t getDisplayColorModes(const sp<IBinder>& display,
+ Vector<android_color_mode_t>* configs);
+ virtual android_color_mode_t getActiveColorMode(const sp<IBinder>& display);
+ virtual status_t setActiveColorMode(const sp<IBinder>& display, android_color_mode_t colorMode);
virtual void setPowerMode(const sp<IBinder>& display, int mode);
virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
virtual status_t clearAnimationFrameStats();
@@ -260,6 +268,9 @@
// called on the main thread in response to setPowerMode()
void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
+ // Called on the main thread in response to setActiveColorMode()
+ void setActiveColorModeInternal(const sp<DisplayDevice>& hw, android_color_mode_t colorMode);
+
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
@@ -368,6 +379,16 @@
return mDisplays.valueFor(dpy);
}
+ int32_t getDisplayType(const sp<IBinder>& display) {
+ if (!display.get()) return NAME_NOT_FOUND;
+ for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
+ if (display == mBuiltinDisplays[i]) {
+ return i;
+ }
+ }
+ return NAME_NOT_FOUND;
+ }
+
// mark a region of a layer stack dirty. this updates the dirty
// region of all screens presenting this layer stack.
void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
@@ -507,6 +528,10 @@
bool mBootFinished;
bool mForceFullDamage;
FenceTracker mFenceTracker;
+#ifdef USE_HWC2
+ bool mPropagateBackpressure = true;
+#endif
+ SurfaceInterceptor mInterceptor;
// these are thread safe
mutable MessageQueue mEventQueue;
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 4ddad94..123407c 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -59,6 +59,8 @@
#include <private/android_filesystem_config.h>
#include <private/gui/SyncFeatures.h>
+#include <set>
+
#include "Client.h"
#include "clz.h"
#include "Colorizer.h"
@@ -161,6 +163,7 @@
mLastTransactionTime(0),
mBootFinished(false),
mForceFullDamage(false),
+ mInterceptor(),
mPrimaryDispSync("PrimaryDispSync"),
mPrimaryHWVsyncEnabled(false),
mHWVsyncAvailable(false),
@@ -587,20 +590,8 @@
return BAD_VALUE;
}
- if (!display.get())
- return NAME_NOT_FOUND;
-
- int32_t type = NAME_NOT_FOUND;
- for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
- if (display == mBuiltinDisplays[i]) {
- type = i;
- break;
- }
- }
-
- if (type < 0) {
- return type;
- }
+ int32_t type = getDisplayType(display);
+ if (type < 0) return type;
// TODO: Not sure if display density should handled by SF any longer
class Density {
@@ -662,7 +653,6 @@
info.ydpi = ydpi;
info.fps = float(1e9 / hwConfig.refresh);
info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
- info.colorTransform = hwConfig.colorTransform;
// This is how far in advance a buffer must be queued for
// presentation at a given time. If you want a buffer to appear
@@ -763,6 +753,55 @@
return NO_ERROR;
}
+status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
+ Vector<android_color_mode_t>* outColorModes) {
+ if (outColorModes == nullptr || display.get() == nullptr) {
+ return BAD_VALUE;
+ }
+
+ int32_t type = getDisplayType(display);
+ if (type < 0) return type;
+
+ std::set<android_color_mode_t> colorModes;
+ for (const HWComposer::DisplayConfig& hwConfig : getHwComposer().getConfigs(type)) {
+ colorModes.insert(hwConfig.colorMode);
+ }
+
+ outColorModes->clear();
+ std::copy(colorModes.cbegin(), colorModes.cend(), std::back_inserter(*outColorModes));
+
+ return NO_ERROR;
+}
+
+android_color_mode_t SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
+ if (display.get() == nullptr) return static_cast<android_color_mode_t>(BAD_VALUE);
+
+ int32_t type = getDisplayType(display);
+ if (type < 0) return static_cast<android_color_mode_t>(type);
+
+ return getHwComposer().getColorMode(type);
+}
+
+status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
+ android_color_mode_t colorMode) {
+ if (display.get() == nullptr || colorMode < 0) {
+ return BAD_VALUE;
+ }
+
+ int32_t type = getDisplayType(display);
+ if (type < 0) return type;
+ const Vector<HWComposer::DisplayConfig>& hwConfigs = getHwComposer().getConfigs(type);
+ HWComposer::DisplayConfig desiredConfig = hwConfigs[getHwComposer().getCurrentConfig(type)];
+ desiredConfig.colorMode = colorMode;
+ for (size_t c = 0; c < hwConfigs.size(); ++c) {
+ const HWComposer::DisplayConfig config = hwConfigs[c];
+ if (config == desiredConfig) {
+ return setActiveConfig(display, c);
+ }
+ }
+ return BAD_VALUE;
+}
+
status_t SurfaceFlinger::clearAnimationFrameStats() {
Mutex::Autolock _l(mStateLock);
mAnimFrameTracker.clearStats();
@@ -2186,6 +2225,8 @@
}
if (transactionFlags) {
+ mInterceptor.saveLayerUpdates(state, flags);
+
// this triggers the transaction
setTransactionFlags(transactionFlags);
@@ -2346,7 +2387,6 @@
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
{
- //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
if (int32_t(w|h) < 0) {
ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
int(w), int(h));
@@ -2381,6 +2421,7 @@
if (result != NO_ERROR) {
return result;
}
+ mInterceptor.saveLayerCreate(layer);
setTransactionFlags(eTransactionNeeded);
return result;
@@ -2428,6 +2469,7 @@
status_t err = NO_ERROR;
sp<Layer> l(client->getLayerUser(handle));
if (l != NULL) {
+ mInterceptor.saveLayerDelete(l);
err = removeLayer(l);
ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
"error removing layer=%p (%s)", l.get(), strerror(-err));
@@ -3155,6 +3197,18 @@
mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
return NO_ERROR;
}
+ case 1020: { // Layer updates interceptor
+ n = data.readInt32();
+ if (n) {
+ ALOGV("Interceptor enabled");
+ mInterceptor.enable(mDrawingState.layersSortedByZ);
+ }
+ else{
+ ALOGV("Interceptor disabled");
+ mInterceptor.disable();
+ }
+ return NO_ERROR;
+ }
}
}
return err;
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
index d2e28ff..4d2cffc 100644
--- a/vulkan/libvulkan/Android.mk
+++ b/vulkan/libvulkan/Android.mk
@@ -25,7 +25,9 @@
-Weverything -Werror \
-Wno-padded \
-Wno-switch-enum \
- -Wno-undef
+ -Wno-undef \
+ -Wno-cast-calling-convention
+
#LOCAL_CFLAGS += -DLOG_NDEBUG=0
LOCAL_CPPFLAGS := -std=c++14 \
-Wno-c99-extensions \