[automerger skipped] Allow for more flexible vsync-offsets am: e203e04eeb
am: 831744932f -s ours
Change-Id: I36354a84acddfe3de347af720d167504653dde69
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 5029352..6337611 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -371,8 +371,8 @@
IServiceManager::DUMP_FLAG_PRIORITY_NORMAL);
ExpectCheckService("Locksmith");
ExpectCheckService("Valet");
- ExpectDumpWithArgs("Locksmith", {"-a", "--dump-priority", "NORMAL"}, "dump1");
- ExpectDumpWithArgs("Valet", {"-a", "--dump-priority", "NORMAL"}, "dump2");
+ ExpectDumpWithArgs("Locksmith", {"--dump-priority", "NORMAL", "-a"}, "dump1");
+ ExpectDumpWithArgs("Valet", {"--dump-priority", "NORMAL", "-a"}, "dump2");
CallMain({"--priority", "NORMAL"});
diff --git a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
index b32c92e..67abc68 100644
--- a/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
+++ b/headers/media_plugin/media/arcvideobridge/IArcVideoBridge.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_IARC_VIDEO_BRIDGE_H
#define ANDROID_IARC_VIDEO_BRIDGE_H
-#include <arc/IArcBridgeService.h>
+#include <arc/MojoBootstrapResult.h>
#include <binder/IInterface.h>
#include <utils/Errors.h>
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index 43346fe..11f8f6b 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -30,8 +30,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 24
-
struct AChoreographer;
typedef struct AChoreographer AChoreographer;
@@ -49,23 +47,23 @@
* Get the AChoreographer instance for the current thread. This must be called
* on an ALooper thread.
*/
-AChoreographer* AChoreographer_getInstance();
+AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
/**
* Post a callback to be run on the next frame. The data pointer provided will
* be passed to the callback function when it's called.
*/
void AChoreographer_postFrameCallback(AChoreographer* choreographer,
- AChoreographer_frameCallback callback, void* data);
+ AChoreographer_frameCallback callback, void* data) __INTRODUCED_IN(24);
+
/**
* Post a callback to be run on the frame following the specified delay. The
* data pointer provided will be passed to the callback function when it's
* called.
*/
void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
- AChoreographer_frameCallback callback, void* data, long delayMillis);
-
-#endif /* __ANDROID_API__ >= 24 */
+ AChoreographer_frameCallback callback, void* data,
+ long delayMillis) __INTRODUCED_IN(24);
__END_DECLS
diff --git a/include/android/configuration.h b/include/android/configuration.h
index 6287332..81aedca 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -30,6 +30,10 @@
#include <android/asset_manager.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -671,53 +675,49 @@
*/
void AConfiguration_setUiModeNight(AConfiguration* config, int32_t uiModeNight);
-#if __ANDROID_API__ >= 13
/**
* Return the current configuration screen width in dp units, or
* ACONFIGURATION_SCREEN_WIDTH_DP_ANY if not set.
*/
-int32_t AConfiguration_getScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's current screen width in dp units.
*/
-void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
/**
* Return the current configuration screen height in dp units, or
* ACONFIGURATION_SCREEN_HEIGHT_DP_ANY if not set.
*/
-int32_t AConfiguration_getScreenHeightDp(AConfiguration* config);
+int32_t AConfiguration_getScreenHeightDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's current screen width in dp units.
*/
-void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value);
+void AConfiguration_setScreenHeightDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
/**
* Return the configuration's smallest screen width in dp units, or
* ACONFIGURATION_SMALLEST_SCREEN_WIDTH_DP_ANY if not set.
*/
-int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config);
+int32_t AConfiguration_getSmallestScreenWidthDp(AConfiguration* config) __INTRODUCED_IN(13);
/**
* Set the configuration's smallest screen width in dp units.
*/
-void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
-#endif /* __ANDROID_API__ >= 13 */
+void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value) __INTRODUCED_IN(13);
-#if __ANDROID_API__ >= 17
/**
* Return the configuration's layout direction, or
* ACONFIGURATION_LAYOUTDIR_ANY if not set.
*/
-int32_t AConfiguration_getLayoutDirection(AConfiguration* config);
+int32_t AConfiguration_getLayoutDirection(AConfiguration* config) __INTRODUCED_IN(17);
/**
* Set the configuration's layout direction.
*/
-void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value);
-#endif /* __ANDROID_API__ >= 17 */
+void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
/**
* Perform a diff between two configurations. Returns a bit mask of
diff --git a/include/android/input.h b/include/android/input.h
index 0829989..3b36d2e 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -56,6 +56,10 @@
#include <android/keycodes.h>
#include <android/looper.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -79,7 +83,7 @@
};
/**
- * Meta key / modifer state.
+ * Meta key / modifier state.
*/
enum {
/** No meta keys are pressed. */
@@ -982,10 +986,8 @@
*/
int32_t AMotionEvent_getMetaState(const AInputEvent* motion_event);
-#if __ANDROID_API__ >= 14
/** Get the button state of all buttons that are pressed. */
-int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event);
-#endif
+int32_t AMotionEvent_getButtonState(const AInputEvent* motion_event) __INTRODUCED_IN(14);
/**
* Get a bitfield indicating which edges, if any, were touched by this motion event.
@@ -1050,14 +1052,12 @@
*/
int32_t AMotionEvent_getPointerId(const AInputEvent* motion_event, size_t pointer_index);
-#if __ANDROID_API__ >= 14
/**
* Get the tool type of a pointer for the given pointer index.
* The tool type indicates the type of tool used to make contact such as a
* finger or stylus, if known.
*/
-int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index);
-#endif
+int32_t AMotionEvent_getToolType(const AInputEvent* motion_event, size_t pointer_index) __INTRODUCED_IN(14);
/**
* Get the original raw X coordinate of this event.
@@ -1147,11 +1147,9 @@
*/
float AMotionEvent_getOrientation(const AInputEvent* motion_event, size_t pointer_index);
-#if __ANDROID_API__ >= 13
/** Get the value of the request axis for the given pointer index. */
float AMotionEvent_getAxisValue(const AInputEvent* motion_event,
- int32_t axis, size_t pointer_index);
-#endif
+ int32_t axis, size_t pointer_index) __INTRODUCED_IN(13);
/**
* Get the number of historical points in this event. These are movements that
@@ -1282,14 +1280,12 @@
float AMotionEvent_getHistoricalOrientation(const AInputEvent* motion_event, size_t pointer_index,
size_t history_index);
-#if __ANDROID_API__ >= 13
/**
* Get the historical value of the request axis for the given pointer index
* that occurred between this event and the previous motion event.
*/
float AMotionEvent_getHistoricalAxisValue(const AInputEvent* motion_event,
- int32_t axis, size_t pointer_index, size_t history_index);
-#endif
+ int32_t axis, size_t pointer_index, size_t history_index) __INTRODUCED_IN(13);
struct AInputQueue;
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 5f2a57f..55df9f8 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -60,8 +60,6 @@
* on failure with an appropriate errno value set.
*/
-#if __ANDROID_API__ >= 24
-
/**
* Set the network to be used by the given socket file descriptor.
*
@@ -70,7 +68,7 @@
* This is the equivalent of: [android.net.Network#bindSocket()](https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket))
*
*/
-int android_setsocknetwork(net_handle_t network, int fd);
+int android_setsocknetwork(net_handle_t network, int fd) __INTRODUCED_IN(23);
/**
@@ -87,7 +85,7 @@
* This is the equivalent of: [android.net.ConnectivityManager#setProcessDefaultNetwork()](https://developer.android.com/reference/android/net/ConnectivityManager.html#setProcessDefaultNetwork(android.net.Network))
*
*/
-int android_setprocnetwork(net_handle_t network);
+int android_setprocnetwork(net_handle_t network) __INTRODUCED_IN(23);
/**
@@ -106,9 +104,7 @@
*/
int android_getaddrinfofornetwork(net_handle_t network,
const char *node, const char *service,
- const struct addrinfo *hints, struct addrinfo **res);
-
-#endif /* __ANDROID_API__ >= 24 */
+ const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
__END_DECLS
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 082fab2..74e43c7 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -44,7 +44,6 @@
*/
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
-#if __ANDROID_API__ >= 26
/**
* Return a Java Surface object derived from the ANativeWindow, for interacting
* with it through Java code. The returned Java object acquires a reference on
@@ -52,8 +51,7 @@
* and will automatically release the reference when the Java object gets garbage
* collected.
*/
-jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window);
-#endif
+jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
#ifdef __cplusplus
};
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 191777c..59229c1 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -478,7 +478,6 @@
ASensorManager* ASensorManager_getInstance();
#endif
-#if __ANDROID_API__ >= __ANDROID_API_O__
/**
* Get a reference to the sensor manager. ASensorManager is a singleton
* per package as different packages may have access to different sensors.
@@ -488,8 +487,7 @@
* ASensorManager* sensorManager = ASensorManager_getInstanceForPackage("foo.bar.baz");
*
*/
-ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName);
-#endif
+ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
/**
* Returns the list of available sensors.
@@ -502,13 +500,11 @@
*/
ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
-#if __ANDROID_API__ >= 21
/**
* Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
* of this type and wakeUp properties exists.
*/
-ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp);
-#endif
+ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
/**
* Creates a new sensor event queue and associate it with a looper.
@@ -525,7 +521,6 @@
*/
int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
-#if __ANDROID_API__ >= __ANDROID_API_O__
/**
* Create direct channel based on shared memory
*
@@ -542,7 +537,7 @@
* {@link ASensorManager_destroyDirectChannel} and
* {@link ASensorManager_configureDirectReport}, or value less or equal to 0 for failures.
*/
-int ASensorManager_createSharedMemoryDirectChannel(ASensorManager* manager, int fd, size_t size);
+int ASensorManager_createSharedMemoryDirectChannel(ASensorManager* manager, int fd, size_t size) __INTRODUCED_IN(26);
/**
* Create direct channel based on AHardwareBuffer
@@ -560,7 +555,7 @@
* {@link ASensorManager_configureDirectReport}, or value less or equal to 0 for failures.
*/
int ASensorManager_createHardwareBufferDirectChannel(
- ASensorManager* manager, AHardwareBuffer const * buffer, size_t size);
+ ASensorManager* manager, AHardwareBuffer const * buffer, size_t size) __INTRODUCED_IN(26);
/**
* Destroy a direct channel
@@ -575,7 +570,7 @@
* {@link ASensorManager_createSharedMemoryDirectChannel} or
* {@link ASensorManager_createHardwareBufferDirectChannel}.
*/
-void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId);
+void ASensorManager_destroyDirectChannel(ASensorManager* manager, int channelId) __INTRODUCED_IN(26);
/**
* Configure direct report on channel
@@ -612,9 +607,8 @@
*
* \return positive token for success or negative error code.
*/
-int ASensorManager_configureDirectReport(
- ASensorManager* manager, ASensor const* sensor, int channelId, int rate);
-#endif
+int ASensorManager_configureDirectReport(ASensorManager* manager,
+ ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
/*****************************************************************************/
@@ -733,35 +727,32 @@
*/
int ASensor_getMinDelay(ASensor const* sensor);
-#if __ANDROID_API__ >= 21
/**
* Returns the maximum size of batches for this sensor. Batches will often be
* smaller, as the hardware fifo might be used for other sensors.
*/
-int ASensor_getFifoMaxEventCount(ASensor const* sensor);
+int ASensor_getFifoMaxEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns the hardware batch fifo size reserved to this sensor.
*/
-int ASensor_getFifoReservedEventCount(ASensor const* sensor);
+int ASensor_getFifoReservedEventCount(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns this sensor's string type.
*/
-const char* ASensor_getStringType(ASensor const* sensor);
+const char* ASensor_getStringType(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns the reporting mode for this sensor. One of AREPORTING_MODE_* constants.
*/
-int ASensor_getReportingMode(ASensor const* sensor);
+int ASensor_getReportingMode(ASensor const* sensor) __INTRODUCED_IN(21);
/**
* Returns true if this is a wake up sensor, false otherwise.
*/
-bool ASensor_isWakeUpSensor(ASensor const* sensor);
-#endif /* __ANDROID_API__ >= 21 */
+bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
-#if __ANDROID_API__ >= __ANDROID_API_O__
/**
* Test if sensor supports a certain type of direct channel.
*
@@ -771,7 +762,8 @@
* or {@link ASENSOR_DIRECT_CHANNEL_TYPE_HARDWARE_BUFFER}.
* \returns true if sensor supports the specified direct channel type.
*/
-bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType);
+bool ASensor_isDirectChannelTypeSupported(ASensor const* sensor, int channelType) __INTRODUCED_IN(26);
+
/**
* Get the highest direct rate level that a sensor support.
*
@@ -781,8 +773,7 @@
* If return value is {@link ASENSOR_DIRECT_RATE_STOP}, it means the sensor
* does not support direct report.
*/
-int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor);
-#endif
+int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
#ifdef __cplusplus
};
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 46d2f4b..0354f17 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -52,8 +52,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= __ANDROID_API_O__
-
/**
* Create a shared memory region.
*
@@ -67,7 +65,7 @@
* \param size size of the shared memory region
* \return file descriptor that denotes the shared memory; error code on failure.
*/
-int ASharedMemory_create(const char *name, size_t size);
+int ASharedMemory_create(const char *name, size_t size) __INTRODUCED_IN(26);
/**
* Get the size of the shared memory region.
@@ -75,7 +73,7 @@
* \param fd file descriptor of the shared memory region
* \return size in bytes; 0 if fd is not a valid shared memory file descriptor.
*/
-size_t ASharedMemory_getSize(int fd);
+size_t ASharedMemory_getSize(int fd) __INTRODUCED_IN(26);
/**
* Restrict access of shared memory region.
@@ -106,9 +104,7 @@
* updated access. Note access can only be removed, but not added back.
* \return 0 for success, error code on failure.
*/
-int ASharedMemory_setProt(int fd, int prot);
-
-#endif
+int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
#ifdef __cplusplus
};
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 85ac78f..d8b514f 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -54,8 +54,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= __ANDROID_API_O_MR1__
-
/**
* Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
* descriptor has all the same properties & capabilities as the FD returned from
@@ -70,9 +68,7 @@
* already closed, if the JNIEnv or jobject is NULL, or if there are too many open file
* descriptors (errno=EMFILE)
*/
-int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory);
-
-#endif
+int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
#ifdef __cplusplus
};
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index 56b3342..db10a16 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -64,7 +64,7 @@
* Failing to do so will result in leaked memory and graphic resources.
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
*/
-void ASurfaceTexture_release(ASurfaceTexture* st);
+void ASurfaceTexture_release(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Returns a reference to an ANativeWindow (i.e. the Producer) for this SurfaceTexture.
@@ -75,7 +75,7 @@
* using ANativeWindow_release(). Failing to do so will result in leaked resources. nullptr is
* returned if \st is null or if it's not an instance of android.graphics.SurfaceTexture
*/
-ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st);
+ANativeWindow* ASurfaceTexture_acquireANativeWindow(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Attach the SurfaceTexture to the OpenGL ES context that is current on the calling thread. A
@@ -92,7 +92,7 @@
* must be unusued in the OpenGL ES context that is current on the calling thread.
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
-int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName);
+int ASurfaceTexture_attachToGLContext(ASurfaceTexture* st, uint32_t texName) __INTRODUCED_IN(28);
/**
* Detach the SurfaceTexture from the OpenGL ES context that owns the OpenGL ES texture object.
@@ -108,7 +108,7 @@
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
-int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st);
+int ASurfaceTexture_detachFromGLContext(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Update the texture image to the most recent frame from the image stream. This may only be
@@ -118,7 +118,7 @@
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
* \return 0 on success, negative posix error code otherwise (see <errno.h>)
*/
-int ASurfaceTexture_updateTexImage(ASurfaceTexture* st);
+int ASurfaceTexture_updateTexImage(ASurfaceTexture* st) __INTRODUCED_IN(28);
/**
* Retrieve the 4x4 texture coordinate transform matrix associated with the texture image set by
@@ -136,7 +136,7 @@
* \param mtx the array into which the 4x4 matrix will be stored. The array must have exactly
* 16 elements.
*/
-void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]);
+void ASurfaceTexture_getTransformMatrix(ASurfaceTexture* st, float mtx[16]) __INTRODUCED_IN(28);
/**
* Retrieve the timestamp associated with the texture image set by the most recent call to
@@ -155,7 +155,7 @@
*
* \param st A ASurfaceTexture reference acquired with ASurfaceTexture_fromSurfaceTexture()
*/
-int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st);
+int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
__END_DECLS
diff --git a/include/android/trace.h b/include/android/trace.h
index d9e5d88..9f59acf 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -37,13 +37,11 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 23
-
/**
* Returns true if tracing is enabled. Use this signal to avoid expensive computation only necessary
* when tracing is enabled.
*/
-bool ATrace_isEnabled();
+bool ATrace_isEnabled() __INTRODUCED_IN(23);
/**
* Writes a tracing message to indicate that the given section of code has begun. This call must be
@@ -53,7 +51,7 @@
* by the tracing mechanism. If sectionName contains these characters they will be replaced with a
* space character in the trace.
*/
-void ATrace_beginSection(const char* sectionName);
+void ATrace_beginSection(const char* sectionName) __INTRODUCED_IN(23);
/**
* Writes a tracing message to indicate that a given section of code has ended. This call must be
@@ -61,9 +59,7 @@
* will mark the end of the most recently begun section of code, so care must be taken to ensure
* that beginSection / endSection pairs are properly nested and called from the same thread.
*/
-void ATrace_endSection();
-
-#endif /* __ANDROID_API__ >= 23 */
+void ATrace_endSection() __INTRODUCED_IN(23);
#ifdef __cplusplus
};
diff --git a/include/batteryservice b/include/batteryservice
deleted file mode 120000
index 2178c32..0000000
--- a/include/batteryservice
+++ /dev/null
@@ -1 +0,0 @@
-../services/batteryservice/include/batteryservice/
\ No newline at end of file
diff --git a/include/input/Input.h b/include/input/Input.h
index cfcafab..15c86eb 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -339,7 +339,7 @@
static const char* getLabel(int32_t keyCode);
static int32_t getKeyCodeFromLabel(const char* label);
-
+
void initialize(
int32_t deviceId,
int32_t source,
@@ -373,6 +373,10 @@
virtual int32_t getType() const { return AINPUT_EVENT_TYPE_MOTION; }
+ inline int32_t getDisplayId() const { return mDisplayId; }
+
+ inline void setDisplayId(int32_t displayId) { mDisplayId = displayId; }
+
inline int32_t getAction() const { return mAction; }
inline int32_t getActionMasked() const { return mAction & AMOTION_EVENT_ACTION_MASK; }
@@ -556,6 +560,7 @@
void initialize(
int32_t deviceId,
int32_t source,
+ int32_t displayId,
int32_t action,
int32_t actionButton,
int32_t flags,
@@ -609,6 +614,7 @@
static int32_t getAxisFromLabel(const char* label);
protected:
+ int32_t mDisplayId;
int32_t mAction;
int32_t mActionButton;
int32_t mFlags;
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 1ea2c2c..ee52661 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -64,7 +64,6 @@
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
- int32_t displayId;
int32_t action;
int32_t flags;
int32_t keyCode;
@@ -305,7 +304,7 @@
* Other errors probably indicate that the channel is broken.
*/
status_t consume(InputEventFactoryInterface* factory, bool consumeBatches,
- nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId);
+ nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
/* Sends a finished signal to the publisher to inform it that the message
* with the specified sequence number has finished being process and whether
@@ -460,10 +459,9 @@
Vector<SeqChain> mSeqChains;
status_t consumeBatch(InputEventFactoryInterface* factory,
- nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId);
+ nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
status_t consumeSamples(InputEventFactoryInterface* factory,
- Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent,
- int32_t* displayId);
+ Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent);
void updateTouchState(InputMessage& msg);
void resampleTouchState(nsecs_t frameTime, MotionEvent* event,
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index b3ae09b..9f08f23 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2307,6 +2307,15 @@
int fd = readFileDescriptor();
if (fd == int(BAD_TYPE)) return BAD_VALUE;
+ if (!ashmem_valid(fd)) {
+ ALOGE("invalid fd");
+ return BAD_VALUE;
+ }
+ int size = ashmem_get_size_region(fd);
+ if (size < 0 || size_t(size) < len) {
+ ALOGE("request size %zu does not match fd size %d", len, size);
+ return BAD_VALUE;
+ }
void* ptr = ::mmap(nullptr, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ,
MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) return NO_MEMORY;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index b29c1d5..ef3e592 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -123,6 +123,7 @@
"android.hardware.graphics.common@1.1",
"libsync",
"libbinder",
+ "libbufferhub",
"libbufferhubqueue", // TODO(b/70046255): Remove this once BufferHub is integrated into libgui.
"libpdx_default_transport",
"libcutils",
@@ -149,6 +150,7 @@
"BufferHubProducer.cpp",
],
exclude_shared_libs: [
+ "libbufferhub",
"libbufferhubqueue",
"libpdx_default_transport",
],
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index ae5cca2..06d597c 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -18,7 +18,9 @@
#include <gui/BufferHubProducer.h>
#include <inttypes.h>
#include <log/log.h>
+#include <private/dvr/detached_buffer.h>
#include <system/window.h>
+#include <ui/DetachedBufferHandle.h>
namespace android {
@@ -224,24 +226,224 @@
return ret;
}
-status_t BufferHubProducer::detachBuffer(int /* slot */) {
- ALOGE("BufferHubProducer::detachBuffer not implemented.");
- return INVALID_OPERATION;
+status_t BufferHubProducer::detachBuffer(int slot) {
+ ALOGV("detachBuffer: slot=%d", slot);
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ return DetachBufferLocked(static_cast<size_t>(slot));
}
-status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* /* out_buffer */,
- sp<Fence>* /* out_fence */) {
- ALOGE("BufferHubProducer::detachNextBuffer not implemented.");
- return INVALID_OPERATION;
+status_t BufferHubProducer::DetachBufferLocked(size_t slot) {
+ if (connected_api_ == kNoConnectedApi) {
+ ALOGE("detachBuffer: BufferHubProducer is not connected.");
+ return NO_INIT;
+ }
+
+ if (slot >= static_cast<size_t>(max_buffer_count_)) {
+ ALOGE("detachBuffer: slot index %zu out of range [0, %d)", slot, max_buffer_count_);
+ return BAD_VALUE;
+ } else if (!buffers_[slot].mBufferState.isDequeued()) {
+ ALOGE("detachBuffer: slot %zu is not owned by the producer (state = %s)", slot,
+ buffers_[slot].mBufferState.string());
+ return BAD_VALUE;
+ } else if (!buffers_[slot].mRequestBufferCalled) {
+ ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot);
+ return BAD_VALUE;
+ }
+ std::shared_ptr<BufferProducer> buffer_producer = queue_->GetBuffer(slot);
+ if (buffer_producer == nullptr || buffer_producer->buffer() == nullptr) {
+ ALOGE("detachBuffer: Invalid BufferProducer at slot %zu.", slot);
+ return BAD_VALUE;
+ }
+ sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+ if (graphic_buffer == nullptr) {
+ ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot);
+ return BAD_VALUE;
+ }
+
+ // Remove the BufferProducer from the ProducerQueue.
+ status_t error = RemoveBuffer(slot);
+ if (error != NO_ERROR) {
+ ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error);
+ return error;
+ }
+
+ // Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject
+ // the handle into the GraphicBuffer object at the requested slot.
+ auto status_or_handle = buffer_producer->Detach();
+ if (!status_or_handle.ok()) {
+ ALOGE("detachBuffer: Failed to detach from a BufferProducer at slot %zu, error=%d.", slot,
+ status_or_handle.error());
+ return BAD_VALUE;
+ }
+ std::unique_ptr<DetachedBufferHandle> handle =
+ DetachedBufferHandle::Create(status_or_handle.take());
+ if (!handle->isValid()) {
+ ALOGE("detachBuffer: Failed to create a DetachedBufferHandle at slot %zu.", slot);
+ return BAD_VALUE;
+ }
+
+ return graphic_buffer->setDetachedBufferHandle(std::move(handle));
}
-status_t BufferHubProducer::attachBuffer(int* /* out_slot */,
- const sp<GraphicBuffer>& /* buffer */) {
- // With this BufferHub backed implementation, we assume (for now) all buffers
- // are allocated and owned by the BufferHub. Thus the attempt of transfering
- // ownership of a buffer to the buffer queue is intentionally unsupported.
- LOG_ALWAYS_FATAL("BufferHubProducer::attachBuffer not supported.");
- return INVALID_OPERATION;
+status_t BufferHubProducer::detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) {
+ ALOGV("detachNextBuffer.");
+
+ if (out_buffer == nullptr || out_fence == nullptr) {
+ ALOGE("detachNextBuffer: Invalid parameter: out_buffer=%p, out_fence=%p", out_buffer,
+ out_fence);
+ return BAD_VALUE;
+ }
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (connected_api_ == kNoConnectedApi) {
+ ALOGE("detachNextBuffer: BufferHubProducer is not connected.");
+ return NO_INIT;
+ }
+
+ // detachNextBuffer is equivalent to calling dequeueBuffer, requestBuffer, and detachBuffer in
+ // sequence, except for two things:
+ //
+ // 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the
+ // function just returns whatever BufferProducer is available from the ProducerQueue and no
+ // buffer allocation or re-allocation will happen.
+ // 2) It will not block, since if it cannot find an appropriate buffer to return, it will return
+ // an error instead.
+ size_t slot = 0;
+ LocalHandle fence;
+
+ // First, dequeue a BufferProducer from the ProducerQueue with no timeout. Report error
+ // immediately if ProducerQueue::Dequeue() fails.
+ auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence);
+ if (!status_or_buffer.ok()) {
+ ALOGE("detachNextBuffer: Failed to dequeue buffer, error=%d.", status_or_buffer.error());
+ return NO_MEMORY;
+ }
+
+ std::shared_ptr<BufferProducer> buffer_producer = status_or_buffer.take();
+ if (buffer_producer == nullptr) {
+ ALOGE("detachNextBuffer: Dequeued buffer is null.");
+ return NO_MEMORY;
+ }
+
+ // With the BufferHub backed solution, slot returned from |queue_->Dequeue| is guaranteed to
+ // be available for producer's use. It's either in free state (if the buffer has never been used
+ // before) or in queued state (if the buffer has been dequeued and queued back to
+ // BufferHubQueue).
+ if (!buffers_[slot].mBufferState.isFree() && !buffers_[slot].mBufferState.isQueued()) {
+ ALOGE("detachNextBuffer: slot %zu is not free or queued, actual state: %s.", slot,
+ buffers_[slot].mBufferState.string());
+ return BAD_VALUE;
+ }
+ if (buffers_[slot].mBufferProducer == nullptr) {
+ ALOGE("detachNextBuffer: BufferProducer at slot %zu is null.", slot);
+ return BAD_VALUE;
+ }
+ if (buffers_[slot].mBufferProducer->id() != buffer_producer->id()) {
+ ALOGE("detachNextBuffer: BufferProducer at slot %zu has mismatched id, actual: "
+ "%d, expected: %d.",
+ slot, buffers_[slot].mBufferProducer->id(), buffer_producer->id());
+ return BAD_VALUE;
+ }
+
+ ALOGV("detachNextBuffer: slot=%zu", slot);
+ buffers_[slot].mBufferState.freeQueued();
+ buffers_[slot].mBufferState.dequeue();
+
+ // Second, request the buffer.
+ sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+ buffers_[slot].mGraphicBuffer = buffer_producer->buffer()->buffer();
+
+ // Finally, detach the buffer and then return.
+ status_t error = DetachBufferLocked(slot);
+ if (error == NO_ERROR) {
+ *out_fence = new Fence(fence.Release());
+ *out_buffer = graphic_buffer;
+ }
+ return error;
+}
+
+status_t BufferHubProducer::attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) {
+ // In the BufferHub design, all buffers are allocated and owned by the BufferHub. Thus only
+ // GraphicBuffers that are originated from BufferHub can be attached to a BufferHubProducer.
+ ALOGV("queueBuffer: buffer=%p", buffer.get());
+
+ if (out_slot == nullptr) {
+ ALOGE("attachBuffer: out_slot cannot be NULL.");
+ return BAD_VALUE;
+ }
+ if (buffer == nullptr || !buffer->isDetachedBuffer()) {
+ ALOGE("attachBuffer: invalid GraphicBuffer.");
+ return BAD_VALUE;
+ }
+
+ std::unique_lock<std::mutex> lock(mutex_);
+
+ if (connected_api_ == kNoConnectedApi) {
+ ALOGE("attachBuffer: BufferQueue has no connected producer");
+ return NO_INIT;
+ }
+
+ // Before attaching the buffer, caller is supposed to call
+ // IGraphicBufferProducer::setGenerationNumber to inform the
+ // BufferHubProducer the next generation number.
+ if (buffer->getGenerationNumber() != generation_number_) {
+ ALOGE("attachBuffer: Mismatched generation number, buffer: %u, queue: %u.",
+ buffer->getGenerationNumber(), generation_number_);
+ return BAD_VALUE;
+ }
+
+ // Creates a BufferProducer from the GraphicBuffer.
+ std::unique_ptr<DetachedBufferHandle> detached_handle = buffer->takeDetachedBufferHandle();
+ if (detached_handle == nullptr) {
+ ALOGE("attachBuffer: DetachedBufferHandle cannot be NULL.");
+ return BAD_VALUE;
+ }
+ auto detached_buffer = DetachedBuffer::Import(std::move(detached_handle->handle()));
+ if (detached_buffer == nullptr) {
+ ALOGE("attachBuffer: DetachedBuffer cannot be NULL.");
+ return BAD_VALUE;
+ }
+ auto status_or_handle = detached_buffer->Promote();
+ if (!status_or_handle.ok()) {
+ ALOGE("attachBuffer: Failed to promote a DetachedBuffer into a BufferProducer, error=%d.",
+ status_or_handle.error());
+ return BAD_VALUE;
+ }
+ std::shared_ptr<BufferProducer> buffer_producer =
+ BufferProducer::Import(status_or_handle.take());
+ if (buffer_producer == nullptr) {
+ ALOGE("attachBuffer: Failed to import BufferProducer.");
+ return BAD_VALUE;
+ }
+
+ // Adds the BufferProducer into the Queue.
+ auto status_or_slot = queue_->InsertBuffer(buffer_producer);
+ if (!status_or_slot.ok()) {
+ ALOGE("attachBuffer: Failed to insert buffer, error=%d.", status_or_slot.error());
+ return BAD_VALUE;
+ }
+
+ size_t slot = status_or_slot.get();
+ ALOGV("attachBuffer: returning slot %zu.", slot);
+ if (slot >= static_cast<size_t>(max_buffer_count_)) {
+ ALOGE("attachBuffer: Invalid slot: %zu.", slot);
+ return BAD_VALUE;
+ }
+
+ // The just attached buffer should be in dequeued state according to IGraphicBufferProducer
+ // interface. In BufferHub's language the buffer should be in Gained state.
+ buffers_[slot].mGraphicBuffer = buffer;
+ buffers_[slot].mBufferState.attachProducer();
+ buffers_[slot].mEglFence = EGL_NO_SYNC_KHR;
+ buffers_[slot].mFence = Fence::NO_FENCE;
+ buffers_[slot].mRequestBufferCalled = true;
+ buffers_[slot].mAcquireCalled = false;
+ buffers_[slot].mNeedsReallocation = false;
+
+ *out_slot = static_cast<int>(slot);
+ return NO_ERROR;
}
status_t BufferHubProducer::queueBuffer(int slot, const QueueBufferInput& input,
@@ -654,26 +856,28 @@
status_t BufferHubProducer::RemoveBuffer(size_t slot) {
auto status = queue_->RemoveBuffer(slot);
if (!status) {
- ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer: %s",
- status.GetErrorMessage().c_str());
+ ALOGE("BufferHubProducer::RemoveBuffer: Failed to remove buffer at slot: %zu, error: %s.",
+ slot, status.GetErrorMessage().c_str());
return INVALID_OPERATION;
}
// Reset in memory objects related the the buffer.
buffers_[slot].mBufferProducer = nullptr;
- buffers_[slot].mGraphicBuffer = nullptr;
buffers_[slot].mBufferState.detachProducer();
+ buffers_[slot].mFence = Fence::NO_FENCE;
+ buffers_[slot].mGraphicBuffer = nullptr;
+ buffers_[slot].mRequestBufferCalled = false;
return NO_ERROR;
}
status_t BufferHubProducer::FreeAllBuffers() {
for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
// Reset in memory objects related the the buffer.
- buffers_[slot].mGraphicBuffer = nullptr;
- buffers_[slot].mBufferState.reset();
- buffers_[slot].mRequestBufferCalled = false;
buffers_[slot].mBufferProducer = nullptr;
+ buffers_[slot].mBufferState.reset();
buffers_[slot].mFence = Fence::NO_FENCE;
+ buffers_[slot].mGraphicBuffer = nullptr;
+ buffers_[slot].mRequestBufferCalled = false;
}
auto status = queue_->FreeAllBuffers();
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index f50379b..5beba02 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -39,8 +39,8 @@
}
BufferItem::BufferItem() :
- mGraphicBuffer(NULL),
- mFence(NULL),
+ mGraphicBuffer(nullptr),
+ mFence(nullptr),
mCrop(Rect::INVALID_RECT),
mTransform(0),
mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
@@ -91,11 +91,11 @@
size_t BufferItem::getFlattenedSize() const {
size_t size = sizeof(uint32_t); // Flags
- if (mGraphicBuffer != 0) {
+ if (mGraphicBuffer != nullptr) {
size += mGraphicBuffer->getFlattenedSize();
size = FlattenableUtils::align<4>(size);
}
- if (mFence != 0) {
+ if (mFence != nullptr) {
size += mFence->getFlattenedSize();
size = FlattenableUtils::align<4>(size);
}
@@ -107,10 +107,10 @@
size_t BufferItem::getFdCount() const {
size_t count = 0;
- if (mGraphicBuffer != 0) {
+ if (mGraphicBuffer != nullptr) {
count += mGraphicBuffer->getFdCount();
}
- if (mFence != 0) {
+ if (mFence != nullptr) {
count += mFence->getFdCount();
}
return count;
@@ -137,13 +137,13 @@
FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
flags = 0;
- if (mGraphicBuffer != 0) {
+ if (mGraphicBuffer != nullptr) {
status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
if (err) return err;
size -= FlattenableUtils::align<4>(buffer);
flags |= 1;
}
- if (mFence != 0) {
+ if (mFence != nullptr) {
status_t err = mFence->flatten(buffer, size, fds, count);
if (err) return err;
size -= FlattenableUtils::align<4>(buffer);
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 89bc0c4..f50bc20 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -107,7 +107,7 @@
void BufferItemConsumer::freeBufferLocked(int slotIndex) {
sp<BufferFreedListener> listener = mBufferFreedListener.promote();
- if (listener != NULL && mSlots[slotIndex].mGraphicBuffer != NULL) {
+ if (listener != nullptr && mSlots[slotIndex].mGraphicBuffer != nullptr) {
// Fire callback if we have a listener registered and the buffer being freed is valid.
BI_LOGV("actually calling onBufferFreed");
listener->onBufferFreed(mSlots[slotIndex].mGraphicBuffer);
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index a8da134..5fb3f0b 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -38,7 +38,7 @@
void BufferQueue::ProxyConsumerListener::onDisconnect() {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onDisconnect();
}
}
@@ -46,7 +46,7 @@
void BufferQueue::ProxyConsumerListener::onFrameAvailable(
const BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onFrameAvailable(item);
}
}
@@ -54,21 +54,21 @@
void BufferQueue::ProxyConsumerListener::onFrameReplaced(
const BufferItem& item) {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onFrameReplaced(item);
}
}
void BufferQueue::ProxyConsumerListener::onBuffersReleased() {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBuffersReleased();
}
}
void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() {
sp<ConsumerListener> listener(mConsumerListener.promote());
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onSidebandStreamChanged();
}
}
@@ -85,21 +85,21 @@
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) {
- LOG_ALWAYS_FATAL_IF(outProducer == NULL,
+ LOG_ALWAYS_FATAL_IF(outProducer == nullptr,
"BufferQueue: outProducer must not be NULL");
- LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
+ LOG_ALWAYS_FATAL_IF(outConsumer == nullptr,
"BufferQueue: outConsumer must not be NULL");
sp<BufferQueueCore> core(new BufferQueueCore());
- LOG_ALWAYS_FATAL_IF(core == NULL,
+ LOG_ALWAYS_FATAL_IF(core == nullptr,
"BufferQueue: failed to create BufferQueueCore");
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
- LOG_ALWAYS_FATAL_IF(producer == NULL,
+ LOG_ALWAYS_FATAL_IF(producer == nullptr,
"BufferQueue: failed to create BufferQueueProducer");
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
- LOG_ALWAYS_FATAL_IF(consumer == NULL,
+ LOG_ALWAYS_FATAL_IF(consumer == nullptr,
"BufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
@@ -109,8 +109,8 @@
#ifndef NO_BUFFERHUB
void BufferQueue::createBufferHubQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer) {
- LOG_ALWAYS_FATAL_IF(outProducer == NULL, "BufferQueue: outProducer must not be NULL");
- LOG_ALWAYS_FATAL_IF(outConsumer == NULL, "BufferQueue: outConsumer must not be NULL");
+ LOG_ALWAYS_FATAL_IF(outProducer == nullptr, "BufferQueue: outProducer must not be NULL");
+ LOG_ALWAYS_FATAL_IF(outConsumer == nullptr, "BufferQueue: outConsumer must not be NULL");
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
@@ -118,16 +118,16 @@
dvr::ProducerQueueConfigBuilder configBuilder;
std::shared_ptr<dvr::ProducerQueue> producerQueue =
dvr::ProducerQueue::Create(configBuilder.Build(), dvr::UsagePolicy{});
- LOG_ALWAYS_FATAL_IF(producerQueue == NULL, "BufferQueue: failed to create ProducerQueue.");
+ LOG_ALWAYS_FATAL_IF(producerQueue == nullptr, "BufferQueue: failed to create ProducerQueue.");
std::shared_ptr<dvr::ConsumerQueue> consumerQueue = producerQueue->CreateConsumerQueue();
- LOG_ALWAYS_FATAL_IF(consumerQueue == NULL, "BufferQueue: failed to create ConsumerQueue.");
+ LOG_ALWAYS_FATAL_IF(consumerQueue == nullptr, "BufferQueue: failed to create ConsumerQueue.");
producer = BufferHubProducer::Create(producerQueue);
consumer = BufferHubConsumer::Create(consumerQueue);
- LOG_ALWAYS_FATAL_IF(producer == NULL, "BufferQueue: failed to create BufferQueueProducer");
- LOG_ALWAYS_FATAL_IF(consumer == NULL, "BufferQueue: failed to create BufferQueueConsumer");
+ LOG_ALWAYS_FATAL_IF(producer == nullptr, "BufferQueue: failed to create BufferQueueProducer");
+ LOG_ALWAYS_FATAL_IF(consumer == nullptr, "BufferQueue: failed to create BufferQueueConsumer");
*outProducer = producer;
*outConsumer = consumer;
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index d70e142..3837c3e 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -255,7 +255,7 @@
// mGraphicBuffer to NULL to avoid unnecessarily remapping this buffer
// on the consumer side
if (outBuffer->mAcquireCalled) {
- outBuffer->mGraphicBuffer = NULL;
+ outBuffer->mGraphicBuffer = nullptr;
}
mCore->mQueue.erase(front);
@@ -272,7 +272,7 @@
VALIDATE_CONSISTENCY();
}
- if (listener != NULL) {
+ if (listener != nullptr) {
for (int i = 0; i < numDroppedBuffers; ++i) {
listener->onBufferReleased();
}
@@ -321,10 +321,10 @@
const sp<android::GraphicBuffer>& buffer) {
ATRACE_CALL();
- if (outSlot == NULL) {
+ if (outSlot == nullptr) {
BQ_LOGE("attachBuffer: outSlot must not be NULL");
return BAD_VALUE;
- } else if (buffer == NULL) {
+ } else if (buffer == nullptr) {
BQ_LOGE("attachBuffer: cannot attach NULL buffer");
return BAD_VALUE;
}
@@ -413,7 +413,7 @@
ATRACE_BUFFER_INDEX(slot);
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS ||
- releaseFence == NULL) {
+ releaseFence == nullptr) {
BQ_LOGE("releaseBuffer: slot %d out of range or fence %p NULL", slot,
releaseFence.get());
return BAD_VALUE;
@@ -465,7 +465,7 @@
} // Autolock scope
// Call back without lock held
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBufferReleased();
}
@@ -476,7 +476,7 @@
const sp<IConsumerListener>& consumerListener, bool controlledByApp) {
ATRACE_CALL();
- if (consumerListener == NULL) {
+ if (consumerListener == nullptr) {
BQ_LOGE("connect: consumerListener may not be NULL");
return BAD_VALUE;
}
@@ -504,13 +504,13 @@
Mutex::Autolock lock(mCore->mMutex);
- if (mCore->mConsumerListener == NULL) {
+ if (mCore->mConsumerListener == nullptr) {
BQ_LOGE("disconnect: no consumer is connected");
return BAD_VALUE;
}
mCore->mIsAbandoned = true;
- mCore->mConsumerListener = NULL;
+ mCore->mConsumerListener = nullptr;
mCore->mQueue.clear();
mCore->freeAllBuffersLocked();
mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
@@ -521,7 +521,7 @@
status_t BufferQueueConsumer::getReleasedBuffers(uint64_t *outSlotMask) {
ATRACE_CALL();
- if (outSlotMask == NULL) {
+ if (outSlotMask == nullptr) {
BQ_LOGE("getReleasedBuffers: outSlotMask may not be NULL");
return BAD_VALUE;
}
@@ -673,7 +673,7 @@
}
}
// Call back without lock held
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBuffersReleased();
}
@@ -772,7 +772,7 @@
if (uid != shellUid) {
#endif
android_errorWriteWithInfoLog(0x534e4554, "27046057",
- static_cast<int32_t>(uid), NULL, 0);
+ static_cast<int32_t>(uid), nullptr, 0);
return PERMISSION_DENIED;
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index c8021e4..ce3a90a 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -166,7 +166,7 @@
} // Autolock scope
// Call back without lock held
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBuffersReleased();
}
@@ -221,7 +221,7 @@
} // Autolock scope
// Call back without lock held
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBuffersReleased();
}
return NO_ERROR;
@@ -450,11 +450,11 @@
mSlots[found].mBufferState.dequeue();
- if ((buffer == NULL) ||
+ if ((buffer == nullptr) ||
buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
{
mSlots[found].mAcquireCalled = false;
- mSlots[found].mGraphicBuffer = NULL;
+ mSlots[found].mGraphicBuffer = nullptr;
mSlots[found].mRequestBufferCalled = false;
mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
@@ -472,7 +472,7 @@
BQ_LOGV("dequeueBuffer: setting buffer age to %" PRIu64,
mCore->mBufferAge);
- if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
+ if (CC_UNLIKELY(mSlots[found].mFence == nullptr)) {
BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
"slot=%d w=%d h=%d format=%u",
found, buffer->width, buffer->height, buffer->format);
@@ -613,7 +613,7 @@
listener = mCore->mConsumerListener;
}
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBuffersReleased();
}
@@ -624,10 +624,10 @@
sp<Fence>* outFence) {
ATRACE_CALL();
- if (outBuffer == NULL) {
+ if (outBuffer == nullptr) {
BQ_LOGE("detachNextBuffer: outBuffer must not be NULL");
return BAD_VALUE;
- } else if (outFence == NULL) {
+ } else if (outFence == nullptr) {
BQ_LOGE("detachNextBuffer: outFence must not be NULL");
return BAD_VALUE;
}
@@ -671,7 +671,7 @@
listener = mCore->mConsumerListener;
}
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBuffersReleased();
}
@@ -682,10 +682,10 @@
const sp<android::GraphicBuffer>& buffer) {
ATRACE_CALL();
- if (outSlot == NULL) {
+ if (outSlot == nullptr) {
BQ_LOGE("attachBuffer: outSlot must not be NULL");
return BAD_VALUE;
- } else if (buffer == NULL) {
+ } else if (buffer == nullptr) {
BQ_LOGE("attachBuffer: cannot attach NULL buffer");
return BAD_VALUE;
}
@@ -767,7 +767,7 @@
const Region& surfaceDamage = input.getSurfaceDamage();
const HdrMetadata& hdrMetadata = input.getHdrMetadata();
- if (acquireFence == NULL) {
+ if (acquireFence == nullptr) {
BQ_LOGE("queueBuffer: fence is NULL");
return BAD_VALUE;
}
@@ -973,9 +973,9 @@
mCallbackCondition.wait(mCallbackMutex);
}
- if (frameAvailableListener != NULL) {
+ if (frameAvailableListener != nullptr) {
frameAvailableListener->onFrameAvailable(item);
- } else if (frameReplacedListener != NULL) {
+ } else if (frameReplacedListener != nullptr) {
frameReplacedListener->onFrameReplaced(item);
}
@@ -1040,7 +1040,7 @@
BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
"(state = %s)", slot, mSlots[slot].mBufferState.string());
return BAD_VALUE;
- } else if (fence == NULL) {
+ } else if (fence == nullptr) {
BQ_LOGE("cancelBuffer: fence is NULL");
return BAD_VALUE;
}
@@ -1070,7 +1070,7 @@
ATRACE_CALL();
Mutex::Autolock lock(mCore->mMutex);
- if (outValue == NULL) {
+ if (outValue == nullptr) {
BQ_LOGE("query: outValue was NULL");
return BAD_VALUE;
}
@@ -1146,12 +1146,12 @@
return NO_INIT;
}
- if (mCore->mConsumerListener == NULL) {
+ if (mCore->mConsumerListener == nullptr) {
BQ_LOGE("connect: BufferQueue has no consumer");
return NO_INIT;
}
- if (output == NULL) {
+ if (output == nullptr) {
BQ_LOGE("connect: output was NULL");
return BAD_VALUE;
}
@@ -1189,10 +1189,10 @@
output->nextFrameNumber = mCore->mFrameCounter + 1;
output->bufferReplaced = false;
- if (listener != NULL) {
+ if (listener != nullptr) {
// Set up a death notification so that we can disconnect
// automatically if the remote producer dies
- if (IInterface::asBinder(listener)->remoteBinder() != NULL) {
+ if (IInterface::asBinder(listener)->remoteBinder() != nullptr) {
status = IInterface::asBinder(listener)->linkToDeath(
static_cast<IBinder::DeathRecipient*>(this));
if (status != NO_ERROR) {
@@ -1269,7 +1269,7 @@
mCore->freeAllBuffersLocked();
// Remove our death notification callback if we have one
- if (mCore->mLinkedToDeath != NULL) {
+ if (mCore->mLinkedToDeath != nullptr) {
sp<IBinder> token =
IInterface::asBinder(mCore->mLinkedToDeath);
// This can fail if we're here because of the death
@@ -1279,8 +1279,8 @@
}
mCore->mSharedBufferSlot =
BufferQueueCore::INVALID_BUFFER_SLOT;
- mCore->mLinkedToDeath = NULL;
- mCore->mConnectedProducerListener = NULL;
+ mCore->mLinkedToDeath = nullptr;
+ mCore->mConnectedProducerListener = nullptr;
mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
mCore->mConnectedPid = -1;
mCore->mSidebandStream.clear();
@@ -1303,7 +1303,7 @@
} // Autolock scope
// Call back without lock held
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onBuffersReleased();
listener->onDisconnect();
}
@@ -1319,7 +1319,7 @@
listener = mCore->mConsumerListener;
} // Autolock scope
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->onSidebandStreamChanged();
}
return NO_ERROR;
@@ -1535,7 +1535,7 @@
Mutex::Autolock lock(mCore->mMutex);
listener = mCore->mConsumerListener;
}
- if (listener != NULL) {
+ if (listener != nullptr) {
listener->addAndGetFrameTimestamps(newTimestamps, outDelta);
}
}
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index f9e292e..abd9921 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -96,7 +96,7 @@
void ConsumerBase::freeBufferLocked(int slotIndex) {
CB_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- mSlots[slotIndex].mGraphicBuffer = 0;
+ mSlots[slotIndex].mGraphicBuffer = nullptr;
mSlots[slotIndex].mFence = Fence::NO_FENCE;
mSlots[slotIndex].mFrameNumber = 0;
}
@@ -110,7 +110,7 @@
listener = mFrameAvailableListener.promote();
}
- if (listener != NULL) {
+ if (listener != nullptr) {
CB_LOGV("actually calling onFrameAvailable");
listener->onFrameAvailable(item);
}
@@ -125,7 +125,7 @@
listener = mFrameAvailableListener.promote();
}
- if (listener != NULL) {
+ if (listener != nullptr) {
CB_LOGV("actually calling onFrameReplaced");
listener->onFrameReplaced(item);
}
@@ -352,8 +352,8 @@
return err;
}
- if (item->mGraphicBuffer != NULL) {
- if (mSlots[item->mSlot].mGraphicBuffer != NULL) {
+ if (item->mGraphicBuffer != nullptr) {
+ if (mSlots[item->mSlot].mGraphicBuffer != nullptr) {
freeBufferLocked(item->mSlot);
}
mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
@@ -468,7 +468,7 @@
if (slot < 0 || slot >= BufferQueue::NUM_BUFFER_SLOTS) {
return false;
}
- return (mSlots[slot].mGraphicBuffer != NULL &&
+ return (mSlots[slot].mGraphicBuffer != nullptr &&
mSlots[slot].mGraphicBuffer->handle == graphicBuffer->handle);
}
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 1757ec1..f5cf1c4 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -34,9 +34,9 @@
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSource vsyncSource) {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- if (sf != NULL) {
+ if (sf != nullptr) {
mEventConnection = sf->createDisplayEventConnection(vsyncSource);
- if (mEventConnection != NULL) {
+ if (mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
mEventConnection->stealReceiveChannel(mDataChannel.get());
}
@@ -47,13 +47,13 @@
}
status_t DisplayEventReceiver::initCheck() const {
- if (mDataChannel != NULL)
+ if (mDataChannel != nullptr)
return NO_ERROR;
return NO_INIT;
}
int DisplayEventReceiver::getFd() const {
- if (mDataChannel == NULL)
+ if (mDataChannel == nullptr)
return NO_INIT;
return mDataChannel->getFd();
@@ -63,7 +63,7 @@
if (int32_t(count) < 0)
return BAD_VALUE;
- if (mEventConnection != NULL) {
+ if (mEventConnection != nullptr) {
mEventConnection->setVsyncRate(count);
return NO_ERROR;
}
@@ -71,7 +71,7 @@
}
status_t DisplayEventReceiver::requestNextVsync() {
- if (mEventConnection != NULL) {
+ if (mEventConnection != nullptr) {
mEventConnection->requestNextVsync();
return NO_ERROR;
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 885efec..8efbef5 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -291,7 +291,7 @@
return err;
}
- if (mReleasedTexImage == NULL) {
+ if (mReleasedTexImage == nullptr) {
mReleasedTexImage = new EglImage(getDebugTexImageBuffer());
}
@@ -321,7 +321,7 @@
sp<GraphicBuffer> GLConsumer::getDebugTexImageBuffer() {
Mutex::Autolock _l(sStaticInitLock);
- if (CC_UNLIKELY(sReleasedTexImageBuffer == NULL)) {
+ if (CC_UNLIKELY(sReleasedTexImageBuffer == nullptr)) {
// The first time, create the debug texture in case the application
// continues to use it.
sp<GraphicBuffer> buffer = new GraphicBuffer(
@@ -357,7 +357,7 @@
// If item->mGraphicBuffer is not null, this buffer has not been acquired
// before, so any prior EglImage created is using a stale buffer. This
// replaces any old EglImage with a new one (using the new buffer).
- if (item->mGraphicBuffer != NULL) {
+ if (item->mGraphicBuffer != nullptr) {
int slot = item->mSlot;
mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
}
@@ -431,7 +431,7 @@
GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
mCurrentTexture, mCurrentTextureImage != NULL ?
- mCurrentTextureImage->graphicBufferHandle() : 0,
+ mCurrentTextureImage->graphicBufferHandle() : nullptr,
slot, mSlots[slot].mGraphicBuffer->handle);
// Hang onto the pointer so that it isn't freed in the call to
@@ -491,7 +491,7 @@
glBindTexture(mTexTarget, mTexName);
if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT &&
- mCurrentTextureImage == NULL) {
+ mCurrentTextureImage == nullptr) {
GLC_LOGE("bindTextureImage: no currently-bound texture");
return NO_INIT;
}
@@ -655,7 +655,7 @@
mTexName = tex;
mAttached = true;
- if (mCurrentTextureImage != NULL) {
+ if (mCurrentTextureImage != nullptr) {
// This may wait for a buffer a second time. This is likely required if
// this is a different context, since otherwise the wait could be skipped
// by bouncing through another context. For the same context the extra
@@ -676,7 +676,7 @@
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
if (SyncFeatures::getInstance().useNativeFenceSync()) {
EGLSyncKHR sync = eglCreateSyncKHR(dpy,
- EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+ EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
if (sync == EGL_NO_SYNC_KHR) {
GLC_LOGE("syncForReleaseLocked: error creating EGL fence: %#x",
eglGetError());
@@ -720,7 +720,7 @@
// Create a fence for the outstanding accesses in the current
// OpenGL ES context.
- fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
+ fence = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, nullptr);
if (fence == EGL_NO_SYNC_KHR) {
GLC_LOGE("syncForReleaseLocked: error creating fence: %#x",
eglGetError());
@@ -752,11 +752,11 @@
bool needsRecompute = mFilteringEnabled != enabled;
mFilteringEnabled = enabled;
- if (needsRecompute && mCurrentTextureImage==NULL) {
+ if (needsRecompute && mCurrentTextureImage==nullptr) {
GLC_LOGD("setFilteringEnabled called with mCurrentTextureImage == NULL");
}
- if (needsRecompute && mCurrentTextureImage != NULL) {
+ if (needsRecompute && mCurrentTextureImage != nullptr) {
computeCurrentTransformMatrixLocked();
}
}
@@ -938,7 +938,7 @@
}
return (mCurrentTextureImage == nullptr) ?
- NULL : mCurrentTextureImage->graphicBuffer();
+ nullptr : mCurrentTextureImage->graphicBuffer();
}
Rect GLConsumer::getCurrentCrop() const {
@@ -1150,7 +1150,7 @@
attrs[3] = attrs[11];
attrs[4] = EGL_NONE;
}
- eglInitialize(dpy, 0, 0);
+ eglInitialize(dpy, nullptr, nullptr);
EGLImageKHR image = eglCreateImageKHR(dpy, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
if (image == EGL_NO_IMAGE_KHR) {
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index 0749fde..3693d2c 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -190,10 +190,10 @@
virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
sp<Fence>* outFence) {
- if (outBuffer == NULL) {
+ if (outBuffer == nullptr) {
ALOGE("detachNextBuffer: outBuffer must not be NULL");
return BAD_VALUE;
- } else if (outFence == NULL) {
+ } else if (outFence == nullptr) {
ALOGE("detachNextBuffer: outFence must not be NULL");
return BAD_VALUE;
}
@@ -301,7 +301,7 @@
int api, bool producerControlledByApp, QueueBufferOutput* output) {
Parcel data, reply;
data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
- if (listener != NULL) {
+ if (listener != nullptr) {
data.writeInt32(1);
data.writeStrongBinder(IInterface::asBinder(listener));
} else {
@@ -738,8 +738,8 @@
int bufferIdx = data.readInt32();
sp<GraphicBuffer> buffer;
int result = requestBuffer(bufferIdx, &buffer);
- reply->writeInt32(buffer != 0);
- if (buffer != 0) {
+ reply->writeInt32(buffer != nullptr);
+ if (buffer != nullptr) {
reply->write(*buffer);
}
reply->writeInt32(result);
@@ -797,12 +797,12 @@
int32_t result = detachNextBuffer(&buffer, &fence);
reply->writeInt32(result);
if (result == NO_ERROR) {
- reply->writeInt32(buffer != NULL);
- if (buffer != NULL) {
+ reply->writeInt32(buffer != nullptr);
+ if (buffer != nullptr) {
reply->write(*buffer);
}
- reply->writeInt32(fence != NULL);
- if (fence != NULL) {
+ reply->writeInt32(fence != nullptr);
+ if (fence != nullptr) {
reply->write(*fence);
}
}
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 52c9067..2f8e104 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -38,11 +38,11 @@
status_t StreamSplitter::createSplitter(
const sp<IGraphicBufferConsumer>& inputQueue,
sp<StreamSplitter>* outSplitter) {
- if (inputQueue == NULL) {
+ if (inputQueue == nullptr) {
ALOGE("createSplitter: inputQueue must not be NULL");
return BAD_VALUE;
}
- if (outSplitter == NULL) {
+ if (outSplitter == nullptr) {
ALOGE("createSplitter: outSplitter must not be NULL");
return BAD_VALUE;
}
@@ -74,7 +74,7 @@
status_t StreamSplitter::addOutput(
const sp<IGraphicBufferProducer>& outputQueue) {
- if (outputQueue == NULL) {
+ if (outputQueue == nullptr) {
ALOGE("addOutput: outputQueue must not be NULL");
return BAD_VALUE;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 339bd0f..7bddaaf 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -156,7 +156,7 @@
ATRACE_CALL();
DisplayStatInfo stats;
- status_t result = composerService()->getDisplayStats(NULL, &stats);
+ status_t result = composerService()->getDisplayStats(nullptr, &stats);
if (result != NO_ERROR) {
return result;
}
@@ -497,7 +497,7 @@
if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
BufferItem::INVALID_BUFFER_SLOT) {
sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
- if (gbuf != NULL) {
+ if (gbuf != nullptr) {
*buffer = gbuf.get();
*fenceFd = -1;
return OK;
@@ -537,7 +537,7 @@
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen
- ALOGE_IF(fence == NULL, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
+ ALOGE_IF(fence == nullptr, "Surface::dequeueBuffer: received null Fence! buf=%d", buf);
if (result & IGraphicBufferProducer::RELEASE_ALL_BUFFERS) {
freeAllBuffers();
@@ -615,7 +615,7 @@
int Surface::getSlotFromBufferLocked(
android_native_buffer_t* buffer) const {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].buffer != NULL &&
+ if (mSlots[i].buffer != nullptr &&
mSlots[i].buffer->handle == buffer->handle) {
return i;
}
@@ -1264,7 +1264,7 @@
ATRACE_CALL();
ALOGV("Surface::detachNextBuffer");
- if (outBuffer == NULL || outFence == NULL) {
+ if (outBuffer == nullptr || outFence == nullptr) {
return BAD_VALUE;
}
@@ -1273,8 +1273,8 @@
mRemovedBuffers.clear();
}
- sp<GraphicBuffer> buffer(NULL);
- sp<Fence> fence(NULL);
+ sp<GraphicBuffer> buffer(nullptr);
+ sp<Fence> fence(nullptr);
status_t result = mGraphicBufferProducer->detachNextBuffer(
&buffer, &fence);
if (result != NO_ERROR) {
@@ -1282,19 +1282,19 @@
}
*outBuffer = buffer;
- if (fence != NULL && fence->isValid()) {
+ if (fence != nullptr && fence->isValid()) {
*outFence = fence;
} else {
*outFence = Fence::NO_FENCE;
}
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- if (mSlots[i].buffer != NULL &&
+ if (mSlots[i].buffer != nullptr &&
mSlots[i].buffer->getId() == buffer->getId()) {
if (mReportRemovedBuffers) {
mRemovedBuffers.push_back(mSlots[i].buffer);
}
- mSlots[i].buffer = NULL;
+ mSlots[i].buffer = nullptr;
}
}
@@ -1345,7 +1345,7 @@
ATRACE_CALL();
Rect realRect(Rect::EMPTY_RECT);
- if (rect == NULL || rect->isEmpty()) {
+ if (rect == nullptr || rect->isEmpty()) {
realRect.clear();
} else {
realRect = *rect;
@@ -1572,7 +1572,7 @@
void Surface::freeAllBuffers() {
for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
- mSlots[i].buffer = 0;
+ mSlots[i].buffer = nullptr;
}
}
@@ -1612,12 +1612,12 @@
// src and dst with, height and format must be identical. no verification
// is done here.
status_t err;
- uint8_t* src_bits = NULL;
+ uint8_t* src_bits = nullptr;
err = src->lock(GRALLOC_USAGE_SW_READ_OFTEN, reg.bounds(),
reinterpret_cast<void**>(&src_bits));
ALOGE_IF(err, "error locking src buffer %s", strerror(-err));
- uint8_t* dst_bits = NULL;
+ uint8_t* dst_bits = nullptr;
err = dst->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, reg.bounds(),
reinterpret_cast<void**>(&dst_bits), *dstFenceFd);
ALOGE_IF(err, "error locking dst buffer %s", strerror(-err));
@@ -1665,7 +1665,7 @@
status_t Surface::lock(
ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)
{
- if (mLockedBuffer != 0) {
+ if (mLockedBuffer != nullptr) {
ALOGE("Surface::lock failed, already locked");
return INVALID_OPERATION;
}
@@ -1697,7 +1697,7 @@
// figure out if we can copy the frontbuffer back
const sp<GraphicBuffer>& frontBuffer(mPostedBuffer);
- const bool canCopyBack = (frontBuffer != 0 &&
+ const bool canCopyBack = (frontBuffer != nullptr &&
backBuffer->width == frontBuffer->width &&
backBuffer->height == frontBuffer->height &&
backBuffer->format == frontBuffer->format);
@@ -1759,7 +1759,7 @@
status_t Surface::unlockAndPost()
{
- if (mLockedBuffer == 0) {
+ if (mLockedBuffer == nullptr) {
ALOGE("Surface::unlockAndPost failed, no locked buffer");
return INVALID_OPERATION;
}
@@ -1773,7 +1773,7 @@
mLockedBuffer->handle, strerror(-err));
mPostedBuffer = mLockedBuffer;
- mLockedBuffer = 0;
+ mLockedBuffer = nullptr;
return err;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 63560c4..d2b472b 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -81,7 +81,7 @@
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
- if (instance.mComposerService == NULL) {
+ if (instance.mComposerService == nullptr) {
ComposerService::getInstance().connectLocked();
assert(instance.mComposerService != NULL);
ALOGD("ComposerService reconnected");
@@ -92,8 +92,8 @@
void ComposerService::composerServiceDied()
{
Mutex::Autolock _l(mLock);
- mComposerService = NULL;
- mDeathObserver = NULL;
+ mComposerService = nullptr;
+ mDeathObserver = nullptr;
}
// ---------------------------------------------------------------------------
@@ -571,12 +571,12 @@
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- if (sf != 0 && mStatus == NO_INIT) {
+ if (sf != nullptr && mStatus == NO_INIT) {
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
- if (conn != 0) {
+ if (conn != nullptr) {
mClient = conn;
mStatus = NO_ERROR;
}
@@ -606,7 +606,7 @@
// this can be called more than once.
sp<ISurfaceComposerClient> client;
Mutex::Autolock _lm(mLock);
- if (mClient != 0) {
+ if (mClient != nullptr) {
client = mClient; // hold ref while lock is held
mClient.clear();
}
@@ -766,7 +766,7 @@
bool useIdentityTransform, uint32_t rotation,
sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == NULL) return NO_INIT;
+ if (s == nullptr) return NO_INIT;
status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ,
maxLayerZ, useIdentityTransform,
static_cast<ISurfaceComposer::Rotation>(rotation));
@@ -779,7 +779,7 @@
status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
float frameScale, sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == NULL) return NO_INIT;
+ if (s == nullptr) return NO_INIT;
status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale,
false /* childrenOnly */);
return ret;
@@ -788,7 +788,7 @@
status_t ScreenshotClient::captureChildLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
float frameScale, sp<GraphicBuffer>* outBuffer) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
- if (s == NULL) return NO_INIT;
+ if (s == nullptr) return NO_INIT;
status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale,
true /* childrenOnly */);
return ret;
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 5eafbb3..19ad31b 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -86,7 +86,7 @@
}
void SurfaceControl::disconnect() {
- if (mGraphicBufferProducer != NULL) {
+ if (mGraphicBufferProducer != nullptr) {
mGraphicBufferProducer->disconnect(
BufferQueueCore::CURRENTLY_CONNECTED_API);
}
@@ -95,7 +95,7 @@
bool SurfaceControl::isSameSurface(
const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
{
- if (lhs == 0 || rhs == 0)
+ if (lhs == nullptr || rhs == nullptr)
return false;
return lhs->mHandle == rhs->mHandle;
}
@@ -116,7 +116,7 @@
status_t SurfaceControl::validate() const
{
- if (mHandle==0 || mClient==0) {
+ if (mHandle==nullptr || mClient==nullptr) {
ALOGE("invalid handle (%p) or client (%p)",
mHandle.get(), mClient.get());
return NO_INIT;
@@ -128,7 +128,7 @@
const sp<SurfaceControl>& control, Parcel* parcel)
{
sp<IGraphicBufferProducer> bp;
- if (control != NULL) {
+ if (control != nullptr) {
bp = control->mGraphicBufferProducer;
}
return parcel->writeStrongBinder(IInterface::asBinder(bp));
@@ -146,7 +146,7 @@
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
- if (mSurfaceData == 0) {
+ if (mSurfaceData == nullptr) {
return generateSurfaceLocked();
}
return mSurfaceData;
diff --git a/libs/gui/SyncFeatures.cpp b/libs/gui/SyncFeatures.cpp
index afa15c5..fcae05c 100644
--- a/libs/gui/SyncFeatures.cpp
+++ b/libs/gui/SyncFeatures.cpp
@@ -41,7 +41,7 @@
// This can only be called after EGL has been initialized; otherwise the
// check below will abort.
const char* exts = eglQueryStringImplementationANDROID(dpy, EGL_EXTENSIONS);
- LOG_ALWAYS_FATAL_IF(exts == NULL, "eglQueryStringImplementationANDROID failed");
+ LOG_ALWAYS_FATAL_IF(exts == nullptr, "eglQueryStringImplementationANDROID failed");
if (strstr(exts, "EGL_ANDROID_native_fence_sync")) {
// This makes GLConsumer use the EGL_ANDROID_native_fence_sync
// extension to create Android native fences to signal when all
diff --git a/libs/gui/include/gui/BufferHubProducer.h b/libs/gui/include/gui/BufferHubProducer.h
index 23c9909..f7af19b 100644
--- a/libs/gui/include/gui/BufferHubProducer.h
+++ b/libs/gui/include/gui/BufferHubProducer.h
@@ -165,6 +165,10 @@
// buffers are acquired by the consumer, we can't .
status_t FreeAllBuffers();
+ // Helper function that implements the detachBuffer() call, but assuming |mutex_| has been
+ // locked already.
+ status_t DetachBufferLocked(size_t slot);
+
// Concreate implementation backed by BufferHubBuffer.
std::shared_ptr<dvr::ProducerQueue> queue_;
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 01e90e0..02064c6 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -50,9 +50,12 @@
],
}
-// Build a separate binary for each source file to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+// Build a separate binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
+// This test has a main method, and requires a separate binary to be built.
+// To add move tests like this, just add additional cc_test statements,
+// as opposed to adding more source files to this one.
cc_test {
- name: "libgui_separate_binary_test",
+ name: "SurfaceParcelable_test",
test_suites: ["device-tests"],
clang: true,
@@ -61,7 +64,6 @@
"-Werror",
],
- test_per_src: true,
srcs: [
"SurfaceParcelable_test.cpp",
],
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index a35cf11..c20e8fc 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -695,10 +695,7 @@
sp<Fence> fence;
sp<GraphicBuffer> buffer;
- if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
- // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
- ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
- }
+ ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
}
TEST_P(IGraphicBufferProducerTest,
@@ -735,10 +732,7 @@
ASSERT_OK(mProducer->disconnect(TEST_API));
- if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
- // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
- ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
- }
+ ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
}
TEST_P(IGraphicBufferProducerTest,
@@ -778,18 +772,46 @@
sp<GraphicBuffer> buffer;
setupDequeueRequestBuffer(&slot, &fence, &buffer);
+ ASSERT_TRUE(buffer != nullptr);
- if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
- // TODO(b/38137191): Implement BufferHubProducer::detachBuffer
- ASSERT_OK(mProducer->detachBuffer(slot));
+ ASSERT_OK(mProducer->detachBuffer(slot));
+ EXPECT_OK(buffer->initCheck());
+
+ if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
+ // For a GraphicBuffer backed by BufferHub, once detached from an IGBP, it should have
+ // isDetachedBuffer() set. Note that this only applies to BufferHub.
+ EXPECT_TRUE(buffer->isDetachedBuffer());
+ } else {
+ EXPECT_FALSE(buffer->isDetachedBuffer());
}
ASSERT_OK(mProducer->disconnect(TEST_API));
- if (GetParam() == USE_BUFFER_QUEUE_PRODUCER) {
- // TODO(b/69981968): Implement BufferHubProducer::attachBuffer
- ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+ ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+}
+
+TEST_P(IGraphicBufferProducerTest, DetachThenAttach_Succeeds) {
+ int slot = -1;
+ sp<Fence> fence;
+ sp<GraphicBuffer> buffer;
+
+ setupDequeueRequestBuffer(&slot, &fence, &buffer);
+ ASSERT_TRUE(buffer != nullptr);
+
+ ASSERT_OK(mProducer->detachBuffer(slot));
+ EXPECT_OK(buffer->initCheck());
+
+ if (GetParam() == USE_BUFFER_HUB_PRODUCER) {
+ // For a GraphicBuffer backed by BufferHub, once detached from an IGBP, it should have
+ // isDetachedBuffer() set. Note that this only applies to BufferHub.
+ EXPECT_TRUE(buffer->isDetachedBuffer());
+ } else {
+ EXPECT_FALSE(buffer->isDetachedBuffer());
}
+
+ EXPECT_OK(mProducer->attachBuffer(&slot, buffer));
+ EXPECT_FALSE(buffer->isDetachedBuffer());
+ EXPECT_OK(buffer->initCheck());
}
#if USE_BUFFER_HUB_AS_BUFFER_QUEUE
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index a624663..db27e11 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -215,6 +215,7 @@
void MotionEvent::initialize(
int32_t deviceId,
int32_t source,
+ int32_t displayId,
int32_t action,
int32_t actionButton,
int32_t flags,
@@ -231,6 +232,7 @@
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
InputEvent::initialize(deviceId, source);
+ mDisplayId = displayId;
mAction = action;
mActionButton = actionButton;
mFlags = flags;
@@ -251,6 +253,7 @@
void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
InputEvent::initialize(other->mDeviceId, other->mSource);
+ mDisplayId = other->mDisplayId;
mAction = other->mAction;
mActionButton = other->mActionButton;
mFlags = other->mFlags;
@@ -431,6 +434,7 @@
mDeviceId = parcel->readInt32();
mSource = parcel->readInt32();
+ mDisplayId = parcel->readInt32();
mAction = parcel->readInt32();
mActionButton = parcel->readInt32();
mFlags = parcel->readInt32();
@@ -480,6 +484,7 @@
parcel->writeInt32(mDeviceId);
parcel->writeInt32(mSource);
+ parcel->writeInt32(mDisplayId);
parcel->writeInt32(mAction);
parcel->writeInt32(mActionButton);
parcel->writeInt32(mFlags);
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index aa0bf17..f1c3fea 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -303,13 +303,15 @@
const PointerCoords* pointerCoords) {
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' publisher ~ publishMotionEvent: seq=%u, deviceId=%d, source=0x%x, "
+ "displayId=%" PRId32 ", "
"action=0x%x, actionButton=0x%08x, flags=0x%x, edgeFlags=0x%x, "
"metaState=0x%x, buttonState=0x%x, xOffset=%f, yOffset=%f, "
"xPrecision=%f, yPrecision=%f, downTime=%" PRId64 ", eventTime=%" PRId64 ", "
"pointerCount=%" PRIu32,
mChannel->getName().c_str(), seq,
- deviceId, source, action, actionButton, flags, edgeFlags, metaState, buttonState,
- xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime, pointerCount);
+ deviceId, source, displayId, action, actionButton, flags, edgeFlags, metaState,
+ buttonState, xOffset, yOffset, xPrecision, yPrecision, downTime, eventTime,
+ pointerCount);
#endif
if (!seq) {
@@ -398,8 +400,7 @@
}
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
- bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
- int32_t* displayId) {
+ bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
mChannel->getName().c_str(), consumeBatches ? "true" : "false", frameTime);
@@ -407,7 +408,6 @@
*outSeq = 0;
*outEvent = NULL;
- *displayId = -1; // Invalid display.
// Fetch the next input message.
// Loop until an event can be returned or no additional events are received.
@@ -422,7 +422,7 @@
if (result) {
// Consume the next batched event unless batches are being held for later.
if (consumeBatches || result != WOULD_BLOCK) {
- result = consumeBatch(factory, frameTime, outSeq, outEvent, displayId);
+ result = consumeBatch(factory, frameTime, outSeq, outEvent);
if (*outEvent) {
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
@@ -466,7 +466,7 @@
// the previous batch right now and defer the new message until later.
mMsgDeferred = true;
status_t result = consumeSamples(factory,
- batch, batch.samples.size(), outSeq, outEvent, displayId);
+ batch, batch.samples.size(), outSeq, outEvent);
mBatches.removeAt(batchIndex);
if (result) {
return result;
@@ -500,7 +500,7 @@
initializeMotionEvent(motionEvent, &mMsg);
*outSeq = mMsg.body.motion.seq;
*outEvent = motionEvent;
- *displayId = mMsg.body.motion.displayId;
+
#if DEBUG_TRANSPORT_ACTIONS
ALOGD("channel '%s' consumer ~ consumed motion event, seq=%u",
mChannel->getName().c_str(), *outSeq);
@@ -518,14 +518,13 @@
}
status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
- nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) {
+ nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
status_t result;
for (size_t i = mBatches.size(); i > 0; ) {
i--;
Batch& batch = mBatches.editItemAt(i);
if (frameTime < 0) {
- result = consumeSamples(factory, batch, batch.samples.size(),
- outSeq, outEvent, displayId);
+ result = consumeSamples(factory, batch, batch.samples.size(), outSeq, outEvent);
mBatches.removeAt(i);
return result;
}
@@ -539,7 +538,7 @@
continue;
}
- result = consumeSamples(factory, batch, split + 1, outSeq, outEvent, displayId);
+ result = consumeSamples(factory, batch, split + 1, outSeq, outEvent);
const InputMessage* next;
if (batch.samples.isEmpty()) {
mBatches.removeAt(i);
@@ -557,7 +556,7 @@
}
status_t InputConsumer::consumeSamples(InputEventFactoryInterface* factory,
- Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent, int32_t* displayId) {
+ Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent) {
MotionEvent* motionEvent = factory->createMotionEvent();
if (! motionEvent) return NO_MEMORY;
@@ -572,7 +571,6 @@
mSeqChains.push(seqChain);
addSample(motionEvent, &msg);
} else {
- *displayId = msg.body.motion.displayId;
initializeMotionEvent(motionEvent, &msg);
}
chain = msg.body.motion.seq;
@@ -950,6 +948,7 @@
event->initialize(
msg->body.motion.deviceId,
msg->body.motion.source,
+ msg->body.motion.displayId,
msg->body.motion.action,
msg->body.motion.actionButton,
msg->body.motion.flags,
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index c07a812..496158b 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -115,7 +115,7 @@
// Allow the default strategy to be overridden using a system property for debugging.
if (!strategy) {
- int length = property_get("debug.velocitytracker.strategy", value, NULL);
+ int length = property_get("persist.input.velocitytracker.strategy", value, NULL);
if (length > 0) {
strategy = value;
} else {
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index aca9521..f06119f 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -1,7 +1,6 @@
// Build the unit tests.
cc_test {
name: "libinput_tests",
- test_per_src: true,
srcs: [
"InputChannel_test.cpp",
"InputEvent_test.cpp",
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index fd3b7c8..c4b8fe3 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -22,6 +22,9 @@
namespace android {
+// Default display id.
+static constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
+
class BaseTest : public testing::Test {
protected:
virtual void SetUp() { }
@@ -248,7 +251,7 @@
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
- event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE, 0,
+ event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0,
AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
@@ -301,6 +304,7 @@
ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
ASSERT_EQ(2, event->getDeviceId());
ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_TOUCHSCREEN), event->getSource());
+ ASSERT_EQ(DISPLAY_ID, event->getDisplayId());
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, event->getAction());
ASSERT_EQ(AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, event->getFlags());
ASSERT_EQ(AMOTION_EVENT_EDGE_FLAG_TOP, event->getEdgeFlags());
@@ -434,6 +438,11 @@
event.setSource(AINPUT_SOURCE_JOYSTICK);
ASSERT_EQ(static_cast<int>(AINPUT_SOURCE_JOYSTICK), event.getSource());
+ // Set displayId.
+ constexpr int32_t newDisplayId = 2;
+ event.setDisplayId(newDisplayId);
+ ASSERT_EQ(newDisplayId, event.getDisplayId());
+
// Set action.
event.setAction(AMOTION_EVENT_ACTION_CANCEL);
ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, event.getAction());
@@ -557,7 +566,7 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
}
MotionEvent event;
- event.initialize(0, 0, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0,
+ event.initialize(0, 0, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, pointerCount, pointerProperties, pointerCoords);
float originalRawX = 0 + 3;
float originalRawY = -RADIUS + 2;
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index c532241..6c4faed 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -89,9 +89,7 @@
uint32_t consumeSeq;
InputEvent* event;
- int32_t displayId;
- status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
- &displayId);
+ status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
@@ -131,23 +129,23 @@
void InputPublisherAndConsumerTest::PublishAndConsumeMotionEvent() {
status_t status;
- const uint32_t seq = 15;
- const int32_t deviceId = 1;
- const int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
- int32_t displayId = 0;
- const int32_t action = AMOTION_EVENT_ACTION_MOVE;
- const int32_t actionButton = 0;
- const int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
- const int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
- const int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
- const int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
- const float xOffset = -10;
- const float yOffset = -20;
- const float xPrecision = 0.25;
- const float yPrecision = 0.5;
- const nsecs_t downTime = 3;
- const size_t pointerCount = 3;
- const nsecs_t eventTime = 4;
+ constexpr uint32_t seq = 15;
+ constexpr int32_t deviceId = 1;
+ constexpr int32_t source = AINPUT_SOURCE_TOUCHSCREEN;
+ constexpr int32_t displayId = 0;
+ constexpr int32_t action = AMOTION_EVENT_ACTION_MOVE;
+ constexpr int32_t actionButton = 0;
+ constexpr int32_t flags = AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED;
+ constexpr int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_TOP;
+ constexpr int32_t metaState = AMETA_ALT_LEFT_ON | AMETA_ALT_ON;
+ constexpr int32_t buttonState = AMOTION_EVENT_BUTTON_PRIMARY;
+ constexpr float xOffset = -10;
+ constexpr float yOffset = -20;
+ constexpr float xPrecision = 0.25;
+ constexpr float yPrecision = 0.5;
+ constexpr nsecs_t downTime = 3;
+ constexpr size_t pointerCount = 3;
+ constexpr nsecs_t eventTime = 4;
PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
for (size_t i = 0; i < pointerCount; i++) {
@@ -176,8 +174,7 @@
uint32_t consumeSeq;
InputEvent* event;
- status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
- &displayId);
+ status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
ASSERT_EQ(OK, status)
<< "consumer consume should return OK";
@@ -190,6 +187,7 @@
EXPECT_EQ(seq, consumeSeq);
EXPECT_EQ(deviceId, motionEvent->getDeviceId());
EXPECT_EQ(source, motionEvent->getSource());
+ EXPECT_EQ(displayId, motionEvent->getDisplayId());
EXPECT_EQ(action, motionEvent->getAction());
EXPECT_EQ(flags, motionEvent->getFlags());
EXPECT_EQ(edgeFlags, motionEvent->getEdgeFlags());
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index d19f3b8..77cce7a 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -38,14 +38,13 @@
CHECK_OFFSET(InputMessage::Body::Key, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Key, source, 20);
- CHECK_OFFSET(InputMessage::Body::Key, displayId, 24);
- CHECK_OFFSET(InputMessage::Body::Key, action, 28);
- CHECK_OFFSET(InputMessage::Body::Key, flags, 32);
- CHECK_OFFSET(InputMessage::Body::Key, keyCode, 36);
- CHECK_OFFSET(InputMessage::Body::Key, scanCode, 40);
- CHECK_OFFSET(InputMessage::Body::Key, metaState, 44);
- CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 48);
- CHECK_OFFSET(InputMessage::Body::Key, downTime, 56);
+ CHECK_OFFSET(InputMessage::Body::Key, action, 24);
+ CHECK_OFFSET(InputMessage::Body::Key, flags, 28);
+ CHECK_OFFSET(InputMessage::Body::Key, keyCode, 32);
+ CHECK_OFFSET(InputMessage::Body::Key, scanCode, 36);
+ CHECK_OFFSET(InputMessage::Body::Key, metaState, 40);
+ CHECK_OFFSET(InputMessage::Body::Key, repeatCount, 44);
+ CHECK_OFFSET(InputMessage::Body::Key, downTime, 48);
CHECK_OFFSET(InputMessage::Body::Motion, seq, 0);
CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8);
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 43b6012..5242a18 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -26,6 +26,8 @@
namespace android {
+constexpr int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT; // default display id
+
constexpr int32_t DEFAULT_POINTER_ID = 0; // pointer ID used for manually defined tests
// velocity must be in the range (1-tol)*EV <= velocity <= (1+tol)*EV
@@ -89,7 +91,7 @@
// First sample added separately with initialize
coords.setAxisValue(AMOTION_EVENT_AXIS_X, positions[0].x);
coords.setAxisValue(AMOTION_EVENT_AXIS_Y, positions[0].y);
- event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, AMOTION_EVENT_ACTION_MOVE,
+ event->initialize(0, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, AMOTION_EVENT_ACTION_MOVE,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, positions[0].time, 1, properties, &coords);
for (size_t i = 1; i < numSamples; i++) {
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 159f2bd..577cba9 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -42,11 +42,13 @@
BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
: Client{pdx::default_transport::ClientChannel::Create(
std::move(channel_handle))},
- id_(-1) {}
+ id_(-1),
+ cid_(-1) {}
BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
: Client{pdx::default_transport::ClientChannelFactory::Create(
endpoint_path)},
- id_(-1) {}
+ id_(-1),
+ cid_(-1) {}
BufferHubBuffer::~BufferHubBuffer() {
if (metadata_header_ != nullptr) {
@@ -136,6 +138,7 @@
}
id_ = new_id;
+ cid_ = buffer_desc.buffer_cid();
buffer_state_bit_ = buffer_desc.buffer_state_bit();
// Note that here the buffer state is mapped from shared memory as an atomic
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index 0ea77c8..b71f5dc 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -107,8 +107,14 @@
IonBuffer* buffer() { return &buffer_; }
const IonBuffer* buffer() const { return &buffer_; }
+ // Gets ID of the buffer client. All BufferHubBuffer clients derived from the
+ // same buffer in bufferhubd share the same buffer id.
int id() const { return id_; }
+ // Gets the channel id of the buffer client. Each BufferHubBuffer client has
+ // its system unique channel id.
+ int cid() const { return cid_; }
+
// Returns the buffer buffer state.
uint64_t buffer_state() { return buffer_state_->load(); };
@@ -170,6 +176,7 @@
// for logging and debugging purposes only and should not be used for lookup
// or any other functional purpose as a security precaution.
int id_;
+ int cid_;
uint64_t buffer_state_bit_{0ULL};
IonBuffer buffer_;
IonBuffer metadata_buffer_;
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index f4918c4..088a235 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -164,10 +164,11 @@
public:
BufferDescription() = default;
BufferDescription(const IonBuffer& buffer, const IonBuffer& metadata, int id,
- uint64_t buffer_state_bit,
+ int buffer_cid, uint64_t buffer_state_bit,
const FileHandleType& acquire_fence_fd,
const FileHandleType& release_fence_fd)
: id_(id),
+ buffer_cid_(buffer_cid),
buffer_state_bit_(buffer_state_bit),
buffer_(buffer, id),
metadata_(metadata, id),
@@ -180,6 +181,9 @@
// ID of the buffer client. All BufferHubBuffer clients derived from the same
// buffer in bufferhubd share the same buffer id.
int id() const { return id_; }
+ // Channel ID of the buffer client. Each BufferHubBuffer client has its system
+ // unique channel id.
+ int buffer_cid() const { return buffer_cid_; }
// State mask of the buffer client. Each BufferHubBuffer client backed by the
// same buffer channel has uniqued state bit among its siblings. For a
// producer buffer the bit must be kProducerStateBit; for a consumer the bit
@@ -193,6 +197,7 @@
private:
int id_{-1};
+ int buffer_cid_{-1};
uint64_t buffer_state_bit_{0};
// Two IonBuffers: one for the graphic buffer and one for metadata.
NativeBufferHandle<FileHandleType> buffer_;
@@ -202,7 +207,7 @@
FileHandleType acquire_fence_fd_;
FileHandleType release_fence_fd_;
- PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_,
+ PDX_SERIALIZABLE_MEMBERS(BufferDescription<FileHandleType>, id_, buffer_cid_,
buffer_state_bit_, buffer_, metadata_,
acquire_fence_fd_, release_fence_fd_);
@@ -381,6 +386,7 @@
kOpCreateConsumerQueue,
kOpGetQueueInfo,
kOpProducerQueueAllocateBuffers,
+ kOpProducerQueueInsertBuffer,
kOpProducerQueueRemoveBuffer,
kOpConsumerQueueImportBuffers,
// TODO(b/77153033): Separate all those RPC operations into subclasses.
@@ -430,6 +436,8 @@
std::vector<std::pair<LocalChannelHandle, size_t>>(
uint32_t width, uint32_t height, uint32_t layer_count,
uint32_t format, uint64_t usage, size_t buffer_count));
+ PDX_REMOTE_METHOD(ProducerQueueInsertBuffer, kOpProducerQueueInsertBuffer,
+ size_t(int buffer_cid));
PDX_REMOTE_METHOD(ProducerQueueRemoveBuffer, kOpProducerQueueRemoveBuffer,
void(size_t slot));
PDX_REMOTE_METHOD(ConsumerQueueImportBuffers, kOpConsumerQueueImportBuffers,
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 8feb1cd..1f2c517 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -524,6 +524,40 @@
return BufferHubQueue::Enqueue({buffer, slot, 0ULL});
}
+Status<size_t> ProducerQueue::InsertBuffer(
+ const std::shared_ptr<BufferProducer>& buffer) {
+ if (buffer == nullptr ||
+ !BufferHubDefs::IsBufferGained(buffer->buffer_state())) {
+ ALOGE(
+ "ProducerQueue::InsertBuffer: Can only insert a buffer when it's in "
+ "gained state.");
+ return ErrorStatus(EINVAL);
+ }
+
+ auto status_or_slot =
+ InvokeRemoteMethod<BufferHubRPC::ProducerQueueInsertBuffer>(
+ buffer->cid());
+ if (!status_or_slot) {
+ ALOGE(
+ "ProducerQueue::InsertBuffer: Failed to insert producer buffer: "
+ "buffer_cid=%d, error: %s.",
+ buffer->cid(), status_or_slot.GetErrorMessage().c_str());
+ return status_or_slot.error_status();
+ }
+
+ size_t slot = status_or_slot.get();
+
+ // Note that we are calling AddBuffer() from the base class to explicitly
+ // avoid Enqueue() the BufferProducer.
+ auto status = BufferHubQueue::AddBuffer(buffer, slot);
+ if (!status) {
+ ALOGE("ProducerQueue::InsertBuffer: Failed to add buffer: %s.",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
+ }
+ return {slot};
+}
+
Status<void> ProducerQueue::RemoveBuffer(size_t slot) {
auto status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueRemoveBuffer>(slot);
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 60e1c4b..df500b4 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -331,6 +331,13 @@
pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
size_t slot);
+ // Inserts a ProducerBuffer into the queue. On success, the method returns the
+ // |slot| number where the new buffer gets inserted. Note that the buffer
+ // being inserted should be in Gain'ed state prior to the call and it's
+ // considered as already Dequeued when the function returns.
+ pdx::Status<size_t> InsertBuffer(
+ const std::shared_ptr<BufferProducer>& buffer);
+
// Remove producer buffer from the queue.
pdx::Status<void> RemoveBuffer(size_t slot) override;
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 47a2734..2975f56 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -181,6 +181,40 @@
}
}
+TEST_F(BufferHubQueueTest, TestInsertBuffer) {
+ ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
+
+ consumer_queue_ = producer_queue_->CreateConsumerQueue();
+ ASSERT_TRUE(consumer_queue_ != nullptr);
+ EXPECT_EQ(producer_queue_->capacity(), 0);
+ EXPECT_EQ(consumer_queue_->capacity(), 0);
+
+ std::shared_ptr<BufferProducer> p1 = BufferProducer::Create(
+ kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage, 0);
+ ASSERT_TRUE(p1 != nullptr);
+
+ // Inserting a posted buffer will fail.
+ DvrNativeBufferMetadata meta;
+ EXPECT_EQ(p1->PostAsync(&meta, LocalHandle()), 0);
+ auto status_or_slot = producer_queue_->InsertBuffer(p1);
+ EXPECT_FALSE(status_or_slot.ok());
+ EXPECT_EQ(status_or_slot.error(), EINVAL);
+
+ // Inserting a gained buffer will succeed.
+ std::shared_ptr<BufferProducer> p2 = BufferProducer::Create(
+ kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage);
+ ASSERT_TRUE(p2 != nullptr);
+ status_or_slot = producer_queue_->InsertBuffer(p2);
+ EXPECT_TRUE(status_or_slot.ok());
+ // This is the first buffer inserted, should take slot 0.
+ size_t slot = status_or_slot.get();
+ EXPECT_EQ(slot, 0);
+
+ // Wait and expect the consumer to kick up the newly inserted buffer.
+ WaitAndHandleOnce(consumer_queue_.get(), kTimeoutMs);
+ EXPECT_EQ(consumer_queue_->capacity(), 1ULL);
+}
+
TEST_F(BufferHubQueueTest, TestRemoveBuffer) {
ASSERT_TRUE(CreateProducerQueue(config_builder_.Build(), UsagePolicy{}));
DvrNativeBufferMetadata mo;
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index 16906f5..00e4d4e 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -19,7 +19,14 @@
vendor_available: true,
}
+cc_library_headers {
+ name: "libdvr_private_headers",
+ export_include_dirs: ["."],
+ vendor_available: false,
+}
+
cflags = [
+ "-DDVR_TRACKING_IMPLEMENTED=0",
"-DLOG_TAG=\"libdvr\"",
"-DTRACE=0",
"-Wall",
@@ -36,6 +43,7 @@
"dvr_performance.cpp",
"dvr_pose.cpp",
"dvr_surface.cpp",
+ "dvr_tracking.cpp",
"dvr_vsync.cpp",
]
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index d14f040..e099f6a 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -12,6 +12,7 @@
#include <dvr/dvr_display_manager.h>
#include <dvr/dvr_performance.h>
#include <dvr/dvr_surface.h>
+#include <dvr/dvr_tracking.h>
#include <dvr/dvr_vsync.h>
// Headers not yet moved into libdvr.
diff --git a/libs/vr/libdvr/dvr_tracking.cpp b/libs/vr/libdvr/dvr_tracking.cpp
new file mode 100644
index 0000000..73addc9
--- /dev/null
+++ b/libs/vr/libdvr/dvr_tracking.cpp
@@ -0,0 +1,82 @@
+#include "include/dvr/dvr_tracking.h"
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#if !DVR_TRACKING_IMPLEMENTED
+
+extern "C" {
+
+// This file provides the stub implementation of dvrTrackingXXX APIs. On
+// platforms that implement these APIs, set -DDVR_TRACKING_IMPLEMENTED=1 in the
+// build file.
+int dvrTrackingCameraCreate(DvrTrackingCamera**) {
+ ALOGE("dvrTrackingCameraCreate is not implemented.");
+ return -ENOSYS;
+}
+
+void dvrTrackingCameraDestroy(DvrTrackingCamera*) {
+ ALOGE("dvrTrackingCameraDestroy is not implemented.");
+}
+
+int dvrTrackingCameraStart(DvrTrackingCamera*, DvrWriteBufferQueue*) {
+ ALOGE("dvrTrackingCameraCreate is not implemented.");
+ return -ENOSYS;
+}
+
+int dvrTrackingCameraStop(DvrTrackingCamera*) {
+ ALOGE("dvrTrackingCameraCreate is not implemented.");
+ return -ENOSYS;
+}
+
+int dvrTrackingFeatureExtractorCreate(DvrTrackingFeatureExtractor**) {
+ ALOGE("dvrTrackingFeatureExtractorCreate is not implemented.");
+ return -ENOSYS;
+}
+
+void dvrTrackingFeatureExtractorDestroy(DvrTrackingFeatureExtractor*) {
+ ALOGE("dvrTrackingFeatureExtractorDestroy is not implemented.");
+}
+
+int dvrTrackingFeatureExtractorStart(DvrTrackingFeatureExtractor*,
+ DvrTrackingFeatureCallback, void*) {
+ ALOGE("dvrTrackingFeatureExtractorCreate is not implemented.");
+ return -ENOSYS;
+}
+
+int dvrTrackingFeatureExtractorStop(DvrTrackingFeatureExtractor*) {
+ ALOGE("dvrTrackingFeatureExtractorCreate is not implemented.");
+ return -ENOSYS;
+}
+
+int dvrTrackingFeatureExtractorProcessBuffer(DvrTrackingFeatureExtractor*,
+ DvrReadBuffer*,
+ const DvrTrackingBufferMetadata*,
+ bool*) {
+ ALOGE("dvrTrackingFeatureExtractorProcessBuffer is not implemented.");
+ return -ENOSYS;
+}
+
+int dvrTrackingSensorsCreate(DvrTrackingSensors**, const char*) {
+ ALOGE("dvrTrackingSensorsCreate is not implemented.");
+ return -ENOSYS;
+}
+
+void dvrTrackingSensorsDestroy(DvrTrackingSensors*) {
+ ALOGE("dvrTrackingSensorsDestroy is not implemented.");
+}
+
+int dvrTrackingSensorsStart(DvrTrackingSensors*, DvrTrackingSensorEventCallback,
+ void*) {
+ ALOGE("dvrTrackingStart is not implemented.");
+ return -ENOSYS;
+}
+
+int dvrTrackingSensorsStop(DvrTrackingSensors*) {
+ ALOGE("dvrTrackingStop is not implemented.");
+ return -ENOSYS;
+}
+
+} // extern "C"
+
+#endif // DVR_TRACKING_IMPLEMENTED
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 80ffc82..fef8512 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -10,6 +10,7 @@
#include <dvr/dvr_display_types.h>
#include <dvr/dvr_hardware_composer_types.h>
#include <dvr/dvr_pose.h>
+#include <dvr/dvr_tracking_types.h>
#ifdef __cplusplus
extern "C" {
@@ -50,6 +51,12 @@
typedef struct DvrSurfaceAttributeValue DvrSurfaceAttributeValue;
typedef struct DvrSurfaceAttribute DvrSurfaceAttribute;
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrTrackingCamera DvrTrackingCamera;
+typedef struct DvrTrackingFeatureExtractor DvrTrackingFeatureExtractor;
+typedef struct DvrTrackingSensors DvrTrackingSensors;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+
// Note: To avoid breaking others during active development, only modify this
// struct by appending elements to the end.
// If you do feel we should to re-arrange or remove elements, please make a
@@ -367,6 +374,38 @@
typedef int (*DvrPerformanceSetSchedulerPolicyPtr)(
pid_t task_id, const char* scheduler_policy);
+// dvr_tracking.h
+typedef int (*DvrTrackingCameraCreatePtr)(DvrTrackingCamera** out_camera);
+typedef void (*DvrTrackingCameraDestroyPtr)(DvrTrackingCamera* camera);
+typedef int (*DvrTrackingCameraStartPtr)(DvrTrackingCamera* camera,
+ DvrWriteBufferQueue* write_queue);
+typedef int (*DvrTrackingCameraStopPtr)(DvrTrackingCamera* camera);
+
+typedef int (*DvrTrackingFeatureExtractorCreatePtr)(
+ DvrTrackingFeatureExtractor** out_extractor);
+typedef void (*DvrTrackingFeatureExtractorDestroyPtr)(
+ DvrTrackingFeatureExtractor* extractor);
+typedef void (*DvrTrackingFeatureCallback)(void* context,
+ const DvrTrackingFeatures* event);
+typedef int (*DvrTrackingFeatureExtractorStartPtr)(
+ DvrTrackingFeatureExtractor* extractor,
+ DvrTrackingFeatureCallback callback, void* context);
+typedef int (*DvrTrackingFeatureExtractorStopPtr)(
+ DvrTrackingFeatureExtractor* extractor);
+typedef int (*DvrTrackingFeatureExtractorProcessBufferPtr)(
+ DvrTrackingFeatureExtractor* extractor, DvrReadBuffer* buffer,
+ const DvrTrackingBufferMetadata* metadata, bool* out_skipped);
+
+typedef void (*DvrTrackingSensorEventCallback)(void* context,
+ DvrTrackingSensorEvent* event);
+typedef int (*DvrTrackingSensorsCreatePtr)(DvrTrackingSensors** out_sensors,
+ const char* mode);
+typedef void (*DvrTrackingSensorsDestroyPtr)(DvrTrackingSensors* sensors);
+typedef int (*DvrTrackingSensorsStartPtr)(
+ DvrTrackingSensors* sensors, DvrTrackingSensorEventCallback callback,
+ void* context);
+typedef int (*DvrTrackingSensorsStopPtr)(DvrTrackingSensors* sensors);
+
// The buffer metadata that an Android Surface (a.k.a. ANativeWindow)
// will populate. A DvrWriteBufferQueue must be created with this metadata iff
// ANativeWindow access is needed. Please do not remove, modify, or reorder
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index f0d8ec6..6620a37 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -181,3 +181,20 @@
DVR_V1_API_ENTRY(PoseClientGetDataReader);
DVR_V1_API_ENTRY(PoseClientDataCapture);
DVR_V1_API_ENTRY(PoseClientDataReaderDestroy);
+
+// Tracking
+DVR_V1_API_ENTRY(TrackingCameraCreate);
+DVR_V1_API_ENTRY(TrackingCameraDestroy);
+DVR_V1_API_ENTRY(TrackingCameraStart);
+DVR_V1_API_ENTRY(TrackingCameraStop);
+
+DVR_V1_API_ENTRY(TrackingFeatureExtractorCreate);
+DVR_V1_API_ENTRY(TrackingFeatureExtractorDestroy);
+DVR_V1_API_ENTRY(TrackingFeatureExtractorStart);
+DVR_V1_API_ENTRY(TrackingFeatureExtractorStop);
+DVR_V1_API_ENTRY(TrackingFeatureExtractorProcessBuffer);
+
+DVR_V1_API_ENTRY(TrackingSensorsCreate);
+DVR_V1_API_ENTRY(TrackingSensorsDestroy);
+DVR_V1_API_ENTRY(TrackingSensorsStart);
+DVR_V1_API_ENTRY(TrackingSensorsStop);
diff --git a/libs/vr/libdvr/include/dvr/dvr_tracking.h b/libs/vr/libdvr/include/dvr/dvr_tracking.h
new file mode 100644
index 0000000..5e388f3
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_tracking.h
@@ -0,0 +1,185 @@
+#ifndef ANDROID_DVR_TRACKING_H_
+#define ANDROID_DVR_TRACKING_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include <dvr/dvr_tracking_types.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrTrackingCamera DvrTrackingCamera;
+typedef struct DvrTrackingFeatureExtractor DvrTrackingFeatureExtractor;
+typedef struct DvrTrackingSensors DvrTrackingSensors;
+typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+
+// The callback for DvrTrackingFeatureExtractor that will deliver the feature
+// events. This callback is passed to dvrTrackingFeatureExtractorStart.
+typedef void (*DvrTrackingFeatureCallback)(void* context,
+ const DvrTrackingFeatures* event);
+
+// The callback for DvrTrackingSensors session that will deliver the events.
+// This callback is passed to dvrTrackingSensorsStart.
+typedef void (*DvrTrackingSensorEventCallback)(void* context,
+ DvrTrackingSensorEvent* event);
+
+// Creates a DvrTrackingCamera session.
+//
+// On creation, the session is not in operating mode. Client code must call
+// dvrTrackingCameraStart to bootstrap the underlying camera stack.
+//
+// There is no plan to expose camera configuration through this API. All camera
+// parameters are determined by the system optimized for better tracking
+// results. See b/78662281 for detailed deprecation plan of this API and the
+// Stage 2 of VR tracking data source refactoring.
+//
+// @param out_camera The pointer of a DvrTrackingCamera will be filled here if
+// the method call succeeds.
+// @return Zero on success, or negative error code.
+int dvrTrackingCameraCreate(DvrTrackingCamera** out_camera);
+
+// Destroys a DvrTrackingCamera handle.
+//
+// @param camera The DvrTrackingCamera of interest.
+void dvrTrackingCameraDestroy(DvrTrackingCamera* camera);
+
+// Starts the DvrTrackingCamera.
+//
+// On successful return, all DvrReadBufferQueue's associated with the given
+// write_queue will start to receive buffers from the camera stack. Note that
+// clients of this API should not assume the buffer dimension, format, and/or
+// usage of the outcoming buffers, as they are governed by the underlying camera
+// logic. Also note that it's the client's responsibility to consume buffers
+// from DvrReadBufferQueue on time and return them back to the producer;
+// otherwise the camera stack might be blocked.
+//
+// @param camera The DvrTrackingCamera of interest.
+// @param write_queue A DvrWriteBufferQueue that the camera stack can use to
+// populate the buffer into. The queue must be empty and the camera stack
+// will request buffer allocation with proper buffer dimension, format, and
+// usage. Note that the write queue must be created with user_metadata_size
+// set to sizeof(DvrTrackingBufferMetadata). On success, the write_queue
+// handle will become invalid and the ownership of the queue handle will be
+// transferred into the camera; otherwise, the write_queue handle will keep
+// untouched and the caller still has the ownership.
+// @return Zero on success, or negative error code.
+int dvrTrackingCameraStart(DvrTrackingCamera* camera,
+ DvrWriteBufferQueue* write_queue);
+
+// Stops the DvrTrackingCamera.
+//
+// On successful return, the DvrWriteBufferQueue set during
+// dvrTrackingCameraStart will stop getting new buffers from the camera stack.
+//
+// @param camera The DvrTrackingCamera of interest.
+// @return Zero on success, or negative error code.
+int dvrTrackingCameraStop(DvrTrackingCamera* camera);
+
+// Creates a DvrTrackingSensors session.
+//
+// This will initialize but not start device sensors (gyro / accel). Upon
+// successfull creation, the clients can call dvrTrackingSensorsStart to start
+// receiving sensor events.
+//
+// @param out_sensors The pointer of a DvrTrackingSensors will be filled here if
+// the method call succeeds.
+// @param mode The sensor mode.
+// mode="ndk": Use the Android NDK.
+// mode="direct": Use direct mode sensors (lower latency).
+// @return Zero on success, or negative error code.
+int dvrTrackingSensorsCreate(DvrTrackingSensors** out_sensors,
+ const char* mode);
+
+// Destroys a DvrTrackingSensors session.
+//
+// @param sensors The DvrTrackingSensors struct to destroy.
+void dvrTrackingSensorsDestroy(DvrTrackingSensors* sensors);
+
+// Starts the tracking sensor session.
+//
+// This will start the device sensors and start pumping the feature and sensor
+// events as they arrive.
+//
+// @param client A tracking client created by dvrTrackingSensorsCreate.
+// @param context A client supplied pointer that will be passed to the callback.
+// @param callback A callback that will receive the sensor events on an
+// arbitrary thread.
+// @return Zero on success, or negative error code.
+int dvrTrackingSensorsStart(DvrTrackingSensors* sensors,
+ DvrTrackingSensorEventCallback callback,
+ void* context);
+
+// Stops a DvrTrackingSensors session.
+//
+// This will stop the device sensors. dvrTrackingSensorsStart can be called to
+// restart them again.
+//
+// @param client A tracking client created by dvrTrackingClientCreate.
+// @return Zero on success, or negative error code.
+int dvrTrackingSensorsStop(DvrTrackingSensors* sensors);
+
+// Creates a tracking feature extractor.
+//
+// This will initialize but not start the feature extraction session. Upon
+// successful creation, the client can call dvrTrackingFeatureExtractorStart to
+// start receiving features.
+//
+// @param out_extractor The pointer of a DvrTrackingFeatureExtractor will be
+// filled here if the method call succeeds.
+int dvrTrackingFeatureExtractorCreate(
+ DvrTrackingFeatureExtractor** out_extractor);
+
+// Destroys a tracking feature extractor.
+//
+// @param extractor The DvrTrackingFeatureExtractor to destroy.
+void dvrTrackingFeatureExtractorDestroy(DvrTrackingFeatureExtractor* extractor);
+
+// Starts the tracking feature extractor.
+//
+// This will start the extractor and start pumping the output feature events to
+// the registered callback. Note that this method will create one or more
+// threads to handle feature processing.
+//
+// @param extractor The DvrTrackingFeatureExtractor to destroy.
+int dvrTrackingFeatureExtractorStart(DvrTrackingFeatureExtractor* extractor,
+ DvrTrackingFeatureCallback callback,
+ void* context);
+
+// Stops the tracking feature extractor.
+//
+// This will stop the extractor session and clean up all internal resourcse
+// related to this extractor. On succssful return, all internal therad started
+// by dvrTrackingFeatureExtractorStart should be stopped.
+//
+// @param extractor The DvrTrackingFeatureExtractor to destroy.
+int dvrTrackingFeatureExtractorStop(DvrTrackingFeatureExtractor* extractor);
+
+// Processes one buffer to extract features from.
+//
+// The buffer will be sent over to DSP for feature extraction. Once the process
+// is done, the processing thread will invoke DvrTrackingFeatureCallback with
+// newly extracted features. Note that not all buffers will be processed, as the
+// underlying DSP can only process buffers at a certain framerate. If a buffer
+// needs to be skipped, out_skipped filed will be set to true. Also note that
+// for successfully processed stereo buffer, two callbacks (one for each eye)
+// will be fired.
+//
+// @param extractor The DvrTrackingFeatureExtractor to destroy.
+// @param buffer The buffer to extract features from. Note that the buffer must
+// be in acquired state for the buffer to be processed. Also note that the
+// buffer will be released back to its producer on successful return of the
+// method.
+// @param metadata The metadata associated with the buffer. Should be populated
+// by DvrTrackingCamera session as user defined metadata.
+// @param out_skipped On successful return, the field will be set to true iff
+// the buffer was skipped; and false iff the buffer was processed. This
+// field is optional and nullptr can be passed here to ignore the field.
+// @return Zero on success, or negative error code.
+int dvrTrackingFeatureExtractorProcessBuffer(
+ DvrTrackingFeatureExtractor* extractor, DvrReadBuffer* buffer,
+ const DvrTrackingBufferMetadata* metadata, bool* out_skipped);
+
+__END_DECLS
+
+#endif // ANDROID_DVR_TRACKING_H_
diff --git a/libs/vr/libdvr/include/dvr/dvr_tracking_types.h b/libs/vr/libdvr/include/dvr/dvr_tracking_types.h
new file mode 100644
index 0000000..81310d2
--- /dev/null
+++ b/libs/vr/libdvr/include/dvr/dvr_tracking_types.h
@@ -0,0 +1,104 @@
+#ifndef ANDROID_DVR_TRACKING_TYPES_H_
+#define ANDROID_DVR_TRACKING_TYPES_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+typedef struct DvrTrackingBufferMetadata {
+ // Specifies the source of this image.
+ uint32_t camera_mask;
+ // Specifies the memory format of this image.
+ uint32_t format;
+ /// The width of the image data.
+ uint32_t width;
+ /// The height of the image data.
+ uint32_t height;
+ /// The number of bytes per scanline of image data.
+ uint32_t stride;
+ /// The frame number of this image.
+ int32_t frame_number;
+ /// The timestamp of this image in nanoseconds. Taken in the middle of the
+ /// exposure interval.
+ int64_t timestamp_ns;
+ // This is the timestamp for recording when the system using the HAL
+ // received the callback. It will not be populated by the HAL.
+ int64_t callback_timestamp_ns;
+ /// The exposure duration of this image in nanoseconds.
+ int64_t exposure_duration_ns;
+} DvrTrackingBufferMetadata;
+
+// Represents a set of features extracted from a camera frame. Note that this
+// should be in sync with TangoHalCallbacks defined in tango-hal.h.
+typedef struct DvrTrackingFeatures {
+ // Specifies the source of the features.
+ uint32_t camera_mask;
+
+ // This is unused.
+ uint32_t unused;
+
+ // The timestamp in nanoseconds from the image that generated the features.
+ // Taken in the middle of the exposure interval.
+ int64_t timestamp_ns;
+
+ // This is the timestamp for recording when the system using the HAL
+ // received the callback. It will not be populated by the HAL.
+ int64_t callback_timestamp_ns;
+
+ // The frame number from the image that generated the features.
+ int64_t frame_number;
+
+ // The number of features.
+ int count;
+
+ // An array of 2D image points for each feature in the current image.
+ // This is sub-pixel refined extremum location at the fine resolution.
+ float (*positions)[2];
+
+ // The id of these measurements.
+ int32_t* ids;
+
+ // The feature descriptors.
+ uint64_t (*descriptors)[8];
+
+ // Laplacian scores for each feature.
+ float* scores;
+
+ // Is this feature a minimum or maximum in the Laplacian image.
+ // 0 if the feature is a maximum, 1 if it is a minimum.
+ int32_t* is_minimum;
+
+ // This corresponds to the sub-pixel index of the laplacian image
+ // that the extremum was found.
+ float* scales;
+
+ // Computed orientation of keypoint as part of FREAK extraction, except
+ // it's represented in radians and measured anti-clockwise.
+ float* angles;
+
+ // Edge scores for each feature.
+ float* edge_scores;
+} DvrTrackingFeatures;
+
+// Represents a sensor event.
+typedef struct DvrTrackingSensorEvent {
+ // The sensor type.
+ int32_t sensor;
+
+ // Event type.
+ int32_t type;
+
+ // This is the timestamp recorded from the device. Taken in the middle
+ // of the integration interval and adjusted for any low pass filtering.
+ int64_t timestamp_ns;
+
+ // The event data.
+ float x;
+ float y;
+ float z;
+} DvrTrackingSensorEvent;
+
+__END_DECLS
+
+#endif // ANDROID_DVR_TRACKING_TYPES_H_
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index 1ae75fb..b23a0fa 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -12,38 +12,36 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-shared_libraries = [
- "libbase",
- "libbinder",
- "libbufferhubqueue",
- "libcutils",
- "libgui",
- "liblog",
- "libhardware",
- "libui",
- "libutils",
- "libnativewindow",
- "libpdx_default_transport",
-]
-
-static_libraries = [
- "libdvr_static",
- "libchrome",
- "libdvrcommon",
- "libdisplay",
- "libbroadcastring",
-]
-
cc_test {
srcs: [
"dvr_display_manager-test.cpp",
"dvr_named_buffer-test.cpp",
+ "dvr_tracking-test.cpp",
],
header_libs: ["libdvr_headers"],
- static_libs: static_libraries,
- shared_libs: shared_libraries,
+ static_libs: [
+ "libdvr_static",
+ "libchrome",
+ "libdvrcommon",
+ "libdisplay",
+ "libbroadcastring",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "libbufferhubqueue",
+ "libcutils",
+ "libgui",
+ "liblog",
+ "libhardware",
+ "libui",
+ "libutils",
+ "libnativewindow",
+ "libpdx_default_transport",
+ ],
cflags: [
+ "-DDVR_TRACKING_IMPLEMENTED=0",
"-DLOG_TAG=\"dvr_api-test\"",
"-DTRACE=0",
"-Wno-missing-field-initializers",
@@ -52,3 +50,55 @@
],
name: "dvr_api-test",
}
+
+cc_test {
+ name: "dvr_buffer_queue-test",
+
+ // Includes the dvr_api.h header. Tests should only include "dvr_api.h",
+ // and shall only get access to |dvrGetApi|, as other symbols are hidden
+ // from the library.
+ include_dirs: ["frameworks/native/libs/vr/libdvr/include"],
+
+ srcs: ["dvr_buffer_queue-test.cpp"],
+
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ ],
+
+ cflags: [
+ "-DTRACE=0",
+ "-O2",
+ "-g",
+ ],
+
+ // DTS Should only link to NDK libraries.
+ sdk_version: "26",
+ stl: "c++_static",
+}
+
+cc_test {
+ name: "dvr_display-test",
+
+ include_dirs: [
+ "frameworks/native/libs/vr/libdvr/include",
+ "frameworks/native/libs/nativewindow/include",
+ ],
+
+ srcs: ["dvr_display-test.cpp"],
+
+ shared_libs: [
+ "libandroid",
+ "liblog",
+ ],
+
+ cflags: [
+ "-DTRACE=0",
+ "-O2",
+ "-g",
+ ],
+
+ // DTS Should only link to NDK libraries.
+ sdk_version: "26",
+ stl: "c++_static",
+}
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
deleted file mode 100644
index 0f3840d..0000000
--- a/libs/vr/libdvr/tests/Android.mk
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-# TODO(b/73133405): Currently, building cc_test against NDK using Android.bp
-# doesn't work well. Migrate to use Android.bp once b/73133405 gets fixed.
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= dvr_buffer_queue-test
-
-# Includes the dvr_api.h header. Tests should only include "dvr_api.h",
-# and shall only get access to |dvrGetApi|, as other symbols are hidden from the
-# library.
-LOCAL_C_INCLUDES := \
- frameworks/native/libs/vr/libdvr/include \
-
-LOCAL_SANITIZE := thread
-
-LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid \
- liblog \
-
-LOCAL_CFLAGS := \
- -DTRACE=0 \
- -O2 \
- -g \
-
-# DTS Should only link to NDK libraries.
-LOCAL_SDK_VERSION := 26
-LOCAL_NDK_STL_VARIANT := c++_static
-
-include $(BUILD_NATIVE_TEST)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE:= dvr_display-test
-
-LOCAL_C_INCLUDES := \
- frameworks/native/libs/vr/libdvr/include \
- frameworks/native/libs/nativewindow/include
-
-LOCAL_SANITIZE := thread
-
-LOCAL_SRC_FILES := dvr_display-test.cpp
-
-LOCAL_SHARED_LIBRARIES := \
- libandroid \
- liblog
-
-LOCAL_CFLAGS := \
- -DTRACE=0 \
- -O2 \
- -g
-
-# DTS Should only link to NDK libraries.
-LOCAL_SDK_VERSION := 26
-LOCAL_NDK_STL_VARIANT := c++_static
-
-include $(BUILD_NATIVE_TEST)
\ No newline at end of file
diff --git a/libs/vr/libdvr/tests/dvr_tracking-test.cpp b/libs/vr/libdvr/tests/dvr_tracking-test.cpp
new file mode 100644
index 0000000..3b6d6e1
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_tracking-test.cpp
@@ -0,0 +1,103 @@
+#include <android/log.h>
+#include <gtest/gtest.h>
+
+#include "dvr_api_test.h"
+
+namespace {
+
+class DvrTrackingTest : public DvrApiTest {};
+
+#if DVR_TRACKING_IMPLEMENTED
+
+TEST_F(DvrTrackingTest, Implemented) {
+ ASSERT_TRUE(api_.TrackingCameraCreate != nullptr);
+ ASSERT_TRUE(api_.TrackingCameraStart != nullptr);
+ ASSERT_TRUE(api_.TrackingCameraStop != nullptr);
+
+ ASSERT_TRUE(api_.TrackingFeatureExtractorCreate != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorDestroy != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorStart != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorStop != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorProcessBuffer != nullptr);
+}
+
+TEST_F(DvrTrackingTest, CameraCreateFailsForInvalidInput) {
+ int ret;
+ ret = api_.TrackingCameraCreate(nullptr);
+ EXPECT_EQ(ret, -EINVAL);
+
+ DvrTrackingCamera* camera = reinterpret_cast<DvrTrackingCamera*>(42);
+ ret = api_.TrackingCameraCreate(&camera);
+ EXPECT_EQ(ret, -EINVAL);
+}
+
+TEST_F(DvrTrackingTest, CameraCreateDestroy) {
+ DvrTrackingCamera* camera = nullptr;
+ int ret = api_.TrackingCameraCreate(&camera);
+
+ EXPECT_EQ(ret, 0);
+ ASSERT_TRUE(camera != nullptr);
+
+ api_.TrackingCameraDestroy(camera);
+}
+
+TEST_F(DvrTrackingTest, FeatureExtractorCreateFailsForInvalidInput) {
+ int ret;
+ ret = api_.TrackingFeatureExtractorCreate(nullptr);
+ EXPECT_EQ(ret, -EINVAL);
+
+ DvrTrackingFeatureExtractor* camera =
+ reinterpret_cast<DvrTrackingFeatureExtractor*>(42);
+ ret = api_.TrackingFeatureExtractorCreate(&camera);
+ EXPECT_EQ(ret, -EINVAL);
+}
+
+TEST_F(DvrTrackingTest, FeatureExtractorCreateDestroy) {
+ DvrTrackingFeatureExtractor* camera = nullptr;
+ int ret = api_.TrackingFeatureExtractorCreate(&camera);
+
+ EXPECT_EQ(ret, 0);
+ ASSERT_TRUE(camera != nullptr);
+
+ api_.TrackingFeatureExtractorDestroy(camera);
+}
+
+#else // !DVR_TRACKING_IMPLEMENTED
+
+TEST_F(DvrTrackingTest, NotImplemented) {
+ ASSERT_TRUE(api_.TrackingCameraCreate != nullptr);
+ ASSERT_TRUE(api_.TrackingCameraDestroy != nullptr);
+ ASSERT_TRUE(api_.TrackingCameraStart != nullptr);
+ ASSERT_TRUE(api_.TrackingCameraStop != nullptr);
+
+ EXPECT_EQ(api_.TrackingCameraCreate(nullptr), -ENOSYS);
+ EXPECT_EQ(api_.TrackingCameraStart(nullptr, nullptr), -ENOSYS);
+ EXPECT_EQ(api_.TrackingCameraStop(nullptr), -ENOSYS);
+
+ ASSERT_TRUE(api_.TrackingFeatureExtractorCreate != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorDestroy != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorStart != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorStop != nullptr);
+ ASSERT_TRUE(api_.TrackingFeatureExtractorProcessBuffer != nullptr);
+
+ EXPECT_EQ(api_.TrackingFeatureExtractorCreate(nullptr), -ENOSYS);
+ EXPECT_EQ(api_.TrackingFeatureExtractorStart(nullptr, nullptr, nullptr),
+ -ENOSYS);
+ EXPECT_EQ(api_.TrackingFeatureExtractorStop(nullptr), -ENOSYS);
+ EXPECT_EQ(api_.TrackingFeatureExtractorProcessBuffer(nullptr, nullptr,
+ nullptr, nullptr),
+ -ENOSYS);
+
+ ASSERT_TRUE(api_.TrackingSensorsCreate != nullptr);
+ ASSERT_TRUE(api_.TrackingSensorsDestroy != nullptr);
+ ASSERT_TRUE(api_.TrackingSensorsStart != nullptr);
+ ASSERT_TRUE(api_.TrackingSensorsStop != nullptr);
+
+ EXPECT_EQ(api_.TrackingSensorsCreate(nullptr, nullptr), -ENOSYS);
+ EXPECT_EQ(api_.TrackingSensorsStart(nullptr, nullptr, nullptr), -ENOSYS);
+ EXPECT_EQ(api_.TrackingSensorsStop(nullptr), -ENOSYS);
+}
+
+#endif // DVR_TRACKING_IMPLEMENTED
+
+} // namespace
diff --git a/libs/vr/libpdx/private/pdx/service.h b/libs/vr/libpdx/private/pdx/service.h
index 13aa3e9..15fa327 100644
--- a/libs/vr/libpdx/private/pdx/service.h
+++ b/libs/vr/libpdx/private/pdx/service.h
@@ -59,9 +59,18 @@
virtual ~Channel() {}
/*
+ * Accessors to the pid of the last active client.
+ */
+ pid_t GetActiveProcessId() const { return client_pid_; }
+ void SetActiveProcessId(pid_t pid) { client_pid_ = pid; }
+
+ /*
* Utility to get a shared_ptr reference from the channel context pointer.
*/
static std::shared_ptr<Channel> GetFromMessageInfo(const MessageInfo& info);
+
+ private:
+ pid_t client_pid_ = 0;
};
/*
diff --git a/libs/vr/libpdx_uds/service_endpoint.cpp b/libs/vr/libpdx_uds/service_endpoint.cpp
index 32d40e8..ecbfdba 100644
--- a/libs/vr/libpdx_uds/service_endpoint.cpp
+++ b/libs/vr/libpdx_uds/service_endpoint.cpp
@@ -521,6 +521,9 @@
info.flags = 0;
info.service = service_;
info.channel = GetChannelState(channel_id);
+ if (info.channel != nullptr) {
+ info.channel->SetActiveProcessId(request.cred.pid);
+ }
info.send_len = request.send_len;
info.recv_len = request.max_recv_len;
info.fd_count = request.file_descriptors.size();
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 4dc669b..6f3f1d6 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -40,6 +40,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
"libbinder",
"libbase",
"libbufferhubqueue",
@@ -92,3 +93,7 @@
header_libs: headerLibraries,
name: "libvrflinger",
}
+
+subdirs = [
+ "tests",
+]
diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp
new file mode 100644
index 0000000..d500278
--- /dev/null
+++ b/libs/vr/libvrflinger/tests/Android.bp
@@ -0,0 +1,37 @@
+shared_libs = [
+ "android.hardware.configstore-utils",
+ "android.hardware.configstore@1.0",
+ "libbinder",
+ "libbufferhubqueue",
+ "libcutils",
+ "libgui",
+ "libhidlbase",
+ "liblog",
+ "libui",
+ "libutils",
+ "libnativewindow",
+ "libpdx_default_transport",
+]
+
+static_libs = [
+ "libdisplay",
+]
+
+cc_test {
+ srcs: ["vrflinger_test.cpp"],
+ // See go/apct-presubmit for documentation on how this .filter file is used
+ // by Android's automated testing infrastructure for test filtering.
+ data: ["vrflinger_test.filter"],
+ static_libs: static_libs,
+ shared_libs: shared_libs,
+ cflags: [
+ "-DLOG_TAG=\"VrFlingerTest\"",
+ "-DTRACE=0",
+ "-O0",
+ "-g",
+ "-Wall",
+ "-Werror",
+ ],
+ cppflags: ["-std=c++1z"],
+ name: "vrflinger_test",
+}
diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.cpp b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
new file mode 100644
index 0000000..3f7a72f
--- /dev/null
+++ b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
@@ -0,0 +1,229 @@
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.1/types.h>
+#include <android/hardware_buffer.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <configstore/Utils.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <gui/ISurfaceComposer.h>
+#include <log/log.h>
+#include <utils/StrongPointer.h>
+
+#include <chrono>
+#include <memory>
+#include <mutex>
+#include <optional>
+#include <thread>
+
+#include <private/dvr/display_client.h>
+
+using namespace android::hardware::configstore;
+using namespace android::hardware::configstore::V1_0;
+using android::dvr::display::DisplayClient;
+using android::dvr::display::Surface;
+using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceAttributeValue;
+
+namespace android {
+namespace dvr {
+
+// The transaction code for asking surface flinger if vr flinger is active. This
+// is done as a hidden api since it's only used for tests. See the "case 1028"
+// block in SurfaceFlinger::onTransact() in SurfaceFlinger.cpp.
+constexpr uint32_t kIsVrFlingerActiveTransactionCode = 1028;
+
+// The maximum amount of time to give vr flinger to activate/deactivate. If the
+// switch hasn't completed in this amount of time, the test will fail.
+constexpr auto kVrFlingerSwitchMaxTime = std::chrono::seconds(1);
+
+// How long to wait between each check to see if the vr flinger switch
+// completed.
+constexpr auto kVrFlingerSwitchPollInterval = std::chrono::milliseconds(50);
+
+// A Binder connection to surface flinger.
+class SurfaceFlingerConnection {
+ public:
+ static std::unique_ptr<SurfaceFlingerConnection> Create() {
+ sp<ISurfaceComposer> surface_flinger = interface_cast<ISurfaceComposer>(
+ defaultServiceManager()->getService(String16("SurfaceFlinger")));
+ if (surface_flinger == nullptr) {
+ return nullptr;
+ }
+
+ return std::unique_ptr<SurfaceFlingerConnection>(
+ new SurfaceFlingerConnection(surface_flinger));
+ }
+
+ // Returns true if the surface flinger process is still running. We use this
+ // to detect if surface flinger has crashed.
+ bool IsAlive() {
+ IInterface::asBinder(surface_flinger_)->pingBinder();
+ return IInterface::asBinder(surface_flinger_)->isBinderAlive();
+ }
+
+ // Return true if vr flinger is currently active, false otherwise. If there's
+ // an error communicating with surface flinger, std::nullopt is returned.
+ std::optional<bool> IsVrFlingerActive() {
+ Parcel data, reply;
+ status_t result =
+ data.writeInterfaceToken(surface_flinger_->getInterfaceDescriptor());
+ if (result != NO_ERROR) {
+ return std::nullopt;
+ }
+ result = IInterface::asBinder(surface_flinger_)
+ ->transact(kIsVrFlingerActiveTransactionCode, data, &reply);
+ if (result != NO_ERROR) {
+ return std::nullopt;
+ }
+ bool vr_flinger_active;
+ result = reply.readBool(&vr_flinger_active);
+ if (result != NO_ERROR) {
+ return std::nullopt;
+ }
+ return vr_flinger_active;
+ }
+
+ enum class VrFlingerSwitchResult : int8_t {
+ kSuccess,
+ kTimedOut,
+ kCommunicationError,
+ kSurfaceFlingerDied
+ };
+
+ // Wait for vr flinger to become active or inactive.
+ VrFlingerSwitchResult WaitForVrFlinger(bool wait_active) {
+ auto start_time = std::chrono::steady_clock::now();
+ while (1) {
+ std::this_thread::sleep_for(kVrFlingerSwitchPollInterval);
+ if (!IsAlive()) {
+ return VrFlingerSwitchResult::kSurfaceFlingerDied;
+ }
+ std::optional<bool> vr_flinger_active = IsVrFlingerActive();
+ if (!vr_flinger_active.has_value()) {
+ return VrFlingerSwitchResult::kCommunicationError;
+ }
+ if (vr_flinger_active.value() == wait_active) {
+ return VrFlingerSwitchResult::kSuccess;
+ } else if (std::chrono::steady_clock::now() - start_time >
+ kVrFlingerSwitchMaxTime) {
+ return VrFlingerSwitchResult::kTimedOut;
+ }
+ }
+ }
+
+ private:
+ SurfaceFlingerConnection(sp<ISurfaceComposer> surface_flinger)
+ : surface_flinger_(surface_flinger) {}
+
+ sp<ISurfaceComposer> surface_flinger_ = nullptr;
+};
+
+// This test activates vr flinger by creating a vr flinger surface, then
+// deactivates vr flinger by destroying the surface. We verify that vr flinger
+// is activated and deactivated as expected, and that surface flinger doesn't
+// crash.
+//
+// If the device doesn't support vr flinger (as repoted by ConfigStore), the
+// test does nothing.
+//
+// If the device is a standalone vr device, the test also does nothing, since
+// this test verifies the behavior of display handoff from surface flinger to vr
+// flinger and back, and standalone devices never hand control of the display
+// back to surface flinger.
+TEST(VrFlingerTest, ActivateDeactivate) {
+ android::ProcessState::self()->startThreadPool();
+
+ // Exit immediately if the device doesn't support vr flinger. This ConfigStore
+ // check is the same mechanism used by surface flinger to decide if it should
+ // initialize vr flinger.
+ bool vr_flinger_enabled =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::useVrFlinger>(
+ false);
+ if (!vr_flinger_enabled) {
+ return;
+ }
+
+ // This test doesn't apply to standalone vr devices.
+ if (property_get_bool("ro.boot.vr", false)) {
+ return;
+ }
+
+ auto surface_flinger_connection = SurfaceFlingerConnection::Create();
+ ASSERT_NE(surface_flinger_connection, nullptr);
+
+ // Verify we start off with vr flinger disabled.
+ ASSERT_TRUE(surface_flinger_connection->IsAlive());
+ auto vr_flinger_active = surface_flinger_connection->IsVrFlingerActive();
+ ASSERT_TRUE(vr_flinger_active.has_value());
+ ASSERT_FALSE(vr_flinger_active.value());
+
+ // Create a vr flinger surface, and verify vr flinger becomes active.
+ // Introduce a scope so that, at the end of the scope, the vr flinger surface
+ // is destroyed, and vr flinger deactivates.
+ {
+ auto display_client = DisplayClient::Create();
+ ASSERT_NE(display_client, nullptr);
+ auto metrics = display_client->GetDisplayMetrics();
+ ASSERT_TRUE(metrics.ok());
+
+ auto surface = Surface::CreateSurface({
+ {SurfaceAttribute::Direct, SurfaceAttributeValue(true)},
+ {SurfaceAttribute::Visible, SurfaceAttributeValue(true)},
+ });
+ ASSERT_TRUE(surface.ok());
+ ASSERT_TRUE(surface.get() != nullptr);
+
+ auto queue = surface.get()->CreateQueue(
+ metrics.get().display_width, metrics.get().display_height,
+ /*layer_count=*/1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
+ AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
+ AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+ /*capacity=*/1,
+ /*metadata_size=*/0);
+ ASSERT_TRUE(queue.ok());
+ ASSERT_TRUE(queue.get() != nullptr);
+
+ size_t slot;
+ pdx::LocalHandle release_fence;
+ auto buffer = queue.get()->Dequeue(/*timeout=*/0, &slot, &release_fence);
+ ASSERT_TRUE(buffer.ok());
+ ASSERT_TRUE(buffer.get() != nullptr);
+
+ ASSERT_EQ(buffer.get()->width(), metrics.get().display_width);
+ ASSERT_EQ(buffer.get()->height(), metrics.get().display_height);
+
+ void* raw_buf = nullptr;
+ ASSERT_GE(buffer.get()->Lock(AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+ /*x=*/0, /*y=*/0, buffer.get()->width(),
+ buffer.get()->height(), &raw_buf),
+ 0);
+ ASSERT_NE(raw_buf, nullptr);
+ uint32_t* pixels = static_cast<uint32_t*>(raw_buf);
+
+ for (int i = 0; i < buffer.get()->stride() * buffer.get()->height(); ++i) {
+ pixels[i] = 0x0000ff00;
+ }
+
+ ASSERT_GE(buffer.get()->Unlock(), 0);
+
+ ASSERT_GE(buffer.get()->Post(/*ready_fence=*/pdx::LocalHandle(),
+ /*meta=*/nullptr,
+ /*user_metadata_size=*/0),
+ 0);
+
+ ASSERT_EQ(
+ surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/true),
+ SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess);
+ }
+
+ // Now that the vr flinger surface is destroyed, vr flinger should deactivate.
+ ASSERT_EQ(
+ surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/false),
+ SurfaceFlingerConnection::VrFlingerSwitchResult::kSuccess);
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.filter b/libs/vr/libvrflinger/tests/vrflinger_test.filter
new file mode 100644
index 0000000..f6f3eff
--- /dev/null
+++ b/libs/vr/libvrflinger/tests/vrflinger_test.filter
@@ -0,0 +1,5 @@
+{
+ "presubmit": {
+ "filter": "VrFlingerTest.*"
+ }
+}
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index c65bddf..3312b03 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -1054,38 +1054,6 @@
egl_tls_t::setContext(EGL_NO_CONTEXT);
}
} else {
-
- if (cur_c != NULL) {
- // Force return to current context for drivers that cannot handle errors
- EGLBoolean restore_result = EGL_FALSE;
- // get a reference to the old current objects
- ContextRef _c2(dp.get(), cur_c);
- SurfaceRef _d2(dp.get(), cur_c->draw);
- SurfaceRef _r2(dp.get(), cur_c->read);
-
- c = cur_c;
- impl_ctx = c->context;
- impl_draw = EGL_NO_SURFACE;
- if (cur_c->draw != EGL_NO_SURFACE) {
- d = get_surface(cur_c->draw);
- impl_draw = d->surface;
- }
- impl_read = EGL_NO_SURFACE;
- if (cur_c->read != EGL_NO_SURFACE) {
- r = get_surface(cur_c->read);
- impl_read = r->surface;
- }
- restore_result = dp->makeCurrent(c, cur_c,
- cur_c->draw, cur_c->read, cur_c->context,
- impl_draw, impl_read, impl_ctx);
- if (restore_result == EGL_TRUE) {
- _c2.acquire();
- _r2.acquire();
- _d2.acquire();
- } else {
- ALOGE("Could not restore original EGL context");
- }
- }
// this will ALOGE the error
egl_connection_t* const cnx = &gEGLImpl;
result = setError(cnx->egl.eglGetError(), (EGLBoolean)EGL_FALSE);
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index 8508c5f..297a8a3 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -55,13 +55,38 @@
void egl_tls_t::validateTLSKey()
{
struct TlsKeyInitializer {
- static void create() {
- pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread);
- }
+ static void create() { pthread_key_create(&sKey, destructTLSData); }
};
pthread_once(&sOnceKey, TlsKeyInitializer::create);
}
+void egl_tls_t::destructTLSData(void* data) {
+ egl_tls_t* tls = static_cast<egl_tls_t*>(data);
+ if (!tls) return;
+
+ // Several things in the call tree of eglReleaseThread expect to be able to get the current
+ // thread state directly from TLS. That's a problem because Bionic has already cleared our
+ // TLS pointer before calling this function (pthread_getspecific(sKey) will return nullptr).
+ // Instead the data is passed as our parameter.
+ //
+ // Ideally we'd refactor this so we have thin wrappers that retrieve thread state from TLS and
+ // then pass it as a parameter (or 'this' pointer) to functions that do the real work without
+ // touching TLS. Then from here we could just call those implementation functions with the the
+ // TLS data we just received as a parameter.
+ //
+ // But that's a fairly invasive refactoring, so to do this robustly in the short term we just
+ // put the data *back* in TLS and call the top-level eglReleaseThread. It and it's call tree
+ // will retrieve the value from TLS, and then finally clear the TLS data. Bionic explicitly
+ // tolerates re-setting the value that it's currently trying to destruct (see
+ // pthread_key_clean_all()). Even if we forgot to clear the restored TLS data, bionic would
+ // call the destructor again, but eventually gives up and just leaks the data rather than
+ // enter an infinite loop.
+ pthread_setspecific(sKey, tls);
+ eglReleaseThread();
+ ALOGE_IF(pthread_getspecific(sKey) != nullptr,
+ "EGL TLS data still exists after eglReleaseThread");
+}
+
void egl_tls_t::setErrorEtcImpl(
const char* caller, int line, EGLint error, bool quiet) {
validateTLSKey();
diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h
index 9feae68..86a375c 100644
--- a/opengl/libs/EGL/egl_tls.h
+++ b/opengl/libs/EGL/egl_tls.h
@@ -38,6 +38,7 @@
egl_tls_t();
static void validateTLSKey();
+ static void destructTLSData(void* data);
static void setErrorEtcImpl(
const char* caller, int line, EGLint error, bool quiet);
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
deleted file mode 100755
index feef318..0000000
--- a/opengl/libs/tools/genfiles
+++ /dev/null
@@ -1,50 +0,0 @@
-#! /bin/sh
-#
-# Copyright (C) 2008 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# Force a specific locale for sorting to avoid irrelevant differences
-# in the generated files that could hide real differences.
-export LC_ALL=POSIX
-
-./glapigen ../../include/GLES/gl.h > ../GLES_CM/gl_api.in
-./glapigen ../../include/GLES/glext.h > ../GLES_CM/glext_api.in
-./glapigen ../../include/GLES3/gl3.h > ../GLES2/gl2_api.in
-./glapigen ../../include/GLES2/gl2ext.h > ../GLES2/gl2ext_api.in
-
-./glentrygen ../../include/GLES/gl.h > /tmp/gl_entries.in
-./glentrygen ../../include/GLES/glext.h > /tmp/glext_entries.in
-./glentrygen ../../include/GLES3/gl3.h > /tmp/gl2_entries.in
-./glentrygen ../../include/GLES2/gl2ext.h > /tmp/gl2ext_entries.in
-
-# The awk command removes lines with the same function name as an earlier
-# line, even if the rest of the line differs. Although signatures of
-# functions with the same name should be the same, the different versions
-# have some irrelevant whitespace and parameter name differences.
-cat /tmp/gl_entries.in \
- /tmp/glext_entries.in \
- /tmp/gl2_entries.in \
- /tmp/gl2ext_entries.in \
- | sort -t, -k2 \
- | awk -F, '!_[$2]++' \
- > ../entries.in
-
-cat ../../include/GLES/gl.h \
- ../../include/GLES/glext.h \
- ../../include/GLES2/gl2ext.h \
- ../../include/GLES3/gl3.h \
- | ./glenumsgen \
- | sort \
- > ../enums.in
-
diff --git a/opengl/libs/tools/glapigen b/opengl/libs/tools/glapigen
deleted file mode 100755
index 4d8334f..0000000
--- a/opengl/libs/tools/glapigen
+++ /dev/null
@@ -1,76 +0,0 @@
-#! /usr/bin/perl
-#
-# Copyright (C) 2008 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-use strict;
-
-sub rtrim($)
-{
- my $string = shift;
- $string =~ s/\s+$//;
- return $string;
-}
-
-while (my $line = <>) {
- next if $line =~ /^\//;
- next if $line =~ /^#/;
- next if $line =~ /^\s*$/;
- if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
- next;
- }
- my $type = rtrim($2);
- my $name = $3;
- my $args = $4;
-
- #printf("%s", $line);
-
- my $prefix = "";
- if ($name eq "glGetString") {
- $prefix = "__";
- }
-
- printf("%s API_ENTRY(%s%s)(%s)", $type, $prefix, $name, $args);
-
- printf(" {\n");
- if ($type eq "void") {
- printf(" CALL_GL_API(%s", $name);
- } else {
- printf(" CALL_GL_API_RETURN(%s", $name);
- }
- my @args = split ',', $args;
- my $len = scalar(@args);
- for (my $num = 0; $num < $len; $num++) {
- if ($args[$num] ne "void") {
- print ", ";
- #
- # extract the name from the parameter
- # type name
- # const type *name
- # type *name
- # type name[4]
- #
- if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) {
- printf("%s", $2);
- }
- }
- }
- printf(");\n");
- printf("}\n");
-}
-
-
-
-
-
diff --git a/opengl/libs/tools/glentrygen b/opengl/libs/tools/glentrygen
deleted file mode 100755
index 170f041..0000000
--- a/opengl/libs/tools/glentrygen
+++ /dev/null
@@ -1,38 +0,0 @@
-#! /usr/bin/perl
-#
-# Copyright (C) 2008 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-use strict;
-
-sub rtrim($)
-{
- my $string = shift;
- $string =~ s/\s+$//;
- return $string;
-}
-
-while (my $line = <>) {
- next if $line =~ /^\//;
- next if $line =~ /^#/;
- next if $line =~ /^\s*$/;
- if ($line !~ /^GL_API(CALL)?\s+(.+)\s+GL_APIENTRY\s+([\w]+)\s*\(([^\)]+)\);/) {
- next;
- }
- my $type = rtrim($2);
- my $name = $3;
- my $args = $4;
-
- printf("GL_ENTRY(%s, %s, %s)\n", $type, $name, $args);
-}
diff --git a/opengl/libs/tools/glenumsgen b/opengl/libs/tools/glenumsgen
deleted file mode 100755
index 2ae5fbf..0000000
--- a/opengl/libs/tools/glenumsgen
+++ /dev/null
@@ -1,38 +0,0 @@
-#! /usr/bin/perl
-#
-# Copyright (C) 2010 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-use strict;
-
-my %enumHash = ();
-
-while (my $line = <STDIN>) {
- next if $line =~ /^\//;
- # Skip bitfield definitions.
- next if $line =~ /_BIT(\d+_|\s+)/;
- if ($line !~ /^#define\s+(\S+)\s+(0x\S+)/) {
- next;
- }
- my $enumName = $1;
- my $enumValue = $2;
- next if exists($enumHash { $enumValue });
- $enumHash { $enumValue } = $enumName;
- printf("GL_ENUM(%s,%s)\n", $enumValue, $enumName);
-}
-
-
-
-
-
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index 186f399..7e2f648 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -2,6 +2,6 @@
name: "libbatteryservice_headers",
vendor_available: true,
export_include_dirs: ["include"],
- header_libs: ["libbinder_headers"],
- export_header_lib_headers: ["libbinder_headers"],
+ header_libs: ["libutils_headers"],
+ export_header_lib_headers: ["libutils_headers"],
}
diff --git a/services/batteryservice/include/batteryservice/BatteryService.h b/services/batteryservice/include/batteryservice/BatteryService.h
index 80ab7f3..1e8eb1e 100644
--- a/services/batteryservice/include/batteryservice/BatteryService.h
+++ b/services/batteryservice/include/batteryservice/BatteryService.h
@@ -17,7 +17,6 @@
#ifndef ANDROID_BATTERYSERVICE_H
#define ANDROID_BATTERYSERVICE_H
-#include <binder/Parcel.h>
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/String8.h>
@@ -54,16 +53,10 @@
int batteryFullCharge;
int batteryChargeCounter;
String8 batteryTechnology;
-
- status_t writeToParcel(Parcel* parcel) const;
- status_t readFromParcel(Parcel* parcel);
};
struct BatteryProperty {
int64_t valueInt64;
-
- status_t writeToParcel(Parcel* parcel) const;
- status_t readFromParcel(Parcel* parcel);
};
}; // namespace android
diff --git a/services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h b/services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h
deleted file mode 100644
index b226dd6..0000000
--- a/services/batteryservice/include/batteryservice/IBatteryPropertiesListener.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IBATTERYPROPERTIESLISTENER_H
-#define ANDROID_IBATTERYPROPERTIESLISTENER_H
-
-#include <binder/IBinder.h>
-#include <binder/IInterface.h>
-
-#include <batteryservice/BatteryService.h>
-
-namespace android {
-
-// must be kept in sync with interface defined in IBatteryPropertiesListener.aidl
-enum {
- TRANSACT_BATTERYPROPERTIESCHANGED = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-// ----------------------------------------------------------------------------
-
-class IBatteryPropertiesListener : public IInterface {
-public:
- DECLARE_META_INTERFACE(BatteryPropertiesListener)
-
- virtual void batteryPropertiesChanged(struct BatteryProperties props) = 0;
-};
-
-// ----------------------------------------------------------------------------
-
-class BnBatteryPropertiesListener: public BnInterface<IBatteryPropertiesListener> {
-public:
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IBATTERYPROPERTIESLISTENER_H
diff --git a/services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h b/services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h
deleted file mode 100644
index a7dbea6..0000000
--- a/services/batteryservice/include/batteryservice/IBatteryPropertiesRegistrar.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_IBATTERYPROPERTIESREGISTRAR_H
-#define ANDROID_IBATTERYPROPERTIESREGISTRAR_H
-
-#include <binder/IInterface.h>
-#include <batteryservice/IBatteryPropertiesListener.h>
-
-namespace android {
-
-// must be kept in sync with interface defined in IBatteryPropertiesRegistrar.aidl
-enum {
- REGISTER_LISTENER = IBinder::FIRST_CALL_TRANSACTION,
- UNREGISTER_LISTENER,
- GET_PROPERTY,
- SCHEDULE_UPDATE,
-};
-
-class IBatteryPropertiesRegistrar : public IInterface {
-public:
- DECLARE_META_INTERFACE(BatteryPropertiesRegistrar)
-
- virtual void registerListener(const sp<IBatteryPropertiesListener>& listener) = 0;
- virtual void unregisterListener(const sp<IBatteryPropertiesListener>& listener) = 0;
- virtual status_t getProperty(int id, struct BatteryProperty *val) = 0;
- virtual void scheduleUpdate() = 0;
-};
-
-class BnBatteryPropertiesRegistrar : public BnInterface<IBatteryPropertiesRegistrar> {
-public:
- virtual status_t onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags = 0);
-};
-
-}; // namespace android
-
-#endif // ANDROID_IBATTERYPROPERTIESREGISTRAR_H
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 9a449fa..078fbca 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -924,12 +924,13 @@
void InputDispatcher::logOutboundMotionDetailsLocked(const char* prefix, const MotionEntry* entry) {
#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
+ ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
+ ", policyFlags=0x%x, "
"action=0x%x, actionButton=0x%x, flags=0x%x, "
"metaState=0x%x, buttonState=0x%x,"
"edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
prefix,
- entry->eventTime, entry->deviceId, entry->source, entry->policyFlags,
+ entry->eventTime, entry->deviceId, entry->source, entry->displayId, entry->policyFlags,
entry->action, entry->actionButton, entry->flags,
entry->metaState, entry->buttonState,
entry->edgeFlags, entry->xPrecision, entry->yPrecision,
@@ -2384,6 +2385,7 @@
originalMotionEntry->eventTime,
originalMotionEntry->deviceId,
originalMotionEntry->source,
+ originalMotionEntry->displayId,
originalMotionEntry->policyFlags,
action,
originalMotionEntry->actionButton,
@@ -2394,7 +2396,6 @@
originalMotionEntry->xPrecision,
originalMotionEntry->yPrecision,
originalMotionEntry->downTime,
- originalMotionEntry->displayId,
splitPointerCount, splitPointerProperties, splitPointerCoords, 0, 0);
if (originalMotionEntry->injectionState) {
@@ -2423,6 +2424,43 @@
}
}
+/**
+ * If one of the meta shortcuts is detected, process them here:
+ * Meta + Backspace -> generate BACK
+ * Meta + Enter -> generate HOME
+ * This will potentially overwrite keyCode and metaState.
+ */
+void InputDispatcher::accelerateMetaShortcuts(const int32_t deviceId, const int32_t action,
+ int32_t& keyCode, int32_t& metaState) {
+ if (metaState & AMETA_META_ON && action == AKEY_EVENT_ACTION_DOWN) {
+ int32_t newKeyCode = AKEYCODE_UNKNOWN;
+ if (keyCode == AKEYCODE_DEL) {
+ newKeyCode = AKEYCODE_BACK;
+ } else if (keyCode == AKEYCODE_ENTER) {
+ newKeyCode = AKEYCODE_HOME;
+ }
+ if (newKeyCode != AKEYCODE_UNKNOWN) {
+ AutoMutex _l(mLock);
+ struct KeyReplacement replacement = {keyCode, deviceId};
+ mReplacedKeys.add(replacement, newKeyCode);
+ keyCode = newKeyCode;
+ metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
+ }
+ } else if (action == AKEY_EVENT_ACTION_UP) {
+ // In order to maintain a consistent stream of up and down events, check to see if the key
+ // going up is one we've replaced in a down event and haven't yet replaced in an up event,
+ // even if the modifier was released between the down and the up events.
+ AutoMutex _l(mLock);
+ struct KeyReplacement replacement = {keyCode, deviceId};
+ ssize_t index = mReplacedKeys.indexOfKey(replacement);
+ if (index >= 0) {
+ keyCode = mReplacedKeys.valueAt(index);
+ mReplacedKeys.removeItemsAt(index);
+ metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
+ }
+ }
+}
+
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("notifyKey - eventTime=%" PRId64
@@ -2450,33 +2488,7 @@
policyFlags |= POLICY_FLAG_TRUSTED;
int32_t keyCode = args->keyCode;
- if (metaState & AMETA_META_ON && args->action == AKEY_EVENT_ACTION_DOWN) {
- int32_t newKeyCode = AKEYCODE_UNKNOWN;
- if (keyCode == AKEYCODE_DEL) {
- newKeyCode = AKEYCODE_BACK;
- } else if (keyCode == AKEYCODE_ENTER) {
- newKeyCode = AKEYCODE_HOME;
- }
- if (newKeyCode != AKEYCODE_UNKNOWN) {
- AutoMutex _l(mLock);
- struct KeyReplacement replacement = {keyCode, args->deviceId};
- mReplacedKeys.add(replacement, newKeyCode);
- keyCode = newKeyCode;
- metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
- }
- } else if (args->action == AKEY_EVENT_ACTION_UP) {
- // In order to maintain a consistent stream of up and down events, check to see if the key
- // going up is one we've replaced in a down event and haven't yet replaced in an up event,
- // even if the modifier was released between the down and the up events.
- AutoMutex _l(mLock);
- struct KeyReplacement replacement = {keyCode, args->deviceId};
- ssize_t index = mReplacedKeys.indexOfKey(replacement);
- if (index >= 0) {
- keyCode = mReplacedKeys.valueAt(index);
- mReplacedKeys.removeItemsAt(index);
- metaState &= ~(AMETA_META_ON | AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON);
- }
- }
+ accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);
KeyEvent event;
event.initialize(args->deviceId, args->source, args->action,
@@ -2526,10 +2538,11 @@
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, policyFlags=0x%x, "
+ ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
+ ", policyFlags=0x%x, "
"action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x,"
"edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64,
- args->eventTime, args->deviceId, args->source, args->policyFlags,
+ args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime);
for (uint32_t i = 0; i < args->pointerCount; i++) {
@@ -2573,7 +2586,8 @@
mLock.unlock();
MotionEvent event;
- event.initialize(args->deviceId, args->source, args->action, args->actionButton,
+ event.initialize(args->deviceId, args->source, args->displayId,
+ args->action, args->actionButton,
args->flags, args->edgeFlags, args->metaState, args->buttonState,
0, 0, args->xPrecision, args->yPrecision,
args->downTime, args->eventTime,
@@ -2589,11 +2603,10 @@
// Just enqueue a new motion event.
MotionEntry* newEntry = new MotionEntry(args->eventTime,
- args->deviceId, args->source, policyFlags,
+ args->deviceId, args->source, args->displayId, policyFlags,
args->action, args->actionButton, args->flags,
args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
- args->displayId,
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
needWake = enqueueInboundEventLocked(newEntry);
@@ -2642,14 +2655,13 @@
}
}
-int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displayId,
+int32_t InputDispatcher::injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("injectInputEvent - eventType=%d, injectorPid=%d, injectorUid=%d, "
- "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x, displayId=%d",
- event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags,
- displayId);
+ "syncMode=%d, timeoutMillis=%d, policyFlags=0x%08x",
+ event->getType(), injectorPid, injectorUid, syncMode, timeoutMillis, policyFlags);
#endif
nsecs_t endTime = now() + milliseconds_to_nanoseconds(timeoutMillis);
@@ -2663,20 +2675,29 @@
EventEntry* lastInjectedEntry;
switch (event->getType()) {
case AINPUT_EVENT_TYPE_KEY: {
- const KeyEvent* keyEvent = static_cast<const KeyEvent*>(event);
- int32_t action = keyEvent->getAction();
+ KeyEvent keyEvent;
+ keyEvent.initialize(*static_cast<const KeyEvent*>(event));
+ int32_t action = keyEvent.getAction();
if (! validateKeyEvent(action)) {
return INPUT_EVENT_INJECTION_FAILED;
}
- int32_t flags = keyEvent->getFlags();
+ int32_t flags = keyEvent.getFlags();
+ int32_t keyCode = keyEvent.getKeyCode();
+ int32_t metaState = keyEvent.getMetaState();
+ accelerateMetaShortcuts(keyEvent.getDeviceId(), action,
+ /*byref*/ keyCode, /*byref*/ metaState);
+ keyEvent.initialize(keyEvent.getDeviceId(), keyEvent.getSource(), action,
+ flags, keyCode, keyEvent.getScanCode(), metaState, 0,
+ keyEvent.getDownTime(), keyEvent.getEventTime());
+
if (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY) {
policyFlags |= POLICY_FLAG_VIRTUAL;
}
if (!(policyFlags & POLICY_FLAG_FILTERED)) {
android::base::Timer t;
- mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
+ mPolicy->interceptKeyBeforeQueueing(&keyEvent, /*byref*/ policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
std::to_string(t.duration().count()).c_str());
@@ -2684,11 +2705,11 @@
}
mLock.lock();
- firstInjectedEntry = new KeyEntry(keyEvent->getEventTime(),
- keyEvent->getDeviceId(), keyEvent->getSource(),
+ firstInjectedEntry = new KeyEntry(keyEvent.getEventTime(),
+ keyEvent.getDeviceId(), keyEvent.getSource(),
policyFlags, action, flags,
- keyEvent->getKeyCode(), keyEvent->getScanCode(), keyEvent->getMetaState(),
- keyEvent->getRepeatCount(), keyEvent->getDownTime());
+ keyEvent.getKeyCode(), keyEvent.getScanCode(), keyEvent.getMetaState(),
+ keyEvent.getRepeatCount(), keyEvent.getDownTime());
lastInjectedEntry = firstInjectedEntry;
break;
}
@@ -2717,12 +2738,13 @@
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
firstInjectedEntry = new MotionEntry(*sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
+ motionEvent->getDeviceId(), motionEvent->getSource(), motionEvent->getDisplayId(),
+ policyFlags,
action, actionButton, motionEvent->getFlags(),
motionEvent->getMetaState(), motionEvent->getButtonState(),
motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
- motionEvent->getDownTime(), displayId,
+ motionEvent->getDownTime(),
uint32_t(pointerCount), pointerProperties, samplePointerCoords,
motionEvent->getXOffset(), motionEvent->getYOffset());
lastInjectedEntry = firstInjectedEntry;
@@ -2730,12 +2752,13 @@
sampleEventTimes += 1;
samplePointerCoords += pointerCount;
MotionEntry* nextInjectedEntry = new MotionEntry(*sampleEventTimes,
- motionEvent->getDeviceId(), motionEvent->getSource(), policyFlags,
+ motionEvent->getDeviceId(), motionEvent->getSource(),
+ motionEvent->getDisplayId(), policyFlags,
action, actionButton, motionEvent->getFlags(),
motionEvent->getMetaState(), motionEvent->getButtonState(),
motionEvent->getEdgeFlags(),
motionEvent->getXPrecision(), motionEvent->getYPrecision(),
- motionEvent->getDownTime(), displayId,
+ motionEvent->getDownTime(),
uint32_t(pointerCount), pointerProperties, samplePointerCoords,
motionEvent->getXOffset(), motionEvent->getYOffset());
lastInjectedEntry->next = nextInjectedEntry;
@@ -4026,18 +4049,19 @@
// --- InputDispatcher::MotionEntry ---
InputDispatcher::MotionEntry::MotionEntry(nsecs_t eventTime, int32_t deviceId,
- uint32_t source, uint32_t policyFlags, int32_t action, int32_t actionButton,
+ uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t actionButton,
int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
float xPrecision, float yPrecision, nsecs_t downTime,
- int32_t displayId, uint32_t pointerCount,
+ uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xOffset, float yOffset) :
EventEntry(TYPE_MOTION, eventTime, policyFlags),
eventTime(eventTime),
- deviceId(deviceId), source(source), action(action), actionButton(actionButton),
- flags(flags), metaState(metaState), buttonState(buttonState),
+ deviceId(deviceId), source(source), displayId(displayId), action(action),
+ actionButton(actionButton), flags(flags), metaState(metaState), buttonState(buttonState),
edgeFlags(edgeFlags), xPrecision(xPrecision), yPrecision(yPrecision),
- downTime(downTime), displayId(displayId), pointerCount(pointerCount) {
+ downTime(downTime), pointerCount(pointerCount) {
for (uint32_t i = 0; i < pointerCount; i++) {
this->pointerProperties[i].copyFrom(pointerProperties[i]);
this->pointerCoords[i].copyFrom(pointerCoords[i]);
@@ -4051,11 +4075,12 @@
}
void InputDispatcher::MotionEntry::appendDescription(std::string& msg) const {
- msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, action=%s, actionButton=0x%08x, "
- "flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
- "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, displayId=%d, pointers=[",
- deviceId, source, motionActionToString(action).c_str(), actionButton, flags, metaState,
- buttonState, edgeFlags, xPrecision, yPrecision, displayId);
+ msg += StringPrintf("MotionEvent(deviceId=%d, source=0x%08x, displayId=%" PRId32
+ ", action=%s, actionButton=0x%08x, flags=0x%08x, metaState=0x%08x, buttonState=0x%08x, "
+ "edgeFlags=0x%08x, xPrecision=%.1f, yPrecision=%.1f, pointers=[",
+ deviceId, source, displayId, motionActionToString(action).c_str(), actionButton, flags,
+ metaState, buttonState, edgeFlags, xPrecision, yPrecision);
+
for (uint32_t i = 0; i < pointerCount; i++) {
if (i) {
msg += ", ";
@@ -4184,8 +4209,8 @@
}
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Dropping inconsistent motion up or cancel event: deviceId=%d, source=%08x, "
- "actionMasked=%d",
- entry->deviceId, entry->source, actionMasked);
+ "displayId=%" PRId32 ", actionMasked=%d",
+ entry->deviceId, entry->source, entry->displayId, actionMasked);
#endif
return false;
}
@@ -4237,8 +4262,8 @@
}
#if DEBUG_OUTBOUND_EVENT_DETAILS
ALOGD("Dropping inconsistent motion pointer up/down or move event: "
- "deviceId=%d, source=%08x, actionMasked=%d",
- entry->deviceId, entry->source, actionMasked);
+ "deviceId=%d, source=%08x, displayId=%" PRId32 ", actionMasked=%d",
+ entry->deviceId, entry->source, entry->displayId, actionMasked);
#endif
return false;
}
@@ -4250,8 +4275,9 @@
return true;
}
#if DEBUG_OUTBOUND_EVENT_DETAILS
- ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x",
- entry->deviceId, entry->source);
+ ALOGD("Dropping inconsistent motion hover exit event: deviceId=%d, source=%08x, "
+ "displayId=%" PRId32,
+ entry->deviceId, entry->source, entry->displayId);
#endif
return false;
}
@@ -4317,11 +4343,11 @@
MotionMemento& memento = mMotionMementos.editTop();
memento.deviceId = entry->deviceId;
memento.source = entry->source;
+ memento.displayId = entry->displayId;
memento.flags = flags;
memento.xPrecision = entry->xPrecision;
memento.yPrecision = entry->yPrecision;
memento.downTime = entry->downTime;
- memento.displayId = entry->displayId;
memento.setPointers(entry);
memento.hovering = hovering;
memento.policyFlags = entry->policyFlags;
@@ -4351,13 +4377,12 @@
const MotionMemento& memento = mMotionMementos.itemAt(i);
if (shouldCancelMotion(memento, options)) {
outEvents.push(new MotionEntry(currentTime,
- memento.deviceId, memento.source, memento.policyFlags,
+ memento.deviceId, memento.source, memento.displayId, memento.policyFlags,
memento.hovering
? AMOTION_EVENT_ACTION_HOVER_EXIT
: AMOTION_EVENT_ACTION_CANCEL,
memento.flags, 0, 0, 0, 0,
memento.xPrecision, memento.yPrecision, memento.downTime,
- memento.displayId,
memento.pointerCount, memento.pointerProperties, memento.pointerCoords,
0, 0));
}
diff --git a/services/inputflinger/InputDispatcher.h b/services/inputflinger/InputDispatcher.h
index 8da8450..82960b7 100644
--- a/services/inputflinger/InputDispatcher.h
+++ b/services/inputflinger/InputDispatcher.h
@@ -299,7 +299,7 @@
*
* This method may be called on any thread (usually by the input manager).
*/
- virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId,
+ virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags) = 0;
@@ -383,7 +383,7 @@
virtual void notifySwitch(const NotifySwitchArgs* args);
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args);
- virtual int32_t injectInputEvent(const InputEvent* event, int32_t displayId,
+ virtual int32_t injectInputEvent(const InputEvent* event,
int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,
uint32_t policyFlags);
@@ -508,6 +508,7 @@
nsecs_t eventTime;
int32_t deviceId;
uint32_t source;
+ int32_t displayId;
int32_t action;
int32_t actionButton;
int32_t flags;
@@ -517,17 +518,15 @@
float xPrecision;
float yPrecision;
nsecs_t downTime;
- int32_t displayId;
uint32_t pointerCount;
PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
MotionEntry(nsecs_t eventTime,
- int32_t deviceId, uint32_t source, uint32_t policyFlags,
+ int32_t deviceId, uint32_t source, int32_t displayId, uint32_t policyFlags,
int32_t action, int32_t actionButton, int32_t flags,
int32_t metaState, int32_t buttonState, int32_t edgeFlags,
- float xPrecision, float yPrecision, nsecs_t downTime,
- int32_t displayId, uint32_t pointerCount,
+ float xPrecision, float yPrecision, nsecs_t downTime, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xOffset, float yOffset);
virtual void appendDescription(std::string& msg) const;
@@ -765,11 +764,11 @@
struct MotionMemento {
int32_t deviceId;
uint32_t source;
+ int32_t displayId;
int32_t flags;
float xPrecision;
float yPrecision;
nsecs_t downTime;
- int32_t displayId;
uint32_t pointerCount;
PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
@@ -932,6 +931,9 @@
};
// Maps the key code replaced, device id tuple to the key code it was replaced with
KeyedVector<KeyReplacement, int32_t> mReplacedKeys;
+ // Process certain Meta + Key combinations
+ void accelerateMetaShortcuts(const int32_t deviceId, const int32_t action,
+ int32_t& keyCode, int32_t& metaState);
// Deferred command processing.
bool haveCommandsLocked() const;
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 520fea4..c36d7cf 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -67,16 +67,17 @@
// --- NotifyMotionArgs ---
NotifyMotionArgs::NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source,
- uint32_t policyFlags,
+ int32_t displayId, uint32_t policyFlags,
int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
- int32_t buttonState, int32_t edgeFlags, int32_t displayId, uint32_t deviceTimestamp,
+ int32_t buttonState, int32_t edgeFlags, uint32_t deviceTimestamp,
uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime) :
- eventTime(eventTime), deviceId(deviceId), source(source), policyFlags(policyFlags),
+ eventTime(eventTime), deviceId(deviceId), source(source), displayId(displayId),
+ policyFlags(policyFlags),
action(action), actionButton(actionButton),
flags(flags), metaState(metaState), buttonState(buttonState),
- edgeFlags(edgeFlags), displayId(displayId), deviceTimestamp(deviceTimestamp),
+ edgeFlags(edgeFlags), deviceTimestamp(deviceTimestamp),
pointerCount(pointerCount),
xPrecision(xPrecision), yPrecision(yPrecision), downTime(downTime) {
for (uint32_t i = 0; i < pointerCount; i++) {
@@ -87,10 +88,10 @@
NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
eventTime(other.eventTime), deviceId(other.deviceId), source(other.source),
- policyFlags(other.policyFlags),
+ displayId(other.displayId), policyFlags(other.policyFlags),
action(other.action), actionButton(other.actionButton), flags(other.flags),
metaState(other.metaState), buttonState(other.buttonState),
- edgeFlags(other.edgeFlags), displayId(other.displayId),
+ edgeFlags(other.edgeFlags),
deviceTimestamp(other.deviceTimestamp), pointerCount(other.pointerCount),
xPrecision(other.xPrecision), yPrecision(other.yPrecision), downTime(other.downTime) {
for (uint32_t i = 0; i < pointerCount; i++) {
diff --git a/services/inputflinger/InputListener.h b/services/inputflinger/InputListener.h
index 77afb34..d24be4c 100644
--- a/services/inputflinger/InputListener.h
+++ b/services/inputflinger/InputListener.h
@@ -82,6 +82,7 @@
nsecs_t eventTime;
int32_t deviceId;
uint32_t source;
+ int32_t displayId;
uint32_t policyFlags;
int32_t action;
int32_t actionButton;
@@ -89,7 +90,6 @@
int32_t metaState;
int32_t buttonState;
int32_t edgeFlags;
- int32_t displayId;
/**
* A timestamp in the input device's time base, not the platform's.
* The units are microseconds since the last reset.
@@ -106,10 +106,11 @@
inline NotifyMotionArgs() { }
- NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, uint32_t policyFlags,
+ NotifyMotionArgs(nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags,
int32_t action, int32_t actionButton, int32_t flags,
int32_t metaState, int32_t buttonState,
- int32_t edgeFlags, int32_t displayId, uint32_t deviceTimestamp, uint32_t pointerCount,
+ int32_t edgeFlags, uint32_t deviceTimestamp, uint32_t pointerCount,
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime);
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index e0cd8a0..50229cb 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -2279,15 +2279,12 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ mOrientation = DISPLAY_ORIENTATION_0;
if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
DisplayViewport v;
if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) {
mOrientation = v.orientation;
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
}
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
}
}
}
@@ -2699,15 +2696,12 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ mOrientation = DISPLAY_ORIENTATION_0;
if (mParameters.orientationAware && mParameters.hasAssociatedDisplay) {
DisplayViewport v;
if (config->getDisplayViewport(ViewportType::VIEWPORT_INTERNAL, NULL, &v)) {
mOrientation = v.orientation;
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
}
- } else {
- mOrientation = DISPLAY_ORIENTATION_0;
}
bumpGeneration();
}
@@ -2894,19 +2888,19 @@
while (!released.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
buttonState &= ~actionButton;
- NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&releaseArgs);
}
}
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, displayId, policyFlags,
motionEventAction, 0, 0, metaState, currentButtonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&args);
@@ -2915,10 +2909,10 @@
while (!pressed.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
buttonState |= actionButton;
- NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&pressArgs);
}
@@ -2929,10 +2923,10 @@
// Send hover move after UP to tell the application that the mouse is hovering now.
if (motionEventAction == AMOTION_EVENT_ACTION_UP
&& (mSource == AINPUT_SOURCE_MOUSE)) {
- NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs hoverArgs(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&hoverArgs);
}
@@ -2942,10 +2936,10 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
mXPrecision, mYPrecision, downTime);
getListener()->notifyMotion(&scrollArgs);
}
@@ -3072,10 +3066,10 @@
int32_t metaState = mContext->getGlobalMetaState();
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
- NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
AMOTION_EVENT_EDGE_FLAG_NONE,
- displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
0, 0, 0);
getListener()->notifyMotion(&scrollArgs);
}
@@ -5413,10 +5407,10 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- mViewport.displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
0, 0, mPointerGesture.downTime);
getListener()->notifyMotion(&args);
}
@@ -6336,9 +6330,9 @@
mPointerSimple.down = false;
// Send up.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_UP, 0, 0, metaState, mLastRawState.buttonState, 0,
- mViewport.displayId, /* deviceTimestamp */ 0,
+ /* deviceTimestamp */ 0,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime);
@@ -6349,9 +6343,9 @@
mPointerSimple.hovering = false;
// Send hover exit.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState, mLastRawState.buttonState, 0,
- mViewport.displayId, /* deviceTimestamp */ 0,
+ /* deviceTimestamp */ 0,
1, &mPointerSimple.lastProperties, &mPointerSimple.lastCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime);
@@ -6364,9 +6358,9 @@
mPointerSimple.downTime = when;
// Send down.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_DOWN, 0, 0, metaState, mCurrentRawState.buttonState, 0,
- mViewport.displayId, /* deviceTimestamp */ 0,
+ /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime);
@@ -6374,9 +6368,9 @@
}
// Send move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, mCurrentRawState.buttonState, 0,
- mViewport.displayId, /* deviceTimestamp */ 0,
+ /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime);
@@ -6388,10 +6382,10 @@
mPointerSimple.hovering = true;
// Send hover enter.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0, metaState,
mCurrentRawState.buttonState, 0,
- mViewport.displayId, /* deviceTimestamp */ 0,
+ /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime);
@@ -6399,10 +6393,10 @@
}
// Send hover move.
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
mCurrentRawState.buttonState, 0,
- mViewport.displayId, /* deviceTimestamp */ 0,
+ /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &mPointerSimple.currentCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime);
@@ -6421,9 +6415,9 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), mSource, mViewport.displayId, policyFlags,
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, mCurrentRawState.buttonState, 0,
- mViewport.displayId, /* deviceTimestamp */ 0,
+ /* deviceTimestamp */ 0,
1, &mPointerSimple.currentProperties, &pointerCoords,
mOrientedXPrecision, mOrientedYPrecision,
mPointerSimple.downTime);
@@ -6484,9 +6478,9 @@
}
}
- NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), source, mViewport.displayId, policyFlags,
action, actionButton, flags, metaState, buttonState, edgeFlags,
- mViewport.displayId, deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
+ deviceTimestamp, pointerCount, pointerProperties, pointerCoords,
xPrecision, yPrecision, downTime);
getListener()->notifyMotion(&args);
}
@@ -7404,9 +7398,10 @@
// TODO: Use the input device configuration to control this behavior more finely.
uint32_t policyFlags = 0;
- NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
+ NotifyMotionArgs args(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE,
+ policyFlags,
AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
- ADISPLAY_ID_NONE, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
+ /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
0, 0, 0);
getListener()->notifyMotion(&args);
}
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index b1d5e61..2faa794 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -6,7 +6,6 @@
"InputReader_test.cpp",
"InputDispatcher_test.cpp",
],
- test_per_src: true,
cflags: [
"-Wall",
"-Werror",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index aa6df24..9c72c77 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -28,7 +28,7 @@
static const int32_t DEVICE_ID = 1;
// An arbitrary display id.
-static const int32_t DISPLAY_ID = 0;
+static const int32_t DISPLAY_ID = ADISPLAY_ID_DEFAULT;
// An arbitrary injector pid / uid pair that has permission to inject events.
static const int32_t INJECTOR_PID = 999;
@@ -124,7 +124,7 @@
/*action*/ -1, 0,
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject key events with undefined action.";
@@ -133,7 +133,7 @@
AKEY_EVENT_ACTION_MULTIPLE, 0,
AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject key events with ACTION_MULTIPLE.";
}
@@ -149,106 +149,106 @@
}
// Rejects undefined motion actions.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
/*action*/ -1, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too large.";
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too large.";
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with 0 pointers.";
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with more than MAX_POINTERS pointers.";
// Rejects motion events with invalid pointer ids.
pointerProperties[0].id = -1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer ids less than 0.";
pointerProperties[0].id = MAX_POINTER_ID + 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
// Rejects motion events with duplicate pointer ids.
pointerProperties[0].id = 1;
pointerProperties[1].id = 1;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID,
AMOTION_EVENT_ACTION_DOWN, 0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
- &event, DISPLAY_ID,
+ &event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with duplicate pointer ids.";
}
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 956844f..f4131d4 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -56,7 +56,7 @@
mService->cleanupConnection(this);
if (mEventCache != NULL) {
- delete mEventCache;
+ delete[] mEventCache;
}
mDestroyed = true;
}
@@ -224,7 +224,7 @@
wp<const SensorEventConnection> const * mapFlushEventsToConnections) {
// filter out events not for this connection
- sensors_event_t* sanitizedBuffer = nullptr;
+ std::unique_ptr<sensors_event_t[]> sanitizedBuffer;
int count = 0;
Mutex::Autolock _l(mConnectionLock);
@@ -293,7 +293,8 @@
scratch = const_cast<sensors_event_t *>(buffer);
count = numEvents;
} else {
- scratch = sanitizedBuffer = new sensors_event_t[numEvents];
+ sanitizedBuffer.reset(new sensors_event_t[numEvents]);
+ scratch = sanitizedBuffer.get();
for (size_t i = 0; i < numEvents; i++) {
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
scratch[count++] = buffer[i++];
@@ -305,7 +306,6 @@
sendPendingFlushEventsLocked();
// Early return if there are no events for this connection.
if (count == 0) {
- delete sanitizedBuffer;
return status_t(NO_ERROR);
}
@@ -323,7 +323,6 @@
// the max cache size that is desired.
if (mCacheSize + count < computeMaxCacheSizeLocked()) {
reAllocateCacheLocked(scratch, count);
- delete sanitizedBuffer;
return status_t(NO_ERROR);
}
// Some events need to be dropped.
@@ -342,7 +341,6 @@
memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
numEventsDropped * sizeof(sensors_event_t));
}
- delete sanitizedBuffer;
return status_t(NO_ERROR);
}
@@ -384,7 +382,6 @@
// Add this file descriptor to the looper to get a callback when this fd is available for
// writing.
updateLooperRegistrationLocked(mService->getLooper());
- delete sanitizedBuffer;
return size;
}
@@ -394,7 +391,6 @@
}
#endif
- delete sanitizedBuffer;
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
@@ -415,7 +411,7 @@
ALOGD_IF(DEBUG_CONNECTIONS, "reAllocateCacheLocked maxCacheSize=%d %d", mMaxCacheSize,
new_cache_size);
- delete mEventCache;
+ delete[] mEventCache;
mEventCache = eventCache_new;
mCacheSize += count;
mMaxCacheSize = new_cache_size;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index c2bb6ad..6943638 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -26,6 +26,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
"android.hardware.power@1.0",
"libbase",
"libbinder",
@@ -69,6 +70,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.3",
"libhidlbase",
"libhidltransport",
"libhwbinder",
@@ -92,6 +94,7 @@
"ContainerLayer.cpp",
"DisplayDevice.cpp",
"DisplayHardware/ComposerHal.cpp",
+ "DisplayHardware/DisplayIdentification.cpp",
"DisplayHardware/FramebufferSurface.cpp",
"DisplayHardware/HWC2.cpp",
"DisplayHardware/HWComposer.cpp",
@@ -105,6 +108,7 @@
"FrameTracker.cpp",
"GpuService.cpp",
"Layer.cpp",
+ "LayerBE.cpp",
"LayerProtoHelper.cpp",
"LayerRejecter.cpp",
"LayerStats.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index fda7906..aae3931 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -98,15 +98,13 @@
}
bool BufferLayer::isProtected() const {
- const sp<GraphicBuffer>& buffer(getBE().compositionInfo.mBuffer);
- return (buffer != 0) &&
- (buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+ const sp<GraphicBuffer>& buffer(mActiveBuffer);
+ return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
}
bool BufferLayer::isVisible() const {
return !(isHiddenByPolicy()) && getAlpha() > 0.0f &&
- (getBE().compositionInfo.mBuffer != nullptr ||
- getBE().compositionInfo.hwc.sidebandStream != nullptr);
+ (mActiveBuffer != nullptr || getBE().compositionInfo.hwc.sidebandStream != nullptr);
}
bool BufferLayer::isFixedSize() const {
@@ -162,7 +160,7 @@
bool useIdentityTransform) const {
ATRACE_CALL();
- if (CC_UNLIKELY(getBE().compositionInfo.mBuffer == 0)) {
+ if (CC_UNLIKELY(mActiveBuffer == 0)) {
// the texture has not been created yet, this Layer has
// in fact never been drawn into. This happens frequently with
// SurfaceView because the WindowManager can't know when the client
@@ -240,8 +238,7 @@
}
// Set things up for texturing.
- mTexture.setDimensions(getBE().compositionInfo.mBuffer->getWidth(),
- getBE().compositionInfo.mBuffer->getHeight());
+ mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
mTexture.setFiltering(useFiltering);
mTexture.setMatrix(textureMatrix);
@@ -291,12 +288,10 @@
bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) {
if (mBufferLatched) {
Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addPreComposition(mCurrentFrameNumber,
- refreshStartTime);
+ mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
}
mRefreshPending = false;
- return mQueuedFrames > 0 || mSidebandStreamChanged ||
- mAutoRefresh;
+ return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
}
bool BufferLayer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
const std::shared_ptr<FenceTime>& presentFence,
@@ -308,8 +303,8 @@
// Update mFrameEventHistory.
{
Mutex::Autolock lock(mFrameEventHistoryMutex);
- mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence,
- presentFence, compositorTiming);
+ mFrameEventHistory.addPostComposition(mCurrentFrameNumber, glDoneFence, presentFence,
+ compositorTiming);
}
// Update mFrameTracker.
@@ -331,7 +326,7 @@
if (presentFence->isValid()) {
mTimeStats.setPresentFence(layerName, mCurrentFrameNumber, presentFence);
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
- } else {
+ } else if (mFlinger->getHwComposer().isConnected(HWC_DISPLAY_PRIMARY)) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
const nsecs_t actualPresentTime =
@@ -364,8 +359,7 @@
return;
}
- auto releaseFenceTime =
- std::make_shared<FenceTime>(mConsumer->getPrevFinalReleaseFence());
+ auto releaseFenceTime = std::make_shared<FenceTime>(mConsumer->getPrevFinalReleaseFence());
mReleaseTimeline.updateSignalTimes();
mReleaseTimeline.push(releaseFenceTime);
@@ -418,7 +412,7 @@
// Capture the old state of the layer for comparisons later
const State& s(getDrawingState());
const bool oldOpacity = isOpaque(s);
- sp<GraphicBuffer> oldBuffer = getBE().compositionInfo.mBuffer;
+ sp<GraphicBuffer> oldBuffer = mActiveBuffer;
if (!allTransactionsSignaled()) {
mFlinger->signalLayerUpdate();
@@ -431,12 +425,12 @@
// buffer mode.
bool queuedBuffer = false;
LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0, mName.string(),
- mOverrideScalingMode, mFreezeGeometryUpdates);
- status_t updateResult =
- mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync,
- &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived);
+ getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
+ getTransformToDisplayInverse(), mFreezeGeometryUpdates);
+
+ status_t updateResult = mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync, &mAutoRefresh,
+ &queuedBuffer, mLastFrameNumberReceived);
+
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
@@ -496,17 +490,16 @@
// Decrement the queued-frames count. Signal another event if we
// have more frames pending.
- if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) ||
- mAutoRefresh) {
+ if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1) || mAutoRefresh) {
mFlinger->signalLayerUpdate();
}
// update the active buffer
- getBE().compositionInfo.mBuffer =
- mConsumer->getCurrentBuffer(&getBE().compositionInfo.mBufferSlot);
- // replicated in LayerBE until FE/BE is ready to be synchronized
- mActiveBuffer = getBE().compositionInfo.mBuffer;
- if (getBE().compositionInfo.mBuffer == nullptr) {
+ mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot);
+ getBE().compositionInfo.mBuffer = mActiveBuffer;
+ getBE().compositionInfo.mBufferSlot = mActiveBufferSlot;
+
+ if (mActiveBuffer == nullptr) {
// this can only happen if the very first buffer was rejected.
return outDirtyRegion;
}
@@ -558,8 +551,7 @@
Rect crop(mConsumer->getCurrentCrop());
const uint32_t transform(mConsumer->getCurrentTransform());
const uint32_t scalingMode(mConsumer->getCurrentScalingMode());
- if ((crop != mCurrentCrop) ||
- (transform != mCurrentTransform) ||
+ if ((crop != mCurrentCrop) || (transform != mCurrentTransform) ||
(scalingMode != mCurrentScalingMode)) {
mCurrentCrop = crop;
mCurrentTransform = transform;
@@ -568,15 +560,14 @@
}
if (oldBuffer != nullptr) {
- uint32_t bufWidth = getBE().compositionInfo.mBuffer->getWidth();
- uint32_t bufHeight = getBE().compositionInfo.mBuffer->getHeight();
- if (bufWidth != uint32_t(oldBuffer->width) ||
- bufHeight != uint32_t(oldBuffer->height)) {
+ uint32_t bufWidth = mActiveBuffer->getWidth();
+ uint32_t bufHeight = mActiveBuffer->getHeight();
+ if (bufWidth != uint32_t(oldBuffer->width) || bufHeight != uint32_t(oldBuffer->height)) {
recomputeVisibleRegions = true;
}
}
- mCurrentOpacity = getOpacityForFormat(getBE().compositionInfo.mBuffer->format);
+ mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
if (oldOpacity != isOpaque(s)) {
recomputeVisibleRegions = true;
}
@@ -615,14 +606,19 @@
mConsumer->setDefaultBufferSize(w, h);
}
-void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+void BufferLayer::setPerFrameData(const sp<const DisplayDevice>& display) {
// Apply this display's projection's viewport to the visible region
// before giving it to the HWC HAL.
- const Transform& tr = displayDevice->getTransform();
- const auto& viewport = displayDevice->getViewport();
+ const Transform& tr = display->getTransform();
+ const auto& viewport = display->getViewport();
Region visible = tr.transform(visibleRegion.intersect(viewport));
- auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcInfo = getBE().mHwcLayers[hwcId];
+ const auto displayId = display->getId();
+ if (!hasHwcLayer(displayId)) {
+ ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)",
+ mName.string(), displayId);
+ return;
+ }
+ auto& hwcInfo = getBE().mHwcLayers[displayId];
auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
if (error != HWC2::Error::None) {
@@ -640,7 +636,7 @@
// Sideband layers
if (getBE().compositionInfo.hwc.sidebandStream.get()) {
- setCompositionType(hwcId, HWC2::Composition::Sideband);
+ setCompositionType(displayId, HWC2::Composition::Sideband);
ALOGV("[%s] Requesting Sideband composition", mName.string());
error = hwcLayer->setSidebandStream(getBE().compositionInfo.hwc.sidebandStream->handle());
if (error != HWC2::Error::None) {
@@ -654,10 +650,10 @@
// Device or Cursor layers
if (mPotentialCursor) {
ALOGV("[%s] Requesting Cursor composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Cursor);
+ setCompositionType(displayId, HWC2::Composition::Cursor);
} else {
ALOGV("[%s] Requesting Device composition", mName.string());
- setCompositionType(hwcId, HWC2::Composition::Device);
+ setCompositionType(displayId, HWC2::Composition::Device);
}
ALOGV("setPerFrameData: dataspace = %d", mCurrentDataSpace);
@@ -668,7 +664,7 @@
}
const HdrMetadata& metadata = mConsumer->getCurrentHdrMetadata();
- error = hwcLayer->setPerFrameMetadata(displayDevice->getSupportedPerFrameMetadata(), metadata);
+ error = hwcLayer->setPerFrameMetadata(display->getSupportedPerFrameMetadata(), metadata);
if (error != HWC2::Error::None && error != HWC2::Error::Unsupported) {
ALOGE("[%s] Failed to set hdrMetadata: %s (%d)", mName.string(),
to_string(error).c_str(), static_cast<int32_t>(error));
@@ -676,8 +672,7 @@
uint32_t hwcSlot = 0;
sp<GraphicBuffer> hwcBuffer;
- hwcInfo.bufferCache.getHwcBuffer(getBE().compositionInfo.mBufferSlot,
- getBE().compositionInfo.mBuffer, &hwcSlot, &hwcBuffer);
+ hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer, &hwcSlot, &hwcBuffer);
auto acquireFence = mConsumer->getCurrentFence();
error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
@@ -691,7 +686,7 @@
bool BufferLayer::isOpaque(const Layer::State& s) const {
// if we don't have a buffer or sidebandStream yet, we're translucent regardless of the
// layer's opaque flag.
- if ((getBE().compositionInfo.hwc.sidebandStream == nullptr) && (getBE().compositionInfo.mBuffer == nullptr)) {
+ if ((getBE().compositionInfo.hwc.sidebandStream == nullptr) && (mActiveBuffer == nullptr)) {
return false;
}
@@ -706,8 +701,7 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
- mConsumer = new BufferLayerConsumer(consumer,
- mFlinger->getRenderEngine(), mTextureName, this);
+ mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
@@ -716,8 +710,9 @@
mProducer->setMaxDequeuedBufferCount(2);
}
- const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
- updateTransformHint(hw);
+ if (const auto display = mFlinger->getDefaultDisplayDevice()) {
+ updateTransformHint(display);
+ }
}
// ---------------------------------------------------------------------------
@@ -739,8 +734,7 @@
// Ensure that callbacks are handled in order
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
- ms2ns(500));
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
ALOGE("[%s] Timed out waiting on callback", mName.string());
}
@@ -763,8 +757,7 @@
// Ensure that callbacks are handled in order
while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
- ms2ns(500));
+ status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
if (result != NO_ERROR) {
ALOGE("[%s] Timed out waiting on callback", mName.string());
}
@@ -935,8 +928,7 @@
// able to be latched. To avoid this, grab this buffer anyway.
return true;
}
- return mQueueItems[0].mFenceTime->getSignalTime() !=
- Fence::SIGNAL_TIME_PENDING;
+ return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
}
uint32_t BufferLayer::getEffectiveScalingMode() const {
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index bf0ca69..7f5ff3f 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -131,7 +131,7 @@
bool isHdrY410() const override;
- void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+ void setPerFrameData(const sp<const DisplayDevice>& display) override;
bool isOpaque(const Layer::State& s) const override;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 512564c..aebe4ea 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -61,12 +61,17 @@
return !isHiddenByPolicy() && s.color.a;
}
-void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
- const Transform& tr = displayDevice->getTransform();
- const auto& viewport = displayDevice->getViewport();
+void ColorLayer::setPerFrameData(const sp<const DisplayDevice>& display) {
+ const Transform& tr = display->getTransform();
+ const auto& viewport = display->getViewport();
Region visible = tr.transform(visibleRegion.intersect(viewport));
- auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcInfo = getBE().mHwcLayers[hwcId];
+ const auto displayId = display->getId();
+ if (!hasHwcLayer(displayId)) {
+ ALOGE("[%s] failed to setPerFrameData: no HWC layer found (%d)",
+ mName.string(), displayId);
+ return;
+ }
+ auto& hwcInfo = getBE().mHwcLayers[displayId];
auto& hwcLayer = hwcInfo.layer;
auto error = hwcLayer->setVisibleRegion(visible);
if (error != HWC2::Error::None) {
@@ -75,7 +80,7 @@
visible.dump(LOG_TAG);
}
- setCompositionType(hwcId, HWC2::Composition::SolidColor);
+ setCompositionType(displayId, HWC2::Composition::SolidColor);
error = hwcLayer->setDataspace(mCurrentDataSpace);
if (error != HWC2::Error::None) {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 0cde398..6a6e7c0 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -34,7 +34,7 @@
bool useIdentityTransform) const;
bool isVisible() const override;
- void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+ void setPerFrameData(const sp<const DisplayDevice>& display) override;
};
} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 543f60a..84b75f4 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -34,7 +34,7 @@
bool useIdentityTransform) const override;
bool isVisible() const override;
- void setPerFrameData(const sp<const DisplayDevice>& displayDevice) override;
+ void setPerFrameData(const sp<const DisplayDevice>& display) override;
};
} // namespace android
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index db095a5..4d2b0ea 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -216,7 +216,7 @@
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
- int32_t hwcId,
+ int32_t id,
bool isSecure,
const wp<IBinder>& displayToken,
const sp<ANativeWindow>& nativeWindow,
@@ -232,7 +232,7 @@
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
- mHwcDisplayId(hwcId),
+ mId(id),
mDisplayToken(displayToken),
mNativeWindow(nativeWindow),
mDisplaySurface(displaySurface),
@@ -301,9 +301,9 @@
DisplayDevice::~DisplayDevice() = default;
void DisplayDevice::disconnect(HWComposer& hwc) {
- if (mHwcDisplayId >= 0) {
- hwc.disconnectDisplay(mHwcDisplayId);
- mHwcDisplayId = -1;
+ if (mId >= 0) {
+ hwc.disconnectDisplay(mId);
+ mId = -1;
}
}
@@ -319,8 +319,8 @@
return mDisplayHeight;
}
-void DisplayDevice::setDisplayName(const String8& displayName) {
- if (!displayName.isEmpty()) {
+void DisplayDevice::setDisplayName(const std::string& displayName) {
+ if (!displayName.empty()) {
// never override the name with an empty name
mDisplayName = displayName;
}
@@ -347,8 +347,8 @@
}
DisplaySurface::CompositionType compositionType;
- bool hasClient = hwc.hasClientComposition(mHwcDisplayId);
- bool hasDevice = hwc.hasDeviceComposition(mHwcDisplayId);
+ bool hasClient = hwc.hasClientComposition(mId);
+ bool hasDevice = hwc.hasDeviceComposition(mId);
if (hasClient && hasDevice) {
compositionType = DisplaySurface::COMPOSITION_MIXED;
} else if (hasClient) {
@@ -365,14 +365,13 @@
}
void DisplayDevice::swapBuffers(HWComposer& hwc) const {
- if (hwc.hasClientComposition(mHwcDisplayId) || hwc.hasFlipClientTargetRequest(mHwcDisplayId)) {
+ if (hwc.hasClientComposition(mId) || hwc.hasFlipClientTargetRequest(mId)) {
mSurface->swapBuffers();
}
status_t result = mDisplaySurface->advanceFrame();
if (result != NO_ERROR) {
- ALOGE("[%s] failed pushing new frame to HWC: %d",
- mDisplayName.string(), result);
+ ALOGE("[%s] failed pushing new frame to HWC: %d", mDisplayName.c_str(), result);
}
}
@@ -437,8 +436,8 @@
return mPowerMode;
}
-bool DisplayDevice::isDisplayOn() const {
- return (mPowerMode != HWC_POWER_MODE_OFF);
+bool DisplayDevice::isPoweredOn() const {
+ return mPowerMode != HWC_POWER_MODE_OFF;
}
// ----------------------------------------------------------------------------
@@ -631,7 +630,7 @@
}
mOrientation = orientation;
- if (mType == DisplayType::DISPLAY_PRIMARY) {
+ if (isPrimary()) {
uint32_t transform = 0;
switch (mOrientation) {
case DisplayState::eOrientationDefault:
@@ -660,11 +659,11 @@
void DisplayDevice::dump(String8& result) const {
const Transform& tr(mGlobalTransform);
ANativeWindow* const window = mNativeWindow.get();
- result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.string());
- result.appendFormat(" type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
+ result.appendFormat("+ DisplayDevice: %s\n", mDisplayName.c_str());
+ result.appendFormat(" type=%x, ID=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p "
"(%d:%d:%d:%d), orient=%2d (type=%08x), "
"flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n",
- mType, mHwcDisplayId, mLayerStack, mDisplayWidth, mDisplayHeight, window,
+ mType, mId, mLayerStack, mDisplayWidth, mDisplayHeight, window,
mSurface->queryRedSize(), mSurface->queryGreenSize(),
mSurface->queryBlueSize(), mSurface->queryAlphaSize(), mOrientation,
tr.getType(), getPageFlipCount(), mIsSecure, mPowerMode, mActiveConfig,
@@ -704,7 +703,7 @@
const Dataspace dataspace = colorModeToDataspace(mode);
const Dataspace hwcDataspace = colorModeToDataspace(hwcColorMode);
- ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mHwcDisplayId,
+ ALOGV("DisplayDevice %d/%d: map (%s, %s) to (%s, %s, %s)", mType, mId,
dataspaceDetails(static_cast<android_dataspace_t>(dataspace)).c_str(),
decodeRenderIntent(intent).c_str(),
dataspaceDetails(static_cast<android_dataspace_t>(hwcDataspace)).c_str(),
@@ -791,18 +790,6 @@
}
}
-std::atomic<int32_t> DisplayDeviceState::nextDisplayId(1);
-
-DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure)
- : type(type),
- layerStack(DisplayDevice::NO_LAYER_STACK),
- orientation(0),
- width(0),
- height(0),
- isSecure(isSecure)
-{
- viewport.makeInvalid();
- frame.makeInvalid();
-}
+std::atomic<int32_t> DisplayDeviceState::sNextSequenceId(1);
} // namespace android
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6c3bd91..f440d29 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -39,6 +39,7 @@
#include "RenderEngine/Surface.h"
#include <memory>
+#include <string>
struct ANativeWindow;
@@ -80,7 +81,7 @@
DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
- int32_t hwcId,
+ int32_t id,
bool isSecure,
const wp<IBinder>& displayToken,
const sp<ANativeWindow>& nativeWindow,
@@ -134,7 +135,8 @@
uint32_t getLayerStack() const { return mLayerStack; }
int32_t getDisplayType() const { return mType; }
bool isPrimary() const { return mType == DISPLAY_PRIMARY; }
- int32_t getHwcDisplayId() const { return mHwcDisplayId; }
+ bool isVirtual() const { return mType == DISPLAY_VIRTUAL; }
+ int32_t getId() const { return mId; }
const wp<IBinder>& getDisplayToken() const { return mDisplayToken; }
int32_t getSupportedPerFrameMetadata() const { return mSupportedPerFrameMetadata; }
@@ -179,8 +181,8 @@
}
inline Rect bounds() const { return getBounds(); }
- void setDisplayName(const String8& displayName);
- const String8& getDisplayName() const { return mDisplayName; }
+ void setDisplayName(const std::string& displayName);
+ const std::string& getDisplayName() const { return mDisplayName; }
bool makeCurrent() const;
void setViewportAndProjection() const;
@@ -192,7 +194,7 @@
*/
int getPowerMode() const;
void setPowerMode(int mode);
- bool isDisplayOn() const;
+ bool isPoweredOn() const;
ui::ColorMode getActiveColorMode() const;
void setActiveColorMode(ui::ColorMode mode);
@@ -224,7 +226,7 @@
*/
sp<SurfaceFlinger> mFlinger;
DisplayType mType;
- int32_t mHwcDisplayId;
+ int32_t mId;
wp<IBinder> mDisplayToken;
// ANativeWindow this display is rendering into
@@ -235,7 +237,7 @@
int mDisplayWidth;
int mDisplayHeight;
mutable uint32_t mPageFlipCount;
- String8 mDisplayName;
+ std::string mDisplayName;
bool mIsSecure;
/*
@@ -313,15 +315,9 @@
};
struct DisplayDeviceState {
- DisplayDeviceState() = default;
- DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure);
+ bool isVirtual() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
- bool isValid() const { return type >= 0; }
- bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
- bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
-
- static std::atomic<int32_t> nextDisplayId;
- int32_t displayId = nextDisplayId++;
+ int32_t sequenceId = sNextSequenceId++;
DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_ID_INVALID;
sp<IGraphicBufferProducer> surface;
uint32_t layerStack = DisplayDevice::NO_LAYER_STACK;
@@ -330,8 +326,11 @@
uint8_t orientation = 0;
uint32_t width = 0;
uint32_t height = 0;
- String8 displayName;
+ std::string displayName;
bool isSecure = false;
+
+private:
+ static std::atomic<int32_t> sNextSequenceId;
};
class DisplayRenderArea : public RenderArea {
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 37ba433..9a9a5c3 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -22,7 +22,6 @@
#include "ComposerHal.h"
-#include <android/hardware/graphics/composer/2.2/IComposer.h>
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
#include <gui/BufferQueue.h>
#include <hidl/HidlTransportUtils.h>
@@ -172,22 +171,31 @@
LOG_ALWAYS_FATAL("failed to get hwcomposer service");
}
- mComposer->createClient(
- [&](const auto& tmpError, const auto& tmpClient)
- {
- if (tmpError == Error::NONE) {
- mClient = tmpClient;
- }
- });
- if (mClient == nullptr) {
- LOG_ALWAYS_FATAL("failed to create composer client");
+ if (sp<IComposer> composer_2_3 = IComposer::castFrom(mComposer)) {
+ composer_2_3->createClient_2_3([&](const auto& tmpError, const auto& tmpClient) {
+ if (tmpError == Error::NONE) {
+ mClient = tmpClient;
+ mClient_2_2 = tmpClient;
+ mClient_2_3 = tmpClient;
+ }
+ });
+ } else {
+ mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+ if (tmpError != Error::NONE) {
+ return;
+ }
+
+ mClient = tmpClient;
+ if (sp<V2_2::IComposer> composer_2_2 = V2_2::IComposer::castFrom(mComposer)) {
+ mClient_2_2 = V2_2::IComposerClient::castFrom(mClient);
+ LOG_ALWAYS_FATAL_IF(mClient_2_2 == nullptr,
+ "IComposer 2.2 did not return IComposerClient 2.2");
+ }
+ });
}
- // 2.2 support is optional
- sp<IComposer> composer_2_2 = IComposer::castFrom(mComposer);
- if (composer_2_2 != nullptr) {
- mClient_2_2 = IComposerClient::castFrom(mClient);
- LOG_ALWAYS_FATAL_IF(mClient_2_2 == nullptr, "IComposer 2.2 did not return IComposerClient 2.2");
+ if (mClient == nullptr) {
+ LOG_ALWAYS_FATAL("failed to create composer client");
}
if (mIsUsingVrComposer) {
@@ -957,6 +965,30 @@
return error;
}
+// Composer HAL 2.3
+
+Error Composer::getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) {
+ if (!mClient_2_3) {
+ return Error::UNSUPPORTED;
+ }
+
+ Error error = kDefaultError;
+ mClient_2_3->getDisplayIdentificationData(display,
+ [&](const auto& tmpError, const auto& tmpPort,
+ const auto& tmpData) {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outPort = tmpPort;
+ *outData = tmpData;
+ });
+
+ return error;
+}
+
CommandReader::~CommandReader()
{
resetData();
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index beee539..bd18b09 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -25,8 +25,8 @@
#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <android/hardware/graphics/common/1.1/types.h>
-#include <android/hardware/graphics/composer/2.2/IComposer.h>
-#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
#include <gui/HdrMetadata.h>
#include <math/mat4.h>
@@ -43,6 +43,7 @@
namespace V2_1 = hardware::graphics::composer::V2_1;
namespace V2_2 = hardware::graphics::composer::V2_2;
+namespace V2_3 = hardware::graphics::composer::V2_3;
using types::V1_0::ColorTransform;
using types::V1_0::Hdr;
@@ -61,8 +62,9 @@
using V2_2::CommandReaderBase;
using V2_2::CommandWriterBase;
-using V2_2::IComposer;
-using V2_2::IComposerClient;
+
+using V2_3::IComposer;
+using V2_3::IComposerClient;
using PerFrameMetadata = IComposerClient::PerFrameMetadata;
using PerFrameMetadataKey = IComposerClient::PerFrameMetadataKey;
@@ -185,6 +187,10 @@
virtual Error getRenderIntents(Display display, ColorMode colorMode,
std::vector<RenderIntent>* outRenderIntents) = 0;
virtual Error getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatrix) = 0;
+
+ // Composer HAL 2.3
+ virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) = 0;
};
namespace impl {
@@ -380,6 +386,10 @@
std::vector<RenderIntent>* outRenderIntents) override;
Error getDataspaceSaturationMatrix(Dataspace dataspace, mat4* outMatrix) override;
+ // Composer HAL 2.3
+ Error getDisplayIdentificationData(Display display, uint8_t* outPort,
+ std::vector<uint8_t>* outData) override;
+
private:
class CommandWriter : public CommandWriterBase {
public:
@@ -405,7 +415,8 @@
sp<V2_1::IComposer> mComposer;
sp<V2_1::IComposerClient> mClient;
- sp<IComposerClient> mClient_2_2;
+ sp<V2_2::IComposerClient> mClient_2_2;
+ sp<IComposerClient> mClient_2_3;
// 64KiB minus a small space for metadata such as read/write pointers
static constexpr size_t kWriterInitialSize =
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
new file mode 100644
index 0000000..dcc4138
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "DisplayIdentification"
+
+#include <algorithm>
+#include <cctype>
+#include <numeric>
+#include <optional>
+
+#include <log/log.h>
+
+#include "DisplayIdentification.h"
+
+namespace android {
+namespace {
+
+using byte_view = std::basic_string_view<uint8_t>;
+
+constexpr size_t kEdidHeaderLength = 5;
+
+std::optional<uint8_t> getEdidDescriptorType(const byte_view& view) {
+ if (view.size() < kEdidHeaderLength || view[0] || view[1] || view[2] || view[4]) {
+ return {};
+ }
+
+ return view[3];
+}
+
+std::string_view parseEdidText(const byte_view& view) {
+ std::string_view text(reinterpret_cast<const char*>(view.data()), view.size());
+ text = text.substr(0, text.find('\n'));
+
+ if (!std::all_of(text.begin(), text.end(), ::isprint)) {
+ ALOGW("Invalid EDID: ASCII text is not printable.");
+ return {};
+ }
+
+ return text;
+}
+
+// Big-endian 16-bit value encodes three 5-bit letters where A is 0b00001.
+template <size_t I>
+char getPnpLetter(uint16_t id) {
+ static_assert(I < 3);
+ const char letter = 'A' + (static_cast<uint8_t>(id >> ((2 - I) * 5)) & 0b00011111) - 1;
+ return letter < 'A' || letter > 'Z' ? '\0' : letter;
+}
+
+DisplayId getEdidDisplayId(uint8_t port, uint16_t manufacturerId, uint32_t displayNameHash) {
+ return (static_cast<DisplayId>(manufacturerId) << 40) |
+ (static_cast<DisplayId>(displayNameHash) << 8) | port;
+}
+
+} // namespace
+
+bool isEdid(const DisplayIdentificationData& data) {
+ const uint8_t kMagic[] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0};
+ return data.size() >= sizeof(kMagic) &&
+ std::equal(std::begin(kMagic), std::end(kMagic), data.begin());
+}
+
+std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) {
+ constexpr size_t kMinLength = 128;
+ if (edid.size() < kMinLength) {
+ ALOGW("Invalid EDID: structure is truncated.");
+ // Attempt parsing even if EDID is malformed.
+ } else {
+ ALOGW_IF(edid[126] != 0, "EDID extensions are currently unsupported.");
+ ALOGW_IF(std::accumulate(edid.begin(), edid.begin() + kMinLength, static_cast<uint8_t>(0)),
+ "Invalid EDID: structure does not checksum.");
+ }
+
+ constexpr size_t kManufacturerOffset = 8;
+ if (edid.size() < kManufacturerOffset + sizeof(uint16_t)) {
+ ALOGE("Invalid EDID: manufacturer ID is truncated.");
+ return {};
+ }
+
+ // Plug and play ID encoded as big-endian 16-bit value.
+ const uint16_t manufacturerId =
+ (edid[kManufacturerOffset] << 8) | edid[kManufacturerOffset + 1];
+
+ const auto pnpId = getPnpId(manufacturerId);
+ if (!pnpId) {
+ ALOGE("Invalid EDID: manufacturer ID is not a valid PnP ID.");
+ return {};
+ }
+
+ constexpr size_t kDescriptorOffset = 54;
+ if (edid.size() < kDescriptorOffset) {
+ ALOGE("Invalid EDID: descriptors are missing.");
+ return {};
+ }
+
+ byte_view view(edid.data(), edid.size());
+ view.remove_prefix(kDescriptorOffset);
+
+ std::string_view displayName;
+ std::string_view serialNumber;
+ std::string_view asciiText;
+
+ constexpr size_t kDescriptorCount = 4;
+ constexpr size_t kDescriptorLength = 18;
+
+ for (size_t i = 0; i < kDescriptorCount; i++) {
+ if (view.size() < kDescriptorLength) {
+ break;
+ }
+
+ if (const auto type = getEdidDescriptorType(view)) {
+ byte_view descriptor(view.data(), kDescriptorLength);
+ descriptor.remove_prefix(kEdidHeaderLength);
+
+ switch (*type) {
+ case 0xfc:
+ displayName = parseEdidText(descriptor);
+ break;
+ case 0xfe:
+ asciiText = parseEdidText(descriptor);
+ break;
+ case 0xff:
+ serialNumber = parseEdidText(descriptor);
+ break;
+ }
+ }
+
+ view.remove_prefix(kDescriptorLength);
+ }
+
+ if (displayName.empty()) {
+ ALOGW("Invalid EDID: falling back to serial number due to missing display name.");
+ displayName = serialNumber;
+ }
+ if (displayName.empty()) {
+ ALOGW("Invalid EDID: falling back to ASCII text due to missing serial number.");
+ displayName = asciiText;
+ }
+ if (displayName.empty()) {
+ ALOGE("Invalid EDID: display name and fallback descriptors are missing.");
+ return {};
+ }
+
+ return Edid{manufacturerId, *pnpId, displayName};
+}
+
+std::optional<PnpId> getPnpId(uint16_t manufacturerId) {
+ const char a = getPnpLetter<0>(manufacturerId);
+ const char b = getPnpLetter<1>(manufacturerId);
+ const char c = getPnpLetter<2>(manufacturerId);
+ return a && b && c ? std::make_optional(PnpId{a, b, c}) : std::nullopt;
+}
+
+std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData& data) {
+ if (!isEdid(data)) {
+ ALOGE("Display identification data has unknown format.");
+ return {};
+ }
+
+ const auto edid = parseEdid(data);
+ if (!edid) {
+ return {};
+ }
+
+ // Hash display name instead of using product code or serial number, since the latter have been
+ // observed to change on some displays with multiple inputs.
+ const auto hash = static_cast<uint32_t>(std::hash<std::string_view>()(edid->displayName));
+ return getEdidDisplayId(port, edid->manufacturerId, hash);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.h b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
new file mode 100644
index 0000000..379f2d3
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <array>
+#include <cstdint>
+#include <optional>
+#include <string_view>
+#include <vector>
+
+namespace android {
+
+using DisplayId = uint64_t;
+using DisplayIdentificationData = std::vector<uint8_t>;
+
+// NUL-terminated plug and play ID.
+using PnpId = std::array<char, 4>;
+
+struct Edid {
+ uint16_t manufacturerId;
+ PnpId pnpId;
+ std::string_view displayName;
+};
+
+bool isEdid(const DisplayIdentificationData&);
+std::optional<Edid> parseEdid(const DisplayIdentificationData&);
+std::optional<PnpId> getPnpId(uint16_t manufacturerId);
+
+std::optional<DisplayId> generateDisplayId(uint8_t port, const DisplayIdentificationData&);
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 61758b6..9546c86 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -124,6 +124,12 @@
return mComposer->getMaxVirtualDisplayCount();
}
+Error Device::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+ std::vector<uint8_t>* outData) const {
+ auto intError = mComposer->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
+ return static_cast<Error>(intError);
+}
+
Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
PixelFormat* format, Display** outDisplay)
{
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 29d7a47..eefab98 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -93,6 +93,9 @@
};
uint32_t getMaxVirtualDisplayCount() const;
+ Error getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+ std::vector<uint8_t>* outData) const;
+
Error createVirtualDisplay(uint32_t width, uint32_t height,
android::ui::PixelFormat* format, Display** outDisplay);
void destroyDisplay(hwc2_display_t displayId);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index f5f7a82..4e98b88 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -54,6 +54,9 @@
#include "../Layer.h" // needed only for debugging
#include "../SurfaceFlinger.h"
+#define LOG_HWC_DISPLAY_ERROR(hwcDisplayId, msg) \
+ ALOGE("%s failed for HWC display %" PRIu64 ": %s", __FUNCTION__, hwcDisplayId, msg)
+
#define LOG_DISPLAY_ERROR(displayId, msg) \
ALOGE("%s failed for display %d: %s", __FUNCTION__, displayId, msg)
@@ -96,6 +99,16 @@
mHwcDevice->registerCallback(callback, sequenceId);
}
+bool HWComposer::getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+ DisplayIdentificationData* outData) const {
+ const auto error = mHwcDevice->getDisplayIdentificationData(hwcDisplayId, outPort, outData);
+ if (error != HWC2::Error::None) {
+ LOG_HWC_DISPLAY_ERROR(hwcDisplayId, to_string(error).c_str());
+ return false;
+ }
+ return true;
+}
+
bool HWComposer::hasCapability(HWC2::Capability capability) const
{
return mHwcDevice->getCapabilities().count(capability) > 0;
@@ -131,53 +144,53 @@
}
}
-void HWComposer::onHotplug(hwc2_display_t displayId, int32_t displayType,
- HWC2::Connection connection) {
+std::optional<DisplayId> HWComposer::onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType,
+ HWC2::Connection connection) {
if (displayType >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
ALOGE("Invalid display type of %d", displayType);
- return;
+ return {};
}
- ALOGV("hotplug: %" PRIu64 ", %s %s", displayId,
- displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external",
- to_string(connection).c_str());
- mHwcDevice->onHotplug(displayId, connection);
+ ALOGV("hotplug: %" PRIu64 ", %s %s", hwcDisplayId,
+ displayType == DisplayDevice::DISPLAY_PRIMARY ? "primary" : "external",
+ to_string(connection).c_str());
+ mHwcDevice->onHotplug(hwcDisplayId, connection);
+
+ std::optional<DisplayId> displayId;
+
+ uint8_t port;
+ DisplayIdentificationData data;
+ if (getDisplayIdentificationData(hwcDisplayId, &port, &data)) {
+ displayId = generateDisplayId(port, data);
+ ALOGE_IF(!displayId, "Failed to generate stable ID for display %" PRIu64, hwcDisplayId);
+ }
+
// Disconnect is handled through HWComposer::disconnectDisplay via
// SurfaceFlinger's onHotplugReceived callback handling
if (connection == HWC2::Connection::Connected) {
- mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(displayId);
- mHwcDisplaySlots[displayId] = displayType;
+ mDisplayData[displayType].hwcDisplay = mHwcDevice->getDisplayById(hwcDisplayId);
+ mHwcDisplaySlots[hwcDisplayId] = displayType;
}
+
+ return displayId;
}
-bool HWComposer::onVsync(hwc2_display_t displayId, int64_t timestamp,
- int32_t* outDisplay) {
- auto display = mHwcDevice->getDisplayById(displayId);
- if (!display) {
- ALOGE("onVsync Failed to find display %" PRIu64, displayId);
- return false;
- }
- auto displayType = HWC2::DisplayType::Invalid;
- auto error = display->getType(&displayType);
- if (error != HWC2::Error::None) {
- ALOGE("onVsync: Failed to determine type of display %" PRIu64,
- display->getId());
+bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplayId) {
+ const auto it = mHwcDisplaySlots.find(hwcDisplayId);
+ if (it == mHwcDisplaySlots.end()) {
+ LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid display");
return false;
}
- if (displayType == HWC2::DisplayType::Virtual) {
- ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
- display->getId());
+ const int32_t displayId = it->second;
+ RETURN_IF_INVALID_DISPLAY(displayId, false);
+
+ const auto& displayData = mDisplayData[displayId];
+ if (displayData.isVirtual) {
+ LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
return false;
}
- if (mHwcDisplaySlots.count(display->getId()) == 0) {
- ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
- display->getId());
- return false;
- }
-
- int32_t disp = mHwcDisplaySlots[display->getId()];
{
Mutex::Autolock _l(mLock);
@@ -185,22 +198,22 @@
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
// out here so they don't cause havoc downstream.
- if (timestamp == mLastHwVSync[disp]) {
+ if (timestamp == mLastHwVSync[displayId]) {
ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
timestamp);
return false;
}
- mLastHwVSync[disp] = timestamp;
+ mLastHwVSync[displayId] = timestamp;
}
- if (outDisplay) {
- *outDisplay = disp;
+ if (outDisplayId) {
+ *outDisplayId = displayId;
}
char tag[16];
- snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
- ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
+ snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", displayId);
+ ATRACE_INT(tag, ++mVSyncCounts[displayId] & 1);
return true;
}
@@ -208,16 +221,15 @@
status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
ui::PixelFormat* format, int32_t *outId) {
if (mRemainingHwcVirtualDisplays == 0) {
- ALOGE("allocateVirtualDisplay: No remaining virtual displays");
+ ALOGE("%s: No remaining virtual displays", __FUNCTION__);
return NO_MEMORY;
}
if (SurfaceFlinger::maxVirtualDisplaySize != 0 &&
(width > SurfaceFlinger::maxVirtualDisplaySize ||
height > SurfaceFlinger::maxVirtualDisplaySize)) {
- ALOGE("createVirtualDisplay: Can't create a virtual display with"
- " a dimension > %" PRIu64 " (tried %u x %u)",
- SurfaceFlinger::maxVirtualDisplaySize, width, height);
+ ALOGE("%s: Display size %ux%u exceeds maximum dimension of %" PRIu64, __FUNCTION__, width,
+ height, SurfaceFlinger::maxVirtualDisplaySize);
return INVALID_OPERATION;
}
@@ -225,7 +237,7 @@
auto error = mHwcDevice->createVirtualDisplay(width, height, format,
&display);
if (error != HWC2::Error::None) {
- ALOGE("allocateVirtualDisplay: Failed to create HWC virtual display");
+ ALOGE("%s: Failed to create HWC virtual display", __FUNCTION__);
return NO_MEMORY;
}
@@ -238,11 +250,13 @@
displaySlot = mDisplayData.size();
mDisplayData.resize(displaySlot + 1);
} else {
- ALOGE("allocateVirtualDisplay: Unable to allocate a display slot");
+ ALOGE("%s: Unable to allocate a display slot", __FUNCTION__);
return NO_MEMORY;
}
- mDisplayData[displaySlot].hwcDisplay = display;
+ auto& displayData = mDisplayData[displaySlot];
+ displayData.hwcDisplay = display;
+ displayData.isVirtual = true;
--mRemainingHwcVirtualDisplays;
*outId = static_cast<int32_t>(displaySlot);
@@ -319,21 +333,19 @@
}
int HWComposer::getActiveConfigIndex(int32_t displayId) const {
- if (!isValidDisplay(displayId)) {
- ALOGV("getActiveConfigIndex: Attempted to access invalid display %d", displayId);
- return -1;
- }
+ RETURN_IF_INVALID_DISPLAY(displayId, -1);
+
int index;
auto error = mDisplayData[displayId].hwcDisplay->getActiveConfigIndex(&index);
if (error == HWC2::Error::BadConfig) {
- ALOGE("getActiveConfigIndex: No config active, returning -1");
+ LOG_DISPLAY_ERROR(displayId, "No active config");
return -1;
- } else if (error != HWC2::Error::None) {
- ALOGE("getActiveConfigIndex failed for display %d: %s (%d)", displayId,
- to_string(error).c_str(), static_cast<int32_t>(error));
- return -1;
- } else if (index < 0) {
- ALOGE("getActiveConfigIndex returned an unknown config for display %d", displayId);
+ }
+
+ RETURN_IF_HWC_ERROR(error, displayId, -1);
+
+ if (index < 0) {
+ LOG_DISPLAY_ERROR(displayId, "Unknown config");
return -1;
}
@@ -365,19 +377,19 @@
void HWComposer::setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled) {
- if (displayId < 0 || displayId >= HWC_DISPLAY_VIRTUAL) {
- ALOGD("setVsyncEnabled: Ignoring for virtual display %d", displayId);
+ RETURN_IF_INVALID_DISPLAY(displayId);
+ auto& displayData = mDisplayData[displayId];
+
+ if (displayData.isVirtual) {
+ LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
return;
}
- RETURN_IF_INVALID_DISPLAY(displayId);
-
// NOTE: we use our own internal lock here because we have to call
// into the HWC with the lock held, and we want to make sure
// that even if HWC blocks (which it shouldn't), it won't
// affect other threads.
Mutex::Autolock _l(mVsyncLock);
- auto& displayData = mDisplayData[displayId];
if (enabled != displayData.vsyncEnabled) {
ATRACE_CALL();
auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
@@ -403,11 +415,11 @@
return NO_ERROR;
}
-status_t HWComposer::prepare(DisplayDevice& displayDevice) {
+status_t HWComposer::prepare(DisplayDevice& display) {
ATRACE_CALL();
Mutex::Autolock _l(mDisplayLock);
- auto displayId = displayDevice.getHwcDisplayId();
+ const auto displayId = display.getId();
if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
ALOGV("Skipping HWComposer prepare for non-HWC display");
return NO_ERROR;
@@ -474,7 +486,7 @@
displayData.hasClientComposition = false;
displayData.hasDeviceComposition = false;
- for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) {
+ for (auto& layer : display.getVisibleLayersSortedByZ()) {
auto hwcLayer = layer->getHwcLayer(displayId);
if (changedTypes.count(hwcLayer) != 0) {
@@ -601,7 +613,8 @@
ALOGV("setPowerMode(%d, %d)", displayId, intMode);
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
- if (displayId >= VIRTUAL_DISPLAY_ID_BASE) {
+ const auto& displayData = mDisplayData[displayId];
+ if (displayData.isVirtual) {
LOG_DISPLAY_ERROR(displayId, "Invalid operation on virtual display");
return INVALID_OPERATION;
}
@@ -611,7 +624,7 @@
setVsyncEnabled(displayId, HWC2::Vsync::Disable);
}
- auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+ auto& hwcDisplay = displayData.hwcDisplay;
switch (mode) {
case HWC2::PowerMode::Off:
case HWC2::PowerMode::On:
@@ -680,43 +693,35 @@
return NO_ERROR;
}
-void HWComposer::disconnectDisplay(int displayId) {
- LOG_ALWAYS_FATAL_IF(displayId < 0);
+void HWComposer::disconnectDisplay(int32_t displayId) {
+ RETURN_IF_INVALID_DISPLAY(displayId);
auto& displayData = mDisplayData[displayId];
- auto displayType = HWC2::DisplayType::Invalid;
- auto error = displayData.hwcDisplay->getType(&displayType);
- RETURN_IF_HWC_ERROR_FOR("getType", error, displayId);
-
// If this was a virtual display, add its slot back for reuse by future
// virtual displays
- if (displayType == HWC2::DisplayType::Virtual) {
+ if (displayData.isVirtual) {
mFreeDisplaySlots.insert(displayId);
++mRemainingHwcVirtualDisplays;
}
- auto hwcId = displayData.hwcDisplay->getId();
- mHwcDisplaySlots.erase(hwcId);
- displayData.reset();
+ const auto hwcDisplayId = displayData.hwcDisplay->getId();
+ mHwcDisplaySlots.erase(hwcDisplayId);
+ displayData = DisplayData();
- mHwcDevice->destroyDisplay(hwcId);
+ mHwcDevice->destroyDisplay(hwcDisplayId);
}
status_t HWComposer::setOutputBuffer(int32_t displayId,
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto& displayData = mDisplayData[displayId];
- auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
- auto displayType = HWC2::DisplayType::Invalid;
- auto error = hwcDisplay->getType(&displayType);
- RETURN_IF_HWC_ERROR_FOR("getType", error, displayId, NAME_NOT_FOUND);
-
- if (displayType != HWC2::DisplayType::Virtual) {
+ if (!displayData.isVirtual) {
LOG_DISPLAY_ERROR(displayId, "Invalid operation on physical display");
return INVALID_OPERATION;
}
- error = hwcDisplay->setOutputBuffer(buffer, acquireFence);
+ auto error = displayData.hwcDisplay->setOutputBuffer(buffer, acquireFence);
RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
return NO_ERROR;
}
@@ -805,26 +810,4 @@
return mDisplayData[displayId].hwcDisplay->getId();
}
-// ---------------------------------------------------------------------------
-
-HWComposer::DisplayData::DisplayData()
- : hasClientComposition(false),
- hasDeviceComposition(false),
- hwcDisplay(nullptr),
- lastPresentFence(Fence::NO_FENCE),
- outbufHandle(nullptr),
- outbufAcquireFence(Fence::NO_FENCE),
- vsyncEnabled(HWC2::Vsync::Disable) {
- ALOGV("Created new DisplayData");
-}
-
-HWComposer::DisplayData::~DisplayData() {
-}
-
-void HWComposer::DisplayData::reset() {
- ALOGV("DisplayData reset");
- *this = DisplayData();
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index f968948..3c5efea 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -37,6 +37,8 @@
#include <set>
#include <vector>
+#include "DisplayIdentification.h"
+
extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
const struct timespec *request,
struct timespec *remain);
@@ -74,6 +76,9 @@
void registerCallback(HWC2::ComposerCallback* callback,
int32_t sequenceId);
+ bool getDisplayIdentificationData(hwc2_display_t hwcDisplayId, uint8_t* outPort,
+ DisplayIdentificationData* outData) const;
+
bool hasCapability(HWC2::Capability capability) const;
// Attempts to allocate a virtual display. If the virtual display is created
@@ -87,7 +92,7 @@
void destroyLayer(int32_t displayId, HWC2::Layer* layer);
// Asks the HAL what it can do
- status_t prepare(DisplayDevice& displayDevice);
+ status_t prepare(DisplayDevice& display);
status_t setClientTarget(int32_t displayId, uint32_t slot,
const sp<Fence>& acquireFence,
@@ -147,9 +152,9 @@
// Returns true if successful, false otherwise. The
// DisplayDevice::DisplayType of the display is returned as an output param.
- bool onVsync(hwc2_display_t displayId, int64_t timestamp,
- int32_t* outDisplay);
- void onHotplug(hwc2_display_t displayId, int32_t displayType, HWC2::Connection connection);
+ bool onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp, int32_t* outDisplay);
+ std::optional<DisplayId> onHotplug(hwc2_display_t hwcDisplayId, int32_t displayType,
+ HWC2::Connection connection);
void setVsyncEnabled(int32_t displayId, HWC2::Vsync enabled);
@@ -183,31 +188,26 @@
// For unit tests
friend TestableSurfaceFlinger;
- static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
-
bool isValidDisplay(int32_t displayId) const;
static void validateChange(HWC2::Composition from, HWC2::Composition to);
struct cb_context;
struct DisplayData {
- DisplayData();
- ~DisplayData();
- void reset();
-
- bool hasClientComposition;
- bool hasDeviceComposition;
- HWC2::Display* hwcDisplay;
+ bool isVirtual = false;
+ bool hasClientComposition = false;
+ bool hasDeviceComposition = false;
+ HWC2::Display* hwcDisplay = nullptr;
HWC2::DisplayRequest displayRequests;
- sp<Fence> lastPresentFence; // signals when the last set op retires
+ sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
- buffer_handle_t outbufHandle;
- sp<Fence> outbufAcquireFence;
+ buffer_handle_t outbufHandle = nullptr;
+ sp<Fence> outbufAcquireFence = Fence::NO_FENCE;
mutable std::unordered_map<int32_t,
std::shared_ptr<const HWC2::Display::Config>> configMap;
// protected by mVsyncLock
- HWC2::Vsync vsyncEnabled;
+ HWC2::Vsync vsyncEnabled = HWC2::Vsync::Disable;
bool validateWasSkipped;
HWC2::Error presentError;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
deleted file mode 100644
index fe7944f..0000000
--- a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_SF_HWCOMPOSER_HWC1_H
-#define ANDROID_SF_HWCOMPOSER_HWC1_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <hardware/hwcomposer_defs.h>
-
-#include <system/graphics.h>
-
-#include <ui/Fence.h>
-
-#include <utils/BitSet.h>
-#include <utils/Condition.h>
-#include <utils/Mutex.h>
-#include <utils/StrongPointer.h>
-#include <utils/Thread.h>
-#include <utils/Timers.h>
-#include <utils/Vector.h>
-
-extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
- const struct timespec *request,
- struct timespec *remain);
-
-struct hwc_composer_device_1;
-struct hwc_display_contents_1;
-struct hwc_layer_1;
-struct hwc_procs;
-struct framebuffer_device_t;
-
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Fence;
-class FloatRect;
-class GraphicBuffer;
-class NativeHandle;
-class Region;
-class String8;
-class SurfaceFlinger;
-
-class HWComposer
-{
-public:
- class EventHandler {
- friend class HWComposer;
- virtual void onVSyncReceived(
- HWComposer* composer, int32_t disp, nsecs_t timestamp) = 0;
- virtual void onHotplugReceived(HWComposer* composer, int disp, bool connected) = 0;
- virtual void onInvalidateReceived(HWComposer* composer) = 0;
- protected:
- virtual ~EventHandler() {}
- };
-
- enum {
- NUM_BUILTIN_DISPLAYS = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
- MAX_HWC_DISPLAYS = HWC_NUM_DISPLAY_TYPES,
- VIRTUAL_DISPLAY_ID_BASE = HWC_DISPLAY_VIRTUAL,
- };
-
- HWComposer(
- const sp<SurfaceFlinger>& flinger,
- EventHandler& handler);
-
- ~HWComposer();
-
- status_t initCheck() const;
-
- // Returns a display ID starting at VIRTUAL_DISPLAY_ID_BASE, this ID is to
- // be used with createWorkList (and all other methods requiring an ID
- // below).
- // IDs below NUM_BUILTIN_DISPLAYS are pre-defined and therefore are
- // always valid.
- // Returns -1 if an ID cannot be allocated
- int32_t allocateDisplayId();
-
- // Recycles the given virtual display ID and frees the associated worklist.
- // IDs below NUM_BUILTIN_DISPLAYS are not recycled.
- status_t freeDisplayId(int32_t id);
-
-
- // Asks the HAL what it can do
- status_t prepare();
-
- // commits the list
- status_t commit();
-
- // set power mode
- status_t setPowerMode(int disp, int mode);
-
- // set active config
- status_t setActiveConfig(int disp, int mode);
-
- // reset state when an external, non-virtual display is disconnected
- void disconnectDisplay(int disp);
-
- // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
- status_t createWorkList(int32_t id, size_t numLayers);
-
- bool supportsFramebufferTarget() const;
-
- // does this display have layers handled by HWC
- bool hasHwcComposition(int32_t id) const;
-
- // does this display have layers handled by GLES
- bool hasGlesComposition(int32_t id) const;
-
- // get the releaseFence file descriptor for a display's framebuffer layer.
- // the release fence is only valid after commit()
- sp<Fence> getAndResetReleaseFence(int32_t id);
-
- // needed forward declarations
- class LayerListIterator;
-
- // return the visual id to be used to find a suitable EGLConfig for
- // *ALL* displays.
- int getVisualID() const;
-
- // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
- int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
- int fbCompositionComplete();
- void fbDump(String8& result);
-
- // Set the output buffer and acquire fence for a virtual display.
- // Returns INVALID_OPERATION if id is not a virtual display.
- status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
- const sp<GraphicBuffer>& buf);
-
- // Get the retire fence for the last committed frame. This fence will
- // signal when the h/w composer is completely finished with the frame.
- // For physical displays, it is no longer being displayed. For virtual
- // displays, writes to the output buffer are complete.
- sp<Fence> getLastRetireFence(int32_t id) const;
-
- status_t setCursorPositionAsync(int32_t id, const Rect &pos);
-
- /*
- * Interface to hardware composer's layers functionality.
- * This abstracts the HAL interface to layers which can evolve in
- * incompatible ways from one release to another.
- * The idea is that we could extend this interface as we add
- * features to h/w composer.
- */
- class HWCLayerInterface {
- protected:
- virtual ~HWCLayerInterface() { }
- public:
- virtual int32_t getCompositionType() const = 0;
- virtual uint32_t getHints() const = 0;
- virtual sp<Fence> getAndResetReleaseFence() = 0;
- virtual void setDefaultState() = 0;
- virtual void setSkip(bool skip) = 0;
- virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
- virtual void setBlending(uint32_t blending) = 0;
- virtual void setTransform(uint32_t transform) = 0;
- virtual void setFrame(const Rect& frame) = 0;
- virtual void setCrop(const FloatRect& crop) = 0;
- virtual void setVisibleRegionScreen(const Region& reg) = 0;
- virtual void setSurfaceDamage(const Region& reg) = 0;
- virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
- virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
- virtual void setAcquireFenceFd(int fenceFd) = 0;
- virtual void setPlaneAlpha(uint8_t alpha) = 0;
- virtual void onDisplayed() = 0;
- };
-
- /*
- * Interface used to implement an iterator to a list
- * of HWCLayer.
- */
- class HWCLayer : public HWCLayerInterface {
- friend class LayerListIterator;
- // select the layer at the given index
- virtual status_t setLayer(size_t index) = 0;
- virtual HWCLayer* dup() = 0;
- static HWCLayer* copy(HWCLayer *rhs) {
- return rhs ? rhs->dup() : nullptr;
- }
- protected:
- virtual ~HWCLayer() { }
- };
-
- /*
- * Iterator through a HWCLayer list.
- * This behaves more or less like a forward iterator.
- */
- class LayerListIterator {
- friend class HWComposer;
- HWCLayer* const mLayerList;
- size_t mIndex;
-
- LayerListIterator() : mLayerList(nullptr), mIndex(0) { }
-
- LayerListIterator(HWCLayer* layer, size_t index)
- : mLayerList(layer), mIndex(index) { }
-
- // we don't allow assignment, because we don't need it for now
- LayerListIterator& operator = (const LayerListIterator& rhs);
-
- public:
- // copy operators
- LayerListIterator(const LayerListIterator& rhs)
- : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
- }
-
- ~LayerListIterator() { delete mLayerList; }
-
- // pre-increment
- LayerListIterator& operator++() {
- mLayerList->setLayer(++mIndex);
- return *this;
- }
-
- // dereference
- HWCLayerInterface& operator * () { return *mLayerList; }
- HWCLayerInterface* operator -> () { return mLayerList; }
-
- // comparison
- bool operator == (const LayerListIterator& rhs) const {
- return mIndex == rhs.mIndex;
- }
- bool operator != (const LayerListIterator& rhs) const {
- return !operator==(rhs);
- }
- };
-
- // Returns an iterator to the beginning of the layer list
- LayerListIterator begin(int32_t id);
-
- // Returns an iterator to the end of the layer list
- LayerListIterator end(int32_t id);
-
-
- // Events handling ---------------------------------------------------------
-
- enum {
- EVENT_VSYNC = HWC_EVENT_VSYNC
- };
-
- void eventControl(int disp, int event, int enabled);
-
- struct DisplayConfig {
- uint32_t width;
- uint32_t height;
- float xdpi;
- float ydpi;
- nsecs_t refresh;
- 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.
- // HWC_DISPLAY_PRIMARY).
- nsecs_t getRefreshTimestamp(int disp) const;
- sp<Fence> getDisplayFence(int disp) const;
- uint32_t getFormat(int disp) const;
- bool isConnected(int disp) const;
-
- // These return the values for the current config of a given display index.
- // To get the values for all configs, use getConfigs below.
- uint32_t getWidth(int disp) const;
- uint32_t getHeight(int disp) const;
- 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;
-
- status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
- uint32_t format);
-
- // this class is only used to fake the VSync event on systems that don't
- // have it.
- class VSyncThread : public Thread {
- HWComposer& mHwc;
- mutable Mutex mLock;
- Condition mCondition;
- bool mEnabled;
- mutable nsecs_t mNextFakeVSync;
- nsecs_t mRefreshPeriod;
- virtual void onFirstRef();
- virtual bool threadLoop();
- public:
- VSyncThread(HWComposer& hwc);
- void setEnabled(bool enabled);
- };
-
- friend class VSyncThread;
-
- // for debugging ----------------------------------------------------------
- void dump(String8& out) const;
-
-private:
- void loadHwcModule();
- int loadFbHalModule();
-
- LayerListIterator getLayerIterator(int32_t id, size_t index);
-
- struct cb_context;
-
- static void hook_invalidate(const struct hwc_procs* procs);
- static void hook_vsync(const struct hwc_procs* procs, int disp,
- int64_t timestamp);
- static void hook_hotplug(const struct hwc_procs* procs, int disp,
- int connected);
-
- inline void invalidate();
- inline void vsync(int disp, int64_t timestamp);
- inline void hotplug(int disp, int connected);
-
- status_t queryDisplayProperties(int disp);
-
- status_t setFramebufferTarget(int32_t id,
- const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
-
- struct DisplayData {
- DisplayData();
- ~DisplayData();
- Vector<DisplayConfig> configs;
- size_t currentConfig;
- uint32_t format; // pixel format from FB hal, for pre-hwc-1.1
- bool connected;
- bool hasFbComp;
- bool hasOvComp;
- size_t capacity;
- hwc_display_contents_1* list;
- hwc_layer_1* framebufferTarget;
- buffer_handle_t fbTargetHandle;
- sp<Fence> lastRetireFence; // signals when the last set op retires
- sp<Fence> lastDisplayFence; // signals when the last set op takes
- // effect on screen
- buffer_handle_t outbufHandle;
- sp<Fence> outbufAcquireFence;
-
- // protected by mEventControlLock
- int32_t events;
-
- // We need to hold "copies" of these for memory management purposes. The
- // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
- // internally doesn't copy the memory unless one of the copies is
- // modified.
- Vector<Region> visibleRegions;
- Vector<Region> surfaceDamageRegions;
- };
-
- sp<SurfaceFlinger> mFlinger;
- framebuffer_device_t* mFbDev;
- struct hwc_composer_device_1* mHwc;
- // invariant: mLists[0] != nullptr iff mHwc != nullptr
- // mLists[i>0] can be nullptr. that display is to be ignored
- struct hwc_display_contents_1* mLists[MAX_HWC_DISPLAYS];
- DisplayData mDisplayData[MAX_HWC_DISPLAYS];
- // protect mDisplayData from races between prepare and dump
- mutable Mutex mDisplayLock;
- size_t mNumDisplays;
-
- cb_context* mCBContext;
- EventHandler& mEventHandler;
- size_t mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
- sp<VSyncThread> mVSyncThread;
- bool mDebugForceFakeVSync;
- BitSet32 mAllocatedDisplayIDs;
-
- // protected by mLock
- mutable Mutex mLock;
- mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
-
- // thread-safe
- mutable Mutex mEventControlLock;
-};
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 9a2817d..c111a27 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -32,11 +32,11 @@
// ---------------------------------------------------------------------------
#define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
+ mDisplayName.c_str(), ##__VA_ARGS__)
#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
+ mDisplayName.c_str(), ##__VA_ARGS__)
#define VDS_LOGV(msg, ...) ALOGV("[%s] " msg, \
- mDisplayName.string(), ##__VA_ARGS__)
+ mDisplayName.c_str(), ##__VA_ARGS__)
static const char* dbgCompositionTypeStr(DisplaySurface::CompositionType type) {
switch (type) {
@@ -52,7 +52,7 @@
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
- const String8& name)
+ const std::string& name)
: ConsumerBase(bqConsumer),
mHwc(hwc),
mDisplayId(dispId),
@@ -102,7 +102,7 @@
}
mOutputFormat = mDefaultOutputFormat;
- ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.string());
+ ConsumerBase::mName = String8::format("VDS: %s", mDisplayName.c_str());
mConsumer->setConsumerName(ConsumerBase::mName);
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 5c8acea..4bd4d0f 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
#define ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
+#include <string>
+
#include "DisplaySurface.h"
#include "HWComposerBufferCache.h"
@@ -77,7 +79,7 @@
const sp<IGraphicBufferProducer>& sink,
const sp<IGraphicBufferProducer>& bqProducer,
const sp<IGraphicBufferConsumer>& bqConsumer,
- const String8& name);
+ const std::string& name);
//
// DisplaySurface interface
@@ -153,7 +155,7 @@
//
HWComposer& mHwc;
const int32_t mDisplayId;
- const String8 mDisplayName;
+ const std::string mDisplayName;
sp<IGraphicBufferProducer> mSource[2]; // indexed by SOURCE_*
uint32_t mDefaultOutputFormat;
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index bc271c8..5a8fd25 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -155,20 +155,17 @@
mCondition.notify_all();
}
-void EventThread::onHotplugReceived(int type, bool connected) {
- ALOGE_IF(type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES,
- "received hotplug event for an invalid display (id=%d)", type);
-
+void EventThread::onHotplugReceived(DisplayType displayType, bool connected) {
std::lock_guard<std::mutex> lock(mMutex);
- if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
- DisplayEventReceiver::Event event;
- event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
- event.header.id = type;
- event.header.timestamp = systemTime();
- event.hotplug.connected = connected;
- mPendingEvents.add(event);
- mCondition.notify_all();
- }
+
+ DisplayEventReceiver::Event event;
+ event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
+ event.header.id = displayType == DisplayType::Primary ? 0 : 1;
+ event.header.timestamp = systemTime();
+ event.hotplug.connected = connected;
+
+ mPendingEvents.add(event);
+ mCondition.notify_all();
}
void EventThread::threadMain() NO_THREAD_SAFETY_ANALYSIS {
@@ -205,7 +202,7 @@
// This will return when (1) a vsync event has been received, and (2) there was
// at least one connection interested in receiving it when we started waiting.
Vector<sp<EventThread::Connection> > EventThread::waitForEventLocked(
- std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* event) {
+ std::unique_lock<std::mutex>* lock, DisplayEventReceiver::Event* outEvent) {
Vector<sp<EventThread::Connection> > signalConnections;
while (signalConnections.isEmpty() && mKeepRunning) {
@@ -214,16 +211,16 @@
size_t vsyncCount = 0;
nsecs_t timestamp = 0;
- for (int32_t i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; i++) {
- timestamp = mVSyncEvent[i].header.timestamp;
+ for (auto& event : mVSyncEvent) {
+ timestamp = event.header.timestamp;
if (timestamp) {
// we have a vsync event to dispatch
if (mInterceptVSyncsCallback) {
mInterceptVSyncsCallback(timestamp);
}
- *event = mVSyncEvent[i];
- mVSyncEvent[i].header.timestamp = 0;
- vsyncCount = mVSyncEvent[i].vsync.count;
+ *outEvent = event;
+ event.header.timestamp = 0;
+ vsyncCount = event.vsync.count;
break;
}
}
@@ -233,7 +230,7 @@
eventPending = !mPendingEvents.isEmpty();
if (eventPending) {
// we have some other event to dispatch
- *event = mPendingEvents[0];
+ *outEvent = mPendingEvents[0];
mPendingEvents.removeAt(0);
}
}
@@ -319,7 +316,7 @@
// FIXME: how do we decide which display id the fake
// vsync came from ?
mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
- mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
+ mVSyncEvent[0].header.id = 0;
mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
mVSyncEvent[0].vsync.count++;
}
@@ -364,8 +361,7 @@
result.appendFormat("VSYNC state: %s\n", mDebugVsyncEnabled ? "enabled" : "disabled");
result.appendFormat(" soft-vsync: %s\n", mUseSoftwareVSync ? "enabled" : "disabled");
result.appendFormat(" numListeners=%zu,\n events-delivered: %u\n",
- mDisplayEventConnections.size(),
- mVSyncEvent[DisplayDevice::DISPLAY_PRIMARY].vsync.count);
+ mDisplayEventConnections.size(), mVSyncEvent[0].vsync.count);
for (size_t i = 0; i < mDisplayEventConnections.size(); i++) {
sp<Connection> connection = mDisplayEventConnections.itemAt(i).promote();
result.appendFormat(" %p: count=%d\n", connection.get(),
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 9c13ed2..a0262b2 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -16,9 +16,11 @@
#pragma once
-#include <stdint.h>
#include <sys/types.h>
+
+#include <array>
#include <condition_variable>
+#include <cstdint>
#include <mutex>
#include <thread>
@@ -31,8 +33,6 @@
#include <utils/Errors.h>
#include <utils/SortedVector.h>
-#include "DisplayDevice.h"
-
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -59,6 +59,9 @@
class EventThread {
public:
+ // TODO: Remove once stable display IDs are plumbed through SF/WM interface.
+ enum class DisplayType { Primary, External };
+
virtual ~EventThread();
virtual sp<BnDisplayEventConnection> createEventConnection() const = 0;
@@ -70,7 +73,7 @@
virtual void onScreenAcquired() = 0;
// called when receiving a hotplug event
- virtual void onHotplugReceived(int type, bool connected) = 0;
+ virtual void onHotplugReceived(DisplayType displayType, bool connected) = 0;
virtual void dump(String8& result) const = 0;
@@ -122,7 +125,7 @@
void onScreenAcquired() override;
// called when receiving a hotplug event
- void onHotplugReceived(int type, bool connected) override;
+ void onHotplugReceived(DisplayType displayType, bool connected) override;
void dump(String8& result) const override;
@@ -155,8 +158,7 @@
// protected by mLock
SortedVector<wp<Connection>> mDisplayEventConnections GUARDED_BY(mMutex);
Vector<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
- DisplayEventReceiver::Event mVSyncEvent[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES] GUARDED_BY(
- mMutex);
+ std::array<DisplayEventReceiver::Event, 2> mVSyncEvent GUARDED_BY(mMutex);
bool mUseSoftwareVSync GUARDED_BY(mMutex) = false;
bool mVsyncEnabled GUARDED_BY(mMutex) = false;
bool mKeepRunning GUARDED_BY(mMutex) = true;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2595ec1..b4b3f4a 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -63,11 +63,6 @@
namespace android {
-LayerBE::LayerBE()
- : mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
-}
-
-
int32_t Layer::sSequence = 1;
Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
@@ -100,7 +95,9 @@
mAutoRefresh(false),
mFreezeGeometryUpdates(false),
mCurrentChildren(LayerVector::StateSet::Current),
- mDrawingChildren(LayerVector::StateSet::Drawing) {
+ mDrawingChildren(LayerVector::StateSet::Drawing),
+ mBE{this, name.string()} {
+
mCurrentCrop.makeInvalid();
uint32_t layerFlags = 0;
@@ -219,32 +216,32 @@
// h/w composer set-up
// ---------------------------------------------------------------------------
-bool Layer::createHwcLayer(HWComposer* hwc, int32_t hwcId) {
- LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0,
- "Already have a layer for hwcId %d", hwcId);
- HWC2::Layer* layer = hwc->createLayer(hwcId);
+bool Layer::createHwcLayer(HWComposer* hwc, int32_t displayId) {
+ LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0,
+ "Already have a layer for display %d", displayId);
+ HWC2::Layer* layer = hwc->createLayer(displayId);
if (!layer) {
return false;
}
- LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[hwcId];
+ LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers[displayId];
hwcInfo.hwc = hwc;
hwcInfo.layer = layer;
layer->setLayerDestroyedListener(
- [this, hwcId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(hwcId); });
+ [this, displayId](HWC2::Layer* /*layer*/) { getBE().mHwcLayers.erase(displayId); });
return true;
}
-bool Layer::destroyHwcLayer(int32_t hwcId) {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
+bool Layer::destroyHwcLayer(int32_t displayId) {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
return false;
}
- auto& hwcInfo = getBE().mHwcLayers[hwcId];
+ auto& hwcInfo = getBE().mHwcLayers[displayId];
LOG_ALWAYS_FATAL_IF(hwcInfo.layer == nullptr, "Attempt to destroy null layer");
LOG_ALWAYS_FATAL_IF(hwcInfo.hwc == nullptr, "Missing HWComposer");
- hwcInfo.hwc->destroyLayer(hwcId, hwcInfo.layer);
+ hwcInfo.hwc->destroyLayer(displayId, hwcInfo.layer);
// The layer destroyed listener should have cleared the entry from
// mHwcLayers. Verify that.
- LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(hwcId) != 0,
+ LOG_ALWAYS_FATAL_IF(getBE().mHwcLayers.count(displayId) != 0,
"Stale layer entry in getBE().mHwcLayers");
return true;
}
@@ -366,7 +363,7 @@
return reduce(floatWin, activeTransparentRegion);
}
-Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const {
+Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& display) const {
// the crop is the area of the window that gets cropped, but not
// scaled in any ways.
const State& s(getDrawingState());
@@ -385,7 +382,7 @@
Transform t = getTransform();
activeCrop = t.transform(activeCrop);
- if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
+ if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
activeCrop.clear();
}
if (!s.finalCrop.isEmpty()) {
@@ -396,14 +393,14 @@
const auto& p = mDrawingParent.promote();
if (p != nullptr) {
- auto parentCrop = p->computeInitialCrop(hw);
+ auto parentCrop = p->computeInitialCrop(display);
activeCrop.intersect(parentCrop, &activeCrop);
}
return activeCrop;
}
-FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const {
+FloatRect Layer::computeCrop(const sp<const DisplayDevice>& display) const {
// the content crop is the area of the content that gets scaled to the
// layer's size. This is in buffer space.
FloatRect crop = getContentCrop().toFloatRect();
@@ -412,7 +409,7 @@
const State& s(getDrawingState());
// Screen space to make reduction to parent crop clearer.
- Rect activeCrop = computeInitialCrop(hw);
+ Rect activeCrop = computeInitialCrop(display);
Transform t = getTransform();
// Back to layer space to work with the content crop.
activeCrop = t.inverse().transform(activeCrop);
@@ -483,15 +480,19 @@
return crop;
}
-void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
-{
- const auto hwcId = displayDevice->getHwcDisplayId();
- auto& hwcInfo = getBE().mHwcLayers[hwcId];
+void Layer::setGeometry(const sp<const DisplayDevice>& display, uint32_t z) {
+ const auto displayId = display->getId();
+ if (!hasHwcLayer(displayId)) {
+ ALOGE("[%s] failed to setGeometry: no HWC layer found (%d)",
+ mName.string(), displayId);
+ return;
+ }
+ auto& hwcInfo = getBE().mHwcLayers[displayId];
// enable this layer
hwcInfo.forceClientComposition = false;
- if (isSecure() && !displayDevice->isSecure()) {
+ if (isSecure() && !display->isSecure()) {
hwcInfo.forceClientComposition = true;
}
@@ -518,7 +519,7 @@
if (!s.crop.isEmpty()) {
Rect activeCrop(s.crop);
activeCrop = t.transform(activeCrop);
- if (!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
+ if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
activeCrop.clear();
}
activeCrop = t.inverse().transform(activeCrop, true);
@@ -547,10 +548,10 @@
frame.clear();
}
}
- if (!frame.intersect(displayDevice->getViewport(), &frame)) {
+ if (!frame.intersect(display->getViewport(), &frame)) {
frame.clear();
}
- const Transform& tr(displayDevice->getTransform());
+ const Transform& tr = display->getTransform();
Rect transformedFrame = tr.transform(frame);
error = hwcLayer->setDisplayFrame(transformedFrame);
if (error != HWC2::Error::None) {
@@ -561,7 +562,7 @@
hwcInfo.displayFrame = transformedFrame;
}
- FloatRect sourceCrop = computeCrop(displayDevice);
+ FloatRect sourceCrop = computeCrop(display);
error = hwcLayer->setSourceCrop(sourceCrop);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set source crop [%.3f, %.3f, %.3f, %.3f]: "
@@ -646,28 +647,28 @@
}
}
-void Layer::forceClientComposition(int32_t hwcId) {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
- ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId);
+void Layer::forceClientComposition(int32_t displayId) {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
+ ALOGE("forceClientComposition: no HWC layer found (%d)", displayId);
return;
}
- getBE().mHwcLayers[hwcId].forceClientComposition = true;
+ getBE().mHwcLayers[displayId].forceClientComposition = true;
}
-bool Layer::getForceClientComposition(int32_t hwcId) {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
- ALOGE("getForceClientComposition: no HWC layer found (%d)", hwcId);
+bool Layer::getForceClientComposition(int32_t displayId) {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
+ ALOGE("getForceClientComposition: no HWC layer found (%d)", displayId);
return false;
}
- return getBE().mHwcLayers[hwcId].forceClientComposition;
+ return getBE().mHwcLayers[displayId].forceClientComposition;
}
-void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) {
- auto hwcId = displayDevice->getHwcDisplayId();
- if (getBE().mHwcLayers.count(hwcId) == 0 ||
- getCompositionType(hwcId) != HWC2::Composition::Cursor) {
+void Layer::updateCursorPosition(const sp<const DisplayDevice>& display) {
+ const auto displayId = display->getId();
+ if (getBE().mHwcLayers.count(displayId) == 0 ||
+ getCompositionType(displayId) != HWC2::Composition::Cursor) {
return;
}
@@ -683,15 +684,15 @@
// Subtract the transparent region and snap to the bounds
Rect bounds = reduce(win, s.activeTransparentRegion);
Rect frame(getTransform().transform(bounds));
- frame.intersect(displayDevice->getViewport(), &frame);
+ frame.intersect(display->getViewport(), &frame);
if (!s.finalCrop.isEmpty()) {
frame.intersect(s.finalCrop, &frame);
}
- auto& displayTransform(displayDevice->getTransform());
+ auto& displayTransform = display->getTransform();
auto position = displayTransform.transform(frame);
- auto error = getBE().mHwcLayers[hwcId].layer->setCursorPosition(position.left,
- position.top);
+ auto error =
+ getBE().mHwcLayers[displayId].layer->setCursorPosition(position.left, position.top);
ALOGE_IF(error != HWC2::Error::None,
"[%s] Failed to set cursor position "
"to (%d, %d): %s (%d)",
@@ -727,12 +728,12 @@
clearWithOpenGL(renderArea, 0, 0, 0, 0);
}
-void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc) {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
+void Layer::setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc) {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
ALOGE("setCompositionType called without a valid HWC layer");
return;
}
- auto& hwcInfo = getBE().mHwcLayers[hwcId];
+ auto& hwcInfo = getBE().mHwcLayers[displayId];
auto& hwcLayer = hwcInfo.layer;
ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(), to_string(type).c_str(),
static_cast<int>(callIntoHwc));
@@ -750,33 +751,33 @@
}
}
-HWC2::Composition Layer::getCompositionType(int32_t hwcId) const {
- if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+HWC2::Composition Layer::getCompositionType(int32_t displayId) const {
+ if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
// If we're querying the composition type for a display that does not
// have a HWC counterpart, then it will always be Client
return HWC2::Composition::Client;
}
- if (getBE().mHwcLayers.count(hwcId) == 0) {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
ALOGE("getCompositionType called with an invalid HWC layer");
return HWC2::Composition::Invalid;
}
- return getBE().mHwcLayers.at(hwcId).compositionType;
+ return getBE().mHwcLayers.at(displayId).compositionType;
}
-void Layer::setClearClientTarget(int32_t hwcId, bool clear) {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
+void Layer::setClearClientTarget(int32_t displayId, bool clear) {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
ALOGE("setClearClientTarget called without a valid HWC layer");
return;
}
- getBE().mHwcLayers[hwcId].clearClientTarget = clear;
+ getBE().mHwcLayers[displayId].clearClientTarget = clear;
}
-bool Layer::getClearClientTarget(int32_t hwcId) const {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
+bool Layer::getClearClientTarget(int32_t displayId) const {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
ALOGE("getClearClientTarget called without a valid HWC layer");
return false;
}
- return getBE().mHwcLayers.at(hwcId).clearClientTarget;
+ return getBE().mHwcLayers.at(displayId).clearClientTarget;
}
bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
@@ -1375,13 +1376,13 @@
return usage;
}
-void Layer::updateTransformHint(const sp<const DisplayDevice>& hw) const {
+void Layer::updateTransformHint(const sp<const DisplayDevice>& display) const {
uint32_t orientation = 0;
if (!mFlinger->mDebugDisableTransformHint) {
// The transform hint is used to improve performance, but we can
// only have a single transform hint, it cannot
// apply to all displays.
- const Transform& planeTransform(hw->getTransform());
+ const Transform& planeTransform = display->getTransform();
orientation = planeTransform.getOrientation();
if (orientation & Transform::ROT_INVALID) {
orientation = 0;
@@ -1421,7 +1422,7 @@
info.mMatrix[1][0] = ds.active.transform[1][0];
info.mMatrix[1][1] = ds.active.transform[1][1];
{
- sp<const GraphicBuffer> buffer = getBE().compositionInfo.mBuffer;
+ sp<const GraphicBuffer> buffer = mActiveBuffer;
if (buffer != 0) {
info.mActiveBufferWidth = buffer->getWidth();
info.mActiveBufferHeight = buffer->getHeight();
@@ -1442,19 +1443,22 @@
}
void Layer::miniDumpHeader(String8& result) {
- result.append("----------------------------------------");
- result.append("---------------------------------------\n");
+ result.append("-------------------------------");
+ result.append("-------------------------------");
+ result.append("-----------------------------\n");
result.append(" Layer name\n");
result.append(" Z | ");
result.append(" Comp Type | ");
+ result.append(" Transform | ");
result.append(" Disp Frame (LTRB) | ");
result.append(" Source Crop (LTRB)\n");
- result.append("----------------------------------------");
- result.append("---------------------------------------\n");
+ result.append("-------------------------------");
+ result.append("-------------------------------");
+ result.append("-----------------------------\n");
}
-void Layer::miniDump(String8& result, int32_t hwcId) const {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
+void Layer::miniDump(String8& result, int32_t displayId) const {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
return;
}
@@ -1472,20 +1476,22 @@
result.appendFormat(" %s\n", name.string());
const Layer::State& layerState(getDrawingState());
- const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(hwcId);
+ const LayerBE::HWCInfo& hwcInfo = getBE().mHwcLayers.at(displayId);
if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) {
result.appendFormat(" rel %6d | ", layerState.z);
} else {
result.appendFormat(" %10d | ", layerState.z);
}
- result.appendFormat("%10s | ", to_string(getCompositionType(hwcId)).c_str());
+ result.appendFormat("%10s | ", to_string(getCompositionType(displayId)).c_str());
+ result.appendFormat("%10s | ", to_string(hwcInfo.transform).c_str());
const Rect& frame = hwcInfo.displayFrame;
result.appendFormat("%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom);
const FloatRect& crop = hwcInfo.sourceCrop;
result.appendFormat("%6.1f %6.1f %6.1f %6.1f\n", crop.left, crop.top, crop.right, crop.bottom);
- result.append("- - - - - - - - - - - - - - - - - - - - ");
- result.append("- - - - - - - - - - - - - - - - - - - -\n");
+ result.append("- - - - - - - - - - - - - - - -");
+ result.append("- - - - - - - - - - - - - - - -");
+ result.append("- - - - - - - - - - - - - - -\n");
}
void Layer::dumpFrameStats(String8& result) const {
@@ -1968,6 +1974,8 @@
auto buffer = getBE().compositionInfo.mBuffer;
if (buffer != nullptr) {
LayerProtoHelper::writeToProto(buffer, layerInfo->mutable_active_buffer());
+ LayerProtoHelper::writeToProto(Transform(mCurrentTransform),
+ layerInfo->mutable_buffer_transform());
}
layerInfo->set_queued_frames(getQueuedFrameCount());
@@ -1976,10 +1984,14 @@
layerInfo->set_app_id(state.appId);
}
-void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) {
+void Layer::writeToProto(LayerProto* layerInfo, int32_t displayId) {
+ if (!hasHwcLayer(displayId)) {
+ return;
+ }
+
writeToProto(layerInfo, LayerVector::StateSet::Drawing);
- const auto& hwcInfo = getBE().mHwcLayers.at(hwcId);
+ const auto& hwcInfo = getBE().mHwcLayers.at(displayId);
const Rect& frame = hwcInfo.displayFrame;
LayerProtoHelper::writeToProto(frame, layerInfo->mutable_hwc_frame());
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 34811fb..fb94058 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -38,6 +38,7 @@
#include "Client.h"
#include "FrameTracker.h"
+#include "LayerBE.h"
#include "LayerVector.h"
#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
@@ -74,70 +75,6 @@
// ---------------------------------------------------------------------------
-struct CompositionInfo {
- HWC2::Composition compositionType;
- sp<GraphicBuffer> mBuffer = nullptr;
- int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
- struct {
- HWComposer* hwc;
- sp<Fence> fence;
- HWC2::BlendMode blendMode;
- Rect displayFrame;
- float alpha;
- FloatRect sourceCrop;
- HWC2::Transform transform;
- int z;
- int type;
- int appId;
- Region visibleRegion;
- Region surfaceDamage;
- sp<NativeHandle> sidebandStream;
- android_dataspace dataspace;
- hwc_color_t color;
- } hwc;
- struct {
- RE::RenderEngine* renderEngine;
- Mesh* mesh;
- } renderEngine;
-};
-
-class LayerBE {
-public:
- LayerBE();
-
- // The mesh used to draw the layer in GLES composition mode
- Mesh mMesh;
-
- // HWC items, accessed from the main thread
- struct HWCInfo {
- HWCInfo()
- : hwc(nullptr),
- layer(nullptr),
- forceClientComposition(false),
- compositionType(HWC2::Composition::Invalid),
- clearClientTarget(false),
- transform(HWC2::Transform::None) {}
-
- HWComposer* hwc;
- HWC2::Layer* layer;
- bool forceClientComposition;
- HWC2::Composition compositionType;
- bool clearClientTarget;
- Rect displayFrame;
- FloatRect sourceCrop;
- HWComposerBufferCache bufferCache;
- HWC2::Transform transform;
- };
-
- // A layer can be attached to multiple displays when operating in mirror mode
- // (a.k.a: when several displays are attached with equal layerStack). In this
- // case we need to keep track. In non-mirror mode, a layer will have only one
- // HWCInfo. This map key is a display layerStack.
- std::unordered_map<int32_t, HWCInfo> mHwcLayers;
-
- CompositionInfo compositionInfo;
-};
-
class Layer : public virtual RefBase {
static int32_t sSequence;
@@ -366,7 +303,7 @@
void writeToProto(LayerProto* layerInfo,
LayerVector::StateSet stateSet = LayerVector::StateSet::Drawing);
- void writeToProto(LayerProto* layerInfo, int32_t hwcId);
+ void writeToProto(LayerProto* layerInfo, int32_t displayId);
protected:
/*
@@ -380,18 +317,18 @@
virtual bool isHdrY410() const { return false; }
- void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z);
- void forceClientComposition(int32_t hwcId);
- bool getForceClientComposition(int32_t hwcId);
- virtual void setPerFrameData(const sp<const DisplayDevice>& displayDevice) = 0;
+ void setGeometry(const sp<const DisplayDevice>& display, uint32_t z);
+ void forceClientComposition(int32_t displayId);
+ bool getForceClientComposition(int32_t displayId);
+ virtual void setPerFrameData(const sp<const DisplayDevice>& display) = 0;
// callIntoHwc exists so we can update our local state and call
// acceptDisplayChanges without unnecessarily updating the device's state
- void setCompositionType(int32_t hwcId, HWC2::Composition type, bool callIntoHwc = true);
- HWC2::Composition getCompositionType(int32_t hwcId) const;
- void setClearClientTarget(int32_t hwcId, bool clear);
- bool getClearClientTarget(int32_t hwcId) const;
- void updateCursorPosition(const sp<const DisplayDevice>& hw);
+ void setCompositionType(int32_t displayId, HWC2::Composition type, bool callIntoHwc = true);
+ HWC2::Composition getCompositionType(int32_t displayId) const;
+ void setClearClientTarget(int32_t displayId, bool clear);
+ bool getClearClientTarget(int32_t displayId) const;
+ void updateCursorPosition(const sp<const DisplayDevice>& display);
/*
* called after page-flip
@@ -488,7 +425,7 @@
// Updates the transform hint in our SurfaceFlingerConsumer to match
// the current orientation of the display device.
- void updateTransformHint(const sp<const DisplayDevice>& hw) const;
+ void updateTransformHint(const sp<const DisplayDevice>& display) const;
/*
* returns the rectangle that crops the content of the layer and scales it
@@ -507,19 +444,17 @@
// -----------------------------------------------------------------------
- bool createHwcLayer(HWComposer* hwc, int32_t hwcId);
- bool destroyHwcLayer(int32_t hwcId);
+ bool createHwcLayer(HWComposer* hwc, int32_t displayId);
+ bool destroyHwcLayer(int32_t displayId);
void destroyAllHwcLayers();
- bool hasHwcLayer(int32_t hwcId) {
- return getBE().mHwcLayers.count(hwcId) > 0;
- }
+ bool hasHwcLayer(int32_t displayId) { return getBE().mHwcLayers.count(displayId) > 0; }
- HWC2::Layer* getHwcLayer(int32_t hwcId) {
- if (getBE().mHwcLayers.count(hwcId) == 0) {
+ HWC2::Layer* getHwcLayer(int32_t displayId) {
+ if (getBE().mHwcLayers.count(displayId) == 0) {
return nullptr;
}
- return getBE().mHwcLayers[hwcId].layer;
+ return getBE().mHwcLayers[displayId].layer;
}
// -----------------------------------------------------------------------
@@ -537,7 +472,7 @@
/* always call base class first */
static void miniDumpHeader(String8& result);
- void miniDump(String8& result, int32_t hwcId) const;
+ void miniDump(String8& result, int32_t displayId) const;
void dumpFrameStats(String8& result) const;
void dumpFrameEvents(String8& result);
void clearFrameStats();
@@ -621,12 +556,12 @@
uint32_t getEffectiveUsage(uint32_t usage) const;
- FloatRect computeCrop(const sp<const DisplayDevice>& hw) const;
+ FloatRect computeCrop(const sp<const DisplayDevice>& display) const;
// Compute the initial crop as specified by parent layers and the
// SurfaceControl for this layer. Does not include buffer crop from the
// IGraphicBufferProducer client, as that should not affect child clipping.
// Returns in screen space.
- Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const;
+ Rect computeInitialCrop(const sp<const DisplayDevice>& display) const;
// drawing
void clearWithOpenGL(const RenderArea& renderArea, float r, float g, float b,
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
new file mode 100644
index 0000000..bef051f
--- /dev/null
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "LayerBE"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "Layer.h"
+
+namespace android {
+
+LayerBE::LayerBE(Layer* layer, std::string layerName)
+ : mLayer(layer),
+ mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2) {
+ compositionInfo.layer = this;
+ compositionInfo.layerName = layerName;
+}
+
+void LayerBE::onLayerDisplayed(const sp<Fence>& releaseFence) {
+ mLayer->onLayerDisplayed(releaseFence);
+}
+
+void CompositionInfo::dumpHwc(const char* tag) const {
+ ALOGV("[%s]\thwcLayer=%p", tag, hwc.hwcLayer);
+ ALOGV("[%s]\tfence=%p", tag, hwc.fence.get());
+ ALOGV("[%s]\ttransform=%d", tag, hwc.transform);
+ ALOGV("[%s]\tz=%d", tag, hwc.z);
+ ALOGV("[%s]\ttype=%d", tag, hwc.type);
+ ALOGV("[%s]\tappId=%d", tag, hwc.appId);
+ ALOGV("[%s]\tdisplayFrame=%4d %4d %4d %4d", tag, hwc.displayFrame.left, hwc.displayFrame.top, hwc.displayFrame.right, hwc.displayFrame.bottom);
+ ALOGV("[%s]\talpha=%.3f", tag, hwc.alpha);
+ ALOGV("[%s]\tsourceCrop=%6.1f %6.1f %6.1f %6.1f", tag, hwc.sourceCrop.left, hwc.sourceCrop.top, hwc.sourceCrop.right, hwc.sourceCrop.bottom);
+
+ std::string label = tag;
+ label+=":visibleRegion";
+ hwc.visibleRegion.dump(label.c_str());
+ label = tag;
+ label+=":surfaceDamage";
+ hwc.surfaceDamage.dump(label.c_str());
+}
+
+void CompositionInfo::dumpRe(const char* tag) const {
+ ALOGV("[%s]\tblackoutLayer=%d", tag, re.blackoutLayer);
+ ALOGV("[%s]\tclearArea=%d", tag, re.clearArea);
+ ALOGV("[%s]\tpreMultipliedAlpha=%d", tag, re.preMultipliedAlpha);
+ ALOGV("[%s]\topaque=%d\n", tag, re.opaque);
+ ALOGV("[%s]\ttexture:name(%d), target(%d), size(%d/%d)", tag, re.texture.getTextureName(), re.texture.getTextureTarget(), (unsigned int)re.texture.getWidth(), (unsigned int)re.texture.getHeight());
+ ALOGV("[%s]\tuseIdentityTransform=%d\n", tag, re.useIdentityTransform);
+}
+
+void CompositionInfo::dump(const char* tag) const {
+ ALOGV("[%s] CompositionInfo", tag);
+ ALOGV("[%s]\tLayerName: %s", tag, layerName.c_str());
+ ALOGV("[%s]\tCompositionType: %d", tag, compositionType);
+ ALOGV("[%s]\tmBuffer = %p", tag, mBuffer.get());
+ ALOGV("[%s]\tmBufferSlot=%d", tag, mBufferSlot);
+ switch (compositionType) {
+ case HWC2::Composition::Device:
+ dumpHwc(tag);
+ break;
+ case HWC2::Composition::Client:
+ dumpRe(tag);
+ default:
+ break;
+ }
+}
+
+}; // namespace android
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
new file mode 100644
index 0000000..f610677
--- /dev/null
+++ b/services/surfaceflinger/LayerBE.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <ui/Region.h>
+
+#include "SurfaceFlinger.h"
+
+#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/HWComposerBufferCache.h"
+#include "RenderEngine/Mesh.h"
+#include "RenderEngine/Texture.h"
+
+namespace android {
+
+class LayerBE;
+
+struct CompositionInfo {
+ std::string layerName;
+ HWC2::Composition compositionType;
+ sp<GraphicBuffer> mBuffer = nullptr;
+ int mBufferSlot = BufferQueue::INVALID_BUFFER_SLOT;
+ LayerBE* layer = nullptr;
+ struct {
+ HWC2::Layer* hwcLayer;
+ sp<Fence> fence;
+ HWC2::BlendMode blendMode = HWC2::BlendMode::Invalid;
+ Rect displayFrame;
+ float alpha;
+ FloatRect sourceCrop;
+ HWC2::Transform transform = HWC2::Transform::None;
+ int z;
+ int type;
+ int appId;
+ Region visibleRegion;
+ Region surfaceDamage;
+ sp<NativeHandle> sidebandStream;
+ android_dataspace dataspace;
+ hwc_color_t color;
+ } hwc;
+ struct {
+ Mesh* mesh;
+ bool blackoutLayer = false;
+ bool clearArea = false;
+ bool preMultipliedAlpha = false;
+ bool opaque = false;
+ half4 color;
+ Texture texture;
+ bool useIdentityTransform = false;
+ } re;
+
+ void dump(const char* tag) const;
+ void dumpHwc(const char* tag) const;
+ void dumpRe(const char* tag) const;
+};
+
+class LayerBE {
+public:
+ friend class Layer;
+ friend class BufferLayer;
+ friend class ColorLayer;
+ friend class SurfaceFlinger;
+
+ LayerBE(Layer* layer, std::string layerName);
+
+ void onLayerDisplayed(const sp<Fence>& releaseFence);
+ Mesh& getMesh() { return mMesh; }
+
+private:
+ Layer*const mLayer;
+ // The mesh used to draw the layer in GLES composition mode
+ Mesh mMesh;
+
+ // HWC items, accessed from the main thread
+ struct HWCInfo {
+ HWCInfo()
+ : hwc(nullptr),
+ layer(nullptr),
+ forceClientComposition(false),
+ compositionType(HWC2::Composition::Invalid),
+ clearClientTarget(false),
+ transform(HWC2::Transform::None) {}
+
+ HWComposer* hwc;
+ HWC2::Layer* layer;
+ bool forceClientComposition;
+ HWC2::Composition compositionType;
+ bool clearClientTarget;
+ Rect displayFrame;
+ FloatRect sourceCrop;
+ HWComposerBufferCache bufferCache;
+ HWC2::Transform transform;
+ };
+
+
+ // A layer can be attached to multiple displays when operating in mirror mode
+ // (a.k.a: when several displays are attached with equal layerStack). In this
+ // case we need to keep track. In non-mirror mode, a layer will have only one
+ // HWCInfo. This map key is a display layerStack.
+ std::unordered_map<int32_t, HWCInfo> mHwcLayers;
+
+ CompositionInfo compositionInfo;
+};
+
+}; // namespace android
+
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index a5f0b98..381ea4a 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -31,6 +31,7 @@
bool stickySet,
const char* name,
int32_t overrideScalingMode,
+ bool transformToDisplayInverse,
bool& freezePositionUpdates)
: mFront(front),
mCurrent(current),
@@ -38,6 +39,7 @@
mStickyTransformSet(stickySet),
mName(name),
mOverrideScalingMode(overrideScalingMode),
+ mTransformToDisplayInverse(transformToDisplayInverse),
mFreezeGeometryUpdates(freezePositionUpdates) {}
bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
@@ -54,6 +56,13 @@
swap(bufWidth, bufHeight);
}
+ if (mTransformToDisplayInverse) {
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
+ if (invTransform & Transform::ROT_90) {
+ swap(bufWidth, bufHeight);
+ }
+ }
+
int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode;
bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
if (mFront.active != mFront.requested) {
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
index 40972aa..63d51de 100644
--- a/services/surfaceflinger/LayerRejecter.h
+++ b/services/surfaceflinger/LayerRejecter.h
@@ -29,6 +29,7 @@
bool stickySet,
const char *name,
int32_t overrideScalingMode,
+ bool transformToDisplayInverse,
bool &freezePositionUpdates);
virtual bool reject(const sp<GraphicBuffer> &buf, const BufferItem &item);
@@ -40,6 +41,7 @@
bool mStickyTransformSet;
const char *mName;
int32_t mOverrideScalingMode;
+ bool mTransformToDisplayInverse;
bool &mFreezeGeometryUpdates;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 66b41f5..e39e623 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -78,6 +78,7 @@
#include "clz.h"
#include "DisplayHardware/ComposerHal.h"
+#include "DisplayHardware/DisplayIdentification.h"
#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"
#include "DisplayHardware/VirtualDisplaySurface.h"
@@ -218,7 +219,7 @@
mLayersAdded(false),
mRepaintEverything(0),
mBootTime(systemTime()),
- mBuiltinDisplays(),
+ mDisplayTokens(),
mVisibleRegionsDirty(false),
mGeometryInvalid(false),
mAnimCompositionPending(false),
@@ -432,28 +433,30 @@
sp<BBinder> token = new DisplayToken(this);
Mutex::Autolock _l(mStateLock);
- DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
+ DisplayDeviceState info;
+ info.type = DisplayDevice::DISPLAY_VIRTUAL;
info.displayName = displayName;
+ info.isSecure = secure;
mCurrentState.displays.add(token, info);
mInterceptor->saveDisplayCreation(info);
return token;
}
-void SurfaceFlinger::destroyDisplay(const sp<IBinder>& display) {
+void SurfaceFlinger::destroyDisplay(const sp<IBinder>& displayToken) {
Mutex::Autolock _l(mStateLock);
- ssize_t idx = mCurrentState.displays.indexOfKey(display);
+ ssize_t idx = mCurrentState.displays.indexOfKey(displayToken);
if (idx < 0) {
- ALOGW("destroyDisplay: invalid display token");
+ ALOGE("destroyDisplay: Invalid display token %p", displayToken.get());
return;
}
const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx));
- if (!info.isVirtualDisplay()) {
+ if (!info.isVirtual()) {
ALOGE("destroyDisplay called for non-virtual display");
return;
}
- mInterceptor->saveDisplayDeletion(info.displayId);
+ mInterceptor->saveDisplayDeletion(info.sequenceId);
mCurrentState.displays.removeItemsAt(idx);
setTransactionFlags(eDisplayTransactionNeeded);
}
@@ -463,7 +466,7 @@
ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
return nullptr;
}
- return mBuiltinDisplays[id];
+ return mDisplayTokens[id];
}
void SurfaceFlinger::bootFinished()
@@ -495,25 +498,11 @@
LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
- sp<LambdaMessage> readProperties = new LambdaMessage([&]() {
- readPersistentProperties();
- });
- postMessageAsync(readProperties);
+ postMessageAsync(new LambdaMessage([this] { readPersistentProperties(); }));
}
void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
- class MessageDestroyGLTexture : public MessageBase {
- RE::RenderEngine& engine;
- uint32_t texture;
- public:
- MessageDestroyGLTexture(RE::RenderEngine& engine, uint32_t texture)
- : engine(engine), texture(texture) {}
- virtual bool handler() {
- engine.deleteTextures(1, &texture);
- return true;
- }
- };
- postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture));
+ postMessageAsync(new LambdaMessage([=] { getRenderEngine().deleteTextures(1, &texture); }));
}
class DispSyncSource final : public VSyncSource, private DispSync::Callback {
@@ -662,7 +651,7 @@
std::make_unique<DispSyncSource>(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs,
true, "app");
mEventThread = std::make_unique<impl::EventThread>(mEventThreadSource.get(),
- [this]() { resyncWithRateLimit(); },
+ [this] { resyncWithRateLimit(); },
impl::EventThread::InterceptVSyncsCallback(),
"appEventThread");
mSfEventThreadSource =
@@ -671,7 +660,7 @@
mSFEventThread =
std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
- [this]() { resyncWithRateLimit(); },
+ [this] { resyncWithRateLimit(); },
[this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
},
@@ -694,31 +683,34 @@
getBE().mHwc->registerCallback(this, getBE().mComposerSequenceId);
// Process any initial hotplug and resulting display changes.
processDisplayHotplugEventsLocked();
- LOG_ALWAYS_FATAL_IF(!getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY),
- "Registered composer callback but didn't create the default primary display");
+ const auto display = getDefaultDisplayDeviceLocked();
+ LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback.");
+ LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(display->getId()),
+ "Internal display is disconnected.");
// make the default display GLContext current so that we can create textures
// when creating Layers (which may happens before we render something)
- getDefaultDisplayDeviceLocked()->makeCurrent();
+ display->makeCurrent();
if (useVrFlinger) {
- auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
+ auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
// This callback is called from the vr flinger dispatch thread. We
// need to call signalTransaction(), which requires holding
// mStateLock when we're not on the main thread. Acquiring
// mStateLock from the vr flinger dispatch thread might trigger a
// deadlock in surface flinger (see b/66916578), so post a message
// to be handled on the main thread instead.
- sp<LambdaMessage> message = new LambdaMessage([=]() {
+ postMessageAsync(new LambdaMessage([=] {
ALOGI("VR request display mode: requestDisplay=%d", requestDisplay);
mVrFlingerRequestsDisplay = requestDisplay;
signalTransaction();
- });
- postMessageAsync(message);
+ }));
};
- mVrFlinger = dvr::VrFlinger::Create(getBE().mHwc->getComposer(),
- getBE().mHwc->getHwcDisplayId(HWC_DISPLAY_PRIMARY).value_or(0),
- vrFlingerRequestDisplayCallback);
+ mVrFlinger = dvr::VrFlinger::Create(getHwComposer().getComposer(),
+ getHwComposer()
+ .getHwcDisplayId(display->getId())
+ .value_or(0),
+ vrFlingerRequestDisplayCallback);
if (!mVrFlinger) {
ALOGE("Failed to start vrflinger");
}
@@ -747,8 +739,8 @@
ALOGE("Run StartPropertySetThread failed!");
}
- mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
- Dataspace::SRGB_LINEAR);
+ mLegacySrgbSaturationMatrix =
+ getHwComposer().getDataspaceSaturationMatrix(display->getId(), Dataspace::SRGB_LINEAR);
ALOGV("Done initializing");
}
@@ -820,18 +812,15 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
- Vector<DisplayInfo>* configs) {
- if (configs == nullptr || display.get() == nullptr) {
+status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken,
+ Vector<DisplayInfo>* configs) {
+ if (!displayToken || !configs) {
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]) {
+ for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
+ if (displayToken == mDisplayTokens[i]) {
type = i;
break;
}
@@ -885,8 +874,8 @@
info.density = density;
// TODO: this needs to go away (currently needed only by webkit)
- sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
- info.orientation = hw ? hw->getOrientation() : 0;
+ const auto display = getDefaultDisplayDeviceLocked();
+ info.orientation = display ? display->getOrientation() : 0;
} else {
// TODO: where should this value come from?
static const int TV_DENSITY = 213;
@@ -930,9 +919,8 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */,
- DisplayStatInfo* stats) {
- if (stats == nullptr) {
+status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>&, DisplayStatInfo* stats) {
+ if (!stats) {
return BAD_VALUE;
}
@@ -943,87 +931,62 @@
return NO_ERROR;
}
-int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
- if (display == nullptr) {
- ALOGE("%s : display is nullptr", __func__);
+int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
+ const auto display = getDisplayDevice(displayToken);
+ if (!display) {
+ ALOGE("getActiveConfig: Invalid display token %p", displayToken.get());
return BAD_VALUE;
}
- sp<const DisplayDevice> device(getDisplayDevice(display));
- if (device != nullptr) {
- return device->getActiveConfig();
- }
-
- return BAD_VALUE;
+ return display->getActiveConfig();
}
-void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode) {
- ALOGD("Set active config mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
- this);
- int32_t type = hw->getDisplayType();
- int currentMode = hw->getActiveConfig();
-
+void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& display, int mode) {
+ int currentMode = display->getActiveConfig();
if (mode == currentMode) {
- ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
return;
}
- if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+ if (display->isVirtual()) {
ALOGW("Trying to set config for virtual display");
return;
}
- hw->setActiveConfig(mode);
- getHwComposer().setActiveConfig(type, mode);
+ display->setActiveConfig(mode);
+ getHwComposer().setActiveConfig(display->getDisplayType(), mode);
}
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) {
- class MessageSetActiveConfig: public MessageBase {
- SurfaceFlinger& mFlinger;
- sp<IBinder> mDisplay;
- int mMode;
- public:
- MessageSetActiveConfig(SurfaceFlinger& flinger, const sp<IBinder>& disp,
- int mode) :
- mFlinger(flinger), mDisplay(disp) { mMode = mode; }
- virtual bool handler() {
- Vector<DisplayInfo> configs;
- mFlinger.getDisplayConfigs(mDisplay, &configs);
- 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 == nullptr) {
- ALOGE("Attempt to set active config = %d for null display %p",
- mMode, mDisplay.get());
- } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to set active config = %d for virtual display",
- mMode);
- } else {
- mFlinger.setActiveConfigInternal(hw, mMode);
- }
- return true;
+status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
+ postMessageSync(new LambdaMessage([&] {
+ Vector<DisplayInfo> configs;
+ getDisplayConfigs(displayToken, &configs);
+ if (mode < 0 || mode >= static_cast<int>(configs.size())) {
+ ALOGE("Attempt to set active config %d for display with %zu configs", mode,
+ configs.size());
+ return;
}
- };
- sp<MessageBase> msg = new MessageSetActiveConfig(*this, display, mode);
- postMessageSync(msg);
+ const auto display = getDisplayDevice(displayToken);
+ if (!display) {
+ ALOGE("Attempt to set active config %d for invalid display token %p", mode,
+ displayToken.get());
+ } else if (display->isVirtual()) {
+ ALOGW("Attempt to set active config %d for virtual display", mode);
+ } else {
+ setActiveConfigInternal(display, mode);
+ }
+ }));
+
return NO_ERROR;
}
-status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& display,
- Vector<ColorMode>* outColorModes) {
- if ((outColorModes == nullptr) || (display.get() == nullptr)) {
+status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
+ Vector<ColorMode>* outColorModes) {
+ if (!displayToken || !outColorModes) {
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]) {
+ for (int i = 0; i < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES; ++i) {
+ if (displayToken == mDisplayTokens[i]) {
type = i;
break;
}
@@ -1045,79 +1008,62 @@
return NO_ERROR;
}
-ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& display) {
- sp<const DisplayDevice> device(getDisplayDevice(display));
- if (device != nullptr) {
- return device->getActiveColorMode();
+ColorMode SurfaceFlinger::getActiveColorMode(const sp<IBinder>& displayToken) {
+ if (const auto display = getDisplayDevice(displayToken)) {
+ return display->getActiveColorMode();
}
return static_cast<ColorMode>(BAD_VALUE);
}
-void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
- ColorMode mode, Dataspace dataSpace,
- RenderIntent renderIntent) {
- int32_t type = hw->getDisplayType();
- ColorMode currentMode = hw->getActiveColorMode();
- Dataspace currentDataSpace = hw->getCompositionDataSpace();
- RenderIntent currentRenderIntent = hw->getActiveRenderIntent();
+void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& display, ColorMode mode,
+ Dataspace dataSpace, RenderIntent renderIntent) {
+ ColorMode currentMode = display->getActiveColorMode();
+ Dataspace currentDataSpace = display->getCompositionDataSpace();
+ RenderIntent currentRenderIntent = display->getActiveRenderIntent();
if (mode == currentMode && dataSpace == currentDataSpace &&
renderIntent == currentRenderIntent) {
return;
}
- if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+ if (display->isVirtual()) {
ALOGW("Trying to set config for virtual display");
return;
}
- hw->setActiveColorMode(mode);
- hw->setCompositionDataSpace(dataSpace);
- hw->setActiveRenderIntent(renderIntent);
- getHwComposer().setActiveColorMode(type, mode, renderIntent);
+ display->setActiveColorMode(mode);
+ display->setCompositionDataSpace(dataSpace);
+ display->setActiveRenderIntent(renderIntent);
+ getHwComposer().setActiveColorMode(display->getDisplayType(), mode, renderIntent);
ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d",
- decodeColorMode(mode).c_str(), mode,
- decodeRenderIntent(renderIntent).c_str(), renderIntent,
- hw->getDisplayType());
+ decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(),
+ renderIntent, display->getDisplayType());
}
-
-status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& display,
- ColorMode colorMode) {
- class MessageSetActiveColorMode: public MessageBase {
- SurfaceFlinger& mFlinger;
- sp<IBinder> mDisplay;
- ColorMode mMode;
- public:
- MessageSetActiveColorMode(SurfaceFlinger& flinger, const sp<IBinder>& disp,
- ColorMode mode) :
- mFlinger(flinger), mDisplay(disp) { mMode = mode; }
- virtual bool handler() {
- Vector<ColorMode> modes;
- mFlinger.getDisplayColorModes(mDisplay, &modes);
- bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
- if (mMode < ColorMode::NATIVE || !exists) {
- ALOGE("Attempt to set invalid active color mode %s (%d) for display %p",
- decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
- return true;
- }
- sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
- if (hw == nullptr) {
- ALOGE("Attempt to set active color mode %s (%d) for null display %p",
- decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
- } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to set active color mode %s %d for virtual display",
- decodeColorMode(mMode).c_str(), mMode);
- } else {
- mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN,
- RenderIntent::COLORIMETRIC);
- }
- return true;
+status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, ColorMode mode) {
+ postMessageSync(new LambdaMessage([&] {
+ Vector<ColorMode> modes;
+ getDisplayColorModes(displayToken, &modes);
+ bool exists = std::find(std::begin(modes), std::end(modes), mode) != std::end(modes);
+ if (mode < ColorMode::NATIVE || !exists) {
+ ALOGE("Attempt to set invalid active color mode %s (%d) for display token %p",
+ decodeColorMode(mode).c_str(), mode, displayToken.get());
+ return;
}
- };
- sp<MessageBase> msg = new MessageSetActiveColorMode(*this, display, colorMode);
- postMessageSync(msg);
+ const auto display = getDisplayDevice(displayToken);
+ if (!display) {
+ ALOGE("Attempt to set active color mode %s (%d) for invalid display token %p",
+ decodeColorMode(mode).c_str(), mode, displayToken.get());
+ } else if (display->isVirtual()) {
+ ALOGW("Attempt to set active color mode %s (%d) for virtual display",
+ decodeColorMode(mode).c_str(), mode);
+ } else {
+ setActiveColorModeInternal(display, mode, Dataspace::UNKNOWN,
+ RenderIntent::COLORIMETRIC);
+ }
+ }));
+
return NO_ERROR;
}
@@ -1133,20 +1079,20 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display,
- HdrCapabilities* outCapabilities) const {
+status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& displayToken,
+ HdrCapabilities* outCapabilities) const {
Mutex::Autolock _l(mStateLock);
- sp<const DisplayDevice> displayDevice(getDisplayDeviceLocked(display));
- if (displayDevice == nullptr) {
- ALOGE("getHdrCapabilities: Invalid display %p", displayDevice.get());
+ const auto display = getDisplayDeviceLocked(displayToken);
+ if (!display) {
+ ALOGE("getHdrCapabilities: Invalid display token %p", displayToken.get());
return BAD_VALUE;
}
// At this point the DisplayDeivce should already be set up,
// meaning the luminance information is already queried from
// hardware composer and stored properly.
- const HdrCapabilities& capabilities = displayDevice->getHdrCapabilities();
+ const HdrCapabilities& capabilities = display->getHdrCapabilities();
*outCapabilities = HdrCapabilities(capabilities.getSupportedHdrTypes(),
capabilities.getDesiredMaxLuminance(),
capabilities.getDesiredMaxAverageLuminance(),
@@ -1156,7 +1102,7 @@
}
status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
- sp<LambdaMessage> enableVSyncInjections = new LambdaMessage([&]() {
+ postMessageSync(new LambdaMessage([&] {
Mutex::Autolock _l(mStateLock);
if (mInjectVSyncs == enable) {
@@ -1168,8 +1114,7 @@
if (mVSyncInjector.get() == nullptr) {
mVSyncInjector = std::make_unique<InjectVSyncSource>();
mInjectorEventThread = std::make_unique<
- impl::EventThread>(mVSyncInjector.get(),
- [this]() { resyncWithRateLimit(); },
+ impl::EventThread>(mVSyncInjector.get(), [this] { resyncWithRateLimit(); },
impl::EventThread::InterceptVSyncsCallback(),
"injEventThread");
}
@@ -1180,8 +1125,8 @@
}
mInjectVSyncs = enable;
- });
- postMessageSync(enableVSyncInjections);
+ }));
+
return NO_ERROR;
}
@@ -1281,7 +1226,6 @@
Mutex::Autolock _l(mHWVsyncLock);
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
mPrimaryDispSync.beginResync();
- //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
mEventControlThread->setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
@@ -1298,7 +1242,12 @@
return;
}
- const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+ const auto displayId = DisplayDevice::DISPLAY_PRIMARY;
+ if (!getHwComposer().isConnected(displayId)) {
+ return;
+ }
+
+ const auto activeConfig = getHwComposer().getActiveConfig(displayId);
const nsecs_t period = activeConfig->getVsyncPeriod();
mPrimaryDispSync.reset();
@@ -1306,7 +1255,6 @@
if (!mPrimaryHWVsyncEnabled) {
mPrimaryDispSync.beginResync();
- //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
mEventControlThread->setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
@@ -1315,7 +1263,6 @@
void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
Mutex::Autolock _l(mHWVsyncLock);
if (mPrimaryHWVsyncEnabled) {
- //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
mEventControlThread->setVsyncEnabled(false);
mPrimaryDispSync.endResync();
mPrimaryHWVsyncEnabled = false;
@@ -1337,8 +1284,8 @@
sLastResyncAttempted = now;
}
-void SurfaceFlinger::onVsyncReceived(int32_t sequenceId,
- hwc2_display_t displayId, int64_t timestamp) {
+void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
+ int64_t timestamp) {
Mutex::Autolock lock(mStateLock);
// Ignore any vsyncs from a previous hardware composer.
if (sequenceId != getBE().mComposerSequenceId) {
@@ -1346,7 +1293,7 @@
}
int32_t type;
- if (!getBE().mHwc->onVsync(displayId, timestamp, &type)) {
+ if (!getBE().mHwc->onVsync(hwcDisplayId, timestamp, &type)) {
return;
}
@@ -1371,9 +1318,9 @@
*compositorTiming = getBE().mCompositorTiming;
}
-void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
HWC2::Connection connection) {
- ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s)", sequenceId, display,
+ ALOGV("%s(%d, %" PRIu64 ", %s)", __FUNCTION__, sequenceId, hwcDisplayId,
connection == HWC2::Connection::Connected ? "connected" : "disconnected");
// Ignore events that do not have the right sequenceId.
@@ -1387,7 +1334,7 @@
// acquire it here.
ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
- mPendingHotplugEvents.emplace_back(HotplugEvent{display, connection});
+ mPendingHotplugEvents.emplace_back(HotplugEvent{hwcDisplayId, connection});
if (std::this_thread::get_id() == mMainThreadId) {
// Process all pending hot plug events immediately if we are on the main thread.
@@ -1397,8 +1344,7 @@
setTransactionFlags(eDisplayTransactionNeeded);
}
-void SurfaceFlinger::onRefreshReceived(int sequenceId,
- hwc2_display_t /*display*/) {
+void SurfaceFlinger::onRefreshReceived(int sequenceId, hwc2_display_t /*hwcDisplayId*/) {
Mutex::Autolock lock(mStateLock);
if (sequenceId != getBE().mComposerSequenceId) {
return;
@@ -1443,8 +1389,9 @@
Mutex::Autolock _l(mStateLock);
- int currentDisplayPowerMode = getDisplayDeviceLocked(
- mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY])->getPowerMode();
+ const auto display = getDefaultDisplayDeviceLocked();
+ LOG_ALWAYS_FATAL_IF(!display);
+ const int currentDisplayPowerMode = display->getPowerMode();
if (!vrFlingerRequestsDisplay) {
mVrFlinger->SeizeDisplayOwnership();
@@ -1469,12 +1416,10 @@
invalidateHwcGeometry();
// Re-enable default display.
- sp<DisplayDevice> hw(getDisplayDeviceLocked(
- mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]));
- setPowerModeInternal(hw, currentDisplayPowerMode, /*stateLockHeld*/ true);
+ setPowerModeInternal(display, currentDisplayPowerMode, /*stateLockHeld*/ true);
// Reset the timing values to account for the period of the swapped in HWC
- const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+ const auto activeConfig = getHwComposer().getActiveConfig(display->getId());
const nsecs_t period = activeConfig->getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(period);
@@ -1494,6 +1439,7 @@
mPreviousPresentFence != Fence::NO_FENCE &&
(mPreviousPresentFence->getSignalTime() ==
Fence::SIGNAL_TIME_PENDING);
+ mFrameMissedCount += frameMissed;
ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
if (frameMissed) {
mTimeStats.incrementMissedFrames();
@@ -1556,13 +1502,10 @@
doComposition();
postComposition(refreshStartTime);
- mPreviousPresentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
-
mHadClientComposition = false;
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
+ for (const auto& [token, display] : mDisplays) {
mHadClientComposition = mHadClientComposition ||
- getBE().mHwc->hasClientComposition(displayDevice->getHwcDisplayId());
+ getBE().mHwc->hasClientComposition(display->getId());
}
mVsyncModulator.onRefreshed(mHadClientComposition);
@@ -1576,21 +1519,20 @@
return;
const bool repaintEverything = mRepaintEverything;
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->isDisplayOn()) {
+ for (const auto& [token, display] : mDisplays) {
+ if (display->isPoweredOn()) {
// transform the dirty region into this screen's coordinate space
- const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
+ const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
if (!dirtyRegion.isEmpty()) {
// redraw the whole screen
- doComposeSurfaces(hw);
+ doComposeSurfaces(display);
// and draw the dirty region
- const int32_t height = hw->getHeight();
+ const int32_t height = display->getHeight();
auto& engine(getRenderEngine());
engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
- hw->swapBuffers(getHwComposer());
+ display->swapBuffers(getHwComposer());
}
}
}
@@ -1601,17 +1543,14 @@
usleep(mDebugRegion * 1000);
}
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- auto& displayDevice = mDisplays[displayId];
- if (!displayDevice->isDisplayOn()) {
+ for (const auto& [token, display] : mDisplays) {
+ if (!display->isPoweredOn()) {
continue;
}
- status_t result = displayDevice->prepareFrame(*getBE().mHwc);
- ALOGE_IF(result != NO_ERROR,
- "prepareFrame for display %zd failed:"
- " %d (%s)",
- displayId, result, strerror(-result));
+ status_t result = display->prepareFrame(*getBE().mHwc);
+ ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
+ display->getId(), result, strerror(-result));
}
}
@@ -1626,19 +1565,14 @@
void SurfaceFlinger::logLayerStats() {
ATRACE_CALL();
if (CC_UNLIKELY(mLayerStats.isEnabled())) {
- int32_t hwcId = -1;
- for (size_t dpy = 0; dpy < mDisplays.size(); ++dpy) {
- const sp<const DisplayDevice>& displayDevice(mDisplays[dpy]);
- if (displayDevice->isPrimary()) {
- hwcId = displayDevice->getHwcDisplayId();
- break;
+ for (const auto& [token, display] : mDisplays) {
+ if (display->isPrimary()) {
+ mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(*display));
+ return;
}
}
- if (hwcId < 0) {
- ALOGE("LayerStats: Hmmm, no primary display?");
- return;
- }
- mLayerStats.logLayerStats(dumpVisibleLayersProtoInfo(hwcId));
+
+ ALOGE("logLayerStats: no primary display");
}
}
@@ -1730,21 +1664,22 @@
}
// |mStateLock| not needed as we are on the main thread
- const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
+ const auto display = getDefaultDisplayDeviceLocked();
getBE().mGlCompositionDoneTimeline.updateSignalTimes();
std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
- if (hw && getBE().mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
+ if (display && getHwComposer().hasClientComposition(display->getId())) {
glCompositionDoneFenceTime =
- std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
+ std::make_shared<FenceTime>(display->getClientTargetAcquireFence());
getBE().mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
} else {
glCompositionDoneFenceTime = FenceTime::NO_FENCE;
}
getBE().mDisplayTimeline.updateSignalTimes();
- sp<Fence> presentFence = getBE().mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
- auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
+ mPreviousPresentFence =
+ display ? getHwComposer().getPresentFence(display->getId()) : Fence::NO_FENCE;
+ auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence);
getBE().mDisplayTimeline.push(presentFenceTime);
nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
@@ -1779,7 +1714,7 @@
}
if (!hasSyncFramework) {
- if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) && hw->isDisplayOn()) {
+ if (display && getHwComposer().isConnected(display->getId()) && display->isPoweredOn()) {
enableHardwareVsync();
}
}
@@ -1790,11 +1725,10 @@
if (presentFenceTime->isValid()) {
mAnimFrameTracker.setActualPresentFence(
std::move(presentFenceTime));
- } else if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
+ } else if (display && getHwComposer().isConnected(display->getId())) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- nsecs_t presentTime =
- getBE().mHwc->getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
+ const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(display->getId());
mAnimFrameTracker.setActualPresentTime(presentTime);
}
mAnimFrameTracker.advanceFrame();
@@ -1805,8 +1739,8 @@
mTimeStats.incrementClientCompositionFrames();
}
- if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY) &&
- hw->getPowerMode() == HWC_POWER_MODE_OFF) {
+ if (display && getHwComposer().isConnected(display->getId()) &&
+ display->getPowerMode() == HWC_POWER_MODE_OFF) {
return;
}
@@ -1836,21 +1770,20 @@
mVisibleRegionsDirty = false;
invalidateHwcGeometry();
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+ for (const auto& pair : mDisplays) {
+ const auto& display = pair.second;
Region opaqueRegion;
Region dirtyRegion;
Vector<sp<Layer>> layersSortedByZ;
Vector<sp<Layer>> layersNeedingFences;
- const sp<DisplayDevice>& displayDevice(mDisplays[dpy]);
- const Transform& tr(displayDevice->getTransform());
- const Rect bounds(displayDevice->getBounds());
- if (displayDevice->isDisplayOn()) {
- computeVisibleRegions(displayDevice, dirtyRegion, opaqueRegion);
+ const Transform& tr = display->getTransform();
+ const Rect bounds = display->getBounds();
+ if (display->isPoweredOn()) {
+ computeVisibleRegions(display, dirtyRegion, opaqueRegion);
mDrawingState.traverseInZOrder([&](Layer* layer) {
bool hwcLayerDestroyed = false;
- if (layer->belongsToDisplay(displayDevice->getLayerStack(),
- displayDevice->isPrimary())) {
+ if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) {
Region drawRegion(tr.transform(
layer->visibleNonTransparentRegion));
drawRegion.andSelf(bounds);
@@ -1859,15 +1792,13 @@
} else {
// Clear out the HWC layer if this layer was
// previously visible, but no longer is
- hwcLayerDestroyed = layer->destroyHwcLayer(
- displayDevice->getHwcDisplayId());
+ hwcLayerDestroyed = layer->destroyHwcLayer(display->getId());
}
} else {
- // WM changes displayDevice->layerStack upon sleep/awake.
+ // WM changes display->layerStack upon sleep/awake.
// Here we make sure we delete the HWC layers even if
// WM changed their layer stack.
- hwcLayerDestroyed = layer->destroyHwcLayer(
- displayDevice->getHwcDisplayId());
+ hwcLayerDestroyed = layer->destroyHwcLayer(display->getId());
}
// If a layer is not going to get a release fence because
@@ -1883,12 +1814,11 @@
}
});
}
- displayDevice->setVisibleLayersSortedByZ(layersSortedByZ);
- displayDevice->setLayersNeedingFences(layersNeedingFences);
- displayDevice->undefinedRegion.set(bounds);
- displayDevice->undefinedRegion.subtractSelf(
- tr.transform(opaqueRegion));
- displayDevice->dirtyRegion.orSelf(dirtyRegion);
+ display->setVisibleLayersSortedByZ(layersSortedByZ);
+ display->setLayersNeedingFences(layersNeedingFences);
+ display->undefinedRegion.set(bounds);
+ display->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
+ display->dirtyRegion.orSelf(dirtyRegion);
}
}
}
@@ -1901,12 +1831,12 @@
// - Dataspace::UNKNOWN
// - Dataspace::BT2020_HLG
// - Dataspace::BT2020_PQ
-Dataspace SurfaceFlinger::getBestDataspace(
- const sp<const DisplayDevice>& displayDevice, Dataspace* outHdrDataSpace) const {
+Dataspace SurfaceFlinger::getBestDataspace(const sp<const DisplayDevice>& display,
+ Dataspace* outHdrDataSpace) const {
Dataspace bestDataSpace = Dataspace::SRGB;
*outHdrDataSpace = Dataspace::UNKNOWN;
- for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ for (const auto& layer : display->getVisibleLayersSortedByZ()) {
switch (layer->getDataSpace()) {
case Dataspace::V0_SCRGB:
case Dataspace::V0_SCRGB_LINEAR:
@@ -1934,9 +1864,8 @@
}
// Pick the ColorMode / Dataspace for the display device.
-void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& displayDevice,
- ColorMode* outMode, Dataspace* outDataSpace,
- RenderIntent* outRenderIntent) const {
+void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& display, ColorMode* outMode,
+ Dataspace* outDataSpace, RenderIntent* outRenderIntent) const {
if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) {
*outMode = ColorMode::NATIVE;
*outDataSpace = Dataspace::UNKNOWN;
@@ -1945,11 +1874,11 @@
}
Dataspace hdrDataSpace;
- Dataspace bestDataSpace = getBestDataspace(displayDevice, &hdrDataSpace);
+ Dataspace bestDataSpace = getBestDataspace(display, &hdrDataSpace);
// respect hdrDataSpace only when there is no legacy HDR support
const bool isHdr = hdrDataSpace != Dataspace::UNKNOWN &&
- !displayDevice->hasLegacyHdrSupport(hdrDataSpace);
+ !display->hasLegacyHdrSupport(hdrDataSpace);
if (isHdr) {
bestDataSpace = hdrDataSpace;
}
@@ -1968,17 +1897,17 @@
break;
}
- displayDevice->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
+ display->getBestColorMode(bestDataSpace, intent, outDataSpace, outMode, outRenderIntent);
}
void SurfaceFlinger::setUpHWComposer() {
ATRACE_CALL();
ALOGV("setUpHWComposer");
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- bool dirty = !mDisplays[dpy]->getDirtyRegion(mRepaintEverything).isEmpty();
- bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
- bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
+ for (const auto& [token, display] : mDisplays) {
+ bool dirty = !display->getDirtyRegion(mRepaintEverything).isEmpty();
+ bool empty = display->getVisibleLayersSortedByZ().size() == 0;
+ bool wasEmpty = !display->lastCompositionHadVisibleLayers;
// If nothing has changed (!dirty), don't recompose.
// If something changed, but we don't currently have any visible layers,
@@ -1990,41 +1919,36 @@
// emit any black frames until a layer is added to the layer stack.
bool mustRecompose = dirty && !(empty && wasEmpty);
- ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
- "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
- mustRecompose ? "doing" : "skipping",
- dirty ? "+" : "-",
- empty ? "+" : "-",
- wasEmpty ? "+" : "-");
+ ALOGV_IF(display->isVirtual(), "Display %d: %s composition (%sdirty %sempty %swasEmpty)",
+ display->getId(), mustRecompose ? "doing" : "skipping", dirty ? "+" : "-",
+ empty ? "+" : "-", wasEmpty ? "+" : "-");
- mDisplays[dpy]->beginFrame(mustRecompose);
+ display->beginFrame(mustRecompose);
if (mustRecompose) {
- mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
+ display->lastCompositionHadVisibleLayers = !empty;
}
}
// build the h/w work list
if (CC_UNLIKELY(mGeometryInvalid)) {
mGeometryInvalid = false;
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
- const auto hwcId = displayDevice->getHwcDisplayId();
- if (hwcId >= 0) {
- const Vector<sp<Layer>>& currentLayers(
- displayDevice->getVisibleLayersSortedByZ());
+ for (const auto& [token, display] : mDisplays) {
+ const auto displayId = display->getId();
+ if (displayId >= 0) {
+ const Vector<sp<Layer>>& currentLayers = display->getVisibleLayersSortedByZ();
for (size_t i = 0; i < currentLayers.size(); i++) {
const auto& layer = currentLayers[i];
- if (!layer->hasHwcLayer(hwcId)) {
- if (!layer->createHwcLayer(getBE().mHwc.get(), hwcId)) {
- layer->forceClientComposition(hwcId);
+ if (!layer->hasHwcLayer(displayId)) {
+ if (!layer->createHwcLayer(getBE().mHwc.get(), displayId)) {
+ layer->forceClientComposition(displayId);
continue;
}
}
- layer->setGeometry(displayDevice, i);
+ layer->setGeometry(display, i);
if (mDebugDisableHWC || mDebugRegion) {
- layer->forceClientComposition(hwcId);
+ layer->forceClientComposition(displayId);
}
}
}
@@ -2032,61 +1956,59 @@
}
// Set the per-frame data
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- auto& displayDevice = mDisplays[displayId];
- const auto hwcId = displayDevice->getHwcDisplayId();
-
- if (hwcId < 0) {
+ for (const auto& [token, display] : mDisplays) {
+ const auto displayId = display->getId();
+ if (displayId < 0) {
continue;
}
+
if (mDrawingState.colorMatrixChanged) {
- displayDevice->setColorTransform(mDrawingState.colorMatrix);
- status_t result = getBE().mHwc->setColorTransform(hwcId, mDrawingState.colorMatrix);
- ALOGE_IF(result != NO_ERROR, "Failed to set color transform on "
- "display %zd: %d", displayId, result);
+ display->setColorTransform(mDrawingState.colorMatrix);
+ status_t result = getBE().mHwc->setColorTransform(displayId, mDrawingState.colorMatrix);
+ ALOGE_IF(result != NO_ERROR, "Failed to set color transform on display %d: %d",
+ displayId, result);
}
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ for (auto& layer : display->getVisibleLayersSortedByZ()) {
if (layer->isHdrY410()) {
- layer->forceClientComposition(hwcId);
+ layer->forceClientComposition(displayId);
} else if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
- !displayDevice->hasHDR10Support()) {
- layer->forceClientComposition(hwcId);
+ !display->hasHDR10Support()) {
+ layer->forceClientComposition(displayId);
} else if ((layer->getDataSpace() == Dataspace::BT2020_HLG ||
layer->getDataSpace() == Dataspace::BT2020_ITU_HLG) &&
- !displayDevice->hasHLGSupport()) {
- layer->forceClientComposition(hwcId);
+ !display->hasHLGSupport()) {
+ layer->forceClientComposition(displayId);
}
- if (layer->getForceClientComposition(hwcId)) {
+ if (layer->getForceClientComposition(displayId)) {
ALOGV("[%s] Requesting Client composition", layer->getName().string());
- layer->setCompositionType(hwcId, HWC2::Composition::Client);
+ layer->setCompositionType(displayId, HWC2::Composition::Client);
continue;
}
- layer->setPerFrameData(displayDevice);
+ layer->setPerFrameData(display);
}
if (hasWideColorDisplay) {
ColorMode colorMode;
Dataspace dataSpace;
RenderIntent renderIntent;
- pickColorMode(displayDevice, &colorMode, &dataSpace, &renderIntent);
- setActiveColorModeInternal(displayDevice, colorMode, dataSpace, renderIntent);
+ pickColorMode(display, &colorMode, &dataSpace, &renderIntent);
+ setActiveColorModeInternal(display, colorMode, dataSpace, renderIntent);
}
}
mDrawingState.colorMatrixChanged = false;
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- auto& displayDevice = mDisplays[displayId];
- if (!displayDevice->isDisplayOn()) {
+ for (const auto& [token, display] : mDisplays) {
+ if (!display->isPoweredOn()) {
continue;
}
- status_t result = displayDevice->prepareFrame(*getBE().mHwc);
- ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:"
- " %d (%s)", displayId, result, strerror(-result));
+ status_t result = display->prepareFrame(*getBE().mHwc);
+ ALOGE_IF(result != NO_ERROR, "prepareFrame for display %d failed: %d (%s)",
+ display->getId(), result, strerror(-result));
}
}
@@ -2095,17 +2017,16 @@
ALOGV("doComposition");
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->isDisplayOn()) {
+ for (const auto& [token, display] : mDisplays) {
+ if (display->isPoweredOn()) {
// transform the dirty region into this screen's coordinate space
- const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
+ const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
// repaint the framebuffer (if needed)
- doDisplayComposition(hw, dirtyRegion);
+ doDisplayComposition(display, dirtyRegion);
- hw->dirtyRegion.clear();
- hw->flip();
+ display->dirtyRegion.clear();
+ display->flip();
}
}
postFramebuffer();
@@ -2119,49 +2040,48 @@
const nsecs_t now = systemTime();
mDebugInSwapBuffers = now;
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- auto& displayDevice = mDisplays[displayId];
- if (!displayDevice->isDisplayOn()) {
+ for (const auto& [token, display] : mDisplays) {
+ if (!display->isPoweredOn()) {
continue;
}
- const auto hwcId = displayDevice->getHwcDisplayId();
- if (hwcId >= 0) {
- getBE().mHwc->presentAndGetReleaseFences(hwcId);
+ const auto displayId = display->getId();
+ if (displayId >= 0) {
+ getBE().mHwc->presentAndGetReleaseFences(displayId);
}
- displayDevice->onSwapBuffersCompleted();
- displayDevice->makeCurrent();
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ display->onSwapBuffersCompleted();
+ display->makeCurrent();
+ for (auto& layer : display->getVisibleLayersSortedByZ()) {
// The layer buffer from the previous frame (if any) is released
// by HWC only when the release fence from this frame (if any) is
// signaled. Always get the release fence from HWC first.
- auto hwcLayer = layer->getHwcLayer(hwcId);
- sp<Fence> releaseFence = getBE().mHwc->getLayerReleaseFence(hwcId, hwcLayer);
+ auto hwcLayer = layer->getHwcLayer(displayId);
+ sp<Fence> releaseFence = getBE().mHwc->getLayerReleaseFence(displayId, hwcLayer);
// If the layer was client composited in the previous frame, we
// need to merge with the previous client target acquire fence.
// Since we do not track that, always merge with the current
// client target acquire fence when it is available, even though
// this is suboptimal.
- if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) {
+ if (layer->getCompositionType(displayId) == HWC2::Composition::Client) {
releaseFence = Fence::merge("LayerRelease", releaseFence,
- displayDevice->getClientTargetAcquireFence());
+ display->getClientTargetAcquireFence());
}
- layer->onLayerDisplayed(releaseFence);
+ layer->getBE().onLayerDisplayed(releaseFence);
}
// We've got a list of layers needing fences, that are disjoint with
- // displayDevice->getVisibleLayersSortedByZ. The best we can do is to
+ // display->getVisibleLayersSortedByZ. The best we can do is to
// supply them with the present fence.
- if (!displayDevice->getLayersNeedingFences().isEmpty()) {
- sp<Fence> presentFence = getBE().mHwc->getPresentFence(hwcId);
- for (auto& layer : displayDevice->getLayersNeedingFences()) {
- layer->onLayerDisplayed(presentFence);
+ if (!display->getLayersNeedingFences().isEmpty()) {
+ sp<Fence> presentFence = getBE().mHwc->getPresentFence(displayId);
+ for (auto& layer : display->getLayersNeedingFences()) {
+ layer->getBE().onLayerDisplayed(presentFence);
}
}
- if (hwcId >= 0) {
- getBE().mHwc->clearReleaseFences(hwcId);
+ if (displayId >= 0) {
+ getBE().mHwc->clearReleaseFences(displayId);
}
}
@@ -2169,8 +2089,9 @@
mDebugInSwapBuffers = 0;
// |mStateLock| not needed as we are on the main thread
- if (getBE().mHwc->isConnected(HWC_DISPLAY_PRIMARY)) {
- uint32_t flipCount = getDefaultDisplayDeviceLocked()->getPageFlipCount();
+ const auto display = getDefaultDisplayDeviceLocked();
+ if (display && getHwComposer().isConnected(display->getId())) {
+ const uint32_t flipCount = display->getPageFlipCount();
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
logFrameStats();
}
@@ -2207,7 +2128,7 @@
// here the transaction has been committed
}
-DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t display,
+DisplayDevice::DisplayType SurfaceFlinger::determineDisplayType(hwc2_display_t hwcDisplayId,
HWC2::Connection connection) const {
// Figure out whether the event is for the primary display or an
// external display by matching the Hwc display id against one for a
@@ -2216,17 +2137,16 @@
// have a connected primary display, we assume the new display is meant to
// be the primary display, and then if we don't have an external display,
// we assume it is that.
- const auto primaryDisplayId =
- getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY);
- const auto externalDisplayId =
+ const auto primaryHwcDisplayId = getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_PRIMARY);
+ const auto externalHwcDisplayId =
getBE().mHwc->getHwcDisplayId(DisplayDevice::DISPLAY_EXTERNAL);
- if (primaryDisplayId && primaryDisplayId == display) {
+ if (primaryHwcDisplayId && primaryHwcDisplayId == hwcDisplayId) {
return DisplayDevice::DISPLAY_PRIMARY;
- } else if (externalDisplayId && externalDisplayId == display) {
- return DisplayDevice::DISPLAY_EXTERNAL;
- } else if (connection == HWC2::Connection::Connected && !primaryDisplayId) {
+ } else if (externalHwcDisplayId && externalHwcDisplayId == hwcDisplayId) {
+ return DisplayDevice::DISPLAY_EXTERNAL;
+ } else if (connection == HWC2::Connection::Connected && !primaryHwcDisplayId) {
return DisplayDevice::DISPLAY_PRIMARY;
- } else if (connection == HWC2::Connection::Connected && !externalDisplayId) {
+ } else if (connection == HWC2::Connection::Connected && !externalHwcDisplayId) {
return DisplayDevice::DISPLAY_EXTERNAL;
}
@@ -2235,9 +2155,9 @@
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
for (const auto& event : mPendingHotplugEvents) {
- auto displayType = determineDisplayType(event.display, event.connection);
+ auto displayType = determineDisplayType(event.hwcDisplayId, event.connection);
if (displayType == DisplayDevice::DISPLAY_ID_INVALID) {
- ALOGW("Unable to determine the display type for display %" PRIu64, event.display);
+ ALOGW("Unable to determine the display type for display %" PRIu64, event.hwcDisplayId);
continue;
}
@@ -2246,29 +2166,34 @@
continue;
}
- getBE().mHwc->onHotplug(event.display, displayType, event.connection);
+ const auto displayId =
+ getBE().mHwc->onHotplug(event.hwcDisplayId, displayType, event.connection);
+ if (displayId) {
+ ALOGV("Display %" PRIu64 " has stable ID %" PRIu64, event.hwcDisplayId, *displayId);
+ }
if (event.connection == HWC2::Connection::Connected) {
- if (!mBuiltinDisplays[displayType].get()) {
+ if (!mDisplayTokens[displayType].get()) {
ALOGV("Creating built in display %d", displayType);
- mBuiltinDisplays[displayType] = new BBinder();
- // All non-virtual displays are currently considered secure.
- DisplayDeviceState info(displayType, true);
+ mDisplayTokens[displayType] = new BBinder();
+ DisplayDeviceState info;
+ info.type = displayType;
info.displayName = displayType == DisplayDevice::DISPLAY_PRIMARY ?
"Built-in Screen" : "External Screen";
- mCurrentState.displays.add(mBuiltinDisplays[displayType], info);
+ info.isSecure = true; // All physical displays are currently considered secure.
+ mCurrentState.displays.add(mDisplayTokens[displayType], info);
mInterceptor->saveDisplayCreation(info);
}
} else {
ALOGV("Removing built in display %d", displayType);
- ssize_t idx = mCurrentState.displays.indexOfKey(mBuiltinDisplays[displayType]);
+ ssize_t idx = mCurrentState.displays.indexOfKey(mDisplayTokens[displayType]);
if (idx >= 0) {
const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx));
- mInterceptor->saveDisplayDeletion(info.displayId);
+ mInterceptor->saveDisplayDeletion(info.sequenceId);
mCurrentState.displays.removeItemsAt(idx);
}
- mBuiltinDisplays[displayType].clear();
+ mDisplayTokens[displayType].clear();
}
processDisplayChangesLocked();
@@ -2278,13 +2203,13 @@
}
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
- const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
+ const wp<IBinder>& displayToken, int32_t displayId, const DisplayDeviceState& state,
const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
bool hasWideColorGamut = false;
std::unordered_map<ColorMode, std::vector<RenderIntent>> hwcColorModes;
if (hasWideColorDisplay) {
- std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
+ std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId);
for (ColorMode colorMode : modes) {
switch (colorMode) {
case ColorMode::DISPLAY_P3:
@@ -2296,14 +2221,14 @@
break;
}
- std::vector<RenderIntent> renderIntents = getHwComposer().getRenderIntents(hwcId,
- colorMode);
+ std::vector<RenderIntent> renderIntents =
+ getHwComposer().getRenderIntents(displayId, colorMode);
hwcColorModes.emplace(colorMode, renderIntents);
}
}
HdrCapabilities hdrCapabilities;
- getHwComposer().getHdrCapabilities(hwcId, &hdrCapabilities);
+ getHwComposer().getHdrCapabilities(displayId, &hdrCapabilities);
auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
auto nativeWindow = nativeWindowSurface->getNativeWindow();
@@ -2313,7 +2238,7 @@
*/
std::unique_ptr<RE::Surface> renderSurface = getRenderEngine().createSurface();
renderSurface->setCritical(state.type == DisplayDevice::DISPLAY_PRIMARY);
- renderSurface->setAsync(state.type >= DisplayDevice::DISPLAY_VIRTUAL);
+ renderSurface->setAsync(state.isVirtual());
renderSurface->setNativeWindow(nativeWindow.get());
const int displayWidth = renderSurface->queryWidth();
const int displayHeight = renderSurface->queryHeight();
@@ -2325,19 +2250,18 @@
// * In makeCurrent(), using eglSwapInterval. Some EGL drivers set the
// window's swap interval in eglMakeCurrent, so they'll override the
// interval we set here.
- if (state.type >= DisplayDevice::DISPLAY_VIRTUAL) {
+ if (state.isVirtual()) {
nativeWindow->setSwapInterval(nativeWindow.get(), 0);
}
// virtual displays are always considered enabled
- auto initialPowerMode = (state.type >= DisplayDevice::DISPLAY_VIRTUAL) ? HWC_POWER_MODE_NORMAL
- : HWC_POWER_MODE_OFF;
+ auto initialPowerMode = state.isVirtual() ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
- sp<DisplayDevice> hw =
- new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
- dispSurface, std::move(renderSurface), displayWidth, displayHeight,
- hasWideColorGamut, hdrCapabilities,
- getHwComposer().getSupportedPerFrameMetadata(hwcId),
+ sp<DisplayDevice> display =
+ new DisplayDevice(this, state.type, displayId, state.isSecure, displayToken,
+ nativeWindow, dispSurface, std::move(renderSurface), displayWidth,
+ displayHeight, hasWideColorGamut, hdrCapabilities,
+ getHwComposer().getSupportedPerFrameMetadata(displayId),
hwcColorModes, initialPowerMode);
if (maxFrameBufferAcquiredBuffers >= 3) {
@@ -2350,16 +2274,16 @@
defaultColorMode = ColorMode::SRGB;
defaultDataSpace = Dataspace::SRGB;
}
- setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace,
+ setActiveColorModeInternal(display, defaultColorMode, defaultDataSpace,
RenderIntent::COLORIMETRIC);
if (state.type < DisplayDevice::DISPLAY_VIRTUAL) {
- hw->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type));
+ display->setActiveConfig(getHwComposer().getActiveConfigIndex(state.type));
}
- hw->setLayerStack(state.layerStack);
- hw->setProjection(state.orientation, state.viewport, state.frame);
- hw->setDisplayName(state.displayName);
+ display->setLayerStack(state.layerStack);
+ display->setProjection(state.orientation, state.viewport, state.frame);
+ display->setDisplayName(state.displayName);
- return hw;
+ return display;
}
void SurfaceFlinger::processDisplayChangesLocked() {
@@ -2384,17 +2308,22 @@
// Call makeCurrent() on the primary display so we can
// be sure that nothing associated with this display
// is current.
- const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
- if (defaultDisplay != nullptr) defaultDisplay->makeCurrent();
- sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
- if (hw != nullptr) hw->disconnect(getHwComposer());
- if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
- mEventThread->onHotplugReceived(draw[i].type, false);
- mDisplays.removeItem(draw.keyAt(i));
+ if (const auto defaultDisplay = getDefaultDisplayDeviceLocked()) {
+ defaultDisplay->makeCurrent();
+ }
+ if (const auto display = getDisplayDeviceLocked(draw.keyAt(i))) {
+ display->disconnect(getHwComposer());
+ }
+ if (draw[i].type == DisplayDevice::DISPLAY_PRIMARY) {
+ mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
+ } else if (draw[i].type == DisplayDevice::DISPLAY_EXTERNAL) {
+ mEventThread->onHotplugReceived(EventThread::DisplayType::External, false);
+ }
+ mDisplays.erase(draw.keyAt(i));
} else {
// this display is in both lists. see if something changed.
const DisplayDeviceState& state(curr[j]);
- const wp<IBinder>& display(curr.keyAt(j));
+ const wp<IBinder>& displayToken = curr.keyAt(j);
const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
if (state_binder != draw_binder) {
@@ -2402,26 +2331,26 @@
// recreating the DisplayDevice, so we just remove it
// from the drawing state, so that it get re-added
// below.
- sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
- if (hw != nullptr) hw->disconnect(getHwComposer());
- mDisplays.removeItem(display);
+ if (const auto display = getDisplayDeviceLocked(displayToken)) {
+ display->disconnect(getHwComposer());
+ }
+ mDisplays.erase(displayToken);
mDrawingState.displays.removeItemsAt(i);
dc--;
// at this point we must loop to the next item
continue;
}
- const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
- if (disp != nullptr) {
+ if (const auto display = getDisplayDeviceLocked(displayToken)) {
if (state.layerStack != draw[i].layerStack) {
- disp->setLayerStack(state.layerStack);
+ display->setLayerStack(state.layerStack);
}
if ((state.orientation != draw[i].orientation) ||
(state.viewport != draw[i].viewport) || (state.frame != draw[i].frame)) {
- disp->setProjection(state.orientation, state.viewport, state.frame);
+ display->setProjection(state.orientation, state.viewport, state.frame);
}
if (state.width != draw[i].width || state.height != draw[i].height) {
- disp->setDisplaySize(state.width, state.height);
+ display->setDisplaySize(state.width, state.height);
}
}
}
@@ -2440,8 +2369,8 @@
sp<IGraphicBufferConsumer> bqConsumer;
mCreateBufferQueue(&bqProducer, &bqConsumer, false);
- int32_t hwcId = -1;
- if (state.isVirtualDisplay()) {
+ int32_t displayId = -1;
+ if (state.isVirtual()) {
// Virtual displays without a surface are dormant:
// they have external state (layer stack, projection,
// etc.) but no internal state (i.e. a DisplayDevice).
@@ -2459,13 +2388,14 @@
ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
auto format = static_cast<ui::PixelFormat>(intFormat);
- getBE().mHwc->allocateVirtualDisplay(width, height, &format, &hwcId);
+ getBE().mHwc->allocateVirtualDisplay(width, height, &format,
+ &displayId);
}
// TODO: Plumb requested format back up to consumer
sp<VirtualDisplaySurface> vds =
- new VirtualDisplaySurface(*getBE().mHwc, hwcId, state.surface,
+ new VirtualDisplaySurface(*getBE().mHwc, displayId, state.surface,
bqProducer, bqConsumer,
state.displayName);
@@ -2478,18 +2408,24 @@
"surface is provided (%p), ignoring it",
state.surface.get());
- hwcId = state.type;
- dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer);
+ displayId = state.type;
+ dispSurface = new FramebufferSurface(*getBE().mHwc, displayId, bqConsumer);
producer = bqProducer;
}
- const wp<IBinder>& display(curr.keyAt(i));
+ const wp<IBinder>& displayToken = curr.keyAt(i);
if (dispSurface != nullptr) {
- mDisplays.add(display,
- setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface,
- producer));
- if (!state.isVirtualDisplay()) {
- mEventThread->onHotplugReceived(state.type, true);
+ mDisplays.emplace(displayToken,
+ setupNewDisplayDeviceInternal(displayToken, displayId, state,
+ dispSurface, producer));
+ if (!state.isVirtual()) {
+ if (state.type == DisplayDevice::DISPLAY_PRIMARY) {
+ mEventThread->onHotplugReceived(EventThread::DisplayType::Primary,
+ true);
+ } else if (state.type == DisplayDevice::DISPLAY_EXTERNAL) {
+ mEventThread->onHotplugReceived(EventThread::DisplayType::External,
+ true);
+ }
}
}
}
@@ -2551,7 +2487,7 @@
// happened yet, so we must use the current state layer list
// (soon to become the drawing state list).
//
- sp<const DisplayDevice> disp;
+ sp<const DisplayDevice> hintDisplay;
uint32_t currentlayerStack = 0;
bool first = true;
mCurrentState.traverseInZOrder([&](Layer* layer) {
@@ -2564,34 +2500,33 @@
// figure out if this layerstack is mirrored
// (more than one display) if so, pick the default display,
// if not, pick the only display it's on.
- disp.clear();
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- sp<const DisplayDevice> hw(mDisplays[dpy]);
- if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
- if (disp == nullptr) {
- disp = std::move(hw);
- } else {
- disp = nullptr;
+ hintDisplay = nullptr;
+ for (const auto& [token, display] : mDisplays) {
+ if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) {
+ if (hintDisplay) {
+ hintDisplay = nullptr;
break;
+ } else {
+ hintDisplay = display;
}
}
}
}
- if (disp == nullptr) {
+ if (!hintDisplay) {
// NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
// redraw after transform hint changes. See bug 8508397.
// could be null when this layer is using a layerStack
// that is not visible on any display. Also can occur at
// screen off/on times.
- disp = getDefaultDisplayDeviceLocked();
+ hintDisplay = getDefaultDisplayDeviceLocked();
}
- // disp can be null if there is no display available at all to get
+ // could be null if there is no display available at all to get
// the transform hint from.
- if (disp != nullptr) {
- layer->updateTransformHint(disp);
+ if (hintDisplay) {
+ layer->updateTransformHint(hintDisplay);
}
first = false;
@@ -2634,14 +2569,13 @@
void SurfaceFlinger::updateCursorAsync()
{
- for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
- auto& displayDevice = mDisplays[displayId];
- if (displayDevice->getHwcDisplayId() < 0) {
+ for (const auto& [token, display] : mDisplays) {
+ if (display->getId() < 0) {
continue;
}
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- layer->updateCursorPosition(displayDevice);
+ for (auto& layer : display->getVisibleLayersSortedByZ()) {
+ layer->updateCursorPosition(display);
}
}
}
@@ -2674,9 +2608,8 @@
mTransactionCV.broadcast();
}
-void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
- Region& outDirtyRegion, Region& outOpaqueRegion)
-{
+void SurfaceFlinger::computeVisibleRegions(const sp<const DisplayDevice>& display,
+ Region& outDirtyRegion, Region& outOpaqueRegion) {
ATRACE_CALL();
ALOGV("computeVisibleRegions");
@@ -2691,8 +2624,9 @@
const Layer::State& s(layer->getDrawingState());
// only consider the layers on the given layer stack
- if (!layer->belongsToDisplay(displayDevice->getLayerStack(), displayDevice->isPrimary()))
+ if (!layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) {
return;
+ }
/*
* opaqueRegion: area of a surface that is fully opaque.
@@ -2812,10 +2746,9 @@
}
void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (layer->belongsToDisplay(hw->getLayerStack(), hw->isPrimary())) {
- hw->dirtyRegion.orSelf(dirty);
+ for (const auto& [token, display] : mDisplays) {
+ if (layer->belongsToDisplay(display->getLayerStack(), display->isPrimary())) {
+ display->dirtyRegion.orSelf(dirty);
}
}
}
@@ -2879,36 +2812,32 @@
mGeometryInvalid = true;
}
-
-void SurfaceFlinger::doDisplayComposition(
- const sp<const DisplayDevice>& displayDevice,
- const Region& inDirtyRegion)
-{
+void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& display,
+ const Region& inDirtyRegion) {
// We only need to actually compose the display if:
// 1) It is being handled by hardware composer, which may need this to
// keep its virtual display state machine in sync, or
// 2) There is work to be done (the dirty region isn't empty)
- bool isHwcDisplay = displayDevice->getHwcDisplayId() >= 0;
+ bool isHwcDisplay = display->getId() >= 0;
if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
ALOGV("Skipping display composition");
return;
}
ALOGV("doDisplayComposition");
- if (!doComposeSurfaces(displayDevice)) return;
+ if (!doComposeSurfaces(display)) return;
// swap buffers (presentation)
- displayDevice->swapBuffers(getHwComposer());
+ display->swapBuffers(getHwComposer());
}
-bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& displayDevice)
-{
+bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& display) {
ALOGV("doComposeSurfaces");
- const Region bounds(displayDevice->bounds());
- const DisplayRenderArea renderArea(displayDevice);
- const auto hwcId = displayDevice->getHwcDisplayId();
- const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId);
+ const Region bounds(display->bounds());
+ const DisplayRenderArea renderArea(display);
+ const auto displayId = display->getId();
+ const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId);
ATRACE_INT("hasClientComposition", hasClientComposition);
bool applyColorMatrix = false;
@@ -2919,14 +2848,14 @@
ALOGV("hasClientComposition");
Dataspace outputDataspace = Dataspace::UNKNOWN;
- if (displayDevice->hasWideColorGamut()) {
- outputDataspace = displayDevice->getCompositionDataSpace();
+ if (display->hasWideColorGamut()) {
+ outputDataspace = display->getCompositionDataSpace();
}
getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
getBE().mRenderEngine->setDisplayMaxLuminance(
- displayDevice->getHdrCapabilities().getDesiredMaxLuminance());
+ display->getHdrCapabilities().getDesiredMaxLuminance());
- const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId);
+ const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(displayId);
const bool skipClientColorTransform = getBE().mHwc->hasCapability(
HWC2::Capability::SkipClientColorTransform);
@@ -2936,18 +2865,18 @@
}
needsLegacyColorMatrix =
- (displayDevice->getActiveRenderIntent() >= RenderIntent::ENHANCE &&
- outputDataspace != Dataspace::UNKNOWN &&
- outputDataspace != Dataspace::SRGB);
+ (display->getActiveRenderIntent() >= RenderIntent::ENHANCE &&
+ outputDataspace != Dataspace::UNKNOWN && outputDataspace != Dataspace::SRGB);
- if (!displayDevice->makeCurrent()) {
+ if (!display->makeCurrent()) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
- displayDevice->getDisplayName().string());
+ display->getDisplayName().c_str());
getRenderEngine().resetCurrentSurface();
// |mStateLock| not needed as we are on the main thread
- if(!getDefaultDisplayDeviceLocked()->makeCurrent()) {
- ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
+ const auto defaultDisplay = getDefaultDisplayDeviceLocked();
+ if (!defaultDisplay || !defaultDisplay->makeCurrent()) {
+ ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
}
return false;
}
@@ -2964,31 +2893,31 @@
// we start with the whole screen area and remove the scissor part
// we're left with the letterbox region
// (common case is that letterbox ends-up being empty)
- const Region letterbox(bounds.subtract(displayDevice->getScissor()));
+ const Region letterbox = bounds.subtract(display->getScissor());
// compute the area to clear
- Region region(displayDevice->undefinedRegion.merge(letterbox));
+ const Region region = display->undefinedRegion.merge(letterbox);
// screen is already cleared here
if (!region.isEmpty()) {
// can happen with SurfaceView
- drawWormhole(displayDevice, region);
+ drawWormhole(display, region);
}
}
- if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
+ if (!display->isPrimary()) {
// just to be on the safe side, we don't set the
// scissor on the main display. It should never be needed
// anyways (though in theory it could since the API allows it).
- const Rect& bounds(displayDevice->getBounds());
- const Rect& scissor(displayDevice->getScissor());
+ const Rect& bounds = display->getBounds();
+ const Rect& scissor = display->getScissor();
if (scissor != bounds) {
// scissor doesn't match the screen's dimensions, so we
// need to clear everything outside of it and enable
// the GL scissor so we don't draw anything where we shouldn't
// enable scissor for this frame
- const uint32_t height = displayDevice->getHeight();
+ const uint32_t height = display->getHeight();
getBE().mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
scissor.getWidth(), scissor.getHeight());
}
@@ -3000,24 +2929,22 @@
*/
ALOGV("Rendering client layers");
- const Transform& displayTransform = displayDevice->getTransform();
+ const Transform& displayTransform = display->getTransform();
bool firstLayer = true;
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ for (auto& layer : display->getVisibleLayersSortedByZ()) {
const Region clip(bounds.intersect(
displayTransform.transform(layer->visibleRegion)));
ALOGV("Layer: %s", layer->getName().string());
- ALOGV(" Composition type: %s",
- to_string(layer->getCompositionType(hwcId)).c_str());
+ ALOGV(" Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str());
if (!clip.isEmpty()) {
- switch (layer->getCompositionType(hwcId)) {
+ switch (layer->getCompositionType(displayId)) {
case HWC2::Composition::Cursor:
case HWC2::Composition::Device:
case HWC2::Composition::Sideband:
case HWC2::Composition::SolidColor: {
const Layer::State& state(layer->getDrawingState());
- if (layer->getClearClientTarget(hwcId) && !firstLayer &&
- layer->isOpaque(state) && (state.color.a == 1.0f)
- && hasClientComposition) {
+ if (layer->getClearClientTarget(displayId) && !firstLayer &&
+ layer->isOpaque(state) && (state.color.a == 1.0f) && hasClientComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
layer->clearWithOpenGL(renderArea);
@@ -3060,8 +2987,9 @@
return true;
}
-void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const {
- const int32_t height = displayDevice->getHeight();
+void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& display,
+ const Region& region) const {
+ const int32_t height = display->getHeight();
auto& engine(getRenderEngine());
engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
}
@@ -3292,53 +3220,51 @@
}
}
-uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
-{
- ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
- if (dpyIdx < 0)
- return 0;
+uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) {
+ const ssize_t index = mCurrentState.displays.indexOfKey(s.token);
+ if (index < 0) return 0;
uint32_t flags = 0;
- DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
- if (disp.isValid()) {
- const uint32_t what = s.what;
- if (what & DisplayState::eSurfaceChanged) {
- if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
- disp.surface = s.surface;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eLayerStackChanged) {
- if (disp.layerStack != s.layerStack) {
- disp.layerStack = s.layerStack;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eDisplayProjectionChanged) {
- if (disp.orientation != s.orientation) {
- disp.orientation = s.orientation;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.frame != s.frame) {
- disp.frame = s.frame;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.viewport != s.viewport) {
- disp.viewport = s.viewport;
- flags |= eDisplayTransactionNeeded;
- }
- }
- if (what & DisplayState::eDisplaySizeChanged) {
- if (disp.width != s.width) {
- disp.width = s.width;
- flags |= eDisplayTransactionNeeded;
- }
- if (disp.height != s.height) {
- disp.height = s.height;
- flags |= eDisplayTransactionNeeded;
- }
+ DisplayDeviceState& state = mCurrentState.displays.editValueAt(index);
+
+ const uint32_t what = s.what;
+ if (what & DisplayState::eSurfaceChanged) {
+ if (IInterface::asBinder(state.surface) != IInterface::asBinder(s.surface)) {
+ state.surface = s.surface;
+ flags |= eDisplayTransactionNeeded;
}
}
+ if (what & DisplayState::eLayerStackChanged) {
+ if (state.layerStack != s.layerStack) {
+ state.layerStack = s.layerStack;
+ flags |= eDisplayTransactionNeeded;
+ }
+ }
+ if (what & DisplayState::eDisplayProjectionChanged) {
+ if (state.orientation != s.orientation) {
+ state.orientation = s.orientation;
+ flags |= eDisplayTransactionNeeded;
+ }
+ if (state.frame != s.frame) {
+ state.frame = s.frame;
+ flags |= eDisplayTransactionNeeded;
+ }
+ if (state.viewport != s.viewport) {
+ state.viewport = s.viewport;
+ flags |= eDisplayTransactionNeeded;
+ }
+ }
+ if (what & DisplayState::eDisplaySizeChanged) {
+ if (state.width != s.width) {
+ state.width = s.width;
+ flags |= eDisplayTransactionNeeded;
+ }
+ if (state.height != s.height) {
+ state.height = s.height;
+ flags |= eDisplayTransactionNeeded;
+ }
+ }
+
return flags;
}
@@ -3600,7 +3526,8 @@
});
}
- ALOGD_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), uniqueName.c_str());
+ ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(),
+ uniqueName.c_str());
return uniqueName;
}
@@ -3671,13 +3598,16 @@
// ---------------------------------------------------------------------------
void SurfaceFlinger::onInitializeDisplays() {
+ const auto displayToken = mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY];
+ if (!displayToken) return;
+
// reset screen orientation and use primary layer stack
Vector<ComposerState> state;
Vector<DisplayState> displays;
DisplayState d;
d.what = DisplayState::eDisplayProjectionChanged |
DisplayState::eLayerStackChanged;
- d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
+ d.token = displayToken;
d.layerStack = 0;
d.orientation = DisplayState::eOrientationDefault;
d.frame.makeInvalid();
@@ -3686,10 +3616,13 @@
d.height = 0;
displays.add(d);
setTransactionState(state, displays, 0);
- setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL,
- /*stateLockHeld*/ false);
- const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+ const auto display = getDisplayDevice(displayToken);
+ if (!display) return;
+
+ setPowerModeInternal(display, HWC_POWER_MODE_NORMAL, /*stateLockHeld*/ false);
+
+ const auto activeConfig = getHwComposer().getActiveConfig(display->getId());
const nsecs_t period = activeConfig->getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(period);
@@ -3699,51 +3632,42 @@
}
void SurfaceFlinger::initializeDisplays() {
- class MessageScreenInitialized : public MessageBase {
- SurfaceFlinger* flinger;
- public:
- explicit MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { }
- virtual bool handler() {
- flinger->onInitializeDisplays();
- return true;
- }
- };
- sp<MessageBase> msg = new MessageScreenInitialized(this);
- postMessageAsync(msg); // we may be called from main thread, use async message
+ // Async since we may be called from the main thread.
+ postMessageAsync(new LambdaMessage([this] { onInitializeDisplays(); }));
}
-void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
- int mode, bool stateLockHeld) {
- ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
- this);
- int32_t type = hw->getDisplayType();
- int currentMode = hw->getPowerMode();
+void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, int mode,
+ bool stateLockHeld) {
+ const int32_t displayId = display->getId();
+ ALOGD("Setting power mode %d on display %d", mode, displayId);
+ int currentMode = display->getPowerMode();
if (mode == currentMode) {
return;
}
- hw->setPowerMode(mode);
- if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+ if (display->isVirtual()) {
ALOGW("Trying to set power mode for virtual display");
return;
}
+ display->setPowerMode(mode);
+
if (mInterceptor->isEnabled()) {
ConditionalLock lock(mStateLock, !stateLockHeld);
- ssize_t idx = mCurrentState.displays.indexOfKey(hw->getDisplayToken());
+ ssize_t idx = mCurrentState.displays.indexOfKey(display->getDisplayToken());
if (idx < 0) {
ALOGW("Surface Interceptor SavePowerMode: invalid display token");
return;
}
- mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).displayId, mode);
+ mInterceptor->savePowerModeUpdate(mCurrentState.displays.valueAt(idx).sequenceId, mode);
}
+ int32_t type = display->getDisplayType();
if (currentMode == HWC_POWER_MODE_OFF) {
// Turn on the display
getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY &&
- mode != HWC_POWER_MODE_DOZE_SUSPEND) {
+ if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
@@ -3765,8 +3689,7 @@
ALOGW("Couldn't set SCHED_OTHER on display off");
}
- if (type == DisplayDevice::DISPLAY_PRIMARY &&
- currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
+ if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
disableHardwareVsync(true); // also cancels any in-progress resync
// FIXME: eventthread only knows about the main display right now
@@ -3780,15 +3703,14 @@
mode == HWC_POWER_MODE_NORMAL) {
// Update display while dozing
getHwComposer().setPowerMode(type, mode);
- if (type == DisplayDevice::DISPLAY_PRIMARY &&
- currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
+ if (display->isPrimary() && currentMode == HWC_POWER_MODE_DOZE_SUSPEND) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true);
}
} else if (mode == HWC_POWER_MODE_DOZE_SUSPEND) {
// Leave display going to doze
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
+ if (display->isPrimary()) {
disableHardwareVsync(true); // also cancels any in-progress resync
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenReleased();
@@ -3798,35 +3720,22 @@
ALOGE("Attempting to set unknown power mode: %d\n", mode);
getHwComposer().setPowerMode(type, mode);
}
- ALOGD("Finished set power mode=%d, type=%d", mode, hw->getDisplayType());
+
+ ALOGD("Finished setting power mode %d on display %d", mode, displayId);
}
-void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
- class MessageSetPowerMode: public MessageBase {
- SurfaceFlinger& mFlinger;
- sp<IBinder> mDisplay;
- int mMode;
- public:
- MessageSetPowerMode(SurfaceFlinger& flinger,
- const sp<IBinder>& disp, int mode) : mFlinger(flinger),
- mDisplay(disp) { mMode = mode; }
- virtual bool handler() {
- sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
- if (hw == nullptr) {
- ALOGE("Attempt to set power mode = %d for null display %p",
- mMode, mDisplay.get());
- } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to set power mode = %d for virtual display",
- mMode);
- } else {
- mFlinger.setPowerModeInternal(
- hw, mMode, /*stateLockHeld*/ false);
- }
- return true;
+void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
+ postMessageSync(new LambdaMessage([&] {
+ const auto display = getDisplayDevice(displayToken);
+ if (!display) {
+ ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
+ displayToken.get());
+ } else if (display->isVirtual()) {
+ ALOGW("Attempt to set power mode %d for virtual display", mode);
+ } else {
+ setPowerModeInternal(display, mode, /*stateLockHeld*/ false);
}
- };
- sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode);
- postMessageSync(msg);
+ }));
}
// ---------------------------------------------------------------------------
@@ -3936,6 +3845,13 @@
dumpAll = false;
}
+ if ((index < numArgs) &&
+ (args[index] == String16("--display-identification"))) {
+ index++;
+ dumpDisplayIdentificationData(result);
+ dumpAll = false;
+ }
+
if ((index < numArgs) && (args[index] == String16("--timestats"))) {
index++;
mTimeStats.parseArgs(asProto, args, index, result);
@@ -3977,9 +3893,12 @@
index++;
}
- const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
- const nsecs_t period = activeConfig->getVsyncPeriod();
- result.appendFormat("%" PRId64 "\n", period);
+ if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY;
+ getHwComposer().isConnected(displayId)) {
+ const auto activeConfig = getBE().mHwc->getActiveConfig(displayId);
+ const nsecs_t period = activeConfig->getVsyncPeriod();
+ result.appendFormat("%" PRId64 "\n", period);
+ }
if (name.isEmpty()) {
mAnimFrameTracker.dumpStats(result);
@@ -4115,6 +4034,48 @@
result.append("\n");
}
+void SurfaceFlinger::dumpDisplayIdentificationData(String8& result) const {
+ for (const auto& [token, display] : mDisplays) {
+ const int32_t displayId = display->getId();
+ const auto hwcDisplayId = getHwComposer().getHwcDisplayId(displayId);
+ if (!hwcDisplayId) {
+ continue;
+ }
+
+ result.appendFormat("Display %d (HWC display %" PRIu64 "): ", displayId, *hwcDisplayId);
+ uint8_t port;
+ DisplayIdentificationData data;
+ if (!getHwComposer().getDisplayIdentificationData(*hwcDisplayId, &port, &data)) {
+ result.append("no identification data\n");
+ continue;
+ }
+
+ if (!isEdid(data)) {
+ result.append("unknown identification data: ");
+ for (uint8_t byte : data) {
+ result.appendFormat("%x ", byte);
+ }
+ result.append("\n");
+ continue;
+ }
+
+ const auto edid = parseEdid(data);
+ if (!edid) {
+ result.append("invalid EDID: ");
+ for (uint8_t byte : data) {
+ result.appendFormat("%x ", byte);
+ }
+ result.append("\n");
+ continue;
+ }
+
+ result.appendFormat("port=%u pnpId=%s displayName=\"", port, edid->pnpId.data());
+ result.append(edid->displayName.data(), edid->displayName.length());
+ result.append("\"\n");
+ }
+ result.append("\n");
+}
+
void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
result.appendFormat("DisplayColorSetting: %s\n",
@@ -4122,20 +4083,19 @@
// TODO: print out if wide-color mode is active or not
- for (size_t d = 0; d < mDisplays.size(); d++) {
- const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
- int32_t hwcId = displayDevice->getHwcDisplayId();
- if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+ for (const auto& [token, display] : mDisplays) {
+ const int32_t displayId = display->getId();
+ if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
continue;
}
- result.appendFormat("Display %d color modes:\n", hwcId);
- std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
+ result.appendFormat("Display %d color modes:\n", displayId);
+ std::vector<ColorMode> modes = getHwComposer().getColorModes(displayId);
for (auto&& mode : modes) {
result.appendFormat(" %s (%d)\n", decodeColorMode(mode).c_str(), mode);
}
- ColorMode currentMode = displayDevice->getActiveColorMode();
+ ColorMode currentMode = display->getActiveColorMode();
result.appendFormat(" Current color mode: %s (%d)\n",
decodeColorMode(currentMode).c_str(), currentMode);
}
@@ -4154,23 +4114,22 @@
return layersProto;
}
-LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(int32_t hwcId) const {
+LayersProto SurfaceFlinger::dumpVisibleLayersProtoInfo(const DisplayDevice& display) const {
LayersProto layersProto;
- const sp<DisplayDevice>& displayDevice(mDisplays[hwcId]);
SizeProto* resolution = layersProto.mutable_resolution();
- resolution->set_w(displayDevice->getWidth());
- resolution->set_h(displayDevice->getHeight());
+ resolution->set_w(display.getWidth());
+ resolution->set_h(display.getHeight());
- layersProto.set_color_mode(decodeColorMode(displayDevice->getActiveColorMode()));
- layersProto.set_color_transform(decodeColorTransform(displayDevice->getColorTransform()));
- layersProto.set_global_transform(
- static_cast<int32_t>(displayDevice->getOrientationTransform()));
+ layersProto.set_color_mode(decodeColorMode(display.getActiveColorMode()));
+ layersProto.set_color_transform(decodeColorTransform(display.getColorTransform()));
+ layersProto.set_global_transform(static_cast<int32_t>(display.getOrientationTransform()));
+ const int32_t displayId = display.getId();
mDrawingState.traverseInZOrder([&](Layer* layer) {
- if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(hwcId)) {
+ if (!layer->visibleRegion.isEmpty() && layer->getBE().mHwcLayers.count(displayId)) {
LayerProto* layerProto = layersProto.add_layers();
- layer->writeToProto(layerProto, hwcId);
+ layer->writeToProto(layerProto, displayId);
}
});
@@ -4208,6 +4167,9 @@
appendGuiConfigString(result);
result.append("\n");
+ result.append("\nDisplay identification data:\n");
+ dumpDisplayIdentificationData(result);
+
result.append("\nWide-Color information:\n");
dumpWideColorInfo(result);
@@ -4217,28 +4179,32 @@
result.append(SyncFeatures::getInstance().toString());
result.append("\n");
- const auto& activeConfig = getBE().mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
-
colorizer.bold(result);
- result.append("DispSync configuration: ");
+ result.append("DispSync configuration:\n");
colorizer.reset(result);
+
const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
- result.appendFormat(
- "app phase %" PRId64 " ns, "
- "sf phase %" PRId64 " ns, "
- "early app phase %" PRId64 " ns, "
- "early sf phase %" PRId64 " ns, "
- "early app gl phase %" PRId64 " ns, "
- "early sf gl phase %" PRId64 " ns, "
- "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
- vsyncPhaseOffsetNs,
- sfVsyncPhaseOffsetNs,
- appEarlyOffset,
- sfEarlyOffset,
- appEarlyGlOffset,
- sfEarlyOffset,
- dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
+ if (const auto displayId = DisplayDevice::DISPLAY_PRIMARY;
+ getHwComposer().isConnected(displayId)) {
+ const auto activeConfig = getHwComposer().getActiveConfig(displayId);
+ result.appendFormat("Display %d: "
+ "app phase %" PRId64 " ns, "
+ "sf phase %" PRId64 " ns, "
+ "early app phase %" PRId64 " ns, "
+ "early sf phase %" PRId64 " ns, "
+ "early app gl phase %" PRId64 " ns, "
+ "early sf gl phase %" PRId64 " ns, "
+ "present offset %" PRId64 " ns (refresh %" PRId64 " ns)",
+ displayId,
+ vsyncPhaseOffsetNs,
+ sfVsyncPhaseOffsetNs,
+ appEarlyOffset,
+ sfEarlyOffset,
+ appEarlyGlOffset,
+ sfEarlyOffset,
+ dispSyncPresentTimeOffset, activeConfig->getVsyncPeriod());
+ }
result.append("\n");
// Dump static screen stats
@@ -4246,6 +4212,8 @@
dumpStaticScreenStats(result);
result.append("\n");
+ result.appendFormat("Missed frame count: %u\n\n", mFrameMissedCount.load());
+
dumpBufferingStats(result);
/*
@@ -4269,9 +4237,8 @@
colorizer.bold(result);
result.appendFormat("Displays (%zu entries)\n", mDisplays.size());
colorizer.reset(result);
- for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
- const sp<const DisplayDevice>& hw(mDisplays[dpy]);
- hw->dump(result);
+ for (const auto& [token, display] : mDisplays) {
+ display->dump(result);
}
result.append("\n");
@@ -4284,31 +4251,30 @@
colorizer.reset(result);
HWComposer& hwc(getHwComposer());
- sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());
+ const auto display = getDefaultDisplayDeviceLocked();
getBE().mRenderEngine->dump(result);
- if (hw) {
- hw->undefinedRegion.dump(result, "undefinedRegion");
- result.appendFormat(" orientation=%d, isDisplayOn=%d\n",
- hw->getOrientation(), hw->isDisplayOn());
+ if (display) {
+ display->undefinedRegion.dump(result, "undefinedRegion");
+ result.appendFormat(" orientation=%d, isPoweredOn=%d\n", display->getOrientation(),
+ display->isPoweredOn());
}
- result.appendFormat(
- " last eglSwapBuffers() time: %f us\n"
- " last transaction time : %f us\n"
- " transaction-flags : %08x\n"
- " refresh-rate : %f fps\n"
- " x-dpi : %f\n"
- " y-dpi : %f\n"
- " gpu_to_cpu_unsupported : %d\n"
- ,
- mLastSwapBufferTime/1000.0,
- mLastTransactionTime/1000.0,
- mTransactionFlags,
- 1e9 / activeConfig->getVsyncPeriod(),
- activeConfig->getDpiX(),
- activeConfig->getDpiY(),
- !mGpuToCpuSupported);
+ result.appendFormat(" last eglSwapBuffers() time: %f us\n"
+ " last transaction time : %f us\n"
+ " transaction-flags : %08x\n"
+ " gpu_to_cpu_unsupported : %d\n",
+ mLastSwapBufferTime / 1000.0, mLastTransactionTime / 1000.0,
+ mTransactionFlags, !mGpuToCpuSupported);
+
+ if (display) {
+ const auto activeConfig = getHwComposer().getActiveConfig(display->getId());
+ result.appendFormat(" refresh-rate : %f fps\n"
+ " x-dpi : %f\n"
+ " y-dpi : %f\n",
+ 1e9 / activeConfig->getVsyncPeriod(), activeConfig->getDpiX(),
+ activeConfig->getDpiY());
+ }
result.appendFormat(" eglSwapBuffers time: %f us\n",
inSwapBuffersDuration/1000.0);
@@ -4325,18 +4291,15 @@
/*
* HWC layer minidump
*/
- for (size_t d = 0; d < mDisplays.size(); d++) {
- const sp<const DisplayDevice>& displayDevice(mDisplays[d]);
- int32_t hwcId = displayDevice->getHwcDisplayId();
- if (hwcId == DisplayDevice::DISPLAY_ID_INVALID) {
+ for (const auto& [token, display] : mDisplays) {
+ const int32_t displayId = display->getId();
+ if (displayId == DisplayDevice::DISPLAY_ID_INVALID) {
continue;
}
- result.appendFormat("Display %d HWC layers:\n", hwcId);
+ result.appendFormat("Display %d HWC layers:\n", displayId);
Layer::miniDumpHeader(result);
- mCurrentState.traverseInZOrder([&](Layer* layer) {
- layer->miniDump(result, hwcId);
- });
+ mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, displayId); });
result.append("\n");
}
@@ -4367,22 +4330,17 @@
}
}
-const Vector< sp<Layer> >&
-SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) {
+const Vector<sp<Layer>>& SurfaceFlinger::getLayerSortedByZForHwcDisplay(int32_t displayId) {
// Note: mStateLock is held here
- wp<IBinder> dpy;
- for (size_t i=0 ; i<mDisplays.size() ; i++) {
- if (mDisplays.valueAt(i)->getHwcDisplayId() == id) {
- dpy = mDisplays.keyAt(i);
- break;
+ for (const auto& [token, display] : mDisplays) {
+ if (display->getId() == displayId) {
+ return getDisplayDeviceLocked(token)->getVisibleLayersSortedByZ();
}
}
- if (dpy == nullptr) {
- ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
- // Just use the primary display so we have something to return
- dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
- }
- return getDisplayDeviceLocked(dpy)->getVisibleLayersSortedByZ();
+
+ ALOGE("%s: Invalid display %d", __FUNCTION__, displayId);
+ static const Vector<sp<Layer>> empty;
+ return empty;
}
bool SurfaceFlinger::startDdmConnection()
@@ -4556,8 +4514,12 @@
reply->writeInt32(mDebugDisableHWC);
return NO_ERROR;
case 1013: {
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- reply->writeInt32(hw->getPageFlipCount());
+ const auto display = getDefaultDisplayDevice();
+ if (!display) {
+ return NAME_NOT_FOUND;
+ }
+
+ reply->writeInt32(display->getPageFlipCount());
return NO_ERROR;
}
case 1014: {
@@ -4688,8 +4650,8 @@
}
// Is a DisplayColorSetting supported?
case 1027: {
- sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- if (!hw) {
+ const auto display = getDefaultDisplayDevice();
+ if (!display) {
return NAME_NOT_FOUND;
}
@@ -4702,14 +4664,21 @@
reply->writeBool(true);
break;
case DisplayColorSetting::ENHANCED:
- reply->writeBool(hw->hasRenderIntent(RenderIntent::ENHANCE));
+ reply->writeBool(display->hasRenderIntent(RenderIntent::ENHANCE));
break;
default: // vendor display color setting
- reply->writeBool(hw->hasRenderIntent(static_cast<RenderIntent>(setting)));
+ reply->writeBool(
+ display->hasRenderIntent(static_cast<RenderIntent>(setting)));
break;
}
return NO_ERROR;
}
+ // Is VrFlinger active?
+ case 1028: {
+ Mutex::Autolock _l(mStateLock);
+ reply->writeBool(getBE().mHwc->isUsingVrComposer());
+ return NO_ERROR;
+ }
}
}
return err;
@@ -4733,22 +4702,22 @@
const int mApi;
};
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& displayToken,
+ sp<GraphicBuffer>* outBuffer, Rect sourceCrop,
+ uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
+ int32_t maxLayerZ, bool useIdentityTransform,
ISurfaceComposer::Rotation rotation) {
ATRACE_CALL();
- if (CC_UNLIKELY(display == 0)) return BAD_VALUE;
+ if (!displayToken) return BAD_VALUE;
- const sp<const DisplayDevice> device(getDisplayDeviceLocked(display));
- if (CC_UNLIKELY(device == 0)) return BAD_VALUE;
+ const auto display = getDisplayDeviceLocked(displayToken);
+ if (!display) return BAD_VALUE;
- DisplayRenderArea renderArea(device, sourceCrop, reqHeight, reqWidth, rotation);
+ DisplayRenderArea renderArea(display, sourceCrop, reqHeight, reqWidth, rotation);
auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
- device, minLayerZ, maxLayerZ, std::placeholders::_1);
+ display, minLayerZ, maxLayerZ, std::placeholders::_1);
return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform);
}
@@ -4890,7 +4859,7 @@
const int uid = IPCThreadState::self()->getCallingUid();
const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
- sp<LambdaMessage> message = new LambdaMessage([&]() {
+ sp<LambdaMessage> message = new LambdaMessage([&] {
// If there is a refresh pending, bug out early and tell the binder thread to try again
// after the refresh.
if (mRefreshPending) {
@@ -4905,7 +4874,7 @@
int fd = -1;
{
Mutex::Autolock _l(mStateLock);
- renderArea.render([&]() {
+ renderArea.render([&] {
result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
useIdentityTransform, forSystem, &fd);
});
@@ -4921,14 +4890,14 @@
status_t result = postMessageAsync(message);
if (result == NO_ERROR) {
- captureCondition.wait(captureLock, [&]() { return captureResult; });
+ captureCondition.wait(captureLock, [&] { return captureResult; });
while (*captureResult == EAGAIN) {
captureResult.reset();
result = postMessageAsync(message);
if (result != NO_ERROR) {
return result;
}
- captureCondition.wait(captureLock, [&]() { return captureResult; });
+ captureCondition.wait(captureLock, [&] { return captureResult; });
}
result = *captureResult;
}
@@ -5146,13 +5115,13 @@
layersSortedByZ.traverseInReverseZOrder(stateSet, visitor);
}
-void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& hw, int32_t minLayerZ,
- int32_t maxLayerZ,
+void SurfaceFlinger::traverseLayersInDisplay(const sp<const DisplayDevice>& display,
+ int32_t minLayerZ, int32_t maxLayerZ,
const LayerVector::Visitor& visitor) {
// We loop through the first level of layers without traversing,
// as we need to interpret min/max layer Z in the top level Z space.
for (const auto& layer : mDrawingState.layersSortedByZ) {
- if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
+ if (!layer->belongsToDisplay(display->getLayerStack(), false)) {
continue;
}
const Layer::State& state(layer->getDrawingState());
@@ -5161,7 +5130,7 @@
continue;
}
layer->traverseInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
- if (!layer->belongsToDisplay(hw->getLayerStack(), false)) {
+ if (!layer->belongsToDisplay(display->getLayerStack(), false)) {
return;
}
if (!layer->isVisible()) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8566b03..87e0699 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -45,6 +45,7 @@
#include <gui/LayerState.h>
#include <gui/OccupancyTracker.h>
+#include <gui/BufferQueue.h>
#include <hardware/hwcomposer_defs.h>
@@ -64,6 +65,7 @@
#include "SurfaceTracing.h"
#include "StartPropertySetThread.h"
#include "TimeStats/TimeStats.h"
+#include "LayerBE.h"
#include "VSyncModulator.h"
#include "DisplayHardware/HWC2.h"
@@ -406,7 +408,7 @@
virtual sp<ISurfaceComposerClient> createConnection();
virtual sp<ISurfaceComposerClient> createScopedConnection(const sp<IGraphicBufferProducer>& gbp);
virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
- virtual void destroyDisplay(const sp<IBinder>& display);
+ virtual void destroyDisplay(const sp<IBinder>& displayToken);
virtual sp<IBinder> getBuiltInDisplay(int32_t id);
virtual void setTransactionState(const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags);
@@ -417,27 +419,26 @@
std::vector<FrameEvent>* outSupported) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
- virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
+ virtual status_t captureScreen(const sp<IBinder>& displayToken, sp<GraphicBuffer>* outBuffer,
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
ISurfaceComposer::Rotation rotation);
virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
const Rect& sourceCrop, float frameScale, bool childrenOnly);
- virtual status_t getDisplayStats(const sp<IBinder>& display,
- DisplayStatInfo* stats);
- 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<ui::ColorMode>* configs);
- virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& display);
- virtual status_t setActiveColorMode(const sp<IBinder>& display, ui::ColorMode colorMode);
- virtual void setPowerMode(const sp<IBinder>& display, int mode);
- virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
+ virtual status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats);
+ virtual status_t getDisplayConfigs(const sp<IBinder>& displayToken,
+ Vector<DisplayInfo>* configs);
+ virtual int getActiveConfig(const sp<IBinder>& displayToken);
+ virtual status_t getDisplayColorModes(const sp<IBinder>& displayToken,
+ Vector<ui::ColorMode>* configs);
+ virtual ui::ColorMode getActiveColorMode(const sp<IBinder>& displayToken);
+ virtual status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
+ virtual void setPowerMode(const sp<IBinder>& displayToken, int mode);
+ virtual status_t setActiveConfig(const sp<IBinder>& displayToken, int id);
virtual status_t clearAnimationFrameStats();
virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
- virtual status_t getHdrCapabilities(const sp<IBinder>& display,
- HdrCapabilities* outCapabilities) const;
+ virtual status_t getHdrCapabilities(const sp<IBinder>& displayToken,
+ HdrCapabilities* outCapabilities) const;
virtual status_t enableVSyncInjections(bool enable);
virtual status_t injectVSync(nsecs_t when);
virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) const;
@@ -456,11 +457,11 @@
/* ------------------------------------------------------------------------
* HWC2::ComposerCallback / HWComposer::EventHandler interface
*/
- void onVsyncReceived(int32_t sequenceId, hwc2_display_t display,
+ void onVsyncReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
int64_t timestamp) override;
- void onHotplugReceived(int32_t sequenceId, hwc2_display_t display,
+ void onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId,
HWC2::Connection connection) override;
- void onRefreshReceived(int32_t sequenceId, hwc2_display_t display) override;
+ void onRefreshReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId) override;
/* ------------------------------------------------------------------------
* Message handling
@@ -475,16 +476,13 @@
// called on the main thread in response to initializeDisplays()
void onInitializeDisplays();
// called on the main thread in response to setActiveConfig()
- void setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode);
+ void setActiveConfigInternal(const sp<DisplayDevice>& display, int mode);
// called on the main thread in response to setPowerMode()
- void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode,
- bool stateLockHeld);
+ void setPowerModeInternal(const sp<DisplayDevice>& display, int mode, bool stateLockHeld);
// Called on the main thread in response to setActiveColorMode()
- void setActiveColorModeInternal(const sp<DisplayDevice>& hw,
- ui::ColorMode colorMode,
- ui::Dataspace dataSpace,
- ui::RenderIntent renderIntent);
+ void setActiveColorModeInternal(const sp<DisplayDevice>& display, ui::ColorMode colorMode,
+ ui::Dataspace dataSpace, ui::RenderIntent renderIntent);
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
@@ -595,38 +593,33 @@
// called when starting, or restarting after system_server death
void initializeDisplays();
- sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) const {
- Mutex::Autolock _l(mStateLock);
- return getDisplayDeviceLocked(dpy);
+ sp<const DisplayDevice> getDisplayDevice(const wp<IBinder>& displayToken) const {
+ Mutex::Autolock _l(mStateLock);
+ return getDisplayDeviceLocked(displayToken);
}
- sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& dpy) {
- Mutex::Autolock _l(mStateLock);
- return getDisplayDeviceLocked(dpy);
+ sp<DisplayDevice> getDisplayDevice(const wp<IBinder>& displayToken) {
+ Mutex::Autolock _l(mStateLock);
+ return getDisplayDeviceLocked(displayToken);
}
// NOTE: can only be called from the main thread or with mStateLock held
- sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) const {
- return mDisplays.valueFor(dpy);
+ sp<const DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) const {
+ return const_cast<SurfaceFlinger*>(this)->getDisplayDeviceLocked(displayToken);
}
// NOTE: can only be called from the main thread or with mStateLock held
- sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& dpy) {
- return mDisplays.valueFor(dpy);
+ sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) {
+ const auto it = mDisplays.find(displayToken);
+ return it == mDisplays.end() ? nullptr : it->second;
}
sp<const DisplayDevice> getDefaultDisplayDeviceLocked() const {
- return getDisplayDeviceLocked(mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY]);
+ return const_cast<SurfaceFlinger*>(this)->getDefaultDisplayDeviceLocked();
}
- 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;
+ sp<DisplayDevice> getDefaultDisplayDeviceLocked() {
+ return getDisplayDeviceLocked(mDisplayTokens[DisplayDevice::DISPLAY_PRIMARY]);
}
// mark a region of a layer stack dirty. this updates the dirty
@@ -643,8 +636,8 @@
* Compositing
*/
void invalidateHwcGeometry();
- void computeVisibleRegions(const sp<const DisplayDevice>& displayDevice,
- Region& dirtyRegion, Region& opaqueRegion);
+ void computeVisibleRegions(const sp<const DisplayDevice>& display, Region& dirtyRegion,
+ Region& opaqueRegion);
void preComposition(nsecs_t refreshStartTime);
void postComposition(nsecs_t refreshStartTime);
@@ -656,37 +649,35 @@
nsecs_t compositeToPresentLatency);
void rebuildLayerStacks();
- ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& displayDevice,
+ ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& display,
ui::Dataspace* outHdrDataSpace) const;
// Returns the appropriate ColorMode, Dataspace and RenderIntent for the
// DisplayDevice. The function only returns the supported ColorMode,
// Dataspace and RenderIntent.
- void pickColorMode(const sp<DisplayDevice>& displayDevice,
- ui::ColorMode* outMode,
- ui::Dataspace* outDataSpace,
- ui::RenderIntent* outRenderIntent) const;
+ void pickColorMode(const sp<DisplayDevice>& display, ui::ColorMode* outMode,
+ ui::Dataspace* outDataSpace, ui::RenderIntent* outRenderIntent) const;
void setUpHWComposer();
void doComposition();
void doDebugFlashRegions();
void doTracing(const char* where);
void logLayerStats();
- void doDisplayComposition(const sp<const DisplayDevice>& displayDevice, const Region& dirtyRegion);
+ void doDisplayComposition(const sp<const DisplayDevice>& display, const Region& dirtyRegion);
- // compose surfaces for display hw. this fails if using GL and the surface
- // has been destroyed and is no longer valid.
- bool doComposeSurfaces(const sp<const DisplayDevice>& displayDevice);
+ // This fails if using GL and the surface has been destroyed.
+ bool doComposeSurfaces(const sp<const DisplayDevice>& display);
void postFramebuffer();
- void drawWormhole(const sp<const DisplayDevice>& displayDevice, const Region& region) const;
+ void drawWormhole(const sp<const DisplayDevice>& display, const Region& region) const;
/* ------------------------------------------------------------------------
* Display management
*/
- DisplayDevice::DisplayType determineDisplayType(hwc2_display_t display,
- HWC2::Connection connection) const;
- sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId,
+ DisplayDevice::DisplayType determineDisplayType(hwc2_display_t hwcDisplayId,
+ HWC2::Connection connection) const;
+ sp<DisplayDevice> setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken,
+ int32_t displayId,
const DisplayDeviceState& state,
const sp<DisplaySurface>& dispSurface,
const sp<IGraphicBufferProducer>& producer);
@@ -736,9 +727,10 @@
void recordBufferingStats(const char* layerName,
std::vector<OccupancyTracker::Segment>&& history);
void dumpBufferingStats(String8& result) const;
+ void dumpDisplayIdentificationData(String8& result) const;
void dumpWideColorInfo(String8& result) const;
LayersProto dumpProtoInfo(LayerVector::StateSet stateSet) const;
- LayersProto dumpVisibleLayersProtoInfo(int32_t hwcId) const;
+ LayersProto dumpVisibleLayersProtoInfo(const DisplayDevice& display) const;
bool isLayerTripleBufferingDisabled() const {
return this->mLayerTripleBufferingDisabled;
@@ -794,7 +786,7 @@
std::unique_ptr<VSyncSource> mSfEventThreadSource;
std::unique_ptr<InjectVSyncSource> mVSyncInjector;
std::unique_ptr<EventControlThread> mEventControlThread;
- sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
+ sp<IBinder> mDisplayTokens[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];
VSyncModulator mVsyncModulator;
@@ -809,7 +801,7 @@
bool mHadClientComposition = false;
struct HotplugEvent {
- hwc2_display_t display;
+ hwc2_display_t hwcDisplayId;
HWC2::Connection connection = HWC2::Connection::Invalid;
};
// protected by mStateLock
@@ -817,7 +809,7 @@
// this may only be written from the main thread with mStateLock held
// it may be read from other threads with mStateLock held
- DefaultKeyedVector< wp<IBinder>, sp<DisplayDevice> > mDisplays;
+ std::map<wp<IBinder>, sp<DisplayDevice>> mDisplays;
// don't use a lock for these, we don't care
int mDebugRegion;
@@ -837,6 +829,7 @@
LayerStats mLayerStats;
TimeStats& mTimeStats = TimeStats::getInstance();
bool mUseHwcVirtualDisplays = false;
+ std::atomic<uint32_t> mFrameMissedCount{0};
// Restrict layers to use two buffers in their bufferqueues.
bool mLayerTripleBufferingDisabled = false;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 4596a21..e70506d 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -122,10 +122,10 @@
transaction->set_synchronous(false);
transaction->set_animation(false);
- addDisplaySurfaceLocked(transaction, display.displayId, display.surface);
- addDisplayLayerStackLocked(transaction, display.displayId, display.layerStack);
- addDisplaySizeLocked(transaction, display.displayId, display.width, display.height);
- addDisplayProjectionLocked(transaction, display.displayId, display.orientation,
+ addDisplaySurfaceLocked(transaction, display.sequenceId, display.surface);
+ addDisplayLayerStackLocked(transaction, display.sequenceId, display.layerStack);
+ addDisplaySizeLocked(transaction, display.sequenceId, display.width, display.height);
+ addDisplayProjectionLocked(transaction, display.sequenceId, display.orientation,
display.viewport, display.frame);
}
@@ -177,10 +177,10 @@
}
DisplayChange* SurfaceInterceptor::createDisplayChangeLocked(Transaction* transaction,
- int32_t displayId)
+ int32_t sequenceId)
{
DisplayChange* dispChange(transaction->add_display_change());
- dispChange->set_id(displayId);
+ dispChange->set_id(sequenceId);
return dispChange;
}
@@ -379,19 +379,19 @@
}
void SurfaceInterceptor::addDisplayChangesLocked(Transaction* transaction,
- const DisplayState& state, int32_t displayId)
+ const DisplayState& state, int32_t sequenceId)
{
if (state.what & DisplayState::eSurfaceChanged) {
- addDisplaySurfaceLocked(transaction, displayId, state.surface);
+ addDisplaySurfaceLocked(transaction, sequenceId, state.surface);
}
if (state.what & DisplayState::eLayerStackChanged) {
- addDisplayLayerStackLocked(transaction, displayId, state.layerStack);
+ addDisplayLayerStackLocked(transaction, sequenceId, state.layerStack);
}
if (state.what & DisplayState::eDisplaySizeChanged) {
- addDisplaySizeLocked(transaction, displayId, state.width, state.height);
+ addDisplaySizeLocked(transaction, sequenceId, state.width, state.height);
}
if (state.what & DisplayState::eDisplayProjectionChanged) {
- addDisplayProjectionLocked(transaction, displayId, state.orientation, state.viewport,
+ addDisplayProjectionLocked(transaction, sequenceId, state.orientation, state.viewport,
state.frame);
}
}
@@ -411,7 +411,7 @@
ssize_t dpyIdx = displays.indexOfKey(disp.token);
if (dpyIdx >= 0) {
const DisplayDeviceState& dispState(displays.valueAt(dpyIdx));
- addDisplayChangesLocked(transaction, disp, dispState.displayId);
+ addDisplayChangesLocked(transaction, disp, dispState.sequenceId);
}
}
}
@@ -448,7 +448,7 @@
event->set_when(timestamp);
}
-void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId,
+void SurfaceInterceptor::addDisplaySurfaceLocked(Transaction* transaction, int32_t sequenceId,
const sp<const IGraphicBufferProducer>& surface)
{
if (surface == nullptr) {
@@ -457,7 +457,7 @@
uint64_t bufferQueueId = 0;
status_t err(surface->getUniqueId(&bufferQueueId));
if (err == NO_ERROR) {
- DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId));
DispSurfaceChange* surfaceChange(dispChange->mutable_surface());
surfaceChange->set_buffer_queue_id(bufferQueueId);
surfaceChange->set_buffer_queue_name(surface->getConsumerName().string());
@@ -469,26 +469,26 @@
}
void SurfaceInterceptor::addDisplayLayerStackLocked(Transaction* transaction,
- int32_t displayId, uint32_t layerStack)
+ int32_t sequenceId, uint32_t layerStack)
{
- DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId));
LayerStackChange* layerStackChange(dispChange->mutable_layer_stack());
layerStackChange->set_layer_stack(layerStack);
}
-void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t displayId,
+void SurfaceInterceptor::addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId,
uint32_t w, uint32_t h)
{
- DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId));
SizeChange* sizeChange(dispChange->mutable_size());
sizeChange->set_w(w);
sizeChange->set_h(h);
}
void SurfaceInterceptor::addDisplayProjectionLocked(Transaction* transaction,
- int32_t displayId, int32_t orientation, const Rect& viewport, const Rect& frame)
+ int32_t sequenceId, int32_t orientation, const Rect& viewport, const Rect& frame)
{
- DisplayChange* dispChange(createDisplayChangeLocked(transaction, displayId));
+ DisplayChange* dispChange(createDisplayChangeLocked(transaction, sequenceId));
ProjectionChange* projectionChange(dispChange->mutable_projection());
projectionChange->set_orientation(orientation);
Rectangle* viewportRect(projectionChange->mutable_viewport());
@@ -501,22 +501,22 @@
const DisplayDeviceState& info)
{
DisplayCreation* creation(increment->mutable_display_creation());
- creation->set_id(info.displayId);
+ creation->set_id(info.sequenceId);
creation->set_name(info.displayName);
creation->set_type(info.type);
creation->set_is_secure(info.isSecure);
}
-void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t displayId) {
+void SurfaceInterceptor::addDisplayDeletionLocked(Increment* increment, int32_t sequenceId) {
DisplayDeletion* deletion(increment->mutable_display_deletion());
- deletion->set_id(displayId);
+ deletion->set_id(sequenceId);
}
-void SurfaceInterceptor::addPowerModeUpdateLocked(Increment* increment, int32_t displayId,
+void SurfaceInterceptor::addPowerModeUpdateLocked(Increment* increment, int32_t sequenceId,
int32_t mode)
{
PowerModeUpdate* powerModeUpdate(increment->mutable_power_mode_update());
- powerModeUpdate->set_id(displayId);
+ powerModeUpdate->set_id(sequenceId);
powerModeUpdate->set_mode(mode);
}
@@ -579,22 +579,22 @@
addDisplayCreationLocked(createTraceIncrementLocked(), info);
}
-void SurfaceInterceptor::saveDisplayDeletion(int32_t displayId) {
+void SurfaceInterceptor::saveDisplayDeletion(int32_t sequenceId) {
if (!mEnabled) {
return;
}
ATRACE_CALL();
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addDisplayDeletionLocked(createTraceIncrementLocked(), displayId);
+ addDisplayDeletionLocked(createTraceIncrementLocked(), sequenceId);
}
-void SurfaceInterceptor::savePowerModeUpdate(int32_t displayId, int32_t mode) {
+void SurfaceInterceptor::savePowerModeUpdate(int32_t sequenceId, int32_t mode) {
if (!mEnabled) {
return;
}
ATRACE_CALL();
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
- addPowerModeUpdateLocked(createTraceIncrementLocked(), displayId, mode);
+ addPowerModeUpdateLocked(createTraceIncrementLocked(), sequenceId, mode);
}
} // namespace impl
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 96defcc..218a1d2 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -66,8 +66,8 @@
// Intercept display data
virtual void saveDisplayCreation(const DisplayDeviceState& info) = 0;
- virtual void saveDisplayDeletion(int32_t displayId) = 0;
- virtual void savePowerModeUpdate(int32_t displayId, int32_t mode) = 0;
+ virtual void saveDisplayDeletion(int32_t sequenceId) = 0;
+ virtual void savePowerModeUpdate(int32_t sequenceId, int32_t mode) = 0;
virtual void saveVSyncEvent(nsecs_t timestamp) = 0;
};
@@ -101,8 +101,8 @@
// Intercept display data
void saveDisplayCreation(const DisplayDeviceState& info) override;
- void saveDisplayDeletion(int32_t displayId) override;
- void savePowerModeUpdate(int32_t displayId, int32_t mode) override;
+ void saveDisplayDeletion(int32_t sequenceId) override;
+ void savePowerModeUpdate(int32_t sequenceId, int32_t mode) override;
void saveVSyncEvent(nsecs_t timestamp) override;
private:
@@ -127,8 +127,8 @@
uint32_t height, uint64_t frameNumber);
void addVSyncUpdateLocked(Increment* increment, nsecs_t timestamp);
void addDisplayCreationLocked(Increment* increment, const DisplayDeviceState& info);
- void addDisplayDeletionLocked(Increment* increment, int32_t displayId);
- void addPowerModeUpdateLocked(Increment* increment, int32_t displayId, int32_t mode);
+ void addDisplayDeletionLocked(Increment* increment, int32_t sequenceId);
+ void addPowerModeUpdateLocked(Increment* increment, int32_t sequenceId, int32_t mode);
// Add surface transactions to the trace
SurfaceChange* createSurfaceChangeLocked(Transaction* transaction, int32_t layerId);
@@ -155,17 +155,17 @@
const Vector<DisplayState>& changedDisplays, uint32_t transactionFlags);
// Add display transactions to the trace
- DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t displayId);
- void addDisplaySurfaceLocked(Transaction* transaction, int32_t displayId,
+ DisplayChange* createDisplayChangeLocked(Transaction* transaction, int32_t sequenceId);
+ void addDisplaySurfaceLocked(Transaction* transaction, int32_t sequenceId,
const sp<const IGraphicBufferProducer>& surface);
- void addDisplayLayerStackLocked(Transaction* transaction, int32_t displayId,
+ void addDisplayLayerStackLocked(Transaction* transaction, int32_t sequenceId,
uint32_t layerStack);
- void addDisplaySizeLocked(Transaction* transaction, int32_t displayId, uint32_t w,
+ void addDisplaySizeLocked(Transaction* transaction, int32_t sequenceId, uint32_t w,
uint32_t h);
- void addDisplayProjectionLocked(Transaction* transaction, int32_t displayId,
+ void addDisplayProjectionLocked(Transaction* transaction, int32_t sequenceId,
int32_t orientation, const Rect& viewport, const Rect& frame);
void addDisplayChangesLocked(Transaction* transaction,
- const DisplayState& state, int32_t displayId);
+ const DisplayState& state, int32_t sequenceId);
bool mEnabled {false};
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index f8c466e..0e9b04e 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -58,7 +58,9 @@
void SurfaceTracing::traceLayers(const char* where, LayersProto layers) {
std::lock_guard<std::mutex> protoGuard(mTraceMutex);
-
+ if (!mEnabled) {
+ return;
+ }
LayersTraceProto* entry = mTrace.add_entry();
entry->set_elapsed_realtime_nanos(elapsedRealtimeNano());
entry->set_where(where);
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index d4f1e29..d7a2886 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -109,7 +109,7 @@
bool TimeStats::recordReadyLocked(const std::string& layerName, TimeRecord* timeRecord) {
if (!timeRecord->ready) {
ALOGV("[%s]-[%" PRIu64 "]-presentFence is still not received", layerName.c_str(),
- timeRecord->frameNumber);
+ timeRecord->frameTime.frameNumber);
return false;
}
@@ -118,11 +118,11 @@
return false;
}
if (timeRecord->acquireFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) {
- timeRecord->acquireTime = timeRecord->acquireFence->getSignalTime();
+ timeRecord->frameTime.acquireTime = timeRecord->acquireFence->getSignalTime();
timeRecord->acquireFence = nullptr;
} else {
ALOGV("[%s]-[%" PRIu64 "]-acquireFence signal time is invalid", layerName.c_str(),
- timeRecord->frameNumber);
+ timeRecord->frameTime.frameNumber);
}
}
@@ -131,11 +131,11 @@
return false;
}
if (timeRecord->presentFence->getSignalTime() != Fence::SIGNAL_TIME_INVALID) {
- timeRecord->presentTime = timeRecord->presentFence->getSignalTime();
+ timeRecord->frameTime.presentTime = timeRecord->presentFence->getSignalTime();
timeRecord->presentFence = nullptr;
} else {
ALOGV("[%s]-[%" PRIu64 "]-presentFence signal time invalid", layerName.c_str(),
- timeRecord->frameNumber);
+ timeRecord->frameTime.frameNumber);
}
}
@@ -172,7 +172,7 @@
while (!timeRecords.empty()) {
if (!recordReadyLocked(layerName, &timeRecords[0])) break;
ALOGV("[%s]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerName.c_str(),
- timeRecords[0].frameNumber, timeRecords[0].presentTime);
+ timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime);
if (prevTimeRecord.ready) {
if (!timeStats.stats.count(layerName)) {
@@ -183,34 +183,34 @@
TimeStatsHelper::TimeStatsLayer& timeStatsLayer = timeStats.stats[layerName];
timeStatsLayer.totalFrames++;
- const int32_t postToPresentMs =
- msBetween(timeRecords[0].postTime, timeRecords[0].presentTime);
+ const int32_t postToPresentMs = msBetween(timeRecords[0].frameTime.postTime,
+ timeRecords[0].frameTime.presentTime);
ALOGV("[%s]-[%" PRIu64 "]-post2present[%d]", layerName.c_str(),
- timeRecords[0].frameNumber, postToPresentMs);
+ timeRecords[0].frameTime.frameNumber, postToPresentMs);
timeStatsLayer.deltas["post2present"].insert(postToPresentMs);
- const int32_t acquireToPresentMs =
- msBetween(timeRecords[0].acquireTime, timeRecords[0].presentTime);
+ const int32_t acquireToPresentMs = msBetween(timeRecords[0].frameTime.acquireTime,
+ timeRecords[0].frameTime.presentTime);
ALOGV("[%s]-[%" PRIu64 "]-acquire2present[%d]", layerName.c_str(),
- timeRecords[0].frameNumber, acquireToPresentMs);
+ timeRecords[0].frameTime.frameNumber, acquireToPresentMs);
timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs);
- const int32_t latchToPresentMs =
- msBetween(timeRecords[0].latchTime, timeRecords[0].presentTime);
+ const int32_t latchToPresentMs = msBetween(timeRecords[0].frameTime.latchTime,
+ timeRecords[0].frameTime.presentTime);
ALOGV("[%s]-[%" PRIu64 "]-latch2present[%d]", layerName.c_str(),
- timeRecords[0].frameNumber, latchToPresentMs);
+ timeRecords[0].frameTime.frameNumber, latchToPresentMs);
timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs);
- const int32_t desiredToPresentMs =
- msBetween(timeRecords[0].desiredTime, timeRecords[0].presentTime);
+ const int32_t desiredToPresentMs = msBetween(timeRecords[0].frameTime.desiredTime,
+ timeRecords[0].frameTime.presentTime);
ALOGV("[%s]-[%" PRIu64 "]-desired2present[%d]", layerName.c_str(),
- timeRecords[0].frameNumber, desiredToPresentMs);
+ timeRecords[0].frameTime.frameNumber, desiredToPresentMs);
timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs);
- const int32_t presentToPresentMs =
- msBetween(prevTimeRecord.presentTime, timeRecords[0].presentTime);
+ const int32_t presentToPresentMs = msBetween(prevTimeRecord.frameTime.presentTime,
+ timeRecords[0].frameTime.presentTime);
ALOGV("[%s]-[%" PRIu64 "]-present2present[%d]", layerName.c_str(),
- timeRecords[0].frameNumber, presentToPresentMs);
+ timeRecords[0].frameTime.frameNumber, presentToPresentMs);
timeStatsLayer.deltas["present2present"].insert(presentToPresentMs);
timeStats.stats[layerName].statsEnd = static_cast<int64_t>(std::time(0));
@@ -225,12 +225,12 @@
// This regular expression captures the following layer names for instance:
// 1) StatusBat#0
// 2) NavigationBar#1
- // 3) com.*#0
- // 4) SurfaceView - com.*#0
- // Using [-\\s\t]+ for the conjunction part between SurfaceView and com.* is
- // a bit more robust in case there's a slight change.
+ // 3) co(m).*#0
+ // 4) SurfaceView - co(m).*#0
+ // Using [-\\s\t]+ for the conjunction part between SurfaceView and co(m).*
+ // is a bit more robust in case there's a slight change.
// The layer name would only consist of . / $ _ 0-9 a-z A-Z in most cases.
- std::regex re("(((SurfaceView[-\\s\\t]+)?com\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+");
+ std::regex re("(((SurfaceView[-\\s\\t]+)?com?\\.[./$\\w]+)|((Status|Navigation)Bar))#\\d+");
return std::regex_match(layerName.begin(), layerName.end(), re);
}
@@ -257,9 +257,12 @@
// ready at the queueBuffer stage. In this case, acquireTime should be given
// a default value as postTime.
TimeRecord timeRecord = {
- .frameNumber = frameNumber,
- .postTime = postTime,
- .acquireTime = postTime,
+ .frameTime =
+ {
+ .frameNumber = frameNumber,
+ .postTime = postTime,
+ .acquireTime = postTime,
+ },
};
layerRecord.timeRecords.push_back(timeRecord);
if (layerRecord.waitData < 0 ||
@@ -278,8 +281,8 @@
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
- if (timeRecord.frameNumber == frameNumber) {
- timeRecord.latchTime = latchTime;
+ if (timeRecord.frameTime.frameNumber == frameNumber) {
+ timeRecord.frameTime.latchTime = latchTime;
}
}
@@ -295,8 +298,8 @@
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
- if (timeRecord.frameNumber == frameNumber) {
- timeRecord.desiredTime = desiredTime;
+ if (timeRecord.frameTime.frameNumber == frameNumber) {
+ timeRecord.frameTime.desiredTime = desiredTime;
}
}
@@ -312,8 +315,8 @@
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
- if (timeRecord.frameNumber == frameNumber) {
- timeRecord.acquireTime = acquireTime;
+ if (timeRecord.frameTime.frameNumber == frameNumber) {
+ timeRecord.frameTime.acquireTime = acquireTime;
}
}
@@ -329,7 +332,7 @@
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
- if (timeRecord.frameNumber == frameNumber) {
+ if (timeRecord.frameTime.frameNumber == frameNumber) {
timeRecord.acquireFence = acquireFence;
}
}
@@ -346,8 +349,8 @@
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
- if (timeRecord.frameNumber == frameNumber) {
- timeRecord.presentTime = presentTime;
+ if (timeRecord.frameTime.frameNumber == frameNumber) {
+ timeRecord.frameTime.presentTime = presentTime;
timeRecord.ready = true;
layerRecord.waitData++;
}
@@ -367,7 +370,7 @@
if (!timeStatsTracker.count(layerName)) return;
LayerRecord& layerRecord = timeStatsTracker[layerName];
TimeRecord& timeRecord = layerRecord.timeRecords[layerRecord.waitData];
- if (timeRecord.frameNumber == frameNumber) {
+ if (timeRecord.frameTime.frameNumber == frameNumber) {
timeRecord.presentFence = presentFence;
timeRecord.ready = true;
layerRecord.waitData++;
@@ -413,7 +416,7 @@
LayerRecord& layerRecord = timeStatsTracker[layerName];
size_t removeAt = 0;
for (const TimeRecord& record : layerRecord.timeRecords) {
- if (record.frameNumber == frameNumber) break;
+ if (record.frameTime.frameNumber == frameNumber) break;
removeAt++;
}
if (removeAt == layerRecord.timeRecords.size()) return;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 8318210..0b1f82e 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -40,14 +40,18 @@
// static const size_t MAX_NUM_LAYER_RECORDS = 200;
static const size_t MAX_NUM_TIME_RECORDS = 64;
- struct TimeRecord {
- bool ready = false;
+ struct FrameTime {
uint64_t frameNumber = 0;
nsecs_t postTime = 0;
nsecs_t latchTime = 0;
nsecs_t acquireTime = 0;
nsecs_t desiredTime = 0;
nsecs_t presentTime = 0;
+ };
+
+ struct TimeRecord {
+ bool ready = false;
+ FrameTime frameTime;
std::shared_ptr<FenceTime> acquireFence;
std::shared_ptr<FenceTime> presentFence;
};
diff --git a/services/surfaceflinger/layerproto/LayerProtoParser.cpp b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
index fcf42f0..e1c0fd3 100644
--- a/services/surfaceflinger/layerproto/LayerProtoParser.cpp
+++ b/services/surfaceflinger/layerproto/LayerProtoParser.cpp
@@ -114,6 +114,7 @@
layer->transform = generateTransform(layerProto.transform());
layer->requestedTransform = generateTransform(layerProto.requested_transform());
layer->activeBuffer = generateActiveBuffer(layerProto.active_buffer());
+ layer->bufferTransform = generateTransform(layerProto.buffer_transform());
layer->queuedFrames = layerProto.queued_frames();
layer->refreshPending = layerProto.refresh_pending();
layer->hwcFrame = generateRect(layerProto.hwc_frame());
@@ -312,6 +313,7 @@
StringAppendF(&result, " zOrderRelativeOf=%s\n",
zOrderRelativeOf == nullptr ? "none" : zOrderRelativeOf->name.c_str());
StringAppendF(&result, " activeBuffer=%s,", activeBuffer.to_string().c_str());
+ StringAppendF(&result, " tr=%s", bufferTransform.to_string().c_str());
StringAppendF(&result, " queued-frames=%d, mRefreshPending=%d,", queuedFrames, refreshPending);
StringAppendF(&result, " windowType=%d, appId=%d", windowType, appId);
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 74a6f28..360e599 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -105,6 +105,7 @@
Layer* parent = 0;
Layer* zOrderRelativeOf = 0;
LayerProtoParser::ActiveBuffer activeBuffer;
+ Transform bufferTransform;
int32_t queuedFrames;
bool refreshPending;
LayerProtoParser::Rect hwcFrame;
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 77c6675..eb34694 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -80,6 +80,8 @@
optional int32 hwc_composition_type = 35;
// If it's a buffer layer, indicate if the content is protected
optional bool is_protected = 36;
+ // If active_buffer is not null, record its transform
+ optional TransformProto buffer_transform = 37;
}
message PositionProto {
diff --git a/services/surfaceflinger/tests/SurfaceFlinger_test.filter b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
index 36424b9..df0c521 100644
--- a/services/surfaceflinger/tests/SurfaceFlinger_test.filter
+++ b/services/surfaceflinger/tests/SurfaceFlinger_test.filter
@@ -1,5 +1,5 @@
{
"presubmit": {
- "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*"
+ "filter": "LayerTransactionTest.*:LayerUpdateTest.*:ChildLayerTest.*:SurfaceFlingerStress.*:CropLatchingTest.*:GeometryLatchingTest.*:ScreenCaptureTest.*:DereferenceSurfaceControlTest.*:SurfaceInterceptorTest.*"
}
}
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index de78c3f..135d2af 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -42,13 +42,16 @@
constexpr uint32_t LAYER_UPDATE = INT_MAX - 2;
constexpr uint32_t SIZE_UPDATE = 134;
constexpr uint32_t STACK_UPDATE = 1;
-constexpr uint64_t DEFERRED_UPDATE = 13;
+constexpr uint64_t DEFERRED_UPDATE = 0;
constexpr float ALPHA_UPDATE = 0.29f;
constexpr float POSITION_UPDATE = 121;
const Rect CROP_UPDATE(16, 16, 32, 32);
const String8 DISPLAY_NAME("SurfaceInterceptor Display Test");
+constexpr auto TEST_SURFACE_NAME = "BG Interceptor Test Surface";
+constexpr auto UNIQUE_TEST_SURFACE_NAME = "BG Interceptor Test Surface#0";
constexpr auto LAYER_NAME = "Layer Create and Delete Test";
+constexpr auto UNIQUE_LAYER_NAME = "Layer Create and Delete Test#0";
constexpr auto DEFAULT_FILENAME = "/data/SurfaceTrace.dat";
@@ -94,30 +97,21 @@
system("service call SurfaceFlinger 1020 i32 0 > /dev/null");
}
-int32_t getSurfaceId(const std::string& surfaceName) {
- enableInterceptor();
- disableInterceptor();
- Trace capturedTrace;
- readProtoFile(&capturedTrace);
+int32_t getSurfaceId(const Trace& capturedTrace, const std::string& surfaceName) {
int32_t layerId = 0;
- for (const auto& increment : *capturedTrace.mutable_increment()) {
+ for (const auto& increment : capturedTrace.increment()) {
if (increment.increment_case() == increment.kSurfaceCreation) {
if (increment.surface_creation().name() == surfaceName) {
layerId = increment.surface_creation().id();
- break;
}
}
}
return layerId;
}
-int32_t getDisplayId(const std::string& displayName) {
- enableInterceptor();
- disableInterceptor();
- Trace capturedTrace;
- readProtoFile(&capturedTrace);
+int32_t getDisplayId(const Trace& capturedTrace, const std::string& displayName) {
int32_t displayId = 0;
- for (const auto& increment : *capturedTrace.mutable_increment()) {
+ for (const auto& increment : capturedTrace.increment()) {
if (increment.increment_case() == increment.kDisplayCreation) {
if (increment.display_creation().name() == displayName) {
displayId = increment.display_creation().id();
@@ -130,36 +124,15 @@
class SurfaceInterceptorTest : public ::testing::Test {
protected:
- virtual void SetUp() {
+ void SetUp() override {
// Allow SurfaceInterceptor write to /data
system("setenforce 0");
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
-
- sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
- ISurfaceComposer::eDisplayIdMain));
- DisplayInfo info;
- SurfaceComposerClient::getDisplayInfo(display, &info);
- ssize_t displayWidth = info.w;
- ssize_t displayHeight = info.h;
-
- // Background surface
- mBGSurfaceControl = mComposerClient->createSurface(
- String8("BG Interceptor Test Surface"), displayWidth, displayHeight,
- PIXEL_FORMAT_RGBA_8888, 0);
- ASSERT_TRUE(mBGSurfaceControl != nullptr);
- ASSERT_TRUE(mBGSurfaceControl->isValid());
- mBGLayerId = getSurfaceId("BG Interceptor Test Surface");
-
- Transaction t;
- t.setDisplayLayerStack(display, 0);
- ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3)
- .show(mBGSurfaceControl)
- .apply());
}
- virtual void TearDown() {
+ void TearDown() override {
mComposerClient->dispose();
mBGSurfaceControl.clear();
mComposerClient.clear();
@@ -168,18 +141,25 @@
sp<SurfaceComposerClient> mComposerClient;
sp<SurfaceControl> mBGSurfaceControl;
int32_t mBGLayerId;
- // Used to verify creation and destruction of surfaces and displays
- int32_t mTargetId;
public:
- void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
- bool (SurfaceInterceptorTest::* verification)(Trace *));
- void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
- SurfaceChange::SurfaceChangeCase changeCase);
- void captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
- Increment::IncrementCase incrementCase);
- void runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&),
- bool intercepted = false);
+ using TestTransactionAction = void (SurfaceInterceptorTest::*)(Transaction&);
+ using TestAction = void (SurfaceInterceptorTest::*)();
+ using TestBooleanVerification = bool (SurfaceInterceptorTest::*)(const Trace&);
+ using TestVerification = void (SurfaceInterceptorTest::*)(const Trace&);
+
+ void setupBackgroundSurface();
+ void preProcessTrace(const Trace& trace);
+
+ // captureTest will enable SurfaceInterceptor, setup background surface,
+ // disable SurfaceInterceptor, collect the trace and process the trace for
+ // id of background surface before further verification.
+ void captureTest(TestTransactionAction action, TestBooleanVerification verification);
+ void captureTest(TestTransactionAction action, SurfaceChange::SurfaceChangeCase changeCase);
+ void captureTest(TestTransactionAction action, Increment::IncrementCase incrementCase);
+ void captureTest(TestAction action, TestBooleanVerification verification);
+ void captureTest(TestAction action, TestVerification verification);
+ void runInTransaction(TestTransactionAction action);
// Verification of changes to a surface
bool positionUpdateFound(const SurfaceChange& change, bool foundPosition);
@@ -196,18 +176,22 @@
bool opaqueFlagUpdateFound(const SurfaceChange& change, bool foundOpaqueFlag);
bool secureFlagUpdateFound(const SurfaceChange& change, bool foundSecureFlag);
bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
- bool surfaceUpdateFound(Trace* trace, SurfaceChange::SurfaceChangeCase changeCase);
- void assertAllUpdatesFound(Trace* trace);
+ bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
+
+ // Find all of the updates in the single trace
+ void assertAllUpdatesFound(const Trace& trace);
// Verification of creation and deletion of a surface
bool surfaceCreationFound(const Increment& increment, bool foundSurface);
- bool surfaceDeletionFound(const Increment& increment, bool foundSurface);
+ bool surfaceDeletionFound(const Increment& increment, const int32_t targetId,
+ bool foundSurface);
bool displayCreationFound(const Increment& increment, bool foundDisplay);
- bool displayDeletionFound(const Increment& increment, bool foundDisplay);
- bool singleIncrementFound(Trace* trace, Increment::IncrementCase incrementCase);
+ bool displayDeletionFound(const Increment& increment, const int32_t targetId,
+ bool foundDisplay);
+ bool singleIncrementFound(const Trace& trace, Increment::IncrementCase incrementCase);
// Verification of buffer updates
- bool bufferUpdatesFound(Trace* trace);
+ bool bufferUpdatesFound(const Trace& trace);
// Perform each of the possible changes to a surface
void positionUpdate(Transaction&);
@@ -230,48 +214,93 @@
void nBufferUpdates();
void runAllUpdates();
+
+private:
+ void captureInTransaction(TestTransactionAction action, Trace*);
+ void capture(TestAction action, Trace*);
};
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
- bool (SurfaceInterceptorTest::* verification)(Trace *))
-{
- runInTransaction(action, true);
- Trace capturedTrace;
- ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- ASSERT_TRUE((this->*verification)(&capturedTrace));
+void SurfaceInterceptorTest::captureInTransaction(TestTransactionAction action, Trace* outTrace) {
+ enableInterceptor();
+ setupBackgroundSurface();
+ runInTransaction(action);
+ disableInterceptor();
+ ASSERT_EQ(NO_ERROR, readProtoFile(outTrace));
+ preProcessTrace(*outTrace);
}
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
- Increment::IncrementCase incrementCase)
-{
- runInTransaction(action, true);
- Trace capturedTrace;
- ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- ASSERT_TRUE(singleIncrementFound(&capturedTrace, incrementCase));
+void SurfaceInterceptorTest::capture(TestAction action, Trace* outTrace) {
+ enableInterceptor();
+ setupBackgroundSurface();
+ (this->*action)();
+ disableInterceptor();
+ ASSERT_EQ(NO_ERROR, readProtoFile(outTrace));
+ preProcessTrace(*outTrace);
}
-void SurfaceInterceptorTest::captureTest(void (SurfaceInterceptorTest::* action)(Transaction&),
- SurfaceChange::SurfaceChangeCase changeCase)
-{
- runInTransaction(action, true);
- Trace capturedTrace;
- ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- ASSERT_TRUE(surfaceUpdateFound(&capturedTrace, changeCase));
+void SurfaceInterceptorTest::setupBackgroundSurface() {
+ sp<IBinder> display(SurfaceComposerClient::getBuiltInDisplay(
+ ISurfaceComposer::eDisplayIdMain));
+ DisplayInfo info;
+ SurfaceComposerClient::getDisplayInfo(display, &info);
+ ssize_t displayWidth = info.w;
+ ssize_t displayHeight = info.h;
+
+ // Background surface
+ mBGSurfaceControl = mComposerClient->createSurface(
+ String8(TEST_SURFACE_NAME), displayWidth, displayHeight,
+ PIXEL_FORMAT_RGBA_8888, 0);
+ ASSERT_TRUE(mBGSurfaceControl != nullptr);
+ ASSERT_TRUE(mBGSurfaceControl->isValid());
+
+ Transaction t;
+ t.setDisplayLayerStack(display, 0);
+ ASSERT_EQ(NO_ERROR, t.setLayer(mBGSurfaceControl, INT_MAX-3)
+ .show(mBGSurfaceControl)
+ .apply());
}
-void SurfaceInterceptorTest::runInTransaction(void (SurfaceInterceptorTest::* action)(Transaction&),
- bool intercepted)
-{
- if (intercepted) {
- enableInterceptor();
- }
+void SurfaceInterceptorTest::preProcessTrace(const Trace& trace) {
+ mBGLayerId = getSurfaceId(trace, UNIQUE_TEST_SURFACE_NAME);
+}
+
+void SurfaceInterceptorTest::captureTest(TestTransactionAction action,
+ TestBooleanVerification verification) {
+ Trace capturedTrace;
+ captureInTransaction(action, &capturedTrace);
+ ASSERT_TRUE((this->*verification)(capturedTrace));
+}
+
+void SurfaceInterceptorTest::captureTest(TestTransactionAction action,
+ Increment::IncrementCase incrementCase) {
+ Trace capturedTrace;
+ captureInTransaction(action, &capturedTrace);
+ ASSERT_TRUE(singleIncrementFound(capturedTrace, incrementCase));
+}
+
+void SurfaceInterceptorTest::captureTest(TestTransactionAction action,
+ SurfaceChange::SurfaceChangeCase changeCase) {
+ Trace capturedTrace;
+ captureInTransaction(action, &capturedTrace);
+ ASSERT_TRUE(surfaceUpdateFound(capturedTrace, changeCase));
+}
+
+void SurfaceInterceptorTest::captureTest(TestAction action, TestBooleanVerification verification) {
+ Trace capturedTrace;
+ capture(action, &capturedTrace);
+ ASSERT_TRUE((this->*verification)(capturedTrace));
+}
+
+void SurfaceInterceptorTest::captureTest(TestAction action, TestVerification verification) {
+ Trace capturedTrace;
+ capture(action, &capturedTrace);
+ (this->*verification)(capturedTrace);
+}
+
+void SurfaceInterceptorTest::runInTransaction(TestTransactionAction action) {
Transaction t;
(this->*action)(t);
t.apply(true);
-
- if (intercepted) {
- disableInterceptor();
- }
}
void SurfaceInterceptorTest::positionUpdate(Transaction& t) {
@@ -338,7 +367,6 @@
void SurfaceInterceptorTest::displayDeletion(Transaction&) {
sp<IBinder> testDisplay = SurfaceComposerClient::createDisplay(DISPLAY_NAME, false);
- mTargetId = getDisplayId(DISPLAY_NAME.string());
SurfaceComposerClient::destroyDisplay(testDisplay);
}
@@ -380,9 +408,8 @@
bool hasY(change.position().y() == POSITION_UPDATE);
if (hasX && hasY && !foundPosition) {
foundPosition = true;
- }
- // Failed because the position update was found a second time
- else if (hasX && hasY && foundPosition) {
+ } else if (hasX && hasY && foundPosition) {
+ // Failed because the position update was found a second time
[] () { FAIL(); }();
}
return foundPosition;
@@ -393,8 +420,7 @@
bool hasHeight(change.size().w() == SIZE_UPDATE);
if (hasWidth && hasHeight && !foundSize) {
foundSize = true;
- }
- else if (hasWidth && hasHeight && foundSize) {
+ } else if (hasWidth && hasHeight && foundSize) {
[] () { FAIL(); }();
}
return foundSize;
@@ -404,8 +430,7 @@
bool hasAlpha(change.alpha().alpha() == ALPHA_UPDATE);
if (hasAlpha && !foundAlpha) {
foundAlpha = true;
- }
- else if (hasAlpha && foundAlpha) {
+ } else if (hasAlpha && foundAlpha) {
[] () { FAIL(); }();
}
return foundAlpha;
@@ -415,8 +440,7 @@
bool hasLayer(change.layer().layer() == LAYER_UPDATE);
if (hasLayer && !foundLayer) {
foundLayer = true;
- }
- else if (hasLayer && foundLayer) {
+ } else if (hasLayer && foundLayer) {
[] () { FAIL(); }();
}
return foundLayer;
@@ -429,24 +453,21 @@
bool hasBottom(change.crop().rectangle().bottom() == CROP_UPDATE.bottom);
if (hasLeft && hasRight && hasTop && hasBottom && !foundCrop) {
foundCrop = true;
- }
- else if (hasLeft && hasRight && hasTop && hasBottom && foundCrop) {
+ } else if (hasLeft && hasRight && hasTop && hasBottom && foundCrop) {
[] () { FAIL(); }();
}
return foundCrop;
}
bool SurfaceInterceptorTest::finalCropUpdateFound(const SurfaceChange& change,
- bool foundFinalCrop)
-{
+ bool foundFinalCrop) {
bool hasLeft(change.final_crop().rectangle().left() == CROP_UPDATE.left);
bool hasTop(change.final_crop().rectangle().top() == CROP_UPDATE.top);
bool hasRight(change.final_crop().rectangle().right() == CROP_UPDATE.right);
bool hasBottom(change.final_crop().rectangle().bottom() == CROP_UPDATE.bottom);
if (hasLeft && hasRight && hasTop && hasBottom && !foundFinalCrop) {
foundFinalCrop = true;
- }
- else if (hasLeft && hasRight && hasTop && hasBottom && foundFinalCrop) {
+ } else if (hasLeft && hasRight && hasTop && hasBottom && foundFinalCrop) {
[] () { FAIL(); }();
}
return foundFinalCrop;
@@ -455,33 +476,29 @@
bool SurfaceInterceptorTest::matrixUpdateFound(const SurfaceChange& change, bool foundMatrix) {
bool hasSx((float)change.matrix().dsdx() == (float)M_SQRT1_2);
bool hasTx((float)change.matrix().dtdx() == (float)M_SQRT1_2);
- bool hasSy((float)change.matrix().dsdy() == (float)-M_SQRT1_2);
- bool hasTy((float)change.matrix().dtdy() == (float)M_SQRT1_2);
+ bool hasSy((float)change.matrix().dsdy() == (float)M_SQRT1_2);
+ bool hasTy((float)change.matrix().dtdy() == (float)-M_SQRT1_2);
if (hasSx && hasTx && hasSy && hasTy && !foundMatrix) {
foundMatrix = true;
- }
- else if (hasSx && hasTx && hasSy && hasTy && foundMatrix) {
+ } else if (hasSx && hasTx && hasSy && hasTy && foundMatrix) {
[] () { FAIL(); }();
}
return foundMatrix;
}
bool SurfaceInterceptorTest::scalingModeUpdateFound(const SurfaceChange& change,
- bool foundScalingMode)
-{
+ bool foundScalingMode) {
bool hasScalingUpdate(change.override_scaling_mode().override_scaling_mode() == SCALING_UPDATE);
if (hasScalingUpdate && !foundScalingMode) {
foundScalingMode = true;
- }
- else if (hasScalingUpdate && foundScalingMode) {
+ } else if (hasScalingUpdate && foundScalingMode) {
[] () { FAIL(); }();
}
return foundScalingMode;
}
bool SurfaceInterceptorTest::transparentRegionHintUpdateFound(const SurfaceChange& change,
- bool foundTransparentRegion)
-{
+ bool foundTransparentRegion) {
auto traceRegion = change.transparent_region_hint().region(0);
bool hasLeft(traceRegion.left() == CROP_UPDATE.left);
bool hasTop(traceRegion.top() == CROP_UPDATE.top);
@@ -489,84 +506,72 @@
bool hasBottom(traceRegion.bottom() == CROP_UPDATE.bottom);
if (hasLeft && hasRight && hasTop && hasBottom && !foundTransparentRegion) {
foundTransparentRegion = true;
- }
- else if (hasLeft && hasRight && hasTop && hasBottom && foundTransparentRegion) {
+ } else if (hasLeft && hasRight && hasTop && hasBottom && foundTransparentRegion) {
[] () { FAIL(); }();
}
return foundTransparentRegion;
}
bool SurfaceInterceptorTest::layerStackUpdateFound(const SurfaceChange& change,
- bool foundLayerStack)
-{
+ bool foundLayerStack) {
bool hasLayerStackUpdate(change.layer_stack().layer_stack() == STACK_UPDATE);
if (hasLayerStackUpdate && !foundLayerStack) {
foundLayerStack = true;
- }
- else if (hasLayerStackUpdate && foundLayerStack) {
+ } else if (hasLayerStackUpdate && foundLayerStack) {
[] () { FAIL(); }();
}
return foundLayerStack;
}
bool SurfaceInterceptorTest::hiddenFlagUpdateFound(const SurfaceChange& change,
- bool foundHiddenFlag)
-{
+ bool foundHiddenFlag) {
bool hasHiddenFlag(change.hidden_flag().hidden_flag());
if (hasHiddenFlag && !foundHiddenFlag) {
foundHiddenFlag = true;
- }
- else if (hasHiddenFlag && foundHiddenFlag) {
+ } else if (hasHiddenFlag && foundHiddenFlag) {
[] () { FAIL(); }();
}
return foundHiddenFlag;
}
bool SurfaceInterceptorTest::opaqueFlagUpdateFound(const SurfaceChange& change,
- bool foundOpaqueFlag)
-{
+ bool foundOpaqueFlag) {
bool hasOpaqueFlag(change.opaque_flag().opaque_flag());
if (hasOpaqueFlag && !foundOpaqueFlag) {
foundOpaqueFlag = true;
- }
- else if (hasOpaqueFlag && foundOpaqueFlag) {
+ } else if (hasOpaqueFlag && foundOpaqueFlag) {
[] () { FAIL(); }();
}
return foundOpaqueFlag;
}
bool SurfaceInterceptorTest::secureFlagUpdateFound(const SurfaceChange& change,
- bool foundSecureFlag)
-{
+ bool foundSecureFlag) {
bool hasSecureFlag(change.secure_flag().secure_flag());
if (hasSecureFlag && !foundSecureFlag) {
foundSecureFlag = true;
- }
- else if (hasSecureFlag && foundSecureFlag) {
+ } else if (hasSecureFlag && foundSecureFlag) {
[] () { FAIL(); }();
}
return foundSecureFlag;
}
bool SurfaceInterceptorTest::deferredTransactionUpdateFound(const SurfaceChange& change,
- bool foundDeferred)
-{
+ bool foundDeferred) {
bool hasId(change.deferred_transaction().layer_id() == mBGLayerId);
bool hasFrameNumber(change.deferred_transaction().frame_number() == DEFERRED_UPDATE);
if (hasId && hasFrameNumber && !foundDeferred) {
foundDeferred = true;
- }
- else if (hasId && hasFrameNumber && foundDeferred) {
+ } else if (hasId && hasFrameNumber && foundDeferred) {
[] () { FAIL(); }();
}
return foundDeferred;
}
-bool SurfaceInterceptorTest::surfaceUpdateFound(Trace* trace,
- SurfaceChange::SurfaceChangeCase changeCase)
-{
+bool SurfaceInterceptorTest::surfaceUpdateFound(const Trace& trace,
+ SurfaceChange::SurfaceChangeCase changeCase) {
bool foundUpdate = false;
- for (const auto& increment : *trace->mutable_increment()) {
+ for (const auto& increment : trace.increment()) {
if (increment.increment_case() == increment.kTransaction) {
for (const auto& change : increment.transaction().surface_change()) {
if (change.id() == mBGLayerId && change.SurfaceChange_case() == changeCase) {
@@ -624,7 +629,7 @@
return foundUpdate;
}
-void SurfaceInterceptorTest::assertAllUpdatesFound(Trace* trace) {
+void SurfaceInterceptorTest::assertAllUpdatesFound(const Trace& trace) {
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kPosition));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kSize));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kAlpha));
@@ -642,24 +647,23 @@
}
bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
- bool isMatch(increment.surface_creation().name() == LAYER_NAME &&
+ bool isMatch(increment.surface_creation().name() == UNIQUE_LAYER_NAME &&
increment.surface_creation().w() == SIZE_UPDATE &&
increment.surface_creation().h() == SIZE_UPDATE);
if (isMatch && !foundSurface) {
foundSurface = true;
- }
- else if (isMatch && foundSurface) {
+ } else if (isMatch && foundSurface) {
[] () { FAIL(); }();
}
return foundSurface;
}
-bool SurfaceInterceptorTest::surfaceDeletionFound(const Increment& increment, bool foundSurface) {
- bool isMatch(increment.surface_deletion().id() == mTargetId);
+bool SurfaceInterceptorTest::surfaceDeletionFound(const Increment& increment,
+ const int32_t targetId, bool foundSurface) {
+ bool isMatch(increment.surface_deletion().id() == targetId);
if (isMatch && !foundSurface) {
foundSurface = true;
- }
- else if (isMatch && foundSurface) {
+ } else if (isMatch && foundSurface) {
[] () { FAIL(); }();
}
return foundSurface;
@@ -670,42 +674,45 @@
increment.display_creation().is_secure());
if (isMatch && !foundDisplay) {
foundDisplay = true;
- }
- else if (isMatch && foundDisplay) {
+ } else if (isMatch && foundDisplay) {
[] () { FAIL(); }();
}
return foundDisplay;
}
-bool SurfaceInterceptorTest::displayDeletionFound(const Increment& increment, bool foundDisplay) {
- bool isMatch(increment.display_deletion().id() == mTargetId);
+bool SurfaceInterceptorTest::displayDeletionFound(const Increment& increment,
+ const int32_t targetId, bool foundDisplay) {
+ bool isMatch(increment.display_deletion().id() == targetId);
if (isMatch && !foundDisplay) {
foundDisplay = true;
- }
- else if (isMatch && foundDisplay) {
+ } else if (isMatch && foundDisplay) {
[] () { FAIL(); }();
}
return foundDisplay;
}
-bool SurfaceInterceptorTest::singleIncrementFound(Trace* trace,
- Increment::IncrementCase incrementCase)
-{
+bool SurfaceInterceptorTest::singleIncrementFound(const Trace& trace,
+ Increment::IncrementCase incrementCase) {
bool foundIncrement = false;
- for (const auto& increment : *trace->mutable_increment()) {
+ for (const auto& increment : trace.increment()) {
if (increment.increment_case() == incrementCase) {
+ int32_t targetId = 0;
switch (incrementCase) {
case Increment::IncrementCase::kSurfaceCreation:
foundIncrement = surfaceCreationFound(increment, foundIncrement);
break;
case Increment::IncrementCase::kSurfaceDeletion:
- foundIncrement = surfaceDeletionFound(increment, foundIncrement);
+ // Find the id of created surface.
+ targetId = getSurfaceId(trace, UNIQUE_LAYER_NAME);
+ foundIncrement = surfaceDeletionFound(increment, targetId, foundIncrement);
break;
case Increment::IncrementCase::kDisplayCreation:
foundIncrement = displayCreationFound(increment, foundIncrement);
break;
case Increment::IncrementCase::kDisplayDeletion:
- foundIncrement = displayDeletionFound(increment, foundIncrement);
+ // Find the id of created display.
+ targetId = getDisplayId(trace, DISPLAY_NAME.string());
+ foundIncrement = displayDeletionFound(increment, targetId, foundIncrement);
break;
default:
/* code */
@@ -716,9 +723,9 @@
return foundIncrement;
}
-bool SurfaceInterceptorTest::bufferUpdatesFound(Trace* trace) {
+bool SurfaceInterceptorTest::bufferUpdatesFound(const Trace& trace) {
uint32_t updates = 0;
- for (const auto& inc : *trace->mutable_increment()) {
+ for (const auto& inc : trace.increment()) {
if (inc.increment_case() == inc.kBufferUpdate && inc.buffer_update().id() == mBGLayerId) {
updates++;
}
@@ -792,14 +799,8 @@
}
TEST_F(SurfaceInterceptorTest, InterceptAllUpdatesWorks) {
- enableInterceptor();
- runAllUpdates();
- disableInterceptor();
-
- // Find all of the updates in the single trace
- Trace capturedTrace;
- ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- assertAllUpdatesFound(&capturedTrace);
+ captureTest(&SurfaceInterceptorTest::runAllUpdates,
+ &SurfaceInterceptorTest::assertAllUpdatesFound);
}
TEST_F(SurfaceInterceptorTest, InterceptSurfaceCreationWorks) {
@@ -808,16 +809,15 @@
}
TEST_F(SurfaceInterceptorTest, InterceptSurfaceDeletionWorks) {
+ enableInterceptor();
sp<SurfaceControl> layerToDelete = mComposerClient->createSurface(String8(LAYER_NAME),
SIZE_UPDATE, SIZE_UPDATE, PIXEL_FORMAT_RGBA_8888, 0);
- this->mTargetId = getSurfaceId(LAYER_NAME);
- enableInterceptor();
mComposerClient->destroySurface(layerToDelete->getHandle());
disableInterceptor();
Trace capturedTrace;
ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceDeletion));
+ ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceDeletion));
}
TEST_F(SurfaceInterceptorTest, InterceptDisplayCreationWorks) {
@@ -826,21 +826,24 @@
}
TEST_F(SurfaceInterceptorTest, InterceptDisplayDeletionWorks) {
- captureTest(&SurfaceInterceptorTest::displayDeletion,
- Increment::IncrementCase::kDisplayDeletion);
+ enableInterceptor();
+ runInTransaction(&SurfaceInterceptorTest::displayDeletion);
+ disableInterceptor();
+ Trace capturedTrace;
+ ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
+ ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kDisplayDeletion));
}
TEST_F(SurfaceInterceptorTest, InterceptBufferUpdateWorks) {
- nBufferUpdates();
- Trace capturedTrace;
- ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
- ASSERT_TRUE(bufferUpdatesFound(&capturedTrace));
+ captureTest(&SurfaceInterceptorTest::nBufferUpdates,
+ &SurfaceInterceptorTest::bufferUpdatesFound);
}
// If the interceptor is enabled while buffer updates are being pushed, the interceptor should
// first create a snapshot of the existing displays and surfaces and then start capturing
// the buffer updates
TEST_F(SurfaceInterceptorTest, InterceptWhileBufferUpdatesWorks) {
+ setupBackgroundSurface();
std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this);
enableInterceptor();
disableInterceptor();
@@ -854,6 +857,7 @@
TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) {
enableInterceptor();
+ setupBackgroundSurface();
std::thread bufferUpdates(&SurfaceInterceptorTest::nBufferUpdates, this);
std::thread surfaceUpdates(&SurfaceInterceptorTest::runAllUpdates, this);
runInTransaction(&SurfaceInterceptorTest::surfaceCreation);
@@ -863,10 +867,11 @@
Trace capturedTrace;
ASSERT_EQ(NO_ERROR, readProtoFile(&capturedTrace));
+ preProcessTrace(capturedTrace);
- assertAllUpdatesFound(&capturedTrace);
- ASSERT_TRUE(bufferUpdatesFound(&capturedTrace));
- ASSERT_TRUE(singleIncrementFound(&capturedTrace, Increment::IncrementCase::kSurfaceCreation));
+ assertAllUpdatesFound(capturedTrace);
+ ASSERT_TRUE(bufferUpdatesFound(capturedTrace));
+ ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceCreation));
}
}
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 8c268b2..508c561 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -18,6 +18,7 @@
test_suites: ["device-tests"],
srcs: [
":libsurfaceflinger_sources",
+ "DisplayIdentificationTest.cpp",
"DisplayTransactionTest.cpp",
"EventControlThreadTest.cpp",
"EventThreadTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
new file mode 100644
index 0000000..9113171
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/DisplayIdentificationTest.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "DisplayHardware/DisplayIdentification.h"
+
+namespace android {
+namespace {
+
+const unsigned char kInternalEdid[] =
+ "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00"
+ "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27"
+ "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30"
+ "\x13\x00\x05\xa3\x10\x00\x00\x19\x00\x00\x00\x0f\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x23\x87\x02\x64\x00\x00\x00\x00\xfe\x00\x53"
+ "\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x00\x00\x00\xfe"
+ "\x00\x31\x32\x31\x41\x54\x31\x31\x2d\x38\x30\x31\x0a\x20\x00\x45";
+
+const unsigned char kExternalEdid[] =
+ "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01"
+ "\x02\x16\x01\x04\xb5\x40\x28\x78\xe2\x8d\x85\xad\x4f\x35\xb1\x25"
+ "\x0e\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+ "\x01\x01\x01\x01\x01\x01\xe2\x68\x00\xa0\xa0\x40\x2e\x60\x30\x20"
+ "\x36\x00\x81\x90\x21\x00\x00\x1a\xbc\x1b\x00\xa0\x50\x20\x17\x30"
+ "\x30\x20\x36\x00\x81\x90\x21\x00\x00\x1a\x00\x00\x00\xfc\x00\x48"
+ "\x50\x20\x5a\x52\x33\x30\x77\x0a\x20\x20\x20\x20\x00\x00\x00\xff"
+ "\x00\x43\x4e\x34\x32\x30\x32\x31\x33\x37\x51\x0a\x20\x20\x00\x71";
+
+// Extended EDID with timing extension.
+const unsigned char kExternalEedid[] =
+ "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00"
+ "\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26"
+ "\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00"
+ "\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
+ "\x45\x00\xa0\x5a\x00\x00\x00\x1e\x66\x21\x56\xaa\x51\x00\x1e\x30"
+ "\x46\x8f\x33\x00\xa0\x5a\x00\x00\x00\x1e\x00\x00\x00\xfd\x00\x18"
+ "\x4b\x0f\x51\x17\x00\x0a\x20\x20\x20\x20\x20\x20\x00\x00\x00\xfc"
+ "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d"
+ "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07"
+ "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01"
+ "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00"
+ "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00"
+ "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0"
+ "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6";
+
+template <size_t N>
+DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&bytes)[N]) {
+ return DisplayIdentificationData(bytes, bytes + N - 1);
+}
+
+} // namespace
+
+TEST(DisplayIdentificationTest, isEdid) {
+ EXPECT_FALSE(isEdid({}));
+
+ EXPECT_TRUE(isEdid(asDisplayIdentificationData(kInternalEdid)));
+ EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEdid)));
+ EXPECT_TRUE(isEdid(asDisplayIdentificationData(kExternalEedid)));
+}
+
+TEST(DisplayIdentificationTest, parseEdid) {
+ auto edid = parseEdid(asDisplayIdentificationData(kInternalEdid));
+ ASSERT_TRUE(edid);
+ EXPECT_EQ(0x4ca3u, edid->manufacturerId);
+ EXPECT_STREQ("SEC", edid->pnpId.data());
+ // ASCII text should be used as fallback if display name and serial number are missing.
+ EXPECT_EQ("121AT11-801", edid->displayName);
+
+ edid = parseEdid(asDisplayIdentificationData(kExternalEdid));
+ ASSERT_TRUE(edid);
+ EXPECT_EQ(0x22f0u, edid->manufacturerId);
+ EXPECT_STREQ("HWP", edid->pnpId.data());
+ EXPECT_EQ("HP ZR30w", edid->displayName);
+
+ edid = parseEdid(asDisplayIdentificationData(kExternalEedid));
+ ASSERT_TRUE(edid);
+ EXPECT_EQ(0x4c2du, edid->manufacturerId);
+ EXPECT_STREQ("SAM", edid->pnpId.data());
+ EXPECT_EQ("SAMSUNG", edid->displayName);
+}
+
+TEST(DisplayIdentificationTest, parseInvalidEdid) {
+ EXPECT_FALSE(isEdid({}));
+ EXPECT_FALSE(parseEdid({}));
+
+ // Display name must be printable.
+ auto data = asDisplayIdentificationData(kExternalEdid);
+ data[97] = '\x1b';
+ auto edid = parseEdid(data);
+ ASSERT_TRUE(edid);
+ // Serial number should be used as fallback if display name is invalid.
+ EXPECT_EQ("CN4202137Q", edid->displayName);
+
+ // Parsing should succeed even if EDID is truncated.
+ data.pop_back();
+ edid = parseEdid(data);
+ ASSERT_TRUE(edid);
+ EXPECT_EQ("CN4202137Q", edid->displayName);
+}
+
+TEST(DisplayIdentificationTest, getPnpId) {
+ EXPECT_FALSE(getPnpId(0));
+ EXPECT_FALSE(getPnpId(static_cast<uint16_t>(-1)));
+
+ EXPECT_STREQ("SEC", getPnpId(0x4ca3u).value_or(PnpId{}).data());
+ EXPECT_STREQ("HWP", getPnpId(0x22f0u).value_or(PnpId{}).data());
+ EXPECT_STREQ("SAM", getPnpId(0x4c2du).value_or(PnpId{}).data());
+}
+
+TEST(DisplayIdentificationTest, generateDisplayId) {
+ const auto primaryId = generateDisplayId(0, asDisplayIdentificationData(kInternalEdid));
+ ASSERT_TRUE(primaryId);
+
+ const auto secondaryId = generateDisplayId(1, asDisplayIdentificationData(kExternalEdid));
+ ASSERT_TRUE(secondaryId);
+
+ const auto tertiaryId = generateDisplayId(2, asDisplayIdentificationData(kExternalEedid));
+ ASSERT_TRUE(tertiaryId);
+
+ // Display IDs should be unique.
+ EXPECT_NE(primaryId, secondaryId);
+ EXPECT_NE(primaryId, tertiaryId);
+ EXPECT_NE(secondaryId, tertiaryId);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 9b308bf..3be2ad0 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -207,11 +207,11 @@
}
bool DisplayTransactionTest::hasDisplayDevice(sp<IBinder> displayToken) {
- return mFlinger.mutableDisplays().indexOfKey(displayToken) >= 0;
+ return mFlinger.mutableDisplays().count(displayToken) == 1;
}
sp<DisplayDevice> DisplayTransactionTest::getDisplayDevice(sp<IBinder> displayToken) {
- return mFlinger.mutableDisplays().valueFor(displayToken);
+ return mFlinger.mutableDisplays()[displayToken];
}
bool DisplayTransactionTest::hasCurrentDisplayState(sp<IBinder> displayToken) {
@@ -234,8 +234,8 @@
*
*/
-template <DisplayDevice::DisplayType type, DisplayDevice::DisplayType hwcId, int width, int height,
- Critical critical, Async async, Secure secure, int grallocUsage>
+template <DisplayDevice::DisplayType type, DisplayDevice::DisplayType displayId, int width,
+ int height, Critical critical, Async async, Secure secure, int grallocUsage>
struct DisplayVariant {
// The display width and height
static constexpr int WIDTH = width;
@@ -245,7 +245,9 @@
// The type for this display
static constexpr DisplayDevice::DisplayType TYPE = type;
- static constexpr DisplayDevice::DisplayType HWCOMPOSER_ID = hwcId;
+ static_assert(TYPE != DisplayDevice::DISPLAY_ID_INVALID);
+
+ static constexpr DisplayDevice::DisplayType DISPLAY_ID = displayId;
// When creating native window surfaces for the framebuffer, whether those should be critical
static constexpr Critical CRITICAL = critical;
@@ -257,7 +259,7 @@
static constexpr Secure SECURE = secure;
static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) {
- auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, HWCOMPOSER_ID);
+ auto injector = FakeDisplayDeviceInjector(test->mFlinger, TYPE, DISPLAY_ID);
injector.setSecure(static_cast<bool>(SECURE));
return injector;
}
@@ -353,6 +355,8 @@
getDisplayAttribute(HWC_DISPLAY_ID, HWC_ACTIVE_CONFIG_ID,
IComposerClient::Attribute::DPI_Y, _))
.WillOnce(DoAll(SetArgPointee<3>(DEFAULT_DPI), Return(Error::NONE)));
+ EXPECT_CALL(*test->mComposer, getDisplayIdentificationData(HWC_DISPLAY_ID, _, _))
+ .WillRepeatedly(Return(Error::UNSUPPORTED));
}
// Called by tests to set up HWC call expectations
@@ -383,11 +387,6 @@
DisplayVariant<type, type, width, height, critical, Async::FALSE,
Secure::TRUE, GRALLOC_USAGE_PHYSICAL_DISPLAY>> {};
-// An invalid display
-using InvalidDisplayVariant =
- DisplayVariant<DisplayDevice::DISPLAY_ID_INVALID, DisplayDevice::DISPLAY_ID_INVALID, 0, 0,
- Critical::FALSE, Async::FALSE, Secure::FALSE, 0>;
-
// A primary display is a physical display that is critical
using PrimaryDisplayVariant =
PhysicalDisplayVariant<1001, DisplayDevice::DISPLAY_PRIMARY, 3840, 2160, Critical::TRUE>;
@@ -684,9 +683,7 @@
Case<PrimaryDisplayVariant, WideColorNotSupportedVariant<PrimaryDisplayVariant>,
HdrNotSupportedVariant<PrimaryDisplayVariant>,
Cta861_3_PerFrameMetadataSupportVariant<PrimaryDisplayVariant>>;
-using InvalidDisplayCase = Case<InvalidDisplayVariant, WideColorSupportNotConfiguredVariant,
- NonHwcDisplayHdrSupportVariant,
- NoPerFrameMetadataSupportVariant<InvalidDisplayVariant>>;
+
/* ------------------------------------------------------------------------
*
* SurfaceFlinger::onHotplugReceived
@@ -694,8 +691,8 @@
TEST_F(DisplayTransactionTest, hotplugEnqueuesEventsForDisplayTransaction) {
constexpr int currentSequenceId = 123;
- constexpr hwc2_display_t displayId1 = 456;
- constexpr hwc2_display_t displayId2 = 654;
+ constexpr hwc2_display_t hwcDisplayId1 = 456;
+ constexpr hwc2_display_t hwcDisplayId2 = 654;
// --------------------------------------------------------------------
// Preconditions
@@ -718,8 +715,8 @@
// Invocation
// Simulate two hotplug events (a connect and a disconnect)
- mFlinger.onHotplugReceived(currentSequenceId, displayId1, HWC2::Connection::Connected);
- mFlinger.onHotplugReceived(currentSequenceId, displayId2, HWC2::Connection::Disconnected);
+ mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId1, HWC2::Connection::Connected);
+ mFlinger.onHotplugReceived(currentSequenceId, hwcDisplayId2, HWC2::Connection::Disconnected);
// --------------------------------------------------------------------
// Postconditions
@@ -730,9 +727,9 @@
// All events should be in the pending event queue.
const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
ASSERT_EQ(2u, pendingEvents.size());
- EXPECT_EQ(displayId1, pendingEvents[0].display);
+ EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
EXPECT_EQ(HWC2::Connection::Connected, pendingEvents[0].connection);
- EXPECT_EQ(displayId2, pendingEvents[1].display);
+ EXPECT_EQ(hwcDisplayId2, pendingEvents[1].hwcDisplayId);
EXPECT_EQ(HWC2::Connection::Disconnected, pendingEvents[1].connection);
}
@@ -1032,7 +1029,10 @@
// --------------------------------------------------------------------
// Invocation
- auto state = DisplayDeviceState(Case::Display::TYPE, static_cast<bool>(Case::Display::SECURE));
+ DisplayDeviceState state;
+ state.type = Case::Display::TYPE;
+ state.isSecure = static_cast<bool>(Case::Display::SECURE);
+
auto device = mFlinger.setupNewDisplayDeviceInternal(displayToken, Case::Display::TYPE, state,
displaySurface, producer);
@@ -1160,13 +1160,23 @@
Case::PerFrameMetadataSupport::setupComposerCallExpectations(this);
EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1);
- EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::TYPE, true)).Times(1);
+ EXPECT_CALL(*mEventThread,
+ onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY
+ ? EventThread::DisplayType::Primary
+ : EventThread::DisplayType::External,
+ true))
+ .Times(1);
}
template <typename Case>
void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() {
EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1);
- EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::TYPE, false)).Times(1);
+ EXPECT_CALL(*mEventThread,
+ onHotplugReceived(Case::Display::TYPE == DisplayDevice::DISPLAY_PRIMARY
+ ? EventThread::DisplayType::Primary
+ : EventThread::DisplayType::External,
+ false))
+ .Times(1);
}
template <typename Case>
@@ -1197,7 +1207,7 @@
static_assert(0 <= Case::Display::TYPE &&
Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES,
"Must use a valid physical display type index for the fixed-size array");
- auto& displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE];
+ auto& displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE];
ASSERT_TRUE(displayToken != nullptr);
verifyDisplayIsConnected<Case>(displayToken);
@@ -1303,7 +1313,7 @@
// The display should not be set up as a built-in display.
ASSERT_TRUE(0 <= Case::Display::TYPE &&
Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES);
- auto displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE];
+ auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE];
EXPECT_TRUE(displayToken == nullptr);
// The existing token should have been removed
@@ -1396,7 +1406,7 @@
// The display should not be set up as a primary built-in display.
ASSERT_TRUE(0 <= Case::Display::TYPE &&
Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES);
- auto displayToken = mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE];
+ auto displayToken = mFlinger.mutableDisplayTokens()[Case::Display::TYPE];
EXPECT_TRUE(displayToken == nullptr);
}
@@ -1439,7 +1449,7 @@
static_assert(0 <= Case::Display::TYPE &&
Case::Display::TYPE < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES,
"Display type must be a built-in display");
- EXPECT_NE(existing.token(), mFlinger.mutableBuiltinDisplays()[Case::Display::TYPE]);
+ EXPECT_NE(existing.token(), mFlinger.mutableDisplayTokens()[Case::Display::TYPE]);
// A new display should be connected in its place
@@ -1468,7 +1478,11 @@
// A virtual display was added to the current state, and it has a
// surface(producer)
sp<BBinder> displayToken = new BBinder();
- DisplayDeviceState info(Case::Display::TYPE, static_cast<bool>(Case::Display::SECURE));
+
+ DisplayDeviceState info;
+ info.type = Case::Display::TYPE;
+ info.isSecure = static_cast<bool>(Case::Display::SECURE);
+
sp<mock::GraphicBufferProducer> surface{new mock::GraphicBufferProducer()};
info.surface = surface;
mFlinger.mutableCurrentState().displays.add(displayToken, info);
@@ -1532,7 +1546,11 @@
// A virtual display was added to the current state, but it does not have a
// surface.
sp<BBinder> displayToken = new BBinder();
- DisplayDeviceState info(Case::Display::TYPE, static_cast<bool>(Case::Display::SECURE));
+
+ DisplayDeviceState info;
+ info.type = Case::Display::TYPE;
+ info.isSecure = static_cast<bool>(Case::Display::SECURE);
+
mFlinger.mutableCurrentState().displays.add(displayToken, info);
// --------------------------------------------------------------------
@@ -1811,40 +1829,6 @@
EXPECT_FALSE(hasCurrentDisplayState(displayToken));
}
-TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWithInvalidDisplay) {
- using Case = InvalidDisplayCase;
-
- // --------------------------------------------------------------------
- // Preconditions
-
- // An invalid display is set up
- auto display = Case::Display::makeFakeExistingDisplayInjector(this);
- display.inject();
-
- // The invalid display has some state
- display.mutableCurrentDisplayState().layerStack = 654u;
-
- // The requested display state tries to change the display state.
- DisplayState state;
- state.what = DisplayState::eLayerStackChanged;
- state.token = display.token();
- state.layerStack = 456;
-
- // --------------------------------------------------------------------
- // Invocation
-
- uint32_t flags = mFlinger.setDisplayStateLocked(state);
-
- // --------------------------------------------------------------------
- // Postconditions
-
- // The returned flags are empty
- EXPECT_EQ(0u, flags);
-
- // The current display layer stack value is unchanged.
- EXPECT_EQ(654u, getCurrentDisplayState(display.token()).layerStack);
-}
-
TEST_F(DisplayTransactionTest, setDisplayStateLockedDoesNothingWhenNoChanges) {
using Case = SimplePrimaryDisplayCase;
@@ -2671,7 +2655,7 @@
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.inject();
- // The diplay is already set to HWC_POWER_MODE_NORMAL
+ // The display is already set to HWC_POWER_MODE_NORMAL
display.mutableDisplayDevice()->setPowerMode(HWC_POWER_MODE_NORMAL);
// --------------------------------------------------------------------
@@ -2685,7 +2669,7 @@
EXPECT_EQ(HWC_POWER_MODE_NORMAL, display.mutableDisplayDevice()->getPowerMode());
}
-TEST_F(SetPowerModeInternalTest, setPowerModeInternalJustSetsInternalStateIfVirtualDisplay) {
+TEST_F(SetPowerModeInternalTest, setPowerModeInternalDoesNothingIfVirtualDisplay) {
using Case = HwcVirtualDisplayCase;
// --------------------------------------------------------------------
@@ -2700,13 +2684,13 @@
auto display = Case::Display::makeFakeExistingDisplayInjector(this);
display.inject();
- // The display is set to HWC_POWER_MODE_OFF
- getDisplayDevice(display.token())->setPowerMode(HWC_POWER_MODE_OFF);
+ // The display is set to HWC_POWER_MODE_NORMAL
+ getDisplayDevice(display.token())->setPowerMode(HWC_POWER_MODE_NORMAL);
// --------------------------------------------------------------------
// Invocation
- mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_NORMAL);
+ mFlinger.setPowerModeInternal(display.mutableDisplayDevice(), HWC_POWER_MODE_OFF);
// --------------------------------------------------------------------
// Postconditions
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 80fdb80..19747bd 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -71,7 +71,8 @@
ConnectionEventRecorder& connectionEventRecorder,
nsecs_t expectedTimestamp, unsigned expectedCount);
void expectVsyncEventReceivedByConnection(nsecs_t expectedTimestamp, unsigned expectedCount);
- void expectHotplugEventReceivedByConnection(int expectedDisplayType, bool expectedConnected);
+ void expectHotplugEventReceivedByConnection(EventThread::DisplayType expectedDisplayType,
+ bool expectedConnected);
AsyncCallRecorder<void (*)(bool)> mVSyncSetEnabledCallRecorder;
AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
@@ -169,13 +170,16 @@
expectedCount);
}
-void EventThreadTest::expectHotplugEventReceivedByConnection(int expectedDisplayType,
- bool expectedConnected) {
+void EventThreadTest::expectHotplugEventReceivedByConnection(
+ EventThread::DisplayType expectedDisplayType, bool expectedConnected) {
+ const uint32_t expectedDisplayId =
+ expectedDisplayType == EventThread::DisplayType::Primary ? 0 : 1;
+
auto args = mConnectionEventCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
const auto& event = std::get<0>(args.value());
EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, event.header.type);
- EXPECT_EQ(static_cast<unsigned>(expectedDisplayType), event.header.id);
+ EXPECT_EQ(expectedDisplayId, event.header.id);
EXPECT_EQ(expectedConnected, event.hotplug.connected);
}
@@ -394,28 +398,23 @@
}
TEST_F(EventThreadTest, postHotplugPrimaryDisconnect) {
- mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, false);
- expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, false);
+ mThread->onHotplugReceived(EventThread::DisplayType::Primary, false);
+ expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, false);
}
TEST_F(EventThreadTest, postHotplugPrimaryConnect) {
- mThread->onHotplugReceived(DisplayDevice::DISPLAY_PRIMARY, true);
- expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_PRIMARY, true);
+ mThread->onHotplugReceived(EventThread::DisplayType::Primary, true);
+ expectHotplugEventReceivedByConnection(EventThread::DisplayType::Primary, true);
}
TEST_F(EventThreadTest, postHotplugExternalDisconnect) {
- mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, false);
- expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, false);
+ mThread->onHotplugReceived(EventThread::DisplayType::External, false);
+ expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, false);
}
TEST_F(EventThreadTest, postHotplugExternalConnect) {
- mThread->onHotplugReceived(DisplayDevice::DISPLAY_EXTERNAL, true);
- expectHotplugEventReceivedByConnection(DisplayDevice::DISPLAY_EXTERNAL, true);
-}
-
-TEST_F(EventThreadTest, postHotplugVirtualDisconnectIsFilteredOut) {
- mThread->onHotplugReceived(DisplayDevice::DISPLAY_VIRTUAL, false);
- EXPECT_FALSE(mConnectionEventCallRecorder.waitForUnexpectedCall().has_value());
+ mThread->onHotplugReceived(EventThread::DisplayType::External, true);
+ expectHotplugEventReceivedByConnection(EventThread::DisplayType::External, true);
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index f1556d8..ae5a100 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -64,15 +64,17 @@
return mFlinger->createDisplay(displayName, secure);
}
- auto destroyDisplay(const sp<IBinder>& display) { return mFlinger->destroyDisplay(display); }
+ auto destroyDisplay(const sp<IBinder>& displayToken) {
+ return mFlinger->destroyDisplay(displayToken);
+ }
auto resetDisplayState() { return mFlinger->resetDisplayState(); }
- auto setupNewDisplayDeviceInternal(const wp<IBinder>& display, int hwcId,
+ auto setupNewDisplayDeviceInternal(const wp<IBinder>& displayToken, int32_t displayId,
const DisplayDeviceState& state,
const sp<DisplaySurface>& dispSurface,
const sp<IGraphicBufferProducer>& producer) {
- return mFlinger->setupNewDisplayDeviceInternal(display, hwcId, state, dispSurface,
+ return mFlinger->setupNewDisplayDeviceInternal(displayToken, displayId, state, dispSurface,
producer);
}
@@ -89,8 +91,9 @@
auto onInitializeDisplays() { return mFlinger->onInitializeDisplays(); }
- auto setPowerModeInternal(const sp<DisplayDevice>& hw, int mode, bool stateLockHeld = false) {
- return mFlinger->setPowerModeInternal(hw, mode, stateLockHeld);
+ auto setPowerModeInternal(const sp<DisplayDevice>& display, int mode,
+ bool stateLockHeld = false) {
+ return mFlinger->setPowerModeInternal(display, mode, stateLockHeld);
}
/* ------------------------------------------------------------------------
@@ -111,7 +114,7 @@
auto& mutableHasWideColorDisplay() { return SurfaceFlinger::hasWideColorDisplay; }
- auto& mutableBuiltinDisplays() { return mFlinger->mBuiltinDisplays; }
+ auto& mutableDisplayTokens() { return mFlinger->mDisplayTokens; }
auto& mutableCurrentState() { return mFlinger->mCurrentState; }
auto& mutableDisplays() { return mFlinger->mDisplays; }
auto& mutableDisplayColorSetting() { return mFlinger->mDisplayColorSetting; }
@@ -230,7 +233,7 @@
display->mutableIsConnected() = true;
ASSERT_TRUE(flinger->mutableHwcDisplayData().size() > static_cast<size_t>(mType));
- flinger->mutableHwcDisplayData()[mType].reset();
+ flinger->mutableHwcDisplayData()[mType] = HWComposer::DisplayData();
flinger->mutableHwcDisplayData()[mType].hwcDisplay = display.get();
flinger->mutableHwcDisplaySlots().emplace(mHwcDisplayId, mType);
@@ -253,8 +256,8 @@
class FakeDisplayDeviceInjector {
public:
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger, DisplayDevice::DisplayType type,
- int hwcId)
- : mFlinger(flinger), mType(type), mHwcId(hwcId) {}
+ int32_t displayId)
+ : mFlinger(flinger), mType(type), mDisplayId(displayId) {}
sp<IBinder> token() const { return mDisplayToken; }
@@ -274,7 +277,7 @@
return mFlinger.mutableCurrentState().displays.valueFor(mDisplayToken);
}
- auto& mutableDisplayDevice() { return mFlinger.mutableDisplays().valueFor(mDisplayToken); }
+ auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
mNativeWindow = nativeWindow;
@@ -299,18 +302,20 @@
sp<DisplayDevice> inject() {
std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> hdrAndRenderIntents;
sp<DisplayDevice> device =
- new DisplayDevice(mFlinger.mFlinger.get(), mType, mHwcId, mSecure, mDisplayToken,
- mNativeWindow, mDisplaySurface, std::move(mRenderSurface), 0,
- 0, false, HdrCapabilities(), 0, hdrAndRenderIntents,
- HWC_POWER_MODE_NORMAL);
- mFlinger.mutableDisplays().add(mDisplayToken, device);
+ new DisplayDevice(mFlinger.mFlinger.get(), mType, mDisplayId, mSecure,
+ mDisplayToken, mNativeWindow, mDisplaySurface,
+ std::move(mRenderSurface), 0, 0, false, HdrCapabilities(), 0,
+ hdrAndRenderIntents, HWC_POWER_MODE_NORMAL);
+ mFlinger.mutableDisplays().emplace(mDisplayToken, device);
- DisplayDeviceState state(mType, mSecure);
+ DisplayDeviceState state;
+ state.type = mType;
+ state.isSecure = mSecure;
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
if (mType >= DisplayDevice::DISPLAY_PRIMARY && mType < DisplayDevice::DISPLAY_VIRTUAL) {
- mFlinger.mutableBuiltinDisplays()[mType] = mDisplayToken;
+ mFlinger.mutableDisplayTokens()[mType] = mDisplayToken;
}
return device;
@@ -320,7 +325,7 @@
TestableSurfaceFlinger& mFlinger;
sp<BBinder> mDisplayToken = new BBinder();
DisplayDevice::DisplayType mType;
- int mHwcId;
+ const int32_t mDisplayId;
sp<ANativeWindow> mNativeWindow;
sp<DisplaySurface> mDisplaySurface;
std::unique_ptr<RE::Surface> mRenderSurface;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 267670a..2a707a4 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -77,6 +77,7 @@
MOCK_METHOD2(getPerFrameMetadataKeys,
Error(Display, std::vector<IComposerClient::PerFrameMetadataKey>*));
MOCK_METHOD2(getDataspaceSaturationMatrix, Error(Dataspace, mat4*));
+ MOCK_METHOD3(getDisplayIdentificationData, Error(Display, uint8_t*, std::vector<uint8_t>*));
MOCK_METHOD3(getReleaseFences, Error(Display, std::vector<Layer>*, std::vector<int>*));
MOCK_METHOD2(presentDisplay, Error(Display, int*));
MOCK_METHOD2(setActiveConfig, Error(Display, Config));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index e6ea663..df9bfc6 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -31,7 +31,7 @@
MOCK_CONST_METHOD0(createEventConnection, sp<BnDisplayEventConnection>());
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
- MOCK_METHOD2(onHotplugReceived, void(int, bool));
+ MOCK_METHOD2(onHotplugReceived, void(DisplayType, bool));
MOCK_CONST_METHOD1(dump, void(String8&));
MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset));
};
diff --git a/services/vr/bufferhubd/detached_buffer_channel.cpp b/services/vr/bufferhubd/detached_buffer_channel.cpp
index a5cf68d..3061805 100644
--- a/services/vr/bufferhubd/detached_buffer_channel.cpp
+++ b/services/vr/bufferhubd/detached_buffer_channel.cpp
@@ -109,6 +109,7 @@
return BufferDescription<BorrowedHandle>{buffer_,
metadata_buffer_,
buffer_id(),
+ channel_id(),
/*buffer_state_bit=*/0,
BorrowedHandle{},
BorrowedHandle{}};
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index b6977aa..97af660 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -236,9 +236,13 @@
BufferDescription<BorrowedHandle> ProducerChannel::GetBuffer(
uint64_t buffer_state_bit) {
- return {
- buffer_, metadata_buffer_, buffer_id(),
- buffer_state_bit, acquire_fence_fd_.Borrow(), release_fence_fd_.Borrow()};
+ return {buffer_,
+ metadata_buffer_,
+ buffer_id(),
+ channel_id(),
+ buffer_state_bit,
+ acquire_fence_fd_.Borrow(),
+ release_fence_fd_.Borrow()};
}
Status<BufferDescription<BorrowedHandle>> ProducerChannel::OnGetBuffer(
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index 67fdf15..10a4ce7 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -43,6 +43,8 @@
~ProducerChannel() override;
+ uint64_t buffer_state() const { return buffer_state_->load(); }
+
bool HandleMessage(Message& message) override;
void HandleImpulse(Message& message) override;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index c0c48c2..88f5508 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -76,6 +76,11 @@
message);
return true;
+ case BufferHubRPC::ProducerQueueInsertBuffer::Opcode:
+ DispatchRemoteMethod<BufferHubRPC::ProducerQueueInsertBuffer>(
+ *this, &ProducerQueueChannel::OnProducerQueueInsertBuffer, message);
+ return true;
+
case BufferHubRPC::ProducerQueueRemoveBuffer::Opcode:
DispatchRemoteMethod<BufferHubRPC::ProducerQueueRemoveBuffer>(
*this, &ProducerQueueChannel::OnProducerQueueRemoveBuffer, message);
@@ -278,6 +283,81 @@
return {{std::move(buffer_handle), slot}};
}
+Status<size_t> ProducerQueueChannel::OnProducerQueueInsertBuffer(
+ pdx::Message& message, int buffer_cid) {
+ ATRACE_NAME("ProducerQueueChannel::InsertBuffer");
+ ALOGD_IF(TRACE,
+ "ProducerQueueChannel::InsertBuffer: channel_id=%d, buffer_cid=%d",
+ channel_id(), buffer_cid);
+
+ if (capacity_ >= BufferHubRPC::kMaxQueueCapacity) {
+ ALOGE("ProducerQueueChannel::InsertBuffer: reaches kMaxQueueCapacity.");
+ return ErrorStatus(E2BIG);
+ }
+ auto producer_channel = std::static_pointer_cast<ProducerChannel>(
+ service()->GetChannel(buffer_cid));
+ if (producer_channel == nullptr ||
+ producer_channel->channel_type() != BufferHubChannel::kProducerType) {
+ // Rejects the request if the requested buffer channel is invalid and/or
+ // it's not a ProducerChannel.
+ ALOGE(
+ "ProducerQueueChannel::InsertBuffer: Invalid buffer_cid=%d, "
+ "producer_buffer=0x%p, channel_type=%d.",
+ buffer_cid, producer_channel.get(),
+ producer_channel == nullptr ? -1 : producer_channel->channel_type());
+ return ErrorStatus(EINVAL);
+ }
+ if (producer_channel->GetActiveProcessId() != message.GetProcessId()) {
+ // Rejects the request if the requested buffer channel is not currently
+ // connected to the caller this is IPC request. This effectively prevents
+ // fake buffer_cid from being injected.
+ ALOGE(
+ "ProducerQueueChannel::InsertBuffer: Requested buffer channel "
+ "(buffer_cid=%d) is not connected to the calling process (pid=%d). "
+ "It's connected to a different process (pid=%d).",
+ buffer_cid, message.GetProcessId(),
+ producer_channel->GetActiveProcessId());
+ return ErrorStatus(EINVAL);
+ }
+ uint64_t buffer_state = producer_channel->buffer_state();
+ if (!BufferHubDefs::IsBufferGained(buffer_state)) {
+ // Rejects the request if the requested buffer is not in Gained state.
+ ALOGE(
+ "ProducerQueueChannel::InsertBuffer: The buffer (cid=%d, "
+ "state=0x%" PRIx64 ") is not in gained state.",
+ buffer_cid, buffer_state);
+ return ErrorStatus(EINVAL);
+ }
+
+ // Register the to-be-inserted buffer's channel_id into the first empty
+ // buffer slot.
+ size_t slot = 0;
+ for (; slot < BufferHubRPC::kMaxQueueCapacity; slot++) {
+ if (buffers_[slot].expired())
+ break;
+ }
+ if (slot == BufferHubRPC::kMaxQueueCapacity) {
+ ALOGE(
+ "ProducerQueueChannel::AllocateBuffer: Cannot find empty slot for new "
+ "buffer allocation.");
+ return ErrorStatus(E2BIG);
+ }
+
+ buffers_[slot] = producer_channel;
+ capacity_++;
+
+ // Notify each consumer channel about the new buffer.
+ for (auto* consumer_channel : consumer_channels_) {
+ ALOGD(
+ "ProducerQueueChannel::AllocateBuffer: Notified consumer with new "
+ "buffer, buffer_cid=%d",
+ buffer_cid);
+ consumer_channel->RegisterNewBuffer(producer_channel, slot);
+ }
+
+ return {slot};
+}
+
Status<void> ProducerQueueChannel::OnProducerQueueRemoveBuffer(
Message& /*message*/, size_t slot) {
if (buffers_[slot].expired()) {
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index e825f47..e4fa243 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -38,8 +38,12 @@
uint32_t format, uint64_t usage,
size_t buffer_count);
- // Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
- // be in Gain'ed state for the producer queue to detach.
+ // Inserts a BufferProducer into the queue. Note that the buffer must be in
+ // Gain'ed state for the operation to succeed.
+ pdx::Status<size_t> OnProducerQueueInsertBuffer(pdx::Message& message, int buffer_cid);
+
+ // Removes a BufferProducer indicated by |slot|. Note that the buffer must be
+ // in Gain'ed state for the operation to succeed.
pdx::Status<void> OnProducerQueueRemoveBuffer(pdx::Message& message,
size_t slot);
diff --git a/services/vr/performanced/performance_service.cpp b/services/vr/performanced/performance_service.cpp
index 4c26671..d304bac 100644
--- a/services/vr/performanced/performance_service.cpp
+++ b/services/vr/performanced/performance_service.cpp
@@ -124,9 +124,6 @@
// TODO(eieio): Replace this witha device-specific config file. This is just a
// hack for now to put some form of permission logic in place while a longer
// term solution is developed.
- using AllowRootSystem =
- CheckAnd<SameProcess,
- CheckOr<UserId<AID_ROOT, AID_SYSTEM>, GroupId<AID_SYSTEM>>>;
using AllowRootSystemGraphics =
CheckAnd<SameProcess, CheckOr<UserId<AID_ROOT, AID_SYSTEM, AID_GRAPHICS>,
GroupId<AID_SYSTEM, AID_GRAPHICS>>>;
@@ -170,17 +167,17 @@
{.timer_slack = kTimerSlackForegroundNs,
.scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
.priority = fifo_low,
- .permission_check = AllowRootSystem::Check}},
+ .permission_check = AllowRootSystemTrusted::Check}},
{"sensors:low",
{.timer_slack = kTimerSlackForegroundNs,
.scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
.priority = fifo_low,
- .permission_check = AllowRootSystem::Check}},
+ .permission_check = AllowRootSystemTrusted::Check}},
{"sensors:high",
{.timer_slack = kTimerSlackForegroundNs,
.scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
.priority = fifo_low + 1,
- .permission_check = AllowRootSystem::Check}},
+ .permission_check = AllowRootSystemTrusted::Check}},
{"vr:system:arp",
{.timer_slack = kTimerSlackForegroundNs,
.scheduler_policy = SCHED_FIFO | SCHED_RESET_ON_FORK,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3db8a39..def1eca 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -575,15 +575,10 @@
break;
}
- // USAGE_CPU_READ_MASK 0xFUL
- // USAGE_CPU_WRITE_MASK (0xFUL << 4)
- // The currently used bits are as below:
- // USAGE_CPU_READ_RARELY = 2UL
- // USAGE_CPU_READ_OFTEN = 3UL
- // USAGE_CPU_WRITE_RARELY = (2UL << 4)
- // USAGE_CPU_WRITE_OFTEN = (3UL << 4)
- *supported = static_cast<VkBool32>(format_supported ||
- (surface->consumer_usage & 0xFFUL) == 0);
+ *supported = static_cast<VkBool32>(
+ format_supported || (surface->consumer_usage &
+ (AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
+ AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0);
return VK_SUCCESS;
}