Merge "libhwc2on1adapter: avoid marking changes if visible regions unchanged" into oc-mr1-dev
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 3c4a933..f29da17 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1796,8 +1796,14 @@
}
const char* volume_uuid_cstr = volume_uuid == nullptr ? nullptr : volume_uuid->c_str();
+
+ // Note that we cannot validate the package path here because the file might not exist
+ // and we cannot call realpath to resolve system symlinks. Since /data/user/0 symlinks to
+ // /data/data/ a lot of validations will fail if we attempt to check the package path.
+ // It is still ok to be more relaxed because any file removal is done after forking and
+ // dropping capabilities.
if (!validate_secondary_dex_path(pkgname.c_str(), dex_path.c_str(), volume_uuid_cstr,
- uid, storage_flag)) {
+ uid, storage_flag, /*validate_package_path*/ false)) {
LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
return false;
}
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index d277bd3..dd32ac6 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -801,7 +801,7 @@
}
bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
- const char* volume_uuid, int uid, int storage_flag) {
+ const char* volume_uuid, int uid, int storage_flag, bool validate_package_path) {
CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
// Empty paths are not allowed.
@@ -815,15 +815,18 @@
// The path should be at most PKG_PATH_MAX long.
if (dex_path.size() > PKG_PATH_MAX) { return false; }
- // The dex_path should be under the app data directory.
- std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
- ? create_data_user_ce_package_path(
- volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
- : create_data_user_de_package_path(
- volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
+ if (validate_package_path) {
+ // If we are asked to validate the package path check that
+ // the dex_path is under the app data directory.
+ std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
+ ? create_data_user_ce_package_path(
+ volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
+ : create_data_user_de_package_path(
+ volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
- if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
- return false;
+ if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
+ return false;
+ }
}
// If we got here we have a valid path.
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index da3a293..e938042 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -125,7 +125,7 @@
int validate_system_app_path(const char* path);
bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
- const char* volume_uuid, int uid, int storage_flag);
+ const char* volume_uuid, int uid, int storage_flag, bool validate_package_path = true);
int get_path_from_env(dir_rec_t* rec, const char* var);
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index 6b7254c..3264666 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -38,4 +38,20 @@
* strings.
*/
@utf8InCpp String[] getNamesForUids(in int[] uids);
+
+ /**
+ * Returns the name of the installer (a package) which installed the named
+ * package. Preloaded packages return the string "preload". Sideloaded packages
+ * return an empty string. Unknown or unknowable are returned as empty strings.
+ */
+
+ @utf8InCpp String getInstallerForPackage(in String packageName);
+
+ /**
+ * Returns the version code of the named package.
+ * Unknown or unknowable versions are returned as 0.
+ */
+
+ int getVersionCodeForPackage(in String packageName);
+
}
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 3e93788..0699fef 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
@@ -66,6 +66,11 @@
explicit operator bool() const { return epoll_fd_.IsValid(); }
+ int GetBufferId(size_t slot) const {
+ return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
+ : -1;
+ }
+
std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
return buffers_[slot];
}
@@ -218,7 +223,7 @@
// Tracks the buffers belonging to this queue. Buffers are stored according to
// "slot" in this vector. Each slot is a logical id of the buffer within this
// queue regardless of its queue position or presence in the ring buffer.
- std::vector<std::shared_ptr<BufferHubBuffer>> buffers_{kMaxQueueCapacity};
+ std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
// Buffers and related data that are available for dequeue.
RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 4d9b215..1a99234 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -44,7 +44,13 @@
}
void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
- delete write_buffer;
+ if (write_buffer != nullptr) {
+ ALOGW_IF(
+ write_buffer->slot != -1,
+ "dvrWriteBufferDestroy: Destroying a buffer associated with a valid "
+ "buffer queue slot. This may indicate possible leaks.");
+ delete write_buffer;
+ }
}
int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer) {
@@ -107,7 +113,15 @@
*read_buffer = new DvrReadBuffer;
}
-void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) {
+ if (read_buffer != nullptr) {
+ ALOGW_IF(
+ read_buffer->slot != -1,
+ "dvrReadBufferDestroy: Destroying a buffer associated with a valid "
+ "buffer queue slot. This may indicate possible leaks.");
+ delete read_buffer;
+ }
+}
int dvrReadBufferIsValid(DvrReadBuffer* read_buffer) {
return read_buffer && read_buffer->read_buffer;
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 4adb5d2..035252d 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -63,7 +63,7 @@
}
int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
- int* out_fence_fd) {
+ int* out_fence_fd, size_t* out_slot) {
size_t slot;
pdx::LocalHandle fence;
std::shared_ptr<BufferProducer> buffer_producer;
@@ -141,6 +141,86 @@
write_buffer->write_buffer = std::move(buffer_producer);
*out_fence_fd = fence.Release();
+ if (out_slot) {
+ // TODO(b/65469368): Remove this null check once dvrWriteBufferQueueDequeue
+ // is deprecated.
+ *out_slot = slot;
+ }
+ return 0;
+}
+
+int DvrWriteBufferQueue::GainBuffer(int timeout,
+ DvrWriteBuffer** out_write_buffer,
+ DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd) {
+ DvrWriteBuffer write_buffer;
+ int fence_fd;
+ size_t slot;
+ const int ret = Dequeue(timeout, &write_buffer, &fence_fd, &slot);
+ if (ret < 0) {
+ ALOGE_IF(
+ ret != -ETIMEDOUT,
+ "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer, ret=%d",
+ ret);
+ return ret;
+ }
+
+ if (write_buffers_[slot] == nullptr) {
+ // Lazy initialization of a write_buffers_ slot. Note that a slot will only
+ // be dynamically allocated once during the entire cycle life of a queue.
+ write_buffers_[slot] = std::make_unique<DvrWriteBuffer>();
+ write_buffers_[slot]->slot = slot;
+ }
+
+ LOG_ALWAYS_FATAL_IF(
+ write_buffers_[slot]->write_buffer,
+ "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
+ write_buffers_[slot]->write_buffer = std::move(write_buffer.write_buffer);
+
+ *out_write_buffer = write_buffers_[slot].release();
+ *out_fence_fd = fence_fd;
+
+ return 0;
+}
+
+int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer,
+ const DvrNativeBufferMetadata* meta,
+ int ready_fence_fd) {
+ LOG_FATAL_IF(
+ (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()),
+ "DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
+
+ // Some basic sanity checks before we put the buffer back into a slot.
+ size_t slot = static_cast<size_t>(write_buffer->slot);
+ if (write_buffers_[slot] != nullptr) {
+ ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot);
+ return -EINVAL;
+ }
+ if (write_buffer->write_buffer == nullptr) {
+ ALOGE("DvrWriteBufferQueue::PostBuffer: Invalid write buffer.");
+ return -EINVAL;
+ }
+ if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) {
+ ALOGE(
+ "DvrWriteBufferQueue::PostBuffer: Buffer to be released does not "
+ "belong to this buffer queue.");
+ return -EINVAL;
+ }
+
+ pdx::LocalHandle fence(ready_fence_fd);
+ // TODO(b/65455724): All BufferHub operations should be async.
+ const int ret = write_buffer->write_buffer->Post(fence, meta, sizeof(*meta));
+ if (ret < 0) {
+ ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d",
+ ret);
+ return ret;
+ }
+
+ // Put the DvrWriteBuffer pointer back into its slot for reuse.
+ write_buffers_[slot].reset(write_buffer);
+ // It's import to reset the write buffer client now. It should stay invalid
+ // until next GainBuffer on the same slot.
+ write_buffers_[slot]->write_buffer = nullptr;
return 0;
}
@@ -236,7 +316,29 @@
if (!write_queue || !write_buffer || !out_fence_fd)
return -EINVAL;
- return write_queue->Dequeue(timeout, write_buffer, out_fence_fd);
+ // TODO(b/65469368): Deprecate this API once new GainBuffer API is in use.
+ return write_queue->Dequeue(timeout, write_buffer, out_fence_fd, nullptr);
+}
+
+int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
+ DvrWriteBuffer** out_write_buffer,
+ DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd) {
+ if (!write_queue || !out_write_buffer || !out_meta || !out_fence_fd)
+ return -EINVAL;
+
+ return write_queue->GainBuffer(timeout, out_write_buffer, out_meta,
+ out_fence_fd);
+}
+
+int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue,
+ DvrWriteBuffer* write_buffer,
+ const DvrNativeBufferMetadata* meta,
+ int ready_fence_fd) {
+ if (!write_queue || !write_buffer || !write_buffer->write_buffer || !meta)
+ return -EINVAL;
+
+ return write_queue->PostBuffer(write_buffer, meta, ready_fence_fd);
}
int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue,
@@ -268,8 +370,8 @@
}
int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,
- int* out_fence_fd, void* out_meta,
- size_t meta_size_bytes) {
+ int* out_fence_fd, size_t* out_slot,
+ void* out_meta, size_t meta_size_bytes) {
if (meta_size_bytes != consumer_queue_->metadata_size()) {
ALOGE(
"DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), "
@@ -291,6 +393,95 @@
read_buffer->read_buffer = buffer_status.take();
*out_fence_fd = acquire_fence.Release();
+
+ if (out_slot) {
+ // TODO(b/65469368): Remove this null check once dvrReadBufferQueueDequeue
+ // is deprecated.
+ *out_slot = slot;
+ }
+ return 0;
+}
+
+int DvrReadBufferQueue::AcquireBuffer(int timeout,
+ DvrReadBuffer** out_read_buffer,
+ DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd) {
+ DvrReadBuffer read_buffer;
+ int fence_fd;
+ size_t slot;
+ const int ret = Dequeue(timeout, &read_buffer, &fence_fd, &slot, out_meta,
+ sizeof(*out_meta));
+ if (ret < 0) {
+ ALOGE_IF(
+ ret != -ETIMEDOUT,
+ "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer, error=%d",
+ ret);
+ return ret;
+ }
+
+ if (read_buffers_[slot] == nullptr) {
+ // Lazy initialization of a read_buffers_ slot. Note that a slot will only
+ // be dynamically allocated once during the entire cycle life of a queue.
+ read_buffers_[slot] = std::make_unique<DvrReadBuffer>();
+ read_buffers_[slot]->slot = slot;
+ }
+
+ LOG_FATAL_IF(
+ read_buffers_[slot]->read_buffer,
+ "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot);
+ read_buffers_[slot]->read_buffer = std::move(read_buffer.read_buffer);
+
+ *out_read_buffer = read_buffers_[slot].release();
+ *out_fence_fd = fence_fd;
+
+ return 0;
+}
+
+int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer,
+ const DvrNativeBufferMetadata* meta,
+ int release_fence_fd) {
+ LOG_FATAL_IF(
+ (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()),
+ "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
+
+ // Some basic sanity checks before we put the buffer back into a slot.
+ size_t slot = static_cast<size_t>(read_buffer->slot);
+ if (read_buffers_[slot] != nullptr) {
+ ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot);
+ return -EINVAL;
+ }
+ if (read_buffer->read_buffer == nullptr) {
+ ALOGE("DvrReadBufferQueue::ReleaseBuffer: Invalid read buffer.");
+ return -EINVAL;
+ }
+ if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) {
+ ALOGE(
+ "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not "
+ "belong to this buffer queue.");
+ return -EINVAL;
+ }
+
+ pdx::LocalHandle fence(release_fence_fd);
+ int ret = 0;
+ if (fence) {
+ ret = read_buffer->read_buffer->Release(fence);
+ } else {
+ // TODO(b/65458354): Send metadata back to producer once shared memory based
+ // metadata is implemented.
+ // TODO(b/65455724): All BufferHub operations should be async.
+ ret = read_buffer->read_buffer->ReleaseAsync();
+ }
+ if (ret < 0) {
+ ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d",
+ ret);
+ return ret;
+ }
+
+ // Put the DvrReadBuffer pointer back into its slot for reuse.
+ read_buffers_[slot].reset(read_buffer);
+ // It's import to reset the read buffer client now. It should stay invalid
+ // until next AcquireBuffer on the same slot.
+ read_buffers_[slot]->read_buffer = nullptr;
return 0;
}
@@ -311,9 +502,11 @@
} else {
consumer_queue_->SetBufferRemovedCallback(
[callback, context](const std::shared_ptr<BufferHubBuffer>& buffer) {
- DvrReadBuffer read_buffer{
- std::static_pointer_cast<BufferConsumer>(buffer)};
- callback(&read_buffer, context);
+ // When buffer is removed from the queue, the slot is already invalid.
+ auto read_buffer = std::make_unique<DvrReadBuffer>();
+ read_buffer->read_buffer =
+ std::static_pointer_cast<BufferConsumer>(buffer);
+ callback(read_buffer.release(), context);
});
}
}
@@ -366,8 +559,30 @@
if (meta_size_bytes != 0 && !out_meta)
return -EINVAL;
- return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, out_meta,
- meta_size_bytes);
+ // TODO(b/65469368): Deprecate this API once new AcquireBuffer API is in use.
+ return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, nullptr,
+ out_meta, meta_size_bytes);
+}
+
+int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout,
+ DvrReadBuffer** out_read_buffer,
+ DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd) {
+ if (!read_queue || !out_read_buffer || !out_meta || !out_fence_fd)
+ return -EINVAL;
+
+ return read_queue->AcquireBuffer(timeout, out_read_buffer, out_meta,
+ out_fence_fd);
+}
+
+int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue,
+ DvrReadBuffer* read_buffer,
+ const DvrNativeBufferMetadata* meta,
+ int release_fence_fd) {
+ if (!read_queue || !read_buffer || !read_buffer->read_buffer || !meta)
+ return -EINVAL;
+
+ return read_queue->ReleaseBuffer(read_buffer, meta, release_fence_fd);
}
int dvrReadBufferQueueSetBufferAvailableCallback(
diff --git a/libs/vr/libdvr/dvr_buffer_queue_internal.h b/libs/vr/libdvr/dvr_buffer_queue_internal.h
index 795d6cd..f9c0bfd 100644
--- a/libs/vr/libdvr/dvr_buffer_queue_internal.h
+++ b/libs/vr/libdvr/dvr_buffer_queue_internal.h
@@ -5,10 +5,14 @@
#include <private/dvr/buffer_hub_queue_client.h>
#include <sys/cdefs.h>
+#include <array>
#include <memory>
+#include "dvr_internal.h"
+
struct ANativeWindow;
+typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata;
typedef struct DvrReadBuffer DvrReadBuffer;
typedef struct DvrReadBufferQueue DvrReadBufferQueue;
typedef struct DvrWriteBuffer DvrWriteBuffer;
@@ -17,6 +21,7 @@
void* context);
struct DvrWriteBufferQueue {
+ using BufferHubQueue = android::dvr::BufferHubQueue;
using ProducerQueue = android::dvr::ProducerQueue;
// Create a concrete object for DvrWriteBufferQueue.
@@ -37,19 +42,28 @@
int GetNativeWindow(ANativeWindow** out_window);
int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
- int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd);
+ int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd,
+ size_t* out_slot);
+ int GainBuffer(int timeout, DvrWriteBuffer** out_write_buffer,
+ DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
+ int PostBuffer(DvrWriteBuffer* write_buffer,
+ const DvrNativeBufferMetadata* meta, int ready_fence_fd);
int ResizeBuffer(uint32_t width, uint32_t height);
private:
std::shared_ptr<ProducerQueue> producer_queue_;
+ std::array<std::unique_ptr<DvrWriteBuffer>, BufferHubQueue::kMaxQueueCapacity>
+ write_buffers_;
uint32_t width_;
uint32_t height_;
uint32_t format_;
+
android::sp<android::Surface> native_window_;
};
struct DvrReadBufferQueue {
+ using BufferHubQueue = android::dvr::BufferHubQueue;
using ConsumerQueue = android::dvr::ConsumerQueue;
explicit DvrReadBufferQueue(
@@ -61,7 +75,11 @@
int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
int Dequeue(int timeout, DvrReadBuffer* read_buffer, int* out_fence_fd,
- void* out_meta, size_t meta_size_bytes);
+ size_t* out_slot, void* out_meta, size_t meta_size_bytes);
+ int AcquireBuffer(int timeout, DvrReadBuffer** out_read_buffer,
+ DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
+ int ReleaseBuffer(DvrReadBuffer* read_buffer,
+ const DvrNativeBufferMetadata* meta, int release_fence_fd);
void SetBufferAvailableCallback(
DvrReadBufferQueueBufferAvailableCallback callback, void* context);
void SetBufferRemovedCallback(
@@ -70,6 +88,8 @@
private:
std::shared_ptr<ConsumerQueue> consumer_queue_;
+ std::array<std::unique_ptr<DvrReadBuffer>, BufferHubQueue::kMaxQueueCapacity>
+ read_buffers_;
};
#endif // ANDROID_DVR_BUFFER_QUEUE_INTERNAL_H_
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index 28b6c28..de8bb96 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -34,10 +34,20 @@
extern "C" {
struct DvrWriteBuffer {
+ // The slot nubmer of the buffer, a valid slot number must be in the range of
+ // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for
+ // DvrWriteBuffer acquired from a DvrWriteBufferQueue.
+ int32_t slot = -1;
+
std::shared_ptr<android::dvr::BufferProducer> write_buffer;
};
struct DvrReadBuffer {
+ // The slot nubmer of the buffer, a valid slot number must be in the range of
+ // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for
+ // DvrReadBuffer acquired from a DvrReadBufferQueue.
+ int32_t slot = -1;
+
std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
};
diff --git a/libs/vr/libdvr/dvr_pose.cpp b/libs/vr/libdvr/dvr_pose.cpp
index 2ac3c0c..c379ef5 100644
--- a/libs/vr/libdvr/dvr_pose.cpp
+++ b/libs/vr/libdvr/dvr_pose.cpp
@@ -9,8 +9,7 @@
using android::dvr::ConsumerQueue;
-int dvrPoseClientGetDataReader(DvrPoseClient* client,
- DvrPoseRawDataType data_type,
+int dvrPoseClientGetDataReader(DvrPoseClient* client, uint64_t data_type,
DvrReadBufferQueue** queue_out) {
if (!client || !queue_out)
return -EINVAL;
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 8d4995a..8f45ce7 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -34,6 +34,7 @@
typedef struct DvrReadBufferQueue DvrReadBufferQueue;
typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
+typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata;
typedef struct DvrSurface DvrSurface;
typedef uint64_t DvrSurfaceAttributeType;
@@ -180,6 +181,13 @@
int timeout,
DvrWriteBuffer* out_buffer,
int* out_fence_fd);
+typedef int (*DvrWriteBufferQueueGainBufferPtr)(
+ DvrWriteBufferQueue* write_queue, int timeout,
+ DvrWriteBuffer** out_write_buffer, DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd);
+typedef int (*DvrWriteBufferQueuePostBufferPtr)(
+ DvrWriteBufferQueue* write_queue, DvrWriteBuffer* write_buffer,
+ const DvrNativeBufferMetadata* meta, int ready_fence_fd);
typedef int (*DvrWriteBufferQueueResizeBufferPtr)(
DvrWriteBufferQueue* write_queue, uint32_t width, uint32_t height);
typedef void (*DvrReadBufferQueueDestroyPtr)(DvrReadBufferQueue* read_queue);
@@ -194,6 +202,13 @@
DvrReadBuffer* out_buffer,
int* out_fence_fd, void* out_meta,
size_t meta_size_bytes);
+typedef int (*DvrReadBufferQueueAcquireBufferPtr)(
+ DvrReadBufferQueue* read_queue, int timeout,
+ DvrReadBuffer** out_read_buffer, DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd);
+typedef int (*DvrReadBufferQueueReleaseBufferPtr)(
+ DvrReadBufferQueue* read_queue, DvrReadBuffer* read_buffer,
+ const DvrNativeBufferMetadata* meta, int release_fence_fd);
typedef void (*DvrReadBufferQueueBufferAvailableCallback)(void* context);
typedef int (*DvrReadBufferQueueSetBufferAvailableCallbackPtr)(
DvrReadBufferQueue* read_queue,
@@ -250,11 +265,11 @@
typedef int (*DvrPoseClientDataCapturePtr)(DvrPoseClient* client,
const DvrPoseDataCaptureRequest* request);
typedef int (*DvrPoseClientDataReaderDestroyPtr)(DvrPoseClient* client,
- DvrPoseRawDataType data_type);
+ uint64_t data_type);
// dvr_pose.h
typedef int (*DvrPoseClientGetDataReaderPtr)(DvrPoseClient* client,
- DvrPoseRawDataType data_type,
+ uint64_t data_type,
DvrReadBufferQueue** read_queue);
// services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 9036773..cce8c7e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -167,6 +167,12 @@
// Gets an ANativeWindow from DvrWriteBufferQueue.
DVR_V1_API_ENTRY(WriteBufferQueueGetANativeWindow);
+// Dvr{Read,Write}BufferQueue API for asynchronous IPC.
+DVR_V1_API_ENTRY(WriteBufferQueueGainBuffer);
+DVR_V1_API_ENTRY(WriteBufferQueuePostBuffer);
+DVR_V1_API_ENTRY(ReadBufferQueueAcquireBuffer);
+DVR_V1_API_ENTRY(ReadBufferQueueReleaseBuffer);
+
// Pose client
DVR_V1_API_ENTRY(PoseClientGetDataReader);
DVR_V1_API_ENTRY(PoseClientDataCapture);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
index 8b9e048..bf695c7 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer_queue.h
@@ -89,21 +89,44 @@
int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
DvrReadBufferQueue** out_read_queue);
-// Dequeue a buffer to write into.
+// @deprecated Please use dvrWriteBufferQueueGainBuffer instead.
+int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
+ DvrWriteBuffer* out_buffer, int* out_fence_fd);
+
+// Gains a buffer to write into.
//
-// @param write_queue The DvrWriteBufferQueue of interest.
+// @param write_queue The DvrWriteBufferQueue to gain buffer from.
// @param timeout Specifies the number of milliseconds that the method will
// block. Specifying a timeout of -1 causes it to block indefinitely,
// while specifying a timeout equal to zero cause it to return immediately,
// even if no buffers are available.
// @param out_buffer A targeting DvrWriteBuffer object to hold the output of the
-// dequeue operation. Must be created by |dvrWriteBufferCreateEmpty|.
+// dequeue operation.
+// @param out_meta A DvrNativeBufferMetadata object populated by the
+// corresponding dvrReadBufferQueueReleaseBuffer API.
// @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which
// signals the release of underlying buffer. The producer should wait until
// this fence clears before writing data into it.
// @return Zero on success, or negative error code.
-int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
- DvrWriteBuffer* out_buffer, int* out_fence_fd);
+int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
+ DvrWriteBuffer** out_write_buffer,
+ DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd);
+
+// Posts a buffer and signals its readiness to be read from.
+//
+// @param write_queue The DvrWriteBufferQueue to post buffer into.
+// @param write_buffer The buffer to be posted.
+// @param meta The buffer metadata describing the buffer.
+// @param ready_fence_fd A sync fence fd defined in NDK's sync.h API, which
+// signals the readdiness of underlying buffer. When a valid fence gets
+// passed in, the consumer will wait the fence to be ready before it starts
+// to ready from the buffer.
+// @return Zero on success, or negative error code.
+int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue,
+ DvrWriteBuffer* write_buffer,
+ const DvrNativeBufferMetadata* meta,
+ int ready_fence_fd);
// Overrides buffer dimension with new width and height.
//
@@ -153,28 +176,45 @@
int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
DvrReadBufferQueue** out_read_queue);
-// Dequeue a buffer to read from.
+// @deprecated Please use dvrReadBufferQueueAcquireBuffer instead.
+int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
+ DvrReadBuffer* out_buffer, int* out_fence_fd,
+ void* out_meta, size_t meta_size_bytes);
+
+// Dequeues a buffer to read from.
//
-// @param read_queue The DvrReadBufferQueue of interest.
+// @param read_queue The DvrReadBufferQueue to acquire buffer from.
// @param timeout Specifies the number of milliseconds that the method will
// block. Specifying a timeout of -1 causes it to block indefinitely,
// while specifying a timeout equal to zero cause it to return immediately,
// even if no buffers are available.
// @param out_buffer A targeting DvrReadBuffer object to hold the output of the
// dequeue operation. Must be created by |dvrReadBufferCreateEmpty|.
+// @param out_meta A DvrNativeBufferMetadata object populated by the
+// corresponding dvrWriteBufferQueuePostBuffer API.
// @param out_fence_fd A sync fence fd defined in NDK's sync.h API, which
// signals the release of underlying buffer. The consumer should wait until
// this fence clears before reading data from it.
-// @param out_meta The memory area where a metadata object will be filled.
-// Can be nullptr iff |meta_size_bytes| is zero (i.e., there is no
-// metadata).
-// @param meta_size_bytes Size of the metadata object caller expects. If it
-// doesn't match the size of actually metadata transported by the buffer
-// queue, the method returns -EINVAL.
// @return Zero on success, or negative error code.
-int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
- DvrReadBuffer* out_buffer, int* out_fence_fd,
- void* out_meta, size_t meta_size_bytes);
+int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout,
+ DvrReadBuffer** out_read_buffer,
+ DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd);
+
+// Releases a buffer and signals its readiness to be written into.
+//
+// @param read_queue The DvrReadBufferQueue to release buffer into.
+// @param read_buffer The buffer to be released.
+// @param meta The buffer metadata describing the buffer.
+// @param release_fence_fd A sync fence fd defined in NDK's sync.h API, which
+// signals the readdiness of underlying buffer. When a valid fence gets
+// passed in, the producer will wait the fence to be ready before it starts
+// to write into the buffer again.
+// @return Zero on success, or negative error code.
+int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue,
+ DvrReadBuffer* read_buffer,
+ const DvrNativeBufferMetadata* meta,
+ int release_fence_fd);
// Callback function which will be called when a buffer is avaiable.
//
diff --git a/libs/vr/libdvr/include/dvr/dvr_pose.h b/libs/vr/libdvr/include/dvr/dvr_pose.h
index 85631f7..8752751 100644
--- a/libs/vr/libdvr/include/dvr/dvr_pose.h
+++ b/libs/vr/libdvr/include/dvr/dvr_pose.h
@@ -99,20 +99,20 @@
} DvrPose;
// Represents a data type that can be streamed from pose service.
-typedef enum DvrPoseRawDataType {
- DVR_POSE_RAW_DATA_STEREO_IMAGE,
- DVR_POSE_RAW_DATA_POINT_CLOUD,
- DVR_POSE_RAW_DATA_FEATURES,
+enum {
+ DVR_POSE_RAW_DATA_STEREO_IMAGE = (1ULL << 0),
+ DVR_POSE_RAW_DATA_POINT_CLOUD = (1ULL << 1),
+ DVR_POSE_RAW_DATA_FEATURES = (1ULL << 2),
// Always last.
- DVR_POSE_RAW_DATA_COUNT,
-} DvrPoseRawDataType;
+ DVR_POSE_RAW_DATA_COUNT = (1ULL << 3),
+};
// A request to retrieve data from the pose service. Expects that a buffer
// queue has been initialized through dvrPoseClientGetDataReader().
typedef struct DvrPoseDataCaptureRequest {
- // The type of data to capture. Refer to enum DvrPoseRawDataType for types.
- DvrPoseRawDataType data_type;
+ // The type of data to capture. Refer to enum DVR_POSE_RAW_DATA_* for types.
+ uint64_t data_type;
// The sample interval. This can be used to skip samples. For example, a
// value of 5 will capture every fifth frame and discard the 4 frames in
// between. Set to 1 to capture all frames.
@@ -144,8 +144,7 @@
// be found in the metadata struct DvrNativeBufferMetadata, where width is
// |crop_right| and height is |crop_bottom|/2. Each image is contiguous in
// memory with stride equal to width.
-int dvrPoseClientGetDataReader(DvrPoseClient* client,
- DvrPoseRawDataType data_type,
+int dvrPoseClientGetDataReader(DvrPoseClient* client, uint64_t data_type,
DvrReadBufferQueue** queue_out);
// TODO(b/65067592): Move pose api's from pose_client.h to here.
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index ab2ee75..a9302a7 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -47,6 +47,7 @@
cflags: [
"-DLOG_TAG=\"dvr_api-test\"",
"-DTRACE=0",
+ "-Wno-missing-field-initializers",
"-O0",
"-g",
],
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index 0b30c38..f1c5e48 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -27,8 +27,6 @@
static constexpr uint64_t kBufferUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
static constexpr size_t kQueueCapacity = 3;
-typedef uint64_t TestMeta;
-
class DvrBufferQueueTest : public ::testing::Test {
public:
static void BufferAvailableCallback(void* context) {
@@ -65,20 +63,20 @@
int buffer_removed_count_{0};
};
-TEST_F(DvrBufferQueueTest, TestWrite_QueueCreateDestroy) {
+TEST_F(DvrBufferQueueTest, WriteQueueCreateDestroy) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- /*capacity=*/0, sizeof(TestMeta), &write_queue_);
+ /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
dvrWriteBufferQueueDestroy(write_queue_);
write_queue_ = nullptr;
}
-TEST_F(DvrBufferQueueTest, TestWrite_QueueGetCapacity) {
+TEST_F(DvrBufferQueueTest, WriteQueueGetCapacity) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- kQueueCapacity, sizeof(TestMeta), &write_queue_);
+ kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
size_t capacity = dvrWriteBufferQueueGetCapacity(write_queue_);
@@ -87,10 +85,10 @@
ASSERT_EQ(kQueueCapacity, capacity);
}
-TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromWriteQueue) {
+TEST_F(DvrBufferQueueTest, CreateReadQueueFromWriteQueue) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- /*capacity=*/0, sizeof(TestMeta), &write_queue_);
+ /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
DvrReadBufferQueue* read_queue = nullptr;
@@ -102,10 +100,10 @@
dvrReadBufferQueueDestroy(read_queue);
}
-TEST_F(DvrBufferQueueTest, TestCreateReadQueueFromReadQueue) {
+TEST_F(DvrBufferQueueTest, CreateReadQueueFromReadQueue) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- /*capacity=*/0, sizeof(TestMeta), &write_queue_);
+ /*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
DvrReadBufferQueue* read_queue1 = nullptr;
@@ -124,102 +122,86 @@
dvrReadBufferQueueDestroy(read_queue2);
}
-TEST_F(DvrBufferQueueTest, CreateEmptyBuffer) {
+TEST_F(DvrBufferQueueTest, GainBuffer) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- kQueueCapacity, sizeof(TestMeta), &write_queue_);
- ASSERT_EQ(0, ret);
+ kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+ ASSERT_EQ(ret, 0);
- DvrReadBuffer* read_buffer = nullptr;
- DvrWriteBuffer* write_buffer = nullptr;
+ DvrWriteBuffer* wb = nullptr;
+ EXPECT_FALSE(dvrWriteBufferIsValid(wb));
- EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
- EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
-
- dvrReadBufferCreateEmpty(&read_buffer);
- ASSERT_NE(nullptr, read_buffer);
-
- dvrWriteBufferCreateEmpty(&write_buffer);
- ASSERT_NE(nullptr, write_buffer);
-
- EXPECT_FALSE(dvrReadBufferIsValid(read_buffer));
- EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
-
- DvrReadBufferQueue* read_queue = nullptr;
-
- ASSERT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
-
- const int kTimeoutMs = 0;
+ DvrNativeBufferMetadata meta = {0};
int fence_fd = -1;
- ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeoutMs,
- write_buffer, &fence_fd));
- EXPECT_EQ(-1, fence_fd);
- EXPECT_TRUE(dvrWriteBufferIsValid(write_buffer));
-
- ASSERT_EQ(0, dvrWriteBufferClear(write_buffer));
- EXPECT_FALSE(dvrWriteBufferIsValid(write_buffer));
+ ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta,
+ &fence_fd);
+ ASSERT_EQ(ret, 0);
+ EXPECT_EQ(fence_fd, -1);
+ EXPECT_NE(wb, nullptr);
+ EXPECT_TRUE(dvrWriteBufferIsValid(wb));
}
-TEST_F(DvrBufferQueueTest, TestDequeuePostDequeueRelease) {
+TEST_F(DvrBufferQueueTest, AcquirePostGainRelease) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- kQueueCapacity, sizeof(TestMeta), &write_queue_);
- ASSERT_EQ(0, ret);
+ kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
+ ASSERT_EQ(ret, 0);
- static constexpr int kTimeout = 0;
DvrReadBufferQueue* read_queue = nullptr;
DvrReadBuffer* rb = nullptr;
DvrWriteBuffer* wb = nullptr;
+ DvrNativeBufferMetadata meta1 = {0};
+ DvrNativeBufferMetadata meta2 = {0};
int fence_fd = -1;
ret = dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue);
- ASSERT_EQ(0, ret);
- ASSERT_NE(nullptr, read_queue);
+ ASSERT_EQ(ret, 0);
+ ASSERT_NE(read_queue, nullptr);
dvrReadBufferQueueSetBufferAvailableCallback(read_queue,
&BufferAvailableCallback, this);
- dvrWriteBufferCreateEmpty(&wb);
- ASSERT_NE(nullptr, wb);
-
- dvrReadBufferCreateEmpty(&rb);
- ASSERT_NE(nullptr, rb);
-
// Gain buffer for writing.
- ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb, &fence_fd);
- ASSERT_EQ(0, ret);
+ ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb, &meta1,
+ &fence_fd);
+ ASSERT_EQ(ret, 0);
+ ASSERT_NE(wb, nullptr);
ASSERT_TRUE(dvrWriteBufferIsValid(wb));
ALOGD_IF(TRACE, "TestDequeuePostDequeueRelease, gain buffer %p, fence_fd=%d",
wb, fence_fd);
android::base::unique_fd release_fence(fence_fd);
// Post buffer to the read_queue.
- TestMeta seq = 42U;
- ret = dvrWriteBufferPost(wb, /* fence */ -1, &seq, sizeof(seq));
- ASSERT_EQ(0, ret);
- dvrWriteBufferDestroy(wb);
+ meta1.timestamp = 42;
+ ret = dvrWriteBufferQueuePostBuffer(write_queue_, wb, &meta1, /*fence=*/-1);
+ ASSERT_EQ(ret, 0);
+ ASSERT_FALSE(dvrWriteBufferIsValid(wb));
wb = nullptr;
// Acquire buffer for reading.
- TestMeta acquired_seq = 0U;
- ret = dvrReadBufferQueueDequeue(read_queue, kTimeout, rb, &fence_fd,
- &acquired_seq, sizeof(acquired_seq));
- ASSERT_EQ(0, ret);
+ ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0, &rb, &meta2,
+ &fence_fd);
+ ASSERT_EQ(ret, 0);
+ ASSERT_NE(rb, nullptr);
// Dequeue is successfully, BufferAvailableCallback should be fired once.
- ASSERT_EQ(1, buffer_available_count_);
+ ASSERT_EQ(buffer_available_count_, 1);
ASSERT_TRUE(dvrReadBufferIsValid(rb));
- ASSERT_EQ(seq, acquired_seq);
+
+ // Metadata should be passed along from producer to consumer properly.
+ ASSERT_EQ(meta1.timestamp, meta2.timestamp);
+
ALOGD_IF(TRACE,
"TestDequeuePostDequeueRelease, acquire buffer %p, fence_fd=%d", rb,
fence_fd);
android::base::unique_fd acquire_fence(fence_fd);
// Release buffer to the write_queue.
- ret = dvrReadBufferRelease(rb, -1);
- ASSERT_EQ(0, ret);
- dvrReadBufferDestroy(rb);
+ ret = dvrReadBufferQueueReleaseBuffer(read_queue, rb, &meta2,
+ /*release_fence_fd=*/-1);
+ ASSERT_EQ(ret, 0);
+ ASSERT_FALSE(dvrReadBufferIsValid(rb));
rb = nullptr;
// TODO(b/34387835) Currently buffer allocation has to happen after all queues
@@ -232,37 +214,18 @@
dvrReadBufferQueueDestroy(read_queue);
}
-TEST_F(DvrBufferQueueTest, TestGetANativeWindow) {
+TEST_F(DvrBufferQueueTest, GetANativeWindow) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- /*capacity=*/0, sizeof(TestMeta), &write_queue_);
- ASSERT_EQ(0, ret);
-
- ANativeWindow* window = nullptr;
-
- // The |write_queue_| doesn't have proper metadata (must be
- // DvrNativeBufferMetadata) configured during creation.
- ret = dvrWriteBufferQueueGetANativeWindow(write_queue_, &window);
- ASSERT_EQ(-EINVAL, ret);
- ASSERT_EQ(nullptr, window);
- dvrWriteBufferQueueDestroy(write_queue_);
- write_queue_ = nullptr;
-
- // A write queue with DvrNativeBufferMetadata should work fine.
- ASSERT_EQ(nullptr, write_queue_);
-
- ret = dvrWriteBufferQueueCreate(
- kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
/*capacity=*/0, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
ASSERT_NE(nullptr, write_queue_);
+ ANativeWindow* window = nullptr;
ret = dvrWriteBufferQueueGetANativeWindow(write_queue_, &window);
ASSERT_EQ(0, ret);
ASSERT_NE(nullptr, window);
- // TODO(b/64723700): Remove dependencies of Android platform bits so that we
- // can run dvr_buffer_queue-test in DTS.
uint32_t width = ANativeWindow_getWidth(window);
uint32_t height = ANativeWindow_getHeight(window);
uint32_t format = ANativeWindow_getFormat(window);
@@ -274,15 +237,15 @@
// Create buffer queue of three buffers and dequeue three buffers out of it.
// Before each dequeue operation, we resize the buffer queue and expect the
// queue always return buffer with desired dimension.
-TEST_F(DvrBufferQueueTest, TestResizeBuffer) {
+TEST_F(DvrBufferQueueTest, ResizeBuffer) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- kQueueCapacity, sizeof(TestMeta), &write_queue_);
+ kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
- static constexpr int kTimeout = 0;
int fence_fd = -1;
+ DvrNativeBufferMetadata meta = {0};
DvrReadBufferQueue* read_queue = nullptr;
DvrWriteBuffer* wb1 = nullptr;
DvrWriteBuffer* wb2 = nullptr;
@@ -300,13 +263,6 @@
dvrReadBufferQueueSetBufferRemovedCallback(read_queue, &BufferRemovedCallback,
this);
- dvrWriteBufferCreateEmpty(&wb1);
- ASSERT_NE(nullptr, wb1);
- dvrWriteBufferCreateEmpty(&wb2);
- ASSERT_NE(nullptr, wb2);
- dvrWriteBufferCreateEmpty(&wb3);
- ASSERT_NE(nullptr, wb3);
-
// Handle all pending events on the read queue.
ret = dvrReadBufferQueueHandleEvents(read_queue);
ASSERT_EQ(0, ret);
@@ -321,7 +277,8 @@
ASSERT_EQ(0, ret);
// Gain first buffer for writing. All buffers will be resized.
- ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb1, &fence_fd);
+ ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb1, &meta,
+ &fence_fd);
ASSERT_EQ(0, ret);
ASSERT_TRUE(dvrWriteBufferIsValid(wb1));
ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p", wb1);
@@ -347,7 +304,8 @@
ASSERT_EQ(0, ret);
// The next buffer we dequeued should have new width.
- ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb2, &fence_fd);
+ ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb2, &meta,
+ &fence_fd);
ASSERT_EQ(0, ret);
ASSERT_TRUE(dvrWriteBufferIsValid(wb2));
ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb2,
@@ -373,7 +331,8 @@
ASSERT_EQ(0, ret);
// The next buffer we dequeued should have new width.
- ret = dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wb3, &fence_fd);
+ ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0, &wb3, &meta,
+ &fence_fd);
ASSERT_EQ(0, ret);
ASSERT_TRUE(dvrWriteBufferIsValid(wb3));
ALOGD_IF(TRACE, "TestResizeBuffer, gain buffer %p, fence_fd=%d", wb3,
@@ -396,78 +355,10 @@
dvrReadBufferQueueDestroy(read_queue);
}
-TEST_F(DvrBufferQueueTest, DequeueEmptyMetadata) {
- // Overrides default queue parameters: Empty metadata.
+TEST_F(DvrBufferQueueTest, ReadQueueEventFd) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- /*capacity=*/1, /*metadata_size=*/0, &write_queue_);
- ASSERT_EQ(0, ret);
-
- DvrReadBuffer* rb = nullptr;
- DvrWriteBuffer* wb = nullptr;
- dvrReadBufferCreateEmpty(&rb);
- dvrWriteBufferCreateEmpty(&wb);
-
- DvrReadBufferQueue* read_queue = nullptr;
- EXPECT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
-
- const int kTimeoutMs = 0;
- int fence_fd = -1;
- EXPECT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, 0, wb, &fence_fd));
-
- EXPECT_EQ(0, dvrWriteBufferPost(wb, /*fence=*/-1, nullptr, 0));
- EXPECT_EQ(0, dvrWriteBufferClear(wb));
- dvrWriteBufferDestroy(wb);
- wb = nullptr;
-
- // When acquire buffer, it's legit to pass nullptr as out_meta iff metadata
- // size is Zero.
- EXPECT_EQ(0, dvrReadBufferQueueDequeue(read_queue, kTimeoutMs, rb, &fence_fd,
- nullptr, 0));
- EXPECT_TRUE(dvrReadBufferIsValid(rb));
-}
-
-TEST_F(DvrBufferQueueTest, DequeueMismatchMetadata) {
- int ret = dvrWriteBufferQueueCreate(
- kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- /*capacity=*/1, sizeof(TestMeta), &write_queue_);
- ASSERT_EQ(0, ret);
-
- DvrReadBuffer* rb = nullptr;
- DvrWriteBuffer* wb = nullptr;
- dvrReadBufferCreateEmpty(&rb);
- dvrWriteBufferCreateEmpty(&wb);
-
- DvrReadBufferQueue* read_queue = nullptr;
- EXPECT_EQ(0, dvrWriteBufferQueueCreateReadQueue(write_queue_, &read_queue));
-
- const int kTimeoutMs = 0;
- int fence_fd = -1;
- EXPECT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, 0, wb, &fence_fd));
-
- TestMeta seq = 42U;
- EXPECT_EQ(0, dvrWriteBufferPost(wb, /*fence=*/-1, &seq, sizeof(seq)));
- EXPECT_EQ(0, dvrWriteBufferClear(wb));
- dvrWriteBufferDestroy(wb);
- wb = nullptr;
-
- // Dequeue with wrong metadata will cause EINVAL.
- int8_t wrong_metadata;
- EXPECT_EQ(-EINVAL,
- dvrReadBufferQueueDequeue(read_queue, kTimeoutMs, rb, &fence_fd,
- &wrong_metadata, sizeof(wrong_metadata)));
- EXPECT_FALSE(dvrReadBufferIsValid(rb));
-
- // Dequeue with empty metadata will cause EINVAL.
- EXPECT_EQ(-EINVAL, dvrReadBufferQueueDequeue(read_queue, kTimeoutMs, rb,
- &fence_fd, nullptr, 0));
- EXPECT_FALSE(dvrReadBufferIsValid(rb));
-}
-
-TEST_F(DvrBufferQueueTest, TestReadQueueEventFd) {
- int ret = dvrWriteBufferQueueCreate(
- kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- kQueueCapacity, sizeof(TestMeta), &write_queue_);
+ kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
DvrReadBufferQueue* read_queue = nullptr;
@@ -483,10 +374,10 @@
// Verifies a Dvr{Read,Write}BufferQueue contains the same set of
// Dvr{Read,Write}Buffer(s) during their lifecycles. And for the same buffer_id,
// the corresponding AHardwareBuffer handle stays the same.
-TEST_F(DvrBufferQueueTest, TestStableBufferIdAndHardwareBuffer) {
+TEST_F(DvrBufferQueueTest, StableBufferIdAndHardwareBuffer) {
int ret = dvrWriteBufferQueueCreate(
kBufferWidth, kBufferHeight, kBufferFormat, kLayerCount, kBufferUsage,
- kQueueCapacity, sizeof(TestMeta), &write_queue_);
+ kQueueCapacity, sizeof(DvrNativeBufferMetadata), &write_queue_);
ASSERT_EQ(0, ret);
int fence_fd = -1;
@@ -497,25 +388,21 @@
std::array<DvrReadBuffer*, kQueueCapacity> rbs;
// Write buffers.
std::array<DvrWriteBuffer*, kQueueCapacity> wbs;
+ // Buffer metadata.
+ std::array<DvrNativeBufferMetadata, kQueueCapacity> metas;
// Hardware buffers for Read buffers.
std::unordered_map<int, AHardwareBuffer*> rhbs;
// Hardware buffers for Write buffers.
std::unordered_map<int, AHardwareBuffer*> whbs;
- for (size_t i = 0; i < kQueueCapacity; i++) {
- dvrReadBufferCreateEmpty(&rbs[i]);
- dvrWriteBufferCreateEmpty(&wbs[i]);
- }
-
constexpr int kNumTests = 100;
- constexpr int kTimeout = 0;
- TestMeta seq = 0U;
// This test runs the following operations many many times. Thus we prefer to
// use ASSERT_XXX rather than EXPECT_XXX to avoid spamming the output.
std::function<void(size_t i)> Gain = [&](size_t i) {
- ASSERT_EQ(0, dvrWriteBufferQueueDequeue(write_queue_, kTimeout, wbs[i],
- &fence_fd));
+ int ret = dvrWriteBufferQueueGainBuffer(write_queue_, /*timeout=*/0,
+ &wbs[i], &metas[i], &fence_fd);
+ ASSERT_EQ(ret, 0);
ASSERT_LT(fence_fd, 0); // expect invalid fence.
ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
int buffer_id = dvrWriteBufferGetId(wbs[i]);
@@ -540,15 +427,16 @@
std::function<void(size_t i)> Post = [&](size_t i) {
ASSERT_TRUE(dvrWriteBufferIsValid(wbs[i]));
- seq++;
- ASSERT_EQ(0, dvrWriteBufferPost(wbs[i], /*fence=*/-1, &seq, sizeof(seq)));
+ metas[i].timestamp++;
+ int ret = dvrWriteBufferQueuePostBuffer(write_queue_, wbs[i], &metas[i],
+ /*fence=*/-1);
+ ASSERT_EQ(ret, 0);
};
std::function<void(size_t i)> Acquire = [&](size_t i) {
- TestMeta out_seq = 0U;
- ASSERT_EQ(0,
- dvrReadBufferQueueDequeue(read_queue, kTimeout, rbs[i], &fence_fd,
- &out_seq, sizeof(out_seq)));
+ int ret = dvrReadBufferQueueAcquireBuffer(read_queue, /*timeout=*/0,
+ &rbs[i], &metas[i], &fence_fd);
+ ASSERT_EQ(ret, 0);
ASSERT_LT(fence_fd, 0); // expect invalid fence.
ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
@@ -574,8 +462,9 @@
std::function<void(size_t i)> Release = [&](size_t i) {
ASSERT_TRUE(dvrReadBufferIsValid(rbs[i]));
- seq++;
- ASSERT_EQ(0, dvrReadBufferRelease(rbs[i], /*fence=*/-1));
+ int ret = dvrReadBufferQueueReleaseBuffer(read_queue, rbs[i], &metas[i],
+ /*release_fence_fd=*/-1);
+ ASSERT_EQ(ret, 0);
};
// Scenario one:
@@ -630,12 +519,6 @@
ASSERT_NO_FATAL_FAILURE(Release(kQueueCapacity - 1 - i));
}
}
-
- // Clean up all read buffers and write buffers.
- for (size_t i = 0; i < kQueueCapacity; i++) {
- dvrReadBufferDestroy(rbs[i]);
- dvrWriteBufferDestroy(wbs[i]);
- }
}
} // namespace
diff --git a/libs/vr/libpdx_uds/client_channel.cpp b/libs/vr/libpdx_uds/client_channel.cpp
index 9d91617..3f785fa 100644
--- a/libs/vr/libpdx_uds/client_channel.cpp
+++ b/libs/vr/libpdx_uds/client_channel.cpp
@@ -90,10 +90,12 @@
size_t send_len = CountVectorSize(send_vector, send_count);
InitRequest(&transaction_state->request, opcode, send_len, max_recv_len,
false);
- auto status = SendData(socket_fd, transaction_state->request);
- if (status && send_len > 0)
- status = SendDataVector(socket_fd, send_vector, send_count);
- return status;
+ if (send_len == 0) {
+ send_vector = nullptr;
+ send_count = 0;
+ }
+ return SendData(socket_fd, transaction_state->request, send_vector,
+ send_count);
}
Status<void> ReceiveResponse(const BorrowedHandle& socket_fd,
diff --git a/libs/vr/libpdx_uds/ipc_helper.cpp b/libs/vr/libpdx_uds/ipc_helper.cpp
index d75ce86..f85b3bb 100644
--- a/libs/vr/libpdx_uds/ipc_helper.cpp
+++ b/libs/vr/libpdx_uds/ipc_helper.cpp
@@ -20,6 +20,9 @@
namespace {
+constexpr size_t kMaxFdCount =
+ 256; // Total of 1KiB of data to transfer these FDs.
+
// Default implementations of Send/Receive interfaces to use standard socket
// send/sendmsg/recv/recvmsg functions.
class SocketSender : public SendInterface {
@@ -175,20 +178,31 @@
}
Status<void> SendPayload::Send(const BorrowedHandle& socket_fd,
- const ucred* cred) {
+ const ucred* cred, const iovec* data_vec,
+ size_t vec_count) {
+ if (file_handles_.size() > kMaxFdCount) {
+ ALOGE(
+ "SendPayload::Send: Trying to send too many file descriptors (%zu), "
+ "max allowed = %zu",
+ file_handles_.size(), kMaxFdCount);
+ return ErrorStatus{EINVAL};
+ }
+
SendInterface* sender = sender_ ? sender_ : &g_socket_sender;
MessagePreamble preamble;
preamble.magic = kMagicPreamble;
preamble.data_size = buffer_.size();
preamble.fd_count = file_handles_.size();
- Status<void> ret = SendAll(sender, socket_fd, &preamble, sizeof(preamble));
- if (!ret)
- return ret;
msghdr msg = {};
- iovec recv_vect = {buffer_.data(), buffer_.size()};
- msg.msg_iov = &recv_vect;
- msg.msg_iovlen = 1;
+ msg.msg_iovlen = 2 + vec_count;
+ msg.msg_iov = static_cast<iovec*>(alloca(sizeof(iovec) * msg.msg_iovlen));
+ msg.msg_iov[0].iov_base = &preamble;
+ msg.msg_iov[0].iov_len = sizeof(preamble);
+ msg.msg_iov[1].iov_base = buffer_.data();
+ msg.msg_iov[1].iov_len = buffer_.size();
+ for (size_t i = 0; i < vec_count; i++)
+ msg.msg_iov[i + 2] = data_vec[i];
if (cred || !file_handles_.empty()) {
const size_t fd_bytes = file_handles_.size() * sizeof(int);
@@ -270,7 +284,15 @@
ucred* cred) {
RecvInterface* receiver = receiver_ ? receiver_ : &g_socket_receiver;
MessagePreamble preamble;
- Status<void> ret = RecvAll(receiver, socket_fd, &preamble, sizeof(preamble));
+ msghdr msg = {};
+ iovec recv_vect = {&preamble, sizeof(preamble)};
+ msg.msg_iov = &recv_vect;
+ msg.msg_iovlen = 1;
+ const size_t receive_fd_bytes = kMaxFdCount * sizeof(int);
+ msg.msg_controllen = CMSG_SPACE(sizeof(ucred)) + CMSG_SPACE(receive_fd_bytes);
+ msg.msg_control = alloca(msg.msg_controllen);
+
+ Status<void> ret = RecvMsgAll(receiver, socket_fd, &msg);
if (!ret)
return ret;
@@ -284,23 +306,6 @@
file_handles_.clear();
read_pos_ = 0;
- msghdr msg = {};
- iovec recv_vect = {buffer_.data(), buffer_.size()};
- msg.msg_iov = &recv_vect;
- msg.msg_iovlen = 1;
-
- if (cred || preamble.fd_count) {
- const size_t receive_fd_bytes = preamble.fd_count * sizeof(int);
- msg.msg_controllen =
- (cred ? CMSG_SPACE(sizeof(ucred)) : 0) +
- (receive_fd_bytes == 0 ? 0 : CMSG_SPACE(receive_fd_bytes));
- msg.msg_control = alloca(msg.msg_controllen);
- }
-
- ret = RecvMsgAll(receiver, socket_fd, &msg);
- if (!ret)
- return ret;
-
bool cred_available = false;
file_handles_.reserve(preamble.fd_count);
cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
@@ -320,6 +325,10 @@
cmsg = CMSG_NXTHDR(&msg, cmsg);
}
+ ret = RecvAll(receiver, socket_fd, buffer_.data(), buffer_.size());
+ if (!ret)
+ return ret;
+
if (cred && !cred_available) {
ALOGE("ReceivePayload::Receive: Failed to obtain message credentials");
ret.SetError(EIO);
diff --git a/libs/vr/libpdx_uds/private/uds/ipc_helper.h b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
index bde16d3..664a0d1 100644
--- a/libs/vr/libpdx_uds/private/uds/ipc_helper.h
+++ b/libs/vr/libpdx_uds/private/uds/ipc_helper.h
@@ -59,7 +59,8 @@
public:
SendPayload(SendInterface* sender = nullptr) : sender_{sender} {}
Status<void> Send(const BorrowedHandle& socket_fd);
- Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred);
+ Status<void> Send(const BorrowedHandle& socket_fd, const ucred* cred,
+ const iovec* data_vec = nullptr, size_t vec_count = 0);
// MessageWriter
void* GetNextWriteBufferSection(size_t size) override;
@@ -156,18 +157,22 @@
};
template <typename T>
-inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data) {
+inline Status<void> SendData(const BorrowedHandle& socket_fd, const T& data,
+ const iovec* data_vec = nullptr,
+ size_t vec_count = 0) {
SendPayload payload;
rpc::Serialize(data, &payload);
- return payload.Send(socket_fd);
+ return payload.Send(socket_fd, nullptr, data_vec, vec_count);
}
template <typename FileHandleType>
inline Status<void> SendData(const BorrowedHandle& socket_fd,
- const RequestHeader<FileHandleType>& request) {
+ const RequestHeader<FileHandleType>& request,
+ const iovec* data_vec = nullptr,
+ size_t vec_count = 0) {
SendPayload payload;
rpc::Serialize(request, &payload);
- return payload.Send(socket_fd, &request.cred);
+ return payload.Send(socket_fd, &request.cred, data_vec, vec_count);
}
Status<void> SendData(const BorrowedHandle& socket_fd, const void* data,
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 40396b9..ef8cca3 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -65,6 +65,7 @@
}
pdx::Status<void> DisplayManagerService::HandleMessage(pdx::Message& message) {
+ ATRACE_NAME("DisplayManagerService::HandleMessage");
auto channel = std::static_pointer_cast<DisplayManager>(message.GetChannel());
switch (message.GetOp()) {
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index af18e21..ac68a5e 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -124,6 +124,8 @@
// surface-specific messages to the per-instance handlers.
Status<void> DisplayService::HandleMessage(pdx::Message& message) {
ALOGD_IF(TRACE, "DisplayService::HandleMessage: opcode=%d", message.GetOp());
+ ATRACE_NAME("DisplayService::HandleMessage");
+
switch (message.GetOp()) {
case DisplayProtocol::GetMetrics::Opcode:
DispatchRemoteMethod<DisplayProtocol::GetMetrics>(
@@ -349,17 +351,9 @@
void DisplayService::UpdateActiveDisplaySurfaces() {
auto visible_surfaces = GetVisibleDisplaySurfaces();
-
- std::sort(visible_surfaces.begin(), visible_surfaces.end(),
- [](const std::shared_ptr<DisplaySurface>& a,
- const std::shared_ptr<DisplaySurface>& b) {
- return a->z_order() < b->z_order();
- });
-
ALOGD_IF(TRACE,
"DisplayService::UpdateActiveDisplaySurfaces: %zd visible surfaces",
visible_surfaces.size());
-
hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
}
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 3418d65..de6477b 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -5,12 +5,14 @@
#include <fcntl.h>
#include <log/log.h>
#include <poll.h>
+#include <stdint.h>
#include <sync/sync.h>
#include <sys/eventfd.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/system_properties.h>
#include <sys/timerfd.h>
+#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <utils/Trace.h>
@@ -30,7 +32,9 @@
using android::hardware::Return;
using android::hardware::Void;
+using android::pdx::ErrorStatus;
using android::pdx::LocalHandle;
+using android::pdx::Status;
using android::pdx::rpc::EmptyVariant;
using android::pdx::rpc::IfAnyOf;
@@ -44,9 +48,8 @@
const char kBacklightBrightnessSysFile[] =
"/sys/class/leds/lcd-backlight/brightness";
-const char kPrimaryDisplayWaitPPEventFile[] = "/sys/class/graphics/fb0/wait_pp";
-
const char kDvrPerformanceProperty[] = "sys.dvr.performance";
+const char kDvrStandaloneProperty[] = "ro.boot.vr";
const char kRightEyeOffsetProperty[] = "dvr.right_eye_offset_ns";
@@ -83,10 +86,30 @@
return true;
}
-} // anonymous namespace
+// Utility to generate scoped tracers with arguments.
+// TODO(eieio): Move/merge this into utils/Trace.h?
+class TraceArgs {
+ public:
+ template <typename... Args>
+ TraceArgs(const char* format, Args&&... args) {
+ std::array<char, 1024> buffer;
+ snprintf(buffer.data(), buffer.size(), format, std::forward<Args>(args)...);
+ atrace_begin(ATRACE_TAG, buffer.data());
+ }
-// HardwareComposer static data;
-constexpr size_t HardwareComposer::kMaxHardwareLayers;
+ ~TraceArgs() { atrace_end(ATRACE_TAG); }
+
+ private:
+ TraceArgs(const TraceArgs&) = delete;
+ void operator=(const TraceArgs&) = delete;
+};
+
+// Macro to define a scoped tracer with arguments. Uses PASTE(x, y) macro
+// defined in utils/Trace.h.
+#define TRACE_FORMAT(format, ...) \
+ TraceArgs PASTE(__tracer, __LINE__) { format, ##__VA_ARGS__ }
+
+} // anonymous namespace
HardwareComposer::HardwareComposer()
: initialized_(false), request_display_callback_(nullptr) {}
@@ -98,18 +121,20 @@
}
bool HardwareComposer::Initialize(
- Hwc2::Composer* hidl, RequestDisplayCallback request_display_callback) {
+ Hwc2::Composer* composer, RequestDisplayCallback request_display_callback) {
if (initialized_) {
ALOGE("HardwareComposer::Initialize: already initialized.");
return false;
}
+ is_standalone_device_ = property_get_bool(kDvrStandaloneProperty, false);
+
request_display_callback_ = request_display_callback;
HWC::Error error = HWC::Error::None;
Hwc2::Config config;
- error = hidl->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
+ error = composer->getActiveConfig(HWC_DISPLAY_PRIMARY, &config);
if (error != HWC::Error::None) {
ALOGE("HardwareComposer: Failed to get current display config : %d",
@@ -117,7 +142,7 @@
return false;
}
- error = GetDisplayMetrics(hidl, HWC_DISPLAY_PRIMARY, config,
+ error = GetDisplayMetrics(composer, HWC_DISPLAY_PRIMARY, config,
&native_display_metrics_);
if (error != HWC::Error::None) {
@@ -140,6 +165,9 @@
display_transform_ = HWC_TRANSFORM_NONE;
display_metrics_ = native_display_metrics_;
+ // Setup the display metrics used by all Layer instances.
+ Layer::SetDisplayMetrics(native_display_metrics_);
+
post_thread_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
LOG_ALWAYS_FATAL_IF(
!post_thread_event_fd_,
@@ -198,9 +226,17 @@
}
void HardwareComposer::OnPostThreadResumed() {
- hidl_.reset(new Hwc2::Composer(false));
- hidl_callback_ = new ComposerCallback;
- hidl_->registerCallback(hidl_callback_);
+ // Phones create a new composer client on resume and destroy it on pause.
+ // Standalones only create the composer client once and then use SetPowerMode
+ // to control the screen on pause/resume.
+ if (!is_standalone_device_ || !composer_) {
+ composer_.reset(new Hwc2::Composer(false));
+ composer_callback_ = new ComposerCallback;
+ composer_->registerCallback(composer_callback_);
+ Layer::SetComposer(composer_.get());
+ } else {
+ SetPowerMode(true);
+ }
EnableVsync(true);
@@ -217,19 +253,19 @@
void HardwareComposer::OnPostThreadPaused() {
retire_fence_fds_.clear();
- display_surfaces_.clear();
+ layers_.clear();
- for (size_t i = 0; i < kMaxHardwareLayers; ++i) {
- layers_[i].Reset();
- }
- active_layer_count_ = 0;
-
- if (hidl_) {
+ if (composer_) {
EnableVsync(false);
}
- hidl_callback_ = nullptr;
- hidl_.reset(nullptr);
+ if (!is_standalone_device_) {
+ composer_callback_ = nullptr;
+ composer_.reset(nullptr);
+ Layer::SetComposer(nullptr);
+ } else {
+ SetPowerMode(false);
+ }
// Trigger target-specific performance mode change.
property_set(kDvrPerformanceProperty, "idle");
@@ -239,29 +275,35 @@
uint32_t num_types;
uint32_t num_requests;
HWC::Error error =
- hidl_->validateDisplay(display, &num_types, &num_requests);
+ composer_->validateDisplay(display, &num_types, &num_requests);
if (error == HWC2_ERROR_HAS_CHANGES) {
// TODO(skiazyk): We might need to inspect the requested changes first, but
// so far it seems like we shouldn't ever hit a bad state.
// error = hwc2_funcs_.accept_display_changes_fn_(hardware_composer_device_,
// display);
- error = hidl_->acceptDisplayChanges(display);
+ error = composer_->acceptDisplayChanges(display);
}
return error;
}
HWC::Error HardwareComposer::EnableVsync(bool enabled) {
- return hidl_->setVsyncEnabled(
+ return composer_->setVsyncEnabled(
HWC_DISPLAY_PRIMARY,
(Hwc2::IComposerClient::Vsync)(enabled ? HWC2_VSYNC_ENABLE
: HWC2_VSYNC_DISABLE));
}
+HWC::Error HardwareComposer::SetPowerMode(bool active) {
+ HWC::PowerMode power_mode = active ? HWC::PowerMode::On : HWC::PowerMode::Off;
+ return composer_->setPowerMode(
+ HWC_DISPLAY_PRIMARY, power_mode.cast<Hwc2::IComposerClient::PowerMode>());
+}
+
HWC::Error HardwareComposer::Present(hwc2_display_t display) {
int32_t present_fence;
- HWC::Error error = hidl_->presentDisplay(display, &present_fence);
+ HWC::Error error = composer_->presentDisplay(display, &present_fence);
// According to the documentation, this fence is signaled at the time of
// vsync/DMA for physical displays.
@@ -275,21 +317,21 @@
return error;
}
-HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* hidl,
+HWC::Error HardwareComposer::GetDisplayAttribute(Hwc2::Composer* composer,
hwc2_display_t display,
hwc2_config_t config,
hwc2_attribute_t attribute,
int32_t* out_value) const {
- return hidl->getDisplayAttribute(
+ return composer->getDisplayAttribute(
display, config, (Hwc2::IComposerClient::Attribute)attribute, out_value);
}
HWC::Error HardwareComposer::GetDisplayMetrics(
- Hwc2::Composer* hidl, hwc2_display_t display, hwc2_config_t config,
+ Hwc2::Composer* composer, hwc2_display_t display, hwc2_config_t config,
HWCDisplayMetrics* out_metrics) const {
HWC::Error error;
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_WIDTH,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_WIDTH,
&out_metrics->width);
if (error != HWC::Error::None) {
ALOGE(
@@ -298,7 +340,7 @@
return error;
}
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_HEIGHT,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_HEIGHT,
&out_metrics->height);
if (error != HWC::Error::None) {
ALOGE(
@@ -307,7 +349,7 @@
return error;
}
- error = GetDisplayAttribute(hidl, display, config,
+ error = GetDisplayAttribute(composer, display, config,
HWC2_ATTRIBUTE_VSYNC_PERIOD,
&out_metrics->vsync_period_ns);
if (error != HWC::Error::None) {
@@ -317,7 +359,7 @@
return error;
}
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_X,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_X,
&out_metrics->dpi.x);
if (error != HWC::Error::None) {
ALOGE(
@@ -326,7 +368,7 @@
return error;
}
- error = GetDisplayAttribute(hidl, display, config, HWC2_ATTRIBUTE_DPI_Y,
+ error = GetDisplayAttribute(composer, display, config, HWC2_ATTRIBUTE_DPI_Y,
&out_metrics->dpi.y);
if (error != HWC::Error::None) {
ALOGE(
@@ -349,10 +391,10 @@
<< std::endl;
stream << "Post thread resumed: " << post_thread_resumed_ << std::endl;
- stream << "Active layers: " << active_layer_count_ << std::endl;
+ stream << "Active layers: " << layers_.size() << std::endl;
stream << std::endl;
- for (size_t i = 0; i < active_layer_count_; i++) {
+ for (size_t i = 0; i < layers_.size(); i++) {
stream << "Layer " << i << ":";
stream << " type=" << layers_[i].GetCompositionType().to_string();
stream << " surface_id=" << layers_[i].GetSurfaceId();
@@ -363,7 +405,7 @@
if (post_thread_resumed_) {
stream << "Hardware Composer Debug Info:" << std::endl;
- stream << hidl_->dumpDebugInfo();
+ stream << composer_->dumpDebugInfo();
}
return stream.str();
@@ -373,8 +415,8 @@
ATRACE_NAME("HardwareComposer::PostLayers");
// Setup the hardware composer layers with current buffers.
- for (size_t i = 0; i < active_layer_count_; i++) {
- layers_[i].Prepare();
+ for (auto& layer : layers_) {
+ layer.Prepare();
}
HWC::Error error = Validate(HWC_DISPLAY_PRIMARY);
@@ -396,20 +438,18 @@
retire_fence_fds_.erase(retire_fence_fds_.begin());
}
- const bool is_frame_pending = IsFramePendingInDriver();
const bool is_fence_pending = static_cast<int32_t>(retire_fence_fds_.size()) >
post_thread_config_.allowed_pending_fence_count;
- if (is_fence_pending || is_frame_pending) {
+ if (is_fence_pending) {
ATRACE_INT("frame_skip_count", ++frame_skip_count_);
- ALOGW_IF(is_frame_pending, "Warning: frame already queued, dropping frame");
ALOGW_IF(is_fence_pending,
"Warning: dropping a frame to catch up with HWC (pending = %zd)",
retire_fence_fds_.size());
- for (size_t i = 0; i < active_layer_count_; i++) {
- layers_[i].Drop();
+ for (auto& layer : layers_) {
+ layer.Drop();
}
return;
} else {
@@ -419,7 +459,7 @@
}
#if TRACE > 1
- for (size_t i = 0; i < active_layer_count_; i++) {
+ for (size_t i = 0; i < layers_.size(); i++) {
ALOGI("HardwareComposer::PostLayers: layer=%zu buffer_id=%d composition=%s",
i, layers_[i].GetBufferId(),
layers_[i].GetCompositionType().to_string().c_str());
@@ -435,18 +475,18 @@
std::vector<Hwc2::Layer> out_layers;
std::vector<int> out_fences;
- error = hidl_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
- &out_fences);
+ error = composer_->getReleaseFences(HWC_DISPLAY_PRIMARY, &out_layers,
+ &out_fences);
ALOGE_IF(error != HWC::Error::None,
"HardwareComposer::PostLayers: Failed to get release fences: %s",
error.to_string().c_str());
- // Perform post-frame bookkeeping. Unused layers are a no-op.
+ // Perform post-frame bookkeeping.
uint32_t num_elements = out_layers.size();
for (size_t i = 0; i < num_elements; ++i) {
- for (size_t j = 0; j < active_layer_count_; ++j) {
- if (layers_[j].GetLayerHandle() == out_layers[i]) {
- layers_[j].Finish(out_fences[i]);
+ for (auto& layer : layers_) {
+ if (layer.GetLayerHandle() == out_layers[i]) {
+ layer.Finish(out_fences[i]);
}
}
}
@@ -462,7 +502,7 @@
pending_surfaces_ = std::move(surfaces);
}
- if (request_display_callback_)
+ if (request_display_callback_ && (!is_standalone_device_ || !composer_))
request_display_callback_(!display_idle);
// Set idle state based on whether there are any surfaces to handle.
@@ -572,60 +612,28 @@
}
}
-// Reads the value of the display driver wait_pingpong state. Returns 0 or 1
-// (the value of the state) on success or a negative error otherwise.
-// TODO(eieio): This is pretty driver specific, this should be moved to a
-// separate class eventually.
-int HardwareComposer::ReadWaitPPState() {
- // Gracefully handle when the kernel does not support this feature.
- if (!primary_display_wait_pp_fd_)
- return 0;
-
- const int wait_pp_fd = primary_display_wait_pp_fd_.Get();
- int ret, error;
-
- ret = lseek(wait_pp_fd, 0, SEEK_SET);
- if (ret < 0) {
- error = errno;
- ALOGE("HardwareComposer::ReadWaitPPState: Failed to seek wait_pp fd: %s",
- strerror(error));
- return -error;
- }
-
- char data = -1;
- ret = read(wait_pp_fd, &data, sizeof(data));
- if (ret < 0) {
- error = errno;
- ALOGE("HardwareComposer::ReadWaitPPState: Failed to read wait_pp state: %s",
- strerror(error));
- return -error;
- }
-
- switch (data) {
- case '0':
- return 0;
- case '1':
- return 1;
- default:
- ALOGE(
- "HardwareComposer::ReadWaitPPState: Unexpected value for wait_pp: %d",
- data);
- return -EINVAL;
- }
+Status<int64_t> HardwareComposer::GetVSyncTime() {
+ auto status = composer_callback_->GetVsyncTime(HWC_DISPLAY_PRIMARY);
+ ALOGE_IF(!status,
+ "HardwareComposer::GetVSyncTime: Failed to get vsync timestamp: %s",
+ status.GetErrorMessage().c_str());
+ return status;
}
// Waits for the next vsync and returns the timestamp of the vsync event. If
// vsync already passed since the last call, returns the latest vsync timestamp
// instead of blocking.
-int HardwareComposer::WaitForVSync(int64_t* timestamp) {
- int error = PostThreadPollInterruptible(
- hidl_callback_->GetVsyncEventFd(), POLLIN, /*timeout_ms*/ 1000);
- if (error == kPostThreadInterrupted || error < 0) {
+Status<int64_t> HardwareComposer::WaitForVSync() {
+ const int64_t predicted_vsync_time =
+ last_vsync_timestamp_ +
+ display_metrics_.vsync_period_ns * vsync_prediction_interval_;
+ const int error = SleepUntil(predicted_vsync_time);
+ if (error < 0) {
+ ALOGE("HardwareComposer::WaifForVSync:: Failed to sleep: %s",
+ strerror(-error));
return error;
- } else {
- *timestamp = hidl_callback_->GetVsyncTime();
- return 0;
}
+ return {predicted_vsync_time};
}
int HardwareComposer::SleepUntil(int64_t wakeup_timestamp) {
@@ -643,8 +651,8 @@
return -error;
}
- return PostThreadPollInterruptible(
- vsync_sleep_timer_fd_, POLLIN, /*timeout_ms*/ -1);
+ return PostThreadPollInterruptible(vsync_sleep_timer_fd_, POLLIN,
+ /*timeout_ms*/ -1);
}
void HardwareComposer::PostThread() {
@@ -667,15 +675,6 @@
strerror(errno));
#endif // ENABLE_BACKLIGHT_BRIGHTNESS
- // Open the wait pingpong status node for the primary display.
- // TODO(eieio): Move this into a platform-specific class.
- primary_display_wait_pp_fd_ =
- LocalHandle(kPrimaryDisplayWaitPPEventFile, O_RDONLY);
- ALOGW_IF(
- !primary_display_wait_pp_fd_,
- "HardwareComposer: Failed to open wait_pp node for primary display: %s",
- strerror(errno));
-
// Create a timerfd based on CLOCK_MONOTINIC.
vsync_sleep_timer_fd_.Reset(timerfd_create(CLOCK_MONOTONIC, 0));
LOG_ALWAYS_FATAL_IF(
@@ -740,26 +739,41 @@
thread_policy_setup =
SetThreadPolicy("graphics:high", "/system/performance");
}
+
+ // Initialize the last vsync timestamp with the current time. The
+ // predictor below uses this time + the vsync interval in absolute time
+ // units for the initial delay. Once the driver starts reporting vsync the
+ // predictor will sync up with the real vsync.
+ last_vsync_timestamp_ = GetSystemClockNs();
}
int64_t vsync_timestamp = 0;
{
- std::array<char, 128> buf;
- snprintf(buf.data(), buf.size(), "wait_vsync|vsync=%d|",
- vsync_count_ + 1);
- ATRACE_NAME(buf.data());
+ TRACE_FORMAT("wait_vsync|vsync=%u;last_timestamp=%" PRId64
+ ";prediction_interval=%d|",
+ vsync_count_ + 1, last_vsync_timestamp_,
+ vsync_prediction_interval_);
- const int error = WaitForVSync(&vsync_timestamp);
+ auto status = WaitForVSync();
ALOGE_IF(
- error < 0,
+ !status,
"HardwareComposer::PostThread: Failed to wait for vsync event: %s",
- strerror(-error));
- // Don't bother processing this frame if a pause was requested
- if (error == kPostThreadInterrupted)
+ status.GetErrorMessage().c_str());
+
+ // If there was an error either sleeping was interrupted due to pausing or
+ // there was an error getting the latest timestamp.
+ if (!status)
continue;
+
+ // Predicted vsync timestamp for this interval. This is stable because we
+ // use absolute time for the wakeup timer.
+ vsync_timestamp = status.get();
}
- ++vsync_count_;
+ // Advance the vsync counter only if the system is keeping up with hardware
+ // vsync to give clients an indication of the delays.
+ if (vsync_prediction_interval_ == 1)
+ ++vsync_count_;
const bool layer_config_changed = UpdateLayerConfig();
@@ -809,6 +823,38 @@
}
}
+ {
+ auto status = GetVSyncTime();
+ if (!status) {
+ ALOGE("HardwareComposer::PostThread: Failed to get VSYNC time: %s",
+ status.GetErrorMessage().c_str());
+ }
+
+ // If we failed to read vsync there might be a problem with the driver.
+ // Since there's nothing we can do just behave as though we didn't get an
+ // updated vsync time and let the prediction continue.
+ const int64_t current_vsync_timestamp =
+ status ? status.get() : last_vsync_timestamp_;
+
+ const bool vsync_delayed =
+ last_vsync_timestamp_ == current_vsync_timestamp;
+ ATRACE_INT("vsync_delayed", vsync_delayed);
+
+ // If vsync was delayed advance the prediction interval and allow the
+ // fence logic in PostLayers() to skip the frame.
+ if (vsync_delayed) {
+ ALOGW(
+ "HardwareComposer::PostThread: VSYNC timestamp did not advance "
+ "since last frame: timestamp=%" PRId64 " prediction_interval=%d",
+ current_vsync_timestamp, vsync_prediction_interval_);
+ vsync_prediction_interval_++;
+ } else {
+ // We have an updated vsync timestamp, reset the prediction interval.
+ last_vsync_timestamp_ = current_vsync_timestamp;
+ vsync_prediction_interval_ = 1;
+ }
+ }
+
PostLayers();
}
}
@@ -827,38 +873,60 @@
ATRACE_NAME("UpdateLayerConfig_HwLayers");
- display_surfaces_.clear();
+ // Sort the new direct surface list by z-order to determine the relative order
+ // of the surfaces. This relative order is used for the HWC z-order value to
+ // insulate VrFlinger and HWC z-order semantics from each other.
+ std::sort(surfaces.begin(), surfaces.end(), [](const auto& a, const auto& b) {
+ return a->z_order() < b->z_order();
+ });
- Layer* target_layer;
- size_t layer_index;
- for (layer_index = 0;
- layer_index < std::min(surfaces.size(), kMaxHardwareLayers);
- layer_index++) {
+ // Prepare a new layer stack, pulling in layers from the previous
+ // layer stack that are still active and updating their attributes.
+ std::vector<Layer> layers;
+ size_t layer_index = 0;
+ for (const auto& surface : surfaces) {
// The bottom layer is opaque, other layers blend.
HWC::BlendMode blending =
layer_index == 0 ? HWC::BlendMode::None : HWC::BlendMode::Coverage;
- layers_[layer_index].Setup(surfaces[layer_index], native_display_metrics_,
- hidl_.get(), blending,
- display_transform_, HWC::Composition::Device,
- layer_index);
- display_surfaces_.push_back(surfaces[layer_index]);
+
+ // Try to find a layer for this surface in the set of active layers.
+ auto search =
+ std::lower_bound(layers_.begin(), layers_.end(), surface->surface_id());
+ const bool found = search != layers_.end() &&
+ search->GetSurfaceId() == surface->surface_id();
+ if (found) {
+ // Update the attributes of the layer that may have changed.
+ search->SetBlending(blending);
+ search->SetZOrder(layer_index); // Relative z-order.
+
+ // Move the existing layer to the new layer set and remove the empty layer
+ // object from the current set.
+ layers.push_back(std::move(*search));
+ layers_.erase(search);
+ } else {
+ // Insert a layer for the new surface.
+ layers.emplace_back(surface, blending, display_transform_,
+ HWC::Composition::Device, layer_index);
+ }
+
+ ALOGI_IF(
+ TRACE,
+ "HardwareComposer::UpdateLayerConfig: layer_index=%zu surface_id=%d",
+ layer_index, layers[layer_index].GetSurfaceId());
+
+ layer_index++;
}
- // Clear unused layers.
- for (size_t i = layer_index; i < kMaxHardwareLayers; i++)
- layers_[i].Reset();
+ // Sort the new layer stack by ascending surface id.
+ std::sort(layers.begin(), layers.end());
- active_layer_count_ = layer_index;
+ // Replace the previous layer set with the new layer set. The destructor of
+ // the previous set will clean up the remaining Layers that are not moved to
+ // the new layer set.
+ layers_ = std::move(layers);
+
ALOGD_IF(TRACE, "HardwareComposer::UpdateLayerConfig: %zd active layers",
- active_layer_count_);
-
- // Any surfaces left over could not be assigned a hardware layer and will
- // not be displayed.
- ALOGW_IF(surfaces.size() != display_surfaces_.size(),
- "HardwareComposer::UpdateLayerConfig: More surfaces than layers: "
- "pending_surfaces=%zu display_surfaces=%zu",
- surfaces.size(), display_surfaces_.size());
-
+ layers_.size());
return true;
}
@@ -874,17 +942,28 @@
}
}
-HardwareComposer::ComposerCallback::ComposerCallback() {
- vsync_event_fd_.Reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
- LOG_ALWAYS_FATAL_IF(
- !vsync_event_fd_,
- "Failed to create vsync event fd : %s",
- strerror(errno));
-}
-
Return<void> HardwareComposer::ComposerCallback::onHotplug(
- Hwc2::Display /*display*/,
- IComposerCallback::Connection /*conn*/) {
+ Hwc2::Display display, IComposerCallback::Connection /*conn*/) {
+ // See if the driver supports the vsync_event node in sysfs.
+ if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES &&
+ !displays_[display].driver_vsync_event_fd) {
+ std::array<char, 1024> buffer;
+ snprintf(buffer.data(), buffer.size(),
+ "/sys/class/graphics/fb%" PRIu64 "/vsync_event", display);
+ if (LocalHandle handle{buffer.data(), O_RDONLY}) {
+ ALOGI(
+ "HardwareComposer::ComposerCallback::onHotplug: Driver supports "
+ "vsync_event node for display %" PRIu64,
+ display);
+ displays_[display].driver_vsync_event_fd = std::move(handle);
+ } else {
+ ALOGI(
+ "HardwareComposer::ComposerCallback::onHotplug: Driver does not "
+ "support vsync_event node for display %" PRIu64,
+ display);
+ }
+ }
+
return Void();
}
@@ -893,40 +972,94 @@
return hardware::Void();
}
-Return<void> HardwareComposer::ComposerCallback::onVsync(
- Hwc2::Display display, int64_t timestamp) {
- if (display == HWC_DISPLAY_PRIMARY) {
- std::lock_guard<std::mutex> lock(vsync_mutex_);
- vsync_time_ = timestamp;
- int error = eventfd_write(vsync_event_fd_.Get(), 1);
- LOG_ALWAYS_FATAL_IF(error != 0, "Failed writing to vsync event fd");
+Return<void> HardwareComposer::ComposerCallback::onVsync(Hwc2::Display display,
+ int64_t timestamp) {
+ TRACE_FORMAT("vsync_callback|display=%" PRIu64 ";timestamp=%" PRId64 "|",
+ display, timestamp);
+ if (display < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+ displays_[display].callback_vsync_timestamp = timestamp;
+ } else {
+ ALOGW(
+ "HardwareComposer::ComposerCallback::onVsync: Received vsync on "
+ "non-physical display: display=%" PRId64,
+ display);
}
return Void();
}
-const pdx::LocalHandle&
-HardwareComposer::ComposerCallback::GetVsyncEventFd() const {
- return vsync_event_fd_;
+Status<int64_t> HardwareComposer::ComposerCallback::GetVsyncTime(
+ Hwc2::Display display) {
+ if (display >= HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+ ALOGE(
+ "HardwareComposer::ComposerCallback::GetVsyncTime: Invalid physical "
+ "display requested: display=%" PRIu64,
+ display);
+ return ErrorStatus(EINVAL);
+ }
+
+ // See if the driver supports direct vsync events.
+ LocalHandle& event_fd = displays_[display].driver_vsync_event_fd;
+ if (!event_fd) {
+ // Fall back to returning the last timestamp returned by the vsync
+ // callback.
+ std::lock_guard<std::mutex> autolock(vsync_mutex_);
+ return displays_[display].callback_vsync_timestamp;
+ }
+
+ // When the driver supports the vsync_event sysfs node we can use it to
+ // determine the latest vsync timestamp, even if the HWC callback has been
+ // delayed.
+
+ // The driver returns data in the form "VSYNC=<timestamp ns>".
+ std::array<char, 32> data;
+ data.fill('\0');
+
+ // Seek back to the beginning of the event file.
+ int ret = lseek(event_fd.Get(), 0, SEEK_SET);
+ if (ret < 0) {
+ const int error = errno;
+ ALOGE(
+ "HardwareComposer::ComposerCallback::GetVsyncTime: Failed to seek "
+ "vsync event fd: %s",
+ strerror(error));
+ return ErrorStatus(error);
+ }
+
+ // Read the vsync event timestamp.
+ ret = read(event_fd.Get(), data.data(), data.size());
+ if (ret < 0) {
+ const int error = errno;
+ ALOGE_IF(error != EAGAIN,
+ "HardwareComposer::ComposerCallback::GetVsyncTime: Error "
+ "while reading timestamp: %s",
+ strerror(error));
+ return ErrorStatus(error);
+ }
+
+ int64_t timestamp;
+ ret = sscanf(data.data(), "VSYNC=%" PRIu64,
+ reinterpret_cast<uint64_t*>(×tamp));
+ if (ret < 0) {
+ const int error = errno;
+ ALOGE(
+ "HardwareComposer::ComposerCallback::GetVsyncTime: Error while "
+ "parsing timestamp: %s",
+ strerror(error));
+ return ErrorStatus(error);
+ }
+
+ return {timestamp};
}
-int64_t HardwareComposer::ComposerCallback::GetVsyncTime() {
- std::lock_guard<std::mutex> lock(vsync_mutex_);
- eventfd_t event;
- eventfd_read(vsync_event_fd_.Get(), &event);
- LOG_ALWAYS_FATAL_IF(vsync_time_ < 0,
- "Attempt to read vsync time before vsync event");
- int64_t return_val = vsync_time_;
- vsync_time_ = -1;
- return return_val;
-}
+Hwc2::Composer* Layer::composer_{nullptr};
+HWCDisplayMetrics Layer::display_metrics_{0, 0, {0, 0}, 0};
void Layer::Reset() {
- if (hidl_ != nullptr && hardware_composer_layer_) {
- hidl_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
+ if (hardware_composer_layer_) {
+ composer_->destroyLayer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_);
hardware_composer_layer_ = 0;
}
- hidl_ = nullptr;
z_order_ = 0;
blending_ = HWC::BlendMode::None;
transform_ = HWC::Transform::None;
@@ -935,38 +1068,52 @@
source_ = EmptyVariant{};
acquire_fence_.Close();
surface_rect_functions_applied_ = false;
+ pending_visibility_settings_ = true;
}
-void Layer::Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
- const HWCDisplayMetrics& display_metrics,
- Hwc2::Composer* hidl, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order) {
- Reset();
- hidl_ = hidl;
- z_order_ = z_order;
- blending_ = blending;
- transform_ = transform;
- composition_type_ = HWC::Composition::Invalid;
- target_composition_type_ = composition_type;
- source_ = SourceSurface{surface};
- CommonLayerSetup(display_metrics);
+Layer::Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_order)
+ : z_order_{z_order},
+ blending_{blending},
+ transform_{transform},
+ target_composition_type_{composition_type},
+ source_{SourceSurface{surface}} {
+ CommonLayerSetup();
}
-void Layer::Setup(const std::shared_ptr<IonBuffer>& buffer,
- const HWCDisplayMetrics& display_metrics,
- Hwc2::Composer* hidl, HWC::BlendMode blending,
- HWC::Transform transform, HWC::Composition composition_type,
- size_t z_order) {
- Reset();
- hidl_ = hidl;
- z_order_ = z_order;
- blending_ = blending;
- transform_ = transform;
- composition_type_ = HWC::Composition::Invalid;
- target_composition_type_ = composition_type;
- source_ = SourceBuffer{buffer};
- CommonLayerSetup(display_metrics);
+Layer::Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order)
+ : z_order_{z_order},
+ blending_{blending},
+ transform_{transform},
+ target_composition_type_{composition_type},
+ source_{SourceBuffer{buffer}} {
+ CommonLayerSetup();
+}
+
+Layer::~Layer() { Reset(); }
+
+Layer::Layer(Layer&& other) { *this = std::move(other); }
+
+Layer& Layer::operator=(Layer&& other) {
+ if (this != &other) {
+ Reset();
+ using std::swap;
+ swap(hardware_composer_layer_, other.hardware_composer_layer_);
+ swap(z_order_, other.z_order_);
+ swap(blending_, other.blending_);
+ swap(transform_, other.transform_);
+ swap(composition_type_, other.composition_type_);
+ swap(target_composition_type_, other.target_composition_type_);
+ swap(source_, other.source_);
+ swap(acquire_fence_, other.acquire_fence_);
+ swap(surface_rect_functions_applied_,
+ other.surface_rect_functions_applied_);
+ swap(pending_visibility_settings_, other.pending_visibility_settings_);
+ }
+ return *this;
}
void Layer::UpdateBuffer(const std::shared_ptr<IonBuffer>& buffer) {
@@ -974,8 +1121,19 @@
std::get<SourceBuffer>(source_) = {buffer};
}
-void Layer::SetBlending(HWC::BlendMode blending) { blending_ = blending; }
-void Layer::SetZOrder(size_t z_order) { z_order_ = z_order; }
+void Layer::SetBlending(HWC::BlendMode blending) {
+ if (blending_ != blending) {
+ blending_ = blending;
+ pending_visibility_settings_ = true;
+ }
+}
+
+void Layer::SetZOrder(size_t z_order) {
+ if (z_order_ != z_order) {
+ z_order_ = z_order;
+ pending_visibility_settings_ = true;
+ }
+}
IonBuffer* Layer::GetBuffer() {
struct Visitor {
@@ -986,67 +1144,65 @@
return source_.Visit(Visitor{});
}
-void Layer::UpdateLayerSettings(const HWCDisplayMetrics& display_metrics) {
- if (!IsLayerSetup()) {
- ALOGE(
- "HardwareComposer::Layer::UpdateLayerSettings: Attempt to update "
- "unused Layer!");
- return;
- }
+void Layer::UpdateVisibilitySettings() {
+ if (pending_visibility_settings_) {
+ pending_visibility_settings_ = false;
+ HWC::Error error;
+ hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+
+ error = composer_->setLayerBlendMode(
+ display, hardware_composer_layer_,
+ blending_.cast<Hwc2::IComposerClient::BlendMode>());
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
+ error.to_string().c_str());
+
+ error =
+ composer_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::UpdateLayerSettings: Error setting z_ order: %s",
+ error.to_string().c_str());
+ }
+}
+
+void Layer::UpdateLayerSettings() {
HWC::Error error;
hwc2_display_t display = HWC_DISPLAY_PRIMARY;
- error = hidl_->setLayerCompositionType(
- display, hardware_composer_layer_,
- composition_type_.cast<Hwc2::IComposerClient::Composition>());
- ALOGE_IF(
- error != HWC::Error::None,
- "Layer::UpdateLayerSettings: Error setting layer composition type: %s",
- error.to_string().c_str());
-
- error = hidl_->setLayerBlendMode(
- display, hardware_composer_layer_,
- blending_.cast<Hwc2::IComposerClient::BlendMode>());
- ALOGE_IF(error != HWC::Error::None,
- "Layer::UpdateLayerSettings: Error setting layer blend mode: %s",
- error.to_string().c_str());
+ UpdateVisibilitySettings();
// TODO(eieio): Use surface attributes or some other mechanism to control
// the layer display frame.
- error = hidl_->setLayerDisplayFrame(
+ error = composer_->setLayerDisplayFrame(
display, hardware_composer_layer_,
- {0, 0, display_metrics.width, display_metrics.height});
+ {0, 0, display_metrics_.width, display_metrics_.height});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer display frame: %s",
error.to_string().c_str());
- error = hidl_->setLayerVisibleRegion(
+ error = composer_->setLayerVisibleRegion(
display, hardware_composer_layer_,
- {{0, 0, display_metrics.width, display_metrics.height}});
+ {{0, 0, display_metrics_.width, display_metrics_.height}});
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer visible region: %s",
error.to_string().c_str());
- error = hidl_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
+ error =
+ composer_->setLayerPlaneAlpha(display, hardware_composer_layer_, 1.0f);
ALOGE_IF(error != HWC::Error::None,
"Layer::UpdateLayerSettings: Error setting layer plane alpha: %s",
error.to_string().c_str());
-
- error = hidl_->setLayerZOrder(display, hardware_composer_layer_, z_order_);
- ALOGE_IF(error != HWC::Error::None,
- "Layer::UpdateLayerSettings: Error setting z_ order: %s",
- error.to_string().c_str());
}
-void Layer::CommonLayerSetup(const HWCDisplayMetrics& display_metrics) {
+void Layer::CommonLayerSetup() {
HWC::Error error =
- hidl_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
- ALOGE_IF(
- error != HWC::Error::None,
- "Layer::CommonLayerSetup: Failed to create layer on primary display: %s",
- error.to_string().c_str());
- UpdateLayerSettings(display_metrics);
+ composer_->createLayer(HWC_DISPLAY_PRIMARY, &hardware_composer_layer_);
+ ALOGE_IF(error != HWC::Error::None,
+ "Layer::CommonLayerSetup: Failed to create layer on primary "
+ "display: %s",
+ error.to_string().c_str());
+ UpdateLayerSettings();
}
void Layer::Prepare() {
@@ -1058,19 +1214,23 @@
std::tie(right, bottom, handle, acquire_fence_) = source.Acquire();
});
- // When a layer is first setup there may be some time before the first buffer
- // arrives. Setup the HWC layer as a solid color to stall for time until the
- // first buffer arrives. Once the first buffer arrives there will always be a
- // buffer for the frame even if it is old.
+ // Update any visibility (blending, z-order) changes that occurred since
+ // last prepare.
+ UpdateVisibilitySettings();
+
+ // When a layer is first setup there may be some time before the first
+ // buffer arrives. Setup the HWC layer as a solid color to stall for time
+ // until the first buffer arrives. Once the first buffer arrives there will
+ // always be a buffer for the frame even if it is old.
if (!handle.get()) {
if (composition_type_ == HWC::Composition::Invalid) {
composition_type_ = HWC::Composition::SolidColor;
- hidl_->setLayerCompositionType(
+ composer_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
Hwc2::IComposerClient::Color layer_color = {0, 0, 0, 0};
- hidl_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
- layer_color);
+ composer_->setLayerColor(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ layer_color);
} else {
// The composition type is already set. Nothing else to do until a
// buffer arrives.
@@ -1078,15 +1238,15 @@
} else {
if (composition_type_ != target_composition_type_) {
composition_type_ = target_composition_type_;
- hidl_->setLayerCompositionType(
+ composer_->setLayerCompositionType(
HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
composition_type_.cast<Hwc2::IComposerClient::Composition>());
}
HWC::Error error{HWC::Error::None};
- error = hidl_->setLayerBuffer(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_, 0, handle,
- acquire_fence_.Get());
+ error =
+ composer_->setLayerBuffer(HWC_DISPLAY_PRIMARY, hardware_composer_layer_,
+ 0, handle, acquire_fence_.Get());
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer buffer: %s",
@@ -1095,9 +1255,9 @@
if (!surface_rect_functions_applied_) {
const float float_right = right;
const float float_bottom = bottom;
- error = hidl_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
- hardware_composer_layer_,
- {0, 0, float_right, float_bottom});
+ error = composer_->setLayerSourceCrop(HWC_DISPLAY_PRIMARY,
+ hardware_composer_layer_,
+ {0, 0, float_right, float_bottom});
ALOGE_IF(error != HWC::Error::None,
"Layer::Prepare: Error setting layer source crop: %s",
diff --git a/libs/vr/libvrflinger/hardware_composer.h b/libs/vr/libvrflinger/hardware_composer.h
index fc0efee..8131e50 100644
--- a/libs/vr/libvrflinger/hardware_composer.h
+++ b/libs/vr/libvrflinger/hardware_composer.h
@@ -52,10 +52,7 @@
// source supplying buffers for the layer's contents.
class Layer {
public:
- Layer() {}
-
- // Releases any shared pointers and fence handles held by this instance.
- void Reset();
+ Layer() = default;
// Sets up the layer to use a display surface as its content source. The Layer
// automatically handles ACQUIRE/RELEASE phases for the surface's buffer train
@@ -66,10 +63,9 @@
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
// |index| is the index of this surface in the DirectDisplaySurface array.
- void Setup(const std::shared_ptr<DirectDisplaySurface>& surface,
- const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_roder);
+ Layer(const std::shared_ptr<DirectDisplaySurface>& surface,
+ HWC::BlendMode blending, HWC::Transform transform,
+ HWC::Composition composition_type, size_t z_roder);
// Sets up the layer to use a direct buffer as its content source. No special
// handling of the buffer is performed; responsibility for updating or
@@ -79,10 +75,17 @@
// |transform| receives HWC_TRANSFORM_* values.
// |composition_type| receives either HWC_FRAMEBUFFER for most layers or
// HWC_FRAMEBUFFER_TARGET (unless you know what you are doing).
- void Setup(const std::shared_ptr<IonBuffer>& buffer,
- const HWCDisplayMetrics& display_metrics, Hwc2::Composer* hidl,
- HWC::BlendMode blending, HWC::Transform transform,
- HWC::Composition composition_type, size_t z_order);
+ Layer(const std::shared_ptr<IonBuffer>& buffer, HWC::BlendMode blending,
+ HWC::Transform transform, HWC::Composition composition_type,
+ size_t z_order);
+
+ Layer(Layer&&);
+ Layer& operator=(Layer&&);
+
+ ~Layer();
+
+ // Releases any shared pointers and fence handles held by this instance.
+ void Reset();
// Layers that use a direct IonBuffer should call this each frame to update
// which buffer will be used for the next PostLayers.
@@ -117,9 +120,6 @@
HWC::Layer GetLayerHandle() const { return hardware_composer_layer_; }
bool IsLayerSetup() const { return !source_.empty(); }
- // Applies all of the settings to this layer using the hwc functions
- void UpdateLayerSettings(const HWCDisplayMetrics& display_metrics);
-
int GetSurfaceId() const {
int surface_id = -1;
pdx::rpc::IfAnyOf<SourceSurface>::Call(
@@ -138,10 +138,39 @@
return buffer_id;
}
- private:
- void CommonLayerSetup(const HWCDisplayMetrics& display_metrics);
+ // Compares Layers by surface id.
+ bool operator<(const Layer& other) const {
+ return GetSurfaceId() < other.GetSurfaceId();
+ }
+ bool operator<(int surface_id) const { return GetSurfaceId() < surface_id; }
- Hwc2::Composer* hidl_ = nullptr;
+ // Sets the composer instance used by all Layer instances.
+ static void SetComposer(Hwc2::Composer* composer) { composer_ = composer; }
+
+ // Sets the display metrics used by all Layer instances.
+ static void SetDisplayMetrics(HWCDisplayMetrics display_metrics) {
+ display_metrics_ = display_metrics;
+ }
+
+ private:
+ void CommonLayerSetup();
+
+ // Applies all of the settings to this layer using the hwc functions
+ void UpdateLayerSettings();
+
+ // Applies visibility settings that may have changed.
+ void UpdateVisibilitySettings();
+
+ // Composer instance shared by all instances of Layer. This must be set
+ // whenever a new instance of the Composer is created. This may be set to
+ // nullptr as long as there are no instances of Layer that might need to use
+ // it.
+ static Hwc2::Composer* composer_;
+
+ // Display metrics shared by all instances of Layer. This must be set at least
+ // once during VrFlinger initialization and is expected to remain constant
+ // thereafter.
+ static HWCDisplayMetrics display_metrics_;
// The hardware composer layer and metrics to use during the prepare cycle.
hwc2_layer_t hardware_composer_layer_ = 0;
@@ -235,6 +264,7 @@
pdx::LocalHandle acquire_fence_;
bool surface_rect_functions_applied_ = false;
+ bool pending_visibility_settings_ = true;
Layer(const Layer&) = delete;
void operator=(const Layer&) = delete;
@@ -254,14 +284,10 @@
using VSyncCallback = std::function<void(int, int64_t, int64_t, uint32_t)>;
using RequestDisplayCallback = std::function<void(bool)>;
- // Since there is no universal way to query the number of hardware layers,
- // just set it to 4 for now.
- static constexpr size_t kMaxHardwareLayers = 4;
-
HardwareComposer();
~HardwareComposer();
- bool Initialize(Hwc2::Composer* hidl,
+ bool Initialize(Hwc2::Composer* composer,
RequestDisplayCallback request_display_callback);
bool IsInitialized() const { return initialized_; }
@@ -299,30 +325,36 @@
void OnDeletedGlobalBuffer(DvrGlobalBufferKey key);
private:
- HWC::Error GetDisplayAttribute(Hwc2::Composer* hidl, hwc2_display_t display,
- hwc2_config_t config,
+ HWC::Error GetDisplayAttribute(Hwc2::Composer* composer,
+ hwc2_display_t display, hwc2_config_t config,
hwc2_attribute_t attributes,
int32_t* out_value) const;
- HWC::Error GetDisplayMetrics(Hwc2::Composer* hidl, hwc2_display_t display,
+ HWC::Error GetDisplayMetrics(Hwc2::Composer* composer, hwc2_display_t display,
hwc2_config_t config,
HWCDisplayMetrics* out_metrics) const;
HWC::Error EnableVsync(bool enabled);
+ HWC::Error SetPowerMode(bool active);
class ComposerCallback : public Hwc2::IComposerCallback {
public:
- ComposerCallback();
+ ComposerCallback() = default;
hardware::Return<void> onHotplug(Hwc2::Display display,
Connection conn) override;
hardware::Return<void> onRefresh(Hwc2::Display display) override;
hardware::Return<void> onVsync(Hwc2::Display display,
int64_t timestamp) override;
- const pdx::LocalHandle& GetVsyncEventFd() const;
- int64_t GetVsyncTime();
+
+ pdx::Status<int64_t> GetVsyncTime(Hwc2::Display display);
+
private:
std::mutex vsync_mutex_;
- pdx::LocalHandle vsync_event_fd_;
- int64_t vsync_time_ = -1;
+
+ struct Display {
+ pdx::LocalHandle driver_vsync_event_fd;
+ int64_t callback_vsync_timestamp{0};
+ };
+ std::array<Display, HWC_NUM_PHYSICAL_DISPLAY_TYPES> displays_;
};
HWC::Error Validate(hwc2_display_t display);
@@ -356,18 +388,16 @@
// the case of a timeout. If we're interrupted, kPostThreadInterrupted will be
// returned.
int PostThreadPollInterruptible(const pdx::LocalHandle& event_fd,
- int requested_events,
- int timeout_ms);
+ int requested_events, int timeout_ms);
// WaitForVSync and SleepUntil are blocking calls made on the post thread that
// can be interrupted by a control thread. If interrupted, these calls return
// kPostThreadInterrupted.
int ReadWaitPPState();
- int WaitForVSync(int64_t* timestamp);
+ pdx::Status<int64_t> WaitForVSync();
+ pdx::Status<int64_t> GetVSyncTime();
int SleepUntil(int64_t wakeup_timestamp);
- bool IsFramePendingInDriver() { return ReadWaitPPState() == 1; }
-
// Reconfigures the layer stack if the display surfaces changed since the last
// frame. Called only from the post thread.
bool UpdateLayerConfig();
@@ -385,9 +415,10 @@
void UpdateConfigBuffer();
bool initialized_;
+ bool is_standalone_device_;
- std::unique_ptr<Hwc2::Composer> hidl_;
- sp<ComposerCallback> hidl_callback_;
+ std::unique_ptr<Hwc2::Composer> composer_;
+ sp<ComposerCallback> composer_callback_;
RequestDisplayCallback request_display_callback_;
// Display metrics of the physical display.
@@ -403,13 +434,9 @@
// thread and read by the post thread.
std::vector<std::shared_ptr<DirectDisplaySurface>> pending_surfaces_;
- // The surfaces displayed by the post thread. Used exclusively by the post
- // thread.
- std::vector<std::shared_ptr<DirectDisplaySurface>> display_surfaces_;
-
- // Layer array for handling buffer flow into hardware composer layers.
- std::array<Layer, kMaxHardwareLayers> layers_;
- size_t active_layer_count_ = 0;
+ // Layer set for handling buffer flow into hardware composer layers. This
+ // vector must be sorted by surface_id in ascending order.
+ std::vector<Layer> layers_;
// Handler to hook vsync events outside of this class.
VSyncCallback vsync_callback_;
@@ -419,8 +446,8 @@
std::thread post_thread_;
// Post thread state machine and synchronization primitives.
- PostThreadStateType post_thread_state_{
- PostThreadState::Idle | PostThreadState::Suspended};
+ PostThreadStateType post_thread_state_{PostThreadState::Idle |
+ PostThreadState::Suspended};
std::atomic<bool> post_thread_quiescent_{true};
bool post_thread_resumed_{false};
pdx::LocalHandle post_thread_event_fd_;
@@ -431,15 +458,15 @@
// Backlight LED brightness sysfs node.
pdx::LocalHandle backlight_brightness_fd_;
- // Primary display wait_pingpong state sysfs node.
- pdx::LocalHandle primary_display_wait_pp_fd_;
-
// VSync sleep timerfd.
pdx::LocalHandle vsync_sleep_timer_fd_;
// The timestamp of the last vsync.
int64_t last_vsync_timestamp_ = 0;
+ // The number of vsync intervals to predict since the last vsync.
+ int vsync_prediction_interval_ = 1;
+
// Vsync count since display on.
uint32_t vsync_count_ = 0;
diff --git a/libs/vr/libvrflinger/vr_flinger.cpp b/libs/vr/libvrflinger/vr_flinger.cpp
index fcf94f0..85dc586 100644
--- a/libs/vr/libvrflinger/vr_flinger.cpp
+++ b/libs/vr/libvrflinger/vr_flinger.cpp
@@ -64,9 +64,6 @@
ALOGI("Starting up VrFlinger...");
- setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY);
- set_sched_policy(0, SP_FOREGROUND);
-
// We need to be able to create endpoints with full perms.
umask(0000);
@@ -100,6 +97,9 @@
prctl(PR_SET_NAME, reinterpret_cast<unsigned long>("VrDispatch"), 0, 0, 0);
ALOGI("Entering message loop.");
+ setpriority(PRIO_PROCESS, 0, android::PRIORITY_URGENT_DISPLAY);
+ set_sched_policy(0, SP_FOREGROUND);
+
int ret = dispatcher_->EnterDispatchLoop();
if (ret < 0) {
ALOGE("Dispatch loop exited because: %s\n", strerror(-ret));
diff --git a/libs/vr/libvrflinger/vsync_service.cpp b/libs/vr/libvrflinger/vsync_service.cpp
index 3098b43..fdeb899 100644
--- a/libs/vr/libvrflinger/vsync_service.cpp
+++ b/libs/vr/libvrflinger/vsync_service.cpp
@@ -110,6 +110,7 @@
}
pdx::Status<void> VSyncService::HandleMessage(pdx::Message& message) {
+ ATRACE_NAME("VSyncService::HandleMessage");
switch (message.GetOp()) {
case VSyncProtocol::Wait::Opcode:
AddWaiter(message);
diff --git a/libs/vr/libvrsensor/include/dvr/pose_client.h b/libs/vr/libvrsensor/include/dvr/pose_client.h
index d69d825..bb25f1d 100644
--- a/libs/vr/libvrsensor/include/dvr/pose_client.h
+++ b/libs/vr/libvrsensor/include/dvr/pose_client.h
@@ -167,8 +167,7 @@
const DvrPoseDataCaptureRequest* request);
// Destroys the write buffer queue for the given |data_type|.
-int dvrPoseClientDataReaderDestroy(DvrPoseClient* client,
- DvrPoseRawDataType data_type);
+int dvrPoseClientDataReaderDestroy(DvrPoseClient* client, uint64_t data_type);
#ifdef __cplusplus
} // extern "C"
diff --git a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
index 7198fe8..39592bb 100644
--- a/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
+++ b/libs/vr/libvrsensor/include/private/dvr/pose_client_internal.h
@@ -10,8 +10,7 @@
namespace android {
namespace dvr {
-int dvrPoseClientGetDataReaderHandle(DvrPoseClient *client,
- DvrPoseRawDataType data_type,
+int dvrPoseClientGetDataReaderHandle(DvrPoseClient *client, uint64_t data_type,
ConsumerQueue **queue_out);
} // namespace dvr
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index 4e23e25..4acc085 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -141,7 +141,7 @@
return ReturnStatusOrError(status);
}
- int GetTangoReaderHandle(DvrPoseRawDataType data_type, ConsumerQueue** queue_out) {
+ int GetTangoReaderHandle(uint64_t data_type, ConsumerQueue** queue_out) {
// Get buffer.
Transaction trans{*this};
Status<LocalChannelHandle> status = trans.Send<LocalChannelHandle>(
@@ -169,7 +169,7 @@
return ReturnStatusOrError(status);
}
- int DataReaderDestroy(DvrPoseRawDataType data_type) {
+ int DataReaderDestroy(uint64_t data_type) {
Transaction trans{*this};
Status<int> status = trans.Send<int>(DVR_POSE_TANGO_READER_DESTROY,
&data_type, sizeof(data_type), nullptr,
@@ -296,8 +296,7 @@
ControllerClientState controllers_[MAX_CONTROLLERS];
};
-int dvrPoseClientGetDataReaderHandle(DvrPoseClient* client,
- DvrPoseRawDataType type,
+int dvrPoseClientGetDataReaderHandle(DvrPoseClient* client, uint64_t type,
ConsumerQueue** queue_out) {
return PoseClient::FromC(client)->GetTangoReaderHandle(type, queue_out);
}
@@ -362,8 +361,7 @@
return PoseClient::FromC(client)->DataCapture(request);
}
-int dvrPoseClientDataReaderDestroy(DvrPoseClient* client,
- DvrPoseRawDataType data_type) {
+int dvrPoseClientDataReaderDestroy(DvrPoseClient* client, uint64_t data_type) {
return PoseClient::FromC(client)->DataReaderDestroy(data_type);
}
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 935d0f6..d4266f6 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -257,7 +257,7 @@
const String8* uniqueDisplayId, DisplayViewport* outViewport) const {
const DisplayViewport* viewport = NULL;
if (viewportType == ViewportType::VIEWPORT_VIRTUAL && uniqueDisplayId != NULL) {
- for (DisplayViewport currentViewport : mVirtualDisplays) {
+ for (const DisplayViewport& currentViewport : mVirtualDisplays) {
if (currentViewport.uniqueId == *uniqueDisplayId) {
viewport = ¤tViewport;
break;
diff --git a/services/inputflinger/InputWindow.cpp b/services/inputflinger/InputWindow.cpp
index b54752b..3ae7972 100644
--- a/services/inputflinger/InputWindow.cpp
+++ b/services/inputflinger/InputWindow.cpp
@@ -49,7 +49,8 @@
|| layoutParamsType == TYPE_NAVIGATION_BAR_PANEL
|| layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY
|| layoutParamsType == TYPE_DOCK_DIVIDER
- || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY;
+ || layoutParamsType == TYPE_ACCESSIBILITY_OVERLAY
+ || layoutParamsType == TYPE_INPUT_CONSUMER;
}
bool InputWindowInfo::supportsSplitTouch() const {
diff --git a/services/inputflinger/InputWindow.h b/services/inputflinger/InputWindow.h
index 610290b..9eb2798 100644
--- a/services/inputflinger/InputWindow.h
+++ b/services/inputflinger/InputWindow.h
@@ -101,6 +101,7 @@
TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19,
TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20,
TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21,
+ TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22,
TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24,
TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27,
TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32,
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index ac739a2..cf01ad0 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -755,7 +755,7 @@
}
Error error = kDefaultError;
- mClient->executeCommands(commandLength, commandHandles,
+ auto ret = mClient->executeCommands(commandLength, commandHandles,
[&](const auto& tmpError, const auto& tmpOutChanged,
const auto& tmpOutLength, const auto& tmpOutHandles)
{
@@ -788,6 +788,11 @@
error = Error::NO_RESOURCES;
}
});
+ // executeCommands can fail because of out-of-fd and we do not want to
+ // abort() in that case
+ if (!ret.isOk()) {
+ ALOGE("executeCommands failed because of %s", ret.description().c_str());
+ }
if (error == Error::NONE) {
std::vector<CommandReader::CommandError> commandErrors =