Merge changes I25ddd986,I3cc43b2b
* changes:
BlastBufferQueue: Add support for auto refresh
BlastBufferQueue: Add buffer rejection
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index da342ff..3a62059 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -208,7 +208,7 @@
}
for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
- size_t remain = length;
+ ssize_t remain = length;
char* c = buffer;
if (!oneLine && !cStyle) {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index b1b2aa0..0377075 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2056,7 +2056,7 @@
if (size >= 0 && size < INT32_MAX) {
*outLen = size;
const char* str = (const char*)readInplace(size+1);
- if (str != nullptr) {
+ if (str != nullptr && str[size] == '\0') {
return str;
}
}
@@ -2139,7 +2139,7 @@
if (size >= 0 && size < INT32_MAX) {
*outLen = size;
const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t));
- if (str != nullptr) {
+ if (str != nullptr && str[size] == u'\0') {
return str;
}
}
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index ece25a0..4b2d50d 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -210,6 +210,8 @@
template<typename T>
status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
+ status_t writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val);
+ template<typename T>
status_t writeParcelableVector(const std::vector<T>& val);
template<typename T>
@@ -1229,6 +1231,16 @@
return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
}
+template<typename T>
+status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::optional<T>>>& val) {
+ if (val.get() == nullptr) {
+ return this->writeInt32(-1);
+ }
+
+ using NullableT = std::optional<T>;
+ return unsafeWriteTypedVector<NullableT, const NullableT&>(*val, &Parcel::writeNullableParcelable);
+}
+
template<typename T, std::enable_if_t<std::is_same_v<typename std::underlying_type_t<T>,int32_t>, bool>>
status_t Parcel::writeEnum(const T& val) {
return writeInt32(static_cast<int32_t>(val));
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 3e3eda1..ec7c7d8 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -261,7 +261,7 @@
}
binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
- std::unique_ptr<ParcelFileDescriptor> parcelFd;
+ std::optional<ParcelFileDescriptor> parcelFd;
status_t status = parcel->get()->readParcelable(&parcelFd);
if (status != STATUS_OK) return PruneStatusT(status);
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/parcel_fuzzer/binder.cpp
index a94f06f..96cd215 100644
--- a/libs/binder/parcel_fuzzer/binder.cpp
+++ b/libs/binder/parcel_fuzzer/binder.cpp
@@ -143,6 +143,13 @@
FUZZ_LOG() << "read c-str: " << (str ? str : "<empty string>");
},
PARCEL_READ_OPT_STATUS(android::String8, readString8),
+ [] (const ::android::Parcel& p, uint8_t /*data*/) {
+ FUZZ_LOG() << "about to readString8Inplace";
+ size_t outLen = 0;
+ const char* str = p.readString8Inplace(&outLen);
+ std::string bytes = hexString(str, sizeof(char) * (outLen + 1));
+ FUZZ_LOG() << "readString8Inplace: " << bytes << " size: " << outLen;
+ },
PARCEL_READ_OPT_STATUS(android::String16, readString16),
PARCEL_READ_WITH_STATUS(std::unique_ptr<android::String16>, readString16),
PARCEL_READ_WITH_STATUS(std::optional<android::String16>, readString16),
@@ -150,8 +157,8 @@
FUZZ_LOG() << "about to readString16Inplace";
size_t outLen = 0;
const char16_t* str = p.readString16Inplace(&outLen);
- FUZZ_LOG() << "readString16Inplace: " << hexString(str, sizeof(char16_t) * outLen)
- << " size: " << outLen;
+ std::string bytes = hexString(str, sizeof(char16_t) * (outLen + 1));
+ FUZZ_LOG() << "readString16Inplace: " << bytes << " size: " << outLen;
},
PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readStrongBinder),
PARCEL_READ_WITH_STATUS(android::sp<android::IBinder>, readNullableStrongBinder),
diff --git a/libs/binder/tests/binderParcelTest.cpp b/libs/binder/tests/binderParcelTest.cpp
index 1764228..841d47b 100644
--- a/libs/binder/tests/binderParcelTest.cpp
+++ b/libs/binder/tests/binderParcelTest.cpp
@@ -25,6 +25,40 @@
using android::String8;
using android::status_t;
+TEST(Parcel, NonNullTerminatedString8) {
+ String8 kTestString = String8("test-is-good");
+
+ // write non-null terminated string
+ Parcel p;
+ p.writeString8(kTestString);
+ p.setDataPosition(0);
+ // BAD! assumption of wire format for test
+ // write over length of string
+ p.writeInt32(kTestString.size() - 2);
+
+ p.setDataPosition(0);
+ String8 output;
+ EXPECT_NE(OK, p.readString8(&output));
+ EXPECT_EQ(output.size(), 0);
+}
+
+TEST(Parcel, NonNullTerminatedString16) {
+ String16 kTestString = String16("test-is-good");
+
+ // write non-null terminated string
+ Parcel p;
+ p.writeString16(kTestString);
+ p.setDataPosition(0);
+ // BAD! assumption of wire format for test
+ // write over length of string
+ p.writeInt32(kTestString.size() - 2);
+
+ p.setDataPosition(0);
+ String16 output;
+ EXPECT_NE(OK, p.readString16(&output));
+ EXPECT_EQ(output.size(), 0);
+}
+
// Tests a second operation results in a parcel at the same location as it
// started.
void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 1ec73ce..a375d43 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -397,6 +397,16 @@
return 0;
}
+int AHardwareBuffer_getId(const AHardwareBuffer* buffer, uint64_t* outId) {
+ if (!buffer || !outId) return BAD_VALUE;
+
+ const GraphicBuffer* gb = AHardwareBuffer_to_GraphicBuffer(buffer);
+ if (!gb) return BAD_VALUE;
+
+ *outId = gb->getId();
+
+ return OK;
+}
// ----------------------------------------------------------------------------
// VNDK functions
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index ae5e47b..4fcca9e 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -45,14 +45,14 @@
#ifndef ANDROID_HARDWARE_BUFFER_H
#define ANDROID_HARDWARE_BUFFER_H
+#include <android/rect.h>
#include <inttypes.h>
-
#include <sys/cdefs.h>
-#include <android/rect.h>
-
__BEGIN_DECLS
+// clang-format off
+
/**
* Buffer pixel formats.
*/
@@ -201,9 +201,9 @@
AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK = 0xFUL << 4,
/// The buffer will be read from by the GPU as a texture.
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE = 1UL << 8,
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE = 1UL << 8,
/// The buffer will be written to by the GPU as a framebuffer attachment.
- AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9,
+ AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER = 1UL << 9,
/**
* The buffer will be written to by the GPU as a framebuffer
* attachment.
@@ -214,7 +214,7 @@
* attachment should also have this flag. Use the equivalent flag
* AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER to avoid this confusion.
*/
- AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER,
+ AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT = AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER,
/**
* The buffer will be used as a composer HAL overlay layer.
*
@@ -225,7 +225,7 @@
* directly through AHardwareBuffer_allocate instead of buffers allocated
* by the framework.
*/
- AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY = 1ULL << 11,
+ AHARDWAREBUFFER_USAGE_COMPOSER_OVERLAY = 1ULL << 11,
/**
* The buffer is protected from direct CPU access or being read by
* non-secure hardware, such as video encoders.
@@ -236,19 +236,19 @@
* GL_EXT_protected_textures for more information on how these
* buffers are expected to behave.
*/
- AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14,
+ AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT = 1UL << 14,
/// The buffer will be read by a hardware video encoder.
- AHARDWAREBUFFER_USAGE_VIDEO_ENCODE = 1UL << 16,
+ AHARDWAREBUFFER_USAGE_VIDEO_ENCODE = 1UL << 16,
/**
* The buffer will be used for direct writes from sensors.
* When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB.
*/
- AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA = 1UL << 23,
+ AHARDWAREBUFFER_USAGE_SENSOR_DIRECT_DATA = 1UL << 23,
/**
* The buffer will be used as a shader storage or uniform buffer object.
* When this flag is present, the format must be AHARDWAREBUFFER_FORMAT_BLOB.
*/
- AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24,
+ AHARDWAREBUFFER_USAGE_GPU_DATA_BUFFER = 1UL << 24,
/**
* The buffer will be used as a cube map texture.
* When this flag is present, the buffer must have a layer count
@@ -256,13 +256,13 @@
* bound to OpenGL textures using the extension
* GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image.
*/
- AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP = 1UL << 25,
+ AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP = 1UL << 25,
/**
* The buffer contains a complete mipmap hierarchy.
* Note that buffers with this flag must be bound to OpenGL textures using
* the extension GL_EXT_EGL_image_storage instead of GL_KHR_EGL_image.
*/
- AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE = 1UL << 26,
+ AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE = 1UL << 26,
AHARDWAREBUFFER_USAGE_VENDOR_0 = 1ULL << 28,
AHARDWAREBUFFER_USAGE_VENDOR_1 = 1ULL << 29,
@@ -291,8 +291,8 @@
* parameters of existing ones.
*/
typedef struct AHardwareBuffer_Desc {
- uint32_t width; ///< Width in pixels.
- uint32_t height; ///< Height in pixels.
+ uint32_t width; ///< Width in pixels.
+ uint32_t height; ///< Height in pixels.
/**
* Number of images in an image array. AHardwareBuffers with one
* layer correspond to regular 2D textures. AHardwareBuffers with
@@ -301,21 +301,21 @@
* AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP is present, the buffer is
* a cube map or a cube map array.
*/
- uint32_t layers;
- uint32_t format; ///< One of AHardwareBuffer_Format.
- uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags.
- uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate()
- uint32_t rfu0; ///< Initialize to zero, reserved for future use.
- uint64_t rfu1; ///< Initialize to zero, reserved for future use.
+ uint32_t layers;
+ uint32_t format; ///< One of AHardwareBuffer_Format.
+ uint64_t usage; ///< Combination of AHardwareBuffer_UsageFlags.
+ uint32_t stride; ///< Row stride in pixels, ignored for AHardwareBuffer_allocate()
+ uint32_t rfu0; ///< Initialize to zero, reserved for future use.
+ uint64_t rfu1; ///< Initialize to zero, reserved for future use.
} AHardwareBuffer_Desc;
/**
* Holds data for a single image plane.
*/
typedef struct AHardwareBuffer_Plane {
- void* data; ///< Points to first byte in plane
- uint32_t pixelStride; ///< Distance in bytes from the color channel of one pixel to the next
- uint32_t rowStride; ///< Distance in bytes from the first value of one row of the image to
+ void* _Nullable data; ///< Points to first byte in plane
+ uint32_t pixelStride; ///< Distance in bytes from the color channel of one pixel to the next
+ uint32_t rowStride; ///< Distance in bytes from the first value of one row of the image to
/// the first value of the next row.
} AHardwareBuffer_Plane;
@@ -323,8 +323,8 @@
* Holds all image planes that contain the pixel data.
*/
typedef struct AHardwareBuffer_Planes {
- uint32_t planeCount; ///< Number of distinct planes
- AHardwareBuffer_Plane planes[4]; ///< Array of image planes
+ uint32_t planeCount; ///< Number of distinct planes
+ AHardwareBuffer_Plane planes[4]; ///< Array of image planes
} AHardwareBuffer_Planes;
/**
@@ -332,6 +332,8 @@
*/
typedef struct AHardwareBuffer AHardwareBuffer;
+// clang-format on
+
#if __ANDROID_API__ >= 26
/**
@@ -347,8 +349,8 @@
* \return 0 on success, or an error number of the allocation fails for
* any reason. The returned buffer has a reference count of 1.
*/
-int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* desc,
- AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
+int AHardwareBuffer_allocate(const AHardwareBuffer_Desc* _Nonnull desc,
+ AHardwareBuffer* _Nullable* _Nonnull outBuffer) __INTRODUCED_IN(26);
/**
* Acquire a reference on the given AHardwareBuffer object.
*
@@ -357,7 +359,7 @@
*
* Available since API level 26.
*/
-void AHardwareBuffer_acquire(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
+void AHardwareBuffer_acquire(AHardwareBuffer* _Nonnull buffer) __INTRODUCED_IN(26);
/**
* Remove a reference that was previously acquired with
@@ -365,7 +367,7 @@
*
* Available since API level 26.
*/
-void AHardwareBuffer_release(AHardwareBuffer* buffer) __INTRODUCED_IN(26);
+void AHardwareBuffer_release(AHardwareBuffer* _Nonnull buffer) __INTRODUCED_IN(26);
/**
* Return a description of the AHardwareBuffer in the passed
@@ -373,8 +375,8 @@
*
* Available since API level 26.
*/
-void AHardwareBuffer_describe(const AHardwareBuffer* buffer,
- AHardwareBuffer_Desc* outDesc) __INTRODUCED_IN(26);
+void AHardwareBuffer_describe(const AHardwareBuffer* _Nonnull buffer,
+ AHardwareBuffer_Desc* _Nonnull outDesc) __INTRODUCED_IN(26);
/**
* Lock the AHardwareBuffer for direct CPU access.
@@ -428,8 +430,57 @@
* has more than one layer. Error number if the lock fails for any other
* reason.
*/
-int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
- int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26);
+int AHardwareBuffer_lock(AHardwareBuffer* _Nonnull buffer, uint64_t usage, int32_t fence,
+ const ARect* _Nullable rect, void* _Nullable* _Nonnull outVirtualAddress)
+ __INTRODUCED_IN(26);
+
+/**
+ * Unlock the AHardwareBuffer from direct CPU access.
+ *
+ * Must be called after all changes to the buffer are completed by the
+ * caller. If \a fence is NULL, the function will block until all work
+ * is completed. Otherwise, \a fence will be set either to a valid file
+ * descriptor or to -1. The file descriptor will become signaled once
+ * the unlocking is complete and buffer contents are updated.
+ * The caller is responsible for closing the file descriptor once it's
+ * no longer needed. The value -1 indicates that unlocking has already
+ * completed before the function returned and no further operations are
+ * necessary.
+ *
+ * Available since API level 26.
+ *
+ * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if
+ * the unlock fails for any reason.
+ */
+int AHardwareBuffer_unlock(AHardwareBuffer* _Nonnull buffer, int32_t* _Nullable fence)
+ __INTRODUCED_IN(26);
+
+/**
+ * Send the AHardwareBuffer to an AF_UNIX socket.
+ *
+ * Available since API level 26.
+ *
+ * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
+ * number if the operation fails for any reason.
+ */
+int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* _Nonnull buffer, int socketFd)
+ __INTRODUCED_IN(26);
+
+/**
+ * Receive an AHardwareBuffer from an AF_UNIX socket.
+ *
+ * Available since API level 26.
+ *
+ * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
+ * number if the operation fails for any reason.
+ */
+int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd,
+ AHardwareBuffer* _Nullable* _Nonnull outBuffer)
+ __INTRODUCED_IN(26);
+
+#endif // __ANDROID_API__ >= 26
+
+#if __ANDROID_API__ >= 29
/**
* Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
@@ -458,52 +509,9 @@
* has more than one layer. Error number if the lock fails for any other
* reason.
*/
-int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage,
- int32_t fence, const ARect* rect, AHardwareBuffer_Planes* outPlanes) __INTRODUCED_IN(29);
-
-/**
- * Unlock the AHardwareBuffer from direct CPU access.
- *
- * Must be called after all changes to the buffer are completed by the
- * caller. If \a fence is NULL, the function will block until all work
- * is completed. Otherwise, \a fence will be set either to a valid file
- * descriptor or to -1. The file descriptor will become signaled once
- * the unlocking is complete and buffer contents are updated.
- * The caller is responsible for closing the file descriptor once it's
- * no longer needed. The value -1 indicates that unlocking has already
- * completed before the function returned and no further operations are
- * necessary.
- *
- * Available since API level 26.
- *
- * \return 0 on success. -EINVAL if \a buffer is NULL. Error number if
- * the unlock fails for any reason.
- */
-int AHardwareBuffer_unlock(AHardwareBuffer* buffer, int32_t* fence) __INTRODUCED_IN(26);
-
-/**
- * Send the AHardwareBuffer to an AF_UNIX socket.
- *
- * Available since API level 26.
- *
- * \return 0 on success, -EINVAL if \a buffer is NULL, or an error
- * number if the operation fails for any reason.
- */
-int AHardwareBuffer_sendHandleToUnixSocket(const AHardwareBuffer* buffer, int socketFd) __INTRODUCED_IN(26);
-
-/**
- * Receive an AHardwareBuffer from an AF_UNIX socket.
- *
- * Available since API level 26.
- *
- * \return 0 on success, -EINVAL if \a outBuffer is NULL, or an error
- * number if the operation fails for any reason.
- */
-int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) __INTRODUCED_IN(26);
-
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 29
+int AHardwareBuffer_lockPlanes(AHardwareBuffer* _Nonnull buffer, uint64_t usage, int32_t fence,
+ const ARect* _Nullable rect,
+ AHardwareBuffer_Planes* _Nonnull outPlanes) __INTRODUCED_IN(29);
/**
* Test whether the given format and usage flag combination is
@@ -524,7 +532,7 @@
* \return 1 if the format and usage flag combination is allocatable,
* 0 otherwise.
*/
-int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* desc) __INTRODUCED_IN(29);
+int AHardwareBuffer_isSupported(const AHardwareBuffer_Desc* _Nonnull desc) __INTRODUCED_IN(29);
/**
* Lock an AHardwareBuffer for direct CPU access.
@@ -537,11 +545,29 @@
*
* Available since API level 29.
*/
-int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
- int32_t fence, const ARect* rect, void** outVirtualAddress,
- int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29);
+int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* _Nonnull buffer, uint64_t usage, int32_t fence,
+ const ARect* _Nullable rect,
+ void* _Nullable* _Nonnull outVirtualAddress,
+ int32_t* _Nonnull outBytesPerPixel,
+ int32_t* _Nonnull outBytesPerStride) __INTRODUCED_IN(29);
+
#endif // __ANDROID_API__ >= 29
+#if __ANDROID_API__ >= 31
+
+/**
+ * Get the system wide unique id for an AHardwareBuffer.
+ *
+ * Available since API level 31.
+ *
+ * \return 0 on success, -EINVAL if \a buffer or \a outId is NULL, or an error number if the
+ * operation fails for any reason.
+ */
+int AHardwareBuffer_getId(const AHardwareBuffer* _Nonnull buffer, uint64_t* _Nonnull outId)
+ __INTRODUCED_IN(31);
+
+#endif // __ANDROID_API__ >= 31
+
__END_DECLS
#endif // ANDROID_HARDWARE_BUFFER_H
diff --git a/libs/nativewindow/include/vndk/hardware_buffer.h b/libs/nativewindow/include/vndk/hardware_buffer.h
index 3392d7f..50fe0b7 100644
--- a/libs/nativewindow/include/vndk/hardware_buffer.h
+++ b/libs/nativewindow/include/vndk/hardware_buffer.h
@@ -24,7 +24,14 @@
__BEGIN_DECLS
-const native_handle_t* AHardwareBuffer_getNativeHandle(const AHardwareBuffer* buffer);
+/**
+ * Get the native handle from an AHardwareBuffer.
+ *
+ * \return a non-NULL native handle on success, NULL if \a buffer is nullptr or the operation fails
+ * for any reason.
+ */
+const native_handle_t* _Nullable AHardwareBuffer_getNativeHandle(
+ const AHardwareBuffer* _Nonnull buffer);
enum CreateFromHandleMethod {
// enum values chosen to match internal GraphicBuffer::HandleWrapMethod
@@ -33,9 +40,9 @@
};
/**
- * Create a AHardwareBuffer from a native handle.
+ * Create an AHardwareBuffer from a native handle.
*
- * This function wraps a native handle in a AHardwareBuffer suitable for use by applications or
+ * This function wraps a native handle in an AHardwareBuffer suitable for use by applications or
* other parts of the system. The contents of desc will be returned by AHardwareBuffer_describe().
*
* If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_REGISTER, the handle is assumed to be
@@ -44,10 +51,13 @@
*
* If method is AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, the handle will be cloned and the
* clone registered. The AHardwareBuffer will own the cloned handle but not the original.
+ *
+ * \return 0 on success, -EINVAL if \a desc or \a handle or outBuffer is NULL, or an error number if
+ * the operation fails for any reason.
*/
-int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* desc,
- const native_handle_t* handle, int32_t method,
- AHardwareBuffer** outBuffer);
+int AHardwareBuffer_createFromHandle(const AHardwareBuffer_Desc* _Nonnull desc,
+ const native_handle_t* _Nonnull handle, int32_t method,
+ AHardwareBuffer* _Nullable* _Nonnull outBuffer);
/**
* Buffer pixel formats.
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index de48ec2..24d0e3b 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -4,6 +4,7 @@
AHardwareBuffer_allocate;
AHardwareBuffer_createFromHandle; # llndk # apex
AHardwareBuffer_describe;
+ AHardwareBuffer_getId; # introduced=31
AHardwareBuffer_getNativeHandle; # llndk # apex
AHardwareBuffer_isSupported; # introduced=29
AHardwareBuffer_lock;
diff --git a/libs/nativewindow/tests/AHardwareBufferTest.cpp b/libs/nativewindow/tests/AHardwareBufferTest.cpp
index 71b1f9f..ef863b6 100644
--- a/libs/nativewindow/tests/AHardwareBufferTest.cpp
+++ b/libs/nativewindow/tests/AHardwareBufferTest.cpp
@@ -17,12 +17,11 @@
#define LOG_TAG "AHardwareBuffer_test"
//#define LOG_NDEBUG 0
-#include <android/hardware_buffer.h>
-#include <private/android/AHardwareBufferHelpers.h>
#include <android/hardware/graphics/common/1.0/types.h>
-#include <vndk/hardware_buffer.h>
-
#include <gtest/gtest.h>
+#include <private/android/AHardwareBufferHelpers.h>
+#include <ui/GraphicBuffer.h>
+#include <vndk/hardware_buffer.h>
using namespace android;
using android::hardware::graphics::common::V1_0::BufferUsage;
@@ -131,3 +130,43 @@
AHardwareBuffer_release(buffer);
AHardwareBuffer_release(otherBuffer);
}
+
+TEST(AHardwareBufferTest, GetIdTest) {
+ const uint32_t testWidth = 4;
+ const uint32_t testHeight = 4;
+ const uint32_t testLayers = 1;
+
+ AHardwareBuffer* ahb1 = nullptr;
+ uint64_t id1 = 0;
+ const AHardwareBuffer_Desc desc = {
+ .width = testWidth,
+ .height = testHeight,
+ .layers = testLayers,
+ .format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
+ .usage = AHARDWAREBUFFER_USAGE_CPU_READ_RARELY,
+ };
+ int res = AHardwareBuffer_allocate(&desc, &ahb1);
+ EXPECT_EQ(NO_ERROR, res);
+ EXPECT_NE(nullptr, ahb1);
+ EXPECT_EQ(0, AHardwareBuffer_getId(ahb1, &id1));
+ const GraphicBuffer* gb1 = AHardwareBuffer_to_GraphicBuffer(ahb1);
+ EXPECT_NE(nullptr, gb1);
+ EXPECT_EQ(id1, gb1->getId());
+ EXPECT_NE(id1, 0);
+
+ sp<GraphicBuffer> gb2(new GraphicBuffer(testWidth,
+ testHeight,
+ PIXEL_FORMAT_RGBA_8888,
+ testLayers,
+ GraphicBuffer::USAGE_SW_READ_RARELY,
+ std::string("test")));
+ EXPECT_NE(nullptr, gb2.get());
+ const AHardwareBuffer* ahb2 = AHardwareBuffer_from_GraphicBuffer(gb2.get());
+ EXPECT_NE(nullptr, ahb2);
+ uint64_t id2 = 0;
+ EXPECT_EQ(0, AHardwareBuffer_getId(ahb2, &id2));
+ EXPECT_EQ(id2, gb2->getId());
+ EXPECT_NE(id2, 0);
+
+ EXPECT_NE(id1, id2);
+}
diff --git a/libs/nativewindow/tests/Android.bp b/libs/nativewindow/tests/Android.bp
index cdb3d20..2e4bd99 100644
--- a/libs/nativewindow/tests/Android.bp
+++ b/libs/nativewindow/tests/Android.bp
@@ -24,6 +24,7 @@
"liblog",
"libnativewindow",
"libsync",
+ "libui",
"libutils",
"android.hardware.graphics.common@1.0",
],
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index fff7854..8c5f0e6 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -252,8 +252,8 @@
// initialize the renderer while GL is current
std::unique_ptr<SkiaGLRenderEngine> engine =
- std::make_unique<SkiaGLRenderEngine>(args, display, config, ctxt, placeholder,
- protectedContext, protectedPlaceholder);
+ std::make_unique<SkiaGLRenderEngine>(args, display, ctxt, placeholder, protectedContext,
+ protectedPlaceholder);
ALOGI("OpenGL ES informations:");
ALOGI("vendor : %s", extensions.getVendor());
@@ -306,38 +306,52 @@
}
SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
- EGLConfig config, EGLContext ctxt, EGLSurface placeholder,
+ EGLContext ctxt, EGLSurface placeholder,
EGLContext protectedContext, EGLSurface protectedPlaceholder)
: mEGLDisplay(display),
- mEGLConfig(config),
mEGLContext(ctxt),
mPlaceholderSurface(placeholder),
mProtectedEGLContext(protectedContext),
mProtectedPlaceholderSurface(protectedPlaceholder),
mUseColorManagement(args.useColorManagement) {
- // Suppress unused field warnings for things we definitely will need/use
- // These EGL fields will all be needed for toggling between protected & unprotected contexts
- // Or we need different RE instances for that
- (void)mEGLDisplay;
- (void)mEGLConfig;
- (void)mEGLContext;
- (void)mPlaceholderSurface;
- (void)mProtectedEGLContext;
- (void)mProtectedPlaceholderSurface;
-
sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
LOG_ALWAYS_FATAL_IF(!glInterface.get());
GrContextOptions options;
options.fPreferExternalImagesOverES3 = true;
options.fDisableDistanceFieldPaths = true;
- mGrContext = GrDirectContext::MakeGL(std::move(glInterface), options);
+ mGrContext = GrDirectContext::MakeGL(glInterface, options);
+ if (useProtectedContext(true)) {
+ mProtectedGrContext = GrDirectContext::MakeGL(glInterface, options);
+ useProtectedContext(false);
+ }
if (args.supportsBackgroundBlur) {
mBlurFilter = new BlurFilter();
}
}
+bool SkiaGLRenderEngine::supportsProtectedContent() const {
+ return mProtectedEGLContext != EGL_NO_CONTEXT;
+}
+
+bool SkiaGLRenderEngine::useProtectedContext(bool useProtectedContext) {
+ if (useProtectedContext == mInProtectedContext) {
+ return true;
+ }
+ if (useProtectedContext && supportsProtectedContent()) {
+ return false;
+ }
+ const EGLSurface surface =
+ useProtectedContext ? mProtectedPlaceholderSurface : mPlaceholderSurface;
+ const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
+ const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
+ if (success) {
+ mInProtectedContext = useProtectedContext;
+ }
+ return success;
+}
+
base::unique_fd SkiaGLRenderEngine::flush() {
ATRACE_CALL();
if (!gl::GLExtensions::getInstance().hasNativeFenceSync()) {
@@ -471,22 +485,23 @@
return BAD_VALUE;
}
+ auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext;
+ auto cache = mInProtectedContext ? mProtectedSurfaceCache : mSurfaceCache;
AHardwareBuffer_Desc bufferDesc;
AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc);
-
LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE),
"missing usage");
sk_sp<SkSurface> surface;
if (useFramebufferCache) {
- auto iter = mSurfaceCache.find(buffer->getId());
- if (iter != mSurfaceCache.end()) {
+ auto iter = cache.find(buffer->getId());
+ if (iter != cache.end()) {
ALOGV("Cache hit!");
surface = iter->second;
}
}
if (!surface) {
- surface = SkSurface::MakeFromAHardwareBuffer(mGrContext.get(), buffer->toAHardwareBuffer(),
+ surface = SkSurface::MakeFromAHardwareBuffer(grContext.get(), buffer->toAHardwareBuffer(),
GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
mUseColorManagement
? toColorSpace(display.outputDataspace)
@@ -494,7 +509,7 @@
nullptr);
if (useFramebufferCache && surface) {
ALOGD("Adding to cache");
- mSurfaceCache.insert({buffer->getId(), surface});
+ cache.insert({buffer->getId(), surface});
}
}
if (!surface) {
@@ -705,7 +720,7 @@
} else {
ATRACE_BEGIN("Submit(sync=false)");
}
- bool success = mGrContext->submit(requireSync);
+ bool success = grContext->submit(requireSync);
ATRACE_END();
if (!success) {
ALOGE("Failed to flush RenderEngine commands");
@@ -897,6 +912,7 @@
void SkiaGLRenderEngine::cleanFramebufferCache() {
mSurfaceCache.clear();
+ mProtectedSurfaceCache.clear();
}
} // namespace skia
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 43db3b1..965cb41 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -40,8 +40,8 @@
class SkiaGLRenderEngine : public skia::SkiaRenderEngine {
public:
static std::unique_ptr<SkiaGLRenderEngine> create(const RenderEngineCreationArgs& args);
- SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config,
- EGLContext ctxt, EGLSurface placeholder, EGLContext protectedContext,
+ SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLContext ctxt,
+ EGLSurface placeholder, EGLContext protectedContext,
EGLSurface protectedPlaceholder);
~SkiaGLRenderEngine() override{};
@@ -51,6 +51,9 @@
const sp<GraphicBuffer>& buffer, const bool useFramebufferCache,
base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
void cleanFramebufferCache() override;
+ bool isProtected() const override { return mInProtectedContext; }
+ bool supportsProtectedContent() const override;
+ bool useProtectedContext(bool useProtectedContext) override;
protected:
void dump(std::string& /*result*/) override{};
@@ -81,7 +84,6 @@
const SkMatrix& drawTransform, sk_sp<SkSurface> blurrendSurface);
EGLDisplay mEGLDisplay;
- EGLConfig mEGLConfig;
EGLContext mEGLContext;
EGLSurface mPlaceholderSurface;
EGLContext mProtectedEGLContext;
@@ -100,9 +102,14 @@
sp<Fence> mLastDrawFence;
+ // Graphics context used for creating surfaces and submitting commands
sk_sp<GrDirectContext> mGrContext;
+ // Same as above, but for protected content (eg. DRM)
+ sk_sp<GrDirectContext> mProtectedGrContext;
std::unordered_map<uint64_t, sk_sp<SkSurface>> mSurfaceCache;
+ std::unordered_map<uint64_t, sk_sp<SkSurface>> mProtectedSurfaceCache;
+ bool mInProtectedContext = false;
};
} // namespace skia
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index 340d7bf..d5a19d3 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -80,6 +80,7 @@
cc_library_shared {
name: "libdvr.google",
+ system_ext_specific: true,
owner: "google",
cflags: cflags,
header_libs: ["libdvr_headers"],
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index 1ce9c99..b3534de 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -45,6 +45,7 @@
cc_binary {
name: "pdx_tool",
+ system_ext_specific: true,
defaults: ["pdx_default_transport_compiler_defaults"],
srcs: [
"pdx_tool.cpp",
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index ff5f6d8..b28bff2 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -4490,7 +4490,7 @@
dump += StringPrintf(INDENT3 "%zu: name='%s', id=%" PRId32 ", displayId=%d, "
"portalToDisplayId=%d, paused=%s, focusable=%s, "
"hasWallpaper=%s, visible=%s, alpha=%.2f, "
- "flags=%s, type=0x%08x, "
+ "flags=%s, type=%s, "
"frame=[%d,%d][%d,%d], globalScale=%f, "
"applicationInfo=%s, "
"touchableRegion=",
@@ -4501,7 +4501,7 @@
toString(windowInfo->hasWallpaper),
toString(windowInfo->visible), windowInfo->alpha,
windowInfo->flags.string().c_str(),
- static_cast<int32_t>(windowInfo->type),
+ NamedEnum::string(windowInfo->type).c_str(),
windowInfo->frameLeft, windowInfo->frameTop,
windowInfo->frameRight, windowInfo->frameBottom,
windowInfo->globalScaleFactor,
@@ -4510,11 +4510,13 @@
dump += StringPrintf(", inputFeatures=%s",
windowInfo->inputFeatures.string().c_str());
dump += StringPrintf(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%" PRId64
- "ms, trustedOverlay=%s, hasToken=%s\n",
+ "ms, trustedOverlay=%s, hasToken=%s, "
+ "touchOcclusionMode=%s\n",
windowInfo->ownerPid, windowInfo->ownerUid,
millis(windowInfo->dispatchingTimeout),
toString(windowInfo->trustedOverlay),
- toString(windowInfo->token != nullptr));
+ toString(windowInfo->token != nullptr),
+ toString(windowInfo->touchOcclusionMode).c_str());
windowInfo->transform.dump(dump, "transform", INDENT4);
}
} else {
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 4b4c050..901e19a 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -64,7 +64,7 @@
PowerAdvisor::PowerAdvisor()
: mUseUpdateImminentTimer(getUpdateTimeout() > 0),
mUpdateImminentTimer(
- OneShotTimer::Interval(getUpdateTimeout()),
+ "UpdateImminentTimer", OneShotTimer::Interval(getUpdateTimeout()),
/* resetCallback */ [this] { mSendUpdateImminent.store(false); },
/* timeoutCallback */ [this] { mSendUpdateImminent.store(true); }) {
if (mUseUpdateImminentTimer) {
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index b7b7e46..2511eb3 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -175,6 +175,7 @@
mScheduler(scheduler),
mTunables(tunables),
mIdleTimer(
+ "RegionSamplingIdleTimer",
std::chrono::duration_cast<std::chrono::milliseconds>(
mTunables.mSamplingTimerTimeout),
[] {}, [this] { checkForStaleLuma(); }),
diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
index 2783800..ce3b0c6 100644
--- a/services/surfaceflinger/Scheduler/OneShotTimer.cpp
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
@@ -16,6 +16,8 @@
#include "OneShotTimer.h"
+#include <utils/Log.h>
+#include <utils/Timers.h>
#include <chrono>
#include <sstream>
#include <thread>
@@ -29,25 +31,30 @@
// (tv_sec) is the whole count of seconds. The second (tv_nsec) is the
// nanosecond part of the count. This function takes care of translation.
void calculateTimeoutTime(std::chrono::nanoseconds timestamp, timespec* spec) {
- clock_gettime(CLOCK_MONOTONIC, spec);
- spec->tv_sec += static_cast<__kernel_time_t>(timestamp.count() / kNsToSeconds);
- spec->tv_nsec += timestamp.count() % kNsToSeconds;
+ const nsecs_t timeout = systemTime(CLOCK_MONOTONIC) + timestamp.count();
+ spec->tv_sec = static_cast<__kernel_time_t>(timeout / kNsToSeconds);
+ spec->tv_nsec = timeout % kNsToSeconds;
}
} // namespace
namespace android {
namespace scheduler {
-OneShotTimer::OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+OneShotTimer::OneShotTimer(std::string name, const Interval& interval,
+ const ResetCallback& resetCallback,
const TimeoutCallback& timeoutCallback)
- : mInterval(interval), mResetCallback(resetCallback), mTimeoutCallback(timeoutCallback) {}
+ : mName(std::move(name)),
+ mInterval(interval),
+ mResetCallback(resetCallback),
+ mTimeoutCallback(timeoutCallback) {}
OneShotTimer::~OneShotTimer() {
stop();
}
void OneShotTimer::start() {
- sem_init(&mSemaphore, 0, 0);
+ int result = sem_init(&mSemaphore, 0, 0);
+ LOG_ALWAYS_FATAL_IF(result, "sem_init failed");
if (!mThread.joinable()) {
// Only create thread if it has not been created.
@@ -57,15 +64,21 @@
void OneShotTimer::stop() {
mStopTriggered = true;
- sem_post(&mSemaphore);
+ int result = sem_post(&mSemaphore);
+ LOG_ALWAYS_FATAL_IF(result, "sem_post failed");
if (mThread.joinable()) {
mThread.join();
- sem_destroy(&mSemaphore);
+ result = sem_destroy(&mSemaphore);
+ LOG_ALWAYS_FATAL_IF(result, "sem_destroy failed");
}
}
void OneShotTimer::loop() {
+ if (pthread_setname_np(pthread_self(), mName.c_str())) {
+ ALOGW("Failed to set thread name on dispatch thread");
+ }
+
TimerState state = TimerState::RESET;
while (true) {
bool triggerReset = false;
@@ -77,7 +90,12 @@
}
if (state == TimerState::IDLE) {
- sem_wait(&mSemaphore);
+ int result = sem_wait(&mSemaphore);
+ if (result && errno != EINTR) {
+ std::stringstream ss;
+ ss << "sem_wait failed (" << errno << ")";
+ LOG_ALWAYS_FATAL("%s", ss.str().c_str());
+ }
continue;
}
@@ -101,7 +119,12 @@
// Wait for mInterval time for semaphore signal.
struct timespec ts;
calculateTimeoutTime(std::chrono::nanoseconds(mInterval), &ts);
- sem_clockwait(&mSemaphore, CLOCK_MONOTONIC, &ts);
+ int result = sem_clockwait(&mSemaphore, CLOCK_MONOTONIC, &ts);
+ if (result && errno != ETIMEDOUT && errno != EINTR) {
+ std::stringstream ss;
+ ss << "sem_clockwait failed (" << errno << ")";
+ LOG_ALWAYS_FATAL("%s", ss.str().c_str());
+ }
state = checkForResetAndStop(state);
if (state == TimerState::RESET) {
@@ -135,7 +158,8 @@
void OneShotTimer::reset() {
mResetTriggered = true;
- sem_post(&mSemaphore);
+ int result = sem_post(&mSemaphore);
+ LOG_ALWAYS_FATAL_IF(result, "sem_post failed");
}
std::string OneShotTimer::dump() const {
diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h
index 8bbd4f5..3690ce7 100644
--- a/services/surfaceflinger/Scheduler/OneShotTimer.h
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.h
@@ -36,7 +36,7 @@
using ResetCallback = std::function<void()>;
using TimeoutCallback = std::function<void()>;
- OneShotTimer(const Interval& interval, const ResetCallback& resetCallback,
+ OneShotTimer(std::string name, const Interval& interval, const ResetCallback& resetCallback,
const TimeoutCallback& timeoutCallback);
~OneShotTimer();
@@ -81,6 +81,9 @@
// Semaphore to keep mThread synchronized.
sem_t mSemaphore;
+ // Timer's name.
+ std::string mName;
+
// Interval after which timer expires.
const Interval mInterval;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index a14019e..3706631 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -135,7 +135,7 @@
const auto callback = mOptions.supportKernelTimer ? &Scheduler::kernelIdleTimerCallback
: &Scheduler::idleTimerCallback;
mIdleTimer.emplace(
- std::chrono::milliseconds(millis),
+ "IdleTimer", std::chrono::milliseconds(millis),
[this, callback] { std::invoke(callback, this, TimerState::Reset); },
[this, callback] { std::invoke(callback, this, TimerState::Expired); });
mIdleTimer->start();
@@ -144,7 +144,7 @@
if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
// Touch events are coming to SF every 100ms, so the timer needs to be higher than that
mTouchTimer.emplace(
- std::chrono::milliseconds(millis),
+ "TouchTimer", std::chrono::milliseconds(millis),
[this] { touchTimerCallback(TimerState::Reset); },
[this] { touchTimerCallback(TimerState::Expired); });
mTouchTimer->start();
@@ -152,7 +152,7 @@
if (const int64_t millis = set_display_power_timer_ms(0); millis > 0) {
mDisplayPowerTimer.emplace(
- std::chrono::milliseconds(millis),
+ "DisplayPowerTimer", std::chrono::milliseconds(millis),
[this] { displayPowerTimerCallback(TimerState::Reset); },
[this] { displayPowerTimerCallback(TimerState::Expired); });
mDisplayPowerTimer->start();
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index 75d1e6f..a28ed92 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -77,8 +77,12 @@
if (!validate(timestamp)) {
// VSR could elect to ignore the incongruent timestamp or resetModel(). If ts is ignored,
- // don't insert this ts into mTimestamps ringbuffer.
- if (!mTimestamps.empty()) {
+ // don't insert this ts into mTimestamps ringbuffer. If we are still
+ // in the learning phase we should just clear all timestamps and start
+ // over.
+ if (mTimestamps.size() < kMinimumSamplesForPrediction) {
+ clearTimestamps();
+ } else if (!mTimestamps.empty()) {
mKnownTimestamp =
std::max(timestamp, *std::max_element(mTimestamps.begin(), mTimestamps.end()));
} else {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4e398d3..604a83a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -330,7 +330,7 @@
: mFactory(factory),
mInterceptor(mFactory.createSurfaceInterceptor()),
mTimeStats(std::make_shared<impl::TimeStats>()),
- mFrameTracer(std::make_unique<FrameTracer>()),
+ mFrameTracer(mFactory.createFrameTracer()),
mFrameTimeline(std::make_unique<frametimeline::impl::FrameTimeline>(mTimeStats)),
mEventQueue(mFactory.createMessageQueue()),
mCompositionEngine(mFactory.createCompositionEngine()),
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index 9a8deae..a93f5f6 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -28,6 +28,7 @@
#include "ContainerLayer.h"
#include "DisplayDevice.h"
#include "EffectLayer.h"
+#include "FrameTracer/FrameTracer.h"
#include "Layer.h"
#include "MonitoredProducer.h"
#include "NativeWindowSurface.h"
@@ -130,6 +131,9 @@
return new EffectLayer(args);
}
+std::unique_ptr<FrameTracer> DefaultFactory::createFrameTracer() {
+ return std::make_unique<FrameTracer>();
+}
} // namespace android::surfaceflinger
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
index 40774ef..90032d4 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
@@ -54,6 +54,7 @@
sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) override;
sp<EffectLayer> createEffectLayer(const LayerCreationArgs& args) override;
sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) override;
+ std::unique_ptr<FrameTracer> createFrameTracer() override;
};
} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 2dd563b..69e9c3c 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -34,6 +34,7 @@
class EffectLayer;
class ContainerLayer;
class DisplayDevice;
+class FrameTracer;
class GraphicBuffer;
class HWComposer;
class IGraphicBufferConsumer;
@@ -100,6 +101,7 @@
virtual sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) = 0;
virtual sp<EffectLayer> createEffectLayer(const LayerCreationArgs& args) = 0;
virtual sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) = 0;
+ virtual std::unique_ptr<FrameTracer> createFrameTracer() = 0;
protected:
~Factory() = default;
diff --git a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
index 0208728..cfbb3f5 100644
--- a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
@@ -57,11 +57,12 @@
namespace {
TEST_F(OneShotTimerTest, createAndDestroyTest) {
mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
- 3ms, [] {}, [] {});
+ "TestTimer", 3ms, [] {}, [] {});
}
TEST_F(OneShotTimerTest, startStopTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(30ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 30ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
auto startTime = std::chrono::steady_clock::now();
mIdleTimer->start();
@@ -81,7 +82,8 @@
}
TEST_F(OneShotTimerTest, resetTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 20ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -106,7 +108,8 @@
}
TEST_F(OneShotTimerTest, resetBackToBackTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(20ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 20ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -137,7 +140,8 @@
}
TEST_F(OneShotTimerTest, startNotCalledTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 3ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
// The start hasn't happened, so the callback does not happen.
EXPECT_FALSE(mExpiredTimerCallback.waitForCall(waitTimeForUnexpected3msCallback).has_value());
@@ -149,7 +153,8 @@
}
TEST_F(OneShotTimerTest, idleTimerIdlesTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 3ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -169,7 +174,8 @@
}
TEST_F(OneShotTimerTest, timeoutCallbackExecutionTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 3ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -178,7 +184,8 @@
}
TEST_F(OneShotTimerTest, noCallbacksAfterStopAndResetTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 3ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -192,7 +199,8 @@
}
TEST_F(OneShotTimerTest, noCallbacksAfterStopTest) {
- mIdleTimer = std::make_unique<scheduler::OneShotTimer>(3ms, mResetTimerCallback.getInvocable(),
+ mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 3ms,
+ mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable());
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index a9d9dc0..1b6e9ed 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -83,7 +83,7 @@
mTouchTimer.reset();
}
mTouchTimer.emplace(
- std::chrono::milliseconds(millis),
+ "Testable Touch timer", std::chrono::milliseconds(millis),
[this] { touchTimerCallback(TimerState::Reset); },
[this] { touchTimerCallback(TimerState::Expired); });
mTouchTimer->start();
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 6ce738a..eba3f8e 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -30,6 +30,7 @@
#include "DisplayDevice.h"
#include "EffectLayer.h"
#include "FakeVsyncConfiguration.h"
+#include "FrameTracer/FrameTracer.h"
#include "Layer.h"
#include "NativeWindowSurface.h"
#include "Scheduler/MessageQueue.h"
@@ -41,6 +42,7 @@
#include "TestableScheduler.h"
#include "mock/DisplayHardware/MockDisplay.h"
#include "mock/MockDisplayIdGenerator.h"
+#include "mock/MockFrameTracer.h"
namespace android {
@@ -148,6 +150,10 @@
return nullptr;
}
+ std::unique_ptr<FrameTracer> createFrameTracer() override {
+ return std::make_unique<mock::FrameTracer>();
+ }
+
using CreateBufferQueueFunction =
std::function<void(sp<IGraphicBufferProducer>* /* outProducer */,
sp<IGraphicBufferConsumer>* /* outConsumer */,
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index 3d60479..a142022 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -475,6 +475,20 @@
}
}
+TEST_F(VSyncPredictorTest, InconsistentVsyncValueIsFlushedEventually) {
+ EXPECT_TRUE(tracker.addVsyncTimestamp(600));
+ EXPECT_TRUE(tracker.needsMoreSamples());
+
+ EXPECT_FALSE(tracker.addVsyncTimestamp(mNow += mPeriod));
+
+ for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
+ EXPECT_TRUE(tracker.needsMoreSamples());
+ EXPECT_TRUE(tracker.addVsyncTimestamp(mNow += mPeriod));
+ }
+
+ EXPECT_FALSE(tracker.needsMoreSamples());
+}
+
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index afb3004..7097e7a 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -15,7 +15,6 @@
sharedLibraries = [
"libbase",
"libcutils",
- "libgtest_prod",
"libgui",
"liblog",
"libpdx_default_transport",
@@ -48,6 +47,7 @@
cc_binary {
srcs: ["bufferhubd.cpp"],
+ system_ext_specific: true,
cflags: [
"-DLOG_TAG=\"bufferhubd\"",
"-DTRACE=0",
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 4df7b7c..3728731 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,6 +1,8 @@
cc_library_shared {
name: "libvr_hwc-hal",
+ system_ext_specific: true,
+
srcs: [
"impl/vr_hwc.cpp",
"impl/vr_composer_client.cpp",
@@ -97,6 +99,7 @@
cc_binary {
name: "vr_hwc",
+ system_ext_specific: true,
vintf_fragments: ["manifest_vr_hwc.xml"],
srcs: [
"vr_hardware_composer_service.cpp",
diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp
index 20301f6..0ef8cc4 100644
--- a/services/vr/performanced/Android.bp
+++ b/services/vr/performanced/Android.bp
@@ -30,6 +30,7 @@
cc_binary {
name: "performanced",
+ system_ext_specific: true,
defaults: ["performanced_defaults"],
srcs: [
"cpu_set.cpp",