Merge changes from topic 'vrflinger-cleanup'
* changes:
libbufferhub: Fix native buffer.
libvrflinger: Move display request to avoid duplicate calls.
libvrflinger: Remove superfluous update to display manager.
libvrflinger: Move some tracing to a more verbose level.
libvrflinger: Add additional info to PDX dump.
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 595fbab..d61cbc9 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -446,7 +446,10 @@
// Set the default size of cmdline hashtable
static bool setCmdlineSize()
{
- return writeStr(k_traceCmdlineSizePath, "8192");
+ if (fileExists(k_traceCmdlineSizePath)) {
+ return writeStr(k_traceCmdlineSizePath, "8192");
+ }
+ return true;
}
// Set the clock to the best available option while tracing. Use 'boot' if it's
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 1e0f6f8..aab86c7 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -15,6 +15,8 @@
chown root shell /sys/kernel/tracing/options/overwrite
chown root shell /sys/kernel/debug/tracing/options/print-tgid
chown root shell /sys/kernel/tracing/options/print-tgid
+ chown root shell /sys/kernel/debug/tracing/options/saved_cmdlines_size
+ chown root shell /sys/kernel/tracing/options/saved_cmdlines_size
chown root shell /sys/kernel/debug/tracing/events/sched/sched_switch/enable
chown root shell /sys/kernel/tracing/events/sched/sched_switch/enable
chown root shell /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
@@ -65,6 +67,8 @@
chmod 0664 /sys/kernel/tracing/options/overwrite
chmod 0664 /sys/kernel/debug/tracing/options/print-tgid
chmod 0664 /sys/kernel/tracing/options/print-tgid
+ chmod 0664 /sys/kernel/debug/tracing/options/saved_cmdlines_size
+ chmod 0664 /sys/kernel/tracing/options/saved_cmdlines_size
chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_switch/enable
chmod 0664 /sys/kernel/tracing/events/sched/sched_switch/enable
chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index af78bfb..4ecbf92 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1214,7 +1214,7 @@
// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
bool open_vdex_files(const char* apk_path, const char* out_oat_path, int dexopt_needed,
const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
- Dex2oatFileWrapper* in_vdex_wrapper_fd,
+ bool profile_guided, Dex2oatFileWrapper* in_vdex_wrapper_fd,
Dex2oatFileWrapper* out_vdex_wrapper_fd) {
CHECK(in_vdex_wrapper_fd != nullptr);
CHECK(out_vdex_wrapper_fd != nullptr);
@@ -1224,6 +1224,14 @@
int dexopt_action = abs(dexopt_needed);
bool is_odex_location = dexopt_needed < 0;
std::string in_vdex_path_str;
+
+ // Infer the name of the output VDEX.
+ const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
+ if (out_vdex_path_str.empty()) {
+ return false;
+ }
+
+ bool update_vdex_in_place = false;
if (dexopt_action != DEX2OAT_FROM_SCRATCH) {
// Open the possibly existing vdex. If none exist, we pass -1 to dex2oat for input-vdex-fd.
const char* path = nullptr;
@@ -1242,21 +1250,48 @@
ALOGE("installd cannot compute input vdex location for '%s'\n", path);
return false;
}
- in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+ // We can update in place when all these conditions are met:
+ // 1) The vdex location to write to is the same as the vdex location to read (vdex files
+ // on /system typically cannot be updated in place).
+ // 2) We dex2oat due to boot image change, because we then know the existing vdex file
+ // cannot be currently used by a running process.
+ // 3) We are not doing a profile guided compilation, because dexlayout requires two
+ // different vdex files to operate.
+ update_vdex_in_place =
+ (in_vdex_path_str == out_vdex_path_str) &&
+ (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) &&
+ !profile_guided;
+ if (update_vdex_in_place) {
+ // Open the file read-write to be able to update it.
+ in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
+ if (in_vdex_wrapper_fd->get() == -1) {
+ // If we failed to open the file, we cannot update it in place.
+ update_vdex_in_place = false;
+ }
+ } else {
+ in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+ }
}
- // Infer the name of the output VDEX and create it.
- const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
- if (out_vdex_path_str.empty()) {
- return false;
- }
-
- out_vdex_wrapper_fd->reset(
- open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
- [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
- if (out_vdex_wrapper_fd->get() < 0) {
- ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
- return false;
+ // If we are updating the vdex in place, we do not need to recreate a vdex,
+ // and can use the same existing one.
+ if (update_vdex_in_place) {
+ // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
+ // have bogus stale vdex files.
+ out_vdex_wrapper_fd->reset(
+ in_vdex_wrapper_fd->get(),
+ [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+ // Disable auto close for the in wrapper fd (it will be done when destructing the out
+ // wrapper).
+ in_vdex_wrapper_fd->DisableAutoClose();
+ } else {
+ out_vdex_wrapper_fd->reset(
+ open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+ [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+ if (out_vdex_wrapper_fd->get() < 0) {
+ ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
+ return false;
+ }
}
if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
out_vdex_path_str.c_str(), is_secondary_dex)) {
@@ -1568,7 +1603,7 @@
Dex2oatFileWrapper in_vdex_fd;
Dex2oatFileWrapper out_vdex_fd;
if (!open_vdex_files(dex_path, out_oat_path, dexopt_needed, instruction_set, is_public, uid,
- is_secondary_dex, &in_vdex_fd, &out_vdex_fd)) {
+ is_secondary_dex, profile_guided, &in_vdex_fd, &out_vdex_fd)) {
return -1;
}
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index c2d477e..0a537a3 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -30,7 +30,7 @@
mName(name), mHandle(0), mType(0),
mMinValue(0), mMaxValue(0), mResolution(0),
mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
- mFifoMaxEventCount(0), mRequiredAppOp(0),
+ mFifoMaxEventCount(0), mRequiredAppOp(-1),
mMaxDelay(0), mFlags(0) {
}
@@ -412,6 +412,10 @@
return (mFlags & SENSOR_FLAG_DYNAMIC_SENSOR) != 0;
}
+bool Sensor::isDataInjectionSupported() const {
+ return (mFlags & SENSOR_FLAG_DATA_INJECTION) != 0;
+}
+
bool Sensor::hasAdditionalInfo() const {
return (mFlags & SENSOR_FLAG_ADDITIONAL_INFO) != 0;
}
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
index 043e635..6926f7f 100644
--- a/libs/sensor/include/sensor/Sensor.h
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -90,6 +90,7 @@
uint32_t getFlags() const;
bool isWakeUpSensor() const;
bool isDynamicSensor() const;
+ bool isDataInjectionSupported() const;
bool hasAdditionalInfo() const;
int32_t getHighestDirectReportRateLevel() const;
bool isDirectChannelTypeSupported(int32_t sharedMemType) const;
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index a53c8b0..f0ef299 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -442,46 +442,78 @@
SetupQueue(status.get());
}
-Status<void> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count,
- uint32_t format, uint64_t usage,
- size_t* out_slot) {
- if (out_slot == nullptr) {
- ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
- return ErrorStatus(EINVAL);
- }
-
- if (is_full()) {
- ALOGE("ProducerQueue::AllocateBuffer queue is at maximum capacity: %zu",
- capacity());
+Status<std::vector<size_t>> ProducerQueue::AllocateBuffers(
+ uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
+ uint64_t usage, size_t buffer_count) {
+ if (capacity() + buffer_count > kMaxQueueCapacity) {
+ ALOGE(
+ "ProducerQueue::AllocateBuffers: queue is at capacity: %zu, cannot "
+ "allocate %zu more buffer(s).",
+ capacity(), buffer_count);
return ErrorStatus(E2BIG);
}
- const size_t kBufferCount = 1u;
Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
- width, height, layer_count, format, usage, kBufferCount);
+ width, height, layer_count, format, usage, buffer_count);
if (!status) {
- ALOGE("ProducerQueue::AllocateBuffer failed to create producer buffer: %s",
+ ALOGE("ProducerQueue::AllocateBuffers: failed to allocate buffers: %s",
status.GetErrorMessage().c_str());
return status.error_status();
}
auto buffer_handle_slots = status.take();
- LOG_ALWAYS_FATAL_IF(buffer_handle_slots.size() != kBufferCount,
+ LOG_ALWAYS_FATAL_IF(buffer_handle_slots.size() != buffer_count,
"BufferHubRPC::ProducerQueueAllocateBuffers should "
- "return one and only one buffer handle.");
+ "return %zu buffer handle(s), but returned %zu instead.",
+ buffer_count, buffer_handle_slots.size());
+ std::vector<size_t> buffer_slots;
+ buffer_slots.reserve(buffer_count);
+
+ // Bookkeeping for each buffer.
+ for (auto& hs : buffer_handle_slots) {
+ auto& buffer_handle = hs.first;
+ size_t buffer_slot = hs.second;
+
+ // Note that import might (though very unlikely) fail. If so, buffer_handle
+ // will be closed and included in returned buffer_slots.
+ if (AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
+ buffer_slot)) {
+ ALOGD_IF(TRACE, "ProducerQueue::AllocateBuffers: new buffer at slot: %zu",
+ buffer_slot);
+ buffer_slots.push_back(buffer_slot);
+ }
+ }
+
+ if (buffer_slots.size() == 0) {
+ // Error out if no buffer is allocated and improted.
+ ALOGE(TRACE, "ProducerQueue::AllocateBuffers: no buffer allocated.");
+ ErrorStatus(ENOMEM);
+ }
+
+ return {std::move(buffer_slots)};
+}
+
+Status<size_t> ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t layer_count,
+ uint32_t format, uint64_t usage) {
// We only allocate one buffer at a time.
- auto& buffer_handle = buffer_handle_slots[0].first;
- size_t buffer_slot = buffer_handle_slots[0].second;
- ALOGD_IF(TRACE,
- "ProducerQueue::AllocateBuffer, new buffer, channel_handle: %d",
- buffer_handle.value());
+ constexpr size_t buffer_count = 1;
+ auto status =
+ AllocateBuffers(width, height, layer_count, format, usage, buffer_count);
+ if (!status) {
+ ALOGE("ProducerQueue::AllocateBuffer: Failed to allocate buffer: %s",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
+ }
- *out_slot = buffer_slot;
- return AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
- buffer_slot);
+ if (status.get().size() == 0) {
+ ALOGE(TRACE, "ProducerQueue::AllocateBuffer: no buffer allocated.");
+ ErrorStatus(ENOMEM);
+ }
+
+ return {status.get()[0]};
}
Status<void> ProducerQueue::AddBuffer(
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index fca5eca..0f75a5c 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -612,9 +612,8 @@
uint32_t layer_count,
PixelFormat format,
uint64_t usage) {
- size_t slot;
auto status =
- queue_->AllocateBuffer(width, height, layer_count, format, usage, &slot);
+ queue_->AllocateBuffer(width, height, layer_count, format, usage);
if (!status) {
ALOGE(
"BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s",
@@ -622,6 +621,7 @@
return NO_MEMORY;
}
+ size_t slot = status.get();
auto buffer_producer = queue_->GetBuffer(slot);
LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr,
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 912cee0..d57c7af 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
@@ -274,12 +274,20 @@
BufferHubQueue::GetBuffer(slot));
}
+ // Batch allocate buffers. Once allocated, producer buffers are automatically
+ // enqueue'd into the ProducerQueue and available to use (i.e. in GAINED
+ // state). Upon success, returns a list of slots for each buffer allocated.
+ pdx::Status<std::vector<size_t>> AllocateBuffers(
+ uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
+ uint64_t usage, size_t buffer_count);
+
// Allocate producer buffer to populate the queue. Once allocated, a producer
// buffer is automatically enqueue'd into the ProducerQueue and available to
- // use (i.e. in GAINED state).
- pdx::Status<void> AllocateBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage, size_t* out_slot);
+ // use (i.e. in GAINED state). Upon success, returns the slot number for the
+ // buffer allocated.
+ pdx::Status<size_t> AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t format,
+ uint64_t usage);
// Add a producer buffer to populate the queue. Once added, a producer buffer
// is available to use (i.e. in GAINED state).
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 228212e..e0a4052 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -46,12 +46,12 @@
void AllocateBuffer(size_t* slot_out = nullptr) {
// Create producer buffer.
- size_t slot;
auto status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
- kBufferUsage, &slot);
- ASSERT_TRUE(status.ok());
+ kBufferUsage);
+ ASSERT_TRUE(status.ok());
+ size_t slot = status.take();
if (slot_out)
*slot_out = slot;
}
@@ -478,13 +478,13 @@
UsagePolicy{set_mask, 0, 0, 0}));
// When allocation, leave out |set_mask| from usage bits on purpose.
- size_t slot;
auto status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
- kBufferUsage & ~set_mask, &slot);
+ kBufferUsage & ~set_mask);
ASSERT_TRUE(status.ok());
LocalHandle fence;
+ size_t slot;
auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
@@ -497,13 +497,13 @@
UsagePolicy{0, clear_mask, 0, 0}));
// When allocation, add |clear_mask| into usage bits on purpose.
- size_t slot;
auto status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
- kBufferUsage | clear_mask, &slot);
+ kBufferUsage | clear_mask);
ASSERT_TRUE(status.ok());
LocalHandle fence;
+ size_t slot;
auto p1_status = producer_queue_->Dequeue(0, &slot, &fence);
ASSERT_TRUE(p1_status.ok());
auto p1 = p1_status.take();
@@ -517,16 +517,15 @@
// Now that |deny_set_mask| is illegal, allocation without those bits should
// be able to succeed.
- size_t slot;
auto status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
- kBufferUsage & ~deny_set_mask, &slot);
+ kBufferUsage & ~deny_set_mask);
ASSERT_TRUE(status.ok());
// While allocation with those bits should fail.
status = producer_queue_->AllocateBuffer(kBufferWidth, kBufferHeight,
kBufferLayerCount, kBufferFormat,
- kBufferUsage | deny_set_mask, &slot);
+ kBufferUsage | deny_set_mask);
ASSERT_FALSE(status.ok());
ASSERT_EQ(EINVAL, status.error());
}
@@ -538,16 +537,15 @@
// Now that clearing |deny_clear_mask| is illegal (i.e. setting these bits are
// mandatory), allocation with those bits should be able to succeed.
- size_t slot;
auto status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
- kBufferUsage | deny_clear_mask, &slot);
+ kBufferUsage | deny_clear_mask);
ASSERT_TRUE(status.ok());
// While allocation without those bits should fail.
status = producer_queue_->AllocateBuffer(
kBufferWidth, kBufferHeight, kBufferLayerCount, kBufferFormat,
- kBufferUsage & ~deny_clear_mask, &slot);
+ kBufferUsage & ~deny_clear_mask);
ASSERT_FALSE(status.ok());
ASSERT_EQ(EINVAL, status.error());
}
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 6e7f556..40c158a 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -145,20 +145,12 @@
auto producer_queue = status.take();
ALOGD_IF(TRACE, "Surface::CreateQueue: Allocating %zu buffers...", capacity);
- for (size_t i = 0; i < capacity; i++) {
- size_t slot;
- auto allocate_status = producer_queue->AllocateBuffer(
- width, height, layer_count, format, usage, &slot);
- if (!allocate_status) {
- ALOGE(
- "Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
+ auto allocate_status = producer_queue->AllocateBuffers(
+ width, height, layer_count, format, usage, capacity);
+ if (!allocate_status) {
+ ALOGE("Surface::CreateQueue: Failed to allocate buffer on queue_id=%d: %s",
producer_queue->id(), allocate_status.GetErrorMessage().c_str());
- return allocate_status.error_status();
- }
- ALOGD_IF(
- TRACE,
- "Surface::CreateQueue: Allocated buffer at slot=%zu of capacity=%zu",
- slot, capacity);
+ return allocate_status.error_status();
}
return {std::move(producer_queue)};
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 5f35dcf..dc31917 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -3,6 +3,8 @@
#include <errno.h>
#include <utils/Log.h>
+#include <algorithm>
+
// Headers from libdvr
#include <dvr/dvr_buffer.h>
#include <dvr/dvr_buffer_queue.h>
@@ -23,15 +25,20 @@
ALOGI("dvrGetApi: api=%p struct_size=%zu version=%d", api, struct_size,
version);
if (version == 1) {
- if (struct_size != sizeof(DvrApi_v1)) {
- ALOGE("dvrGetApi: Size mismatch: expected %zu; actual %zu",
- sizeof(DvrApi_v1), struct_size);
- return -EINVAL;
- }
+ // New entry points are added at the end. If the caller's struct and
+ // this library have different sizes, we define the entry points in common.
+ // The caller is expected to handle unset entry points if necessary.
+ size_t clamped_struct_size = std::min(struct_size, sizeof(DvrApi_v1));
DvrApi_v1* dvr_api = static_cast<DvrApi_v1*>(api);
// Defines an API entry for V1 (no version suffix).
-#define DVR_V1_API_ENTRY(name) dvr_api->name = dvr##name
+#define DVR_V1_API_ENTRY(name) \
+ do { \
+ if ((offsetof(DvrApi_v1, name) + sizeof(dvr_api->name)) <= \
+ clamped_struct_size) { \
+ dvr_api->name = dvr##name; \
+ } \
+ } while (0)
#include "include/dvr/dvr_api_entries.h"
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 5d01c8f..aa2ed94 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -122,7 +122,7 @@
}
auto allocate_status = producer_queue_->AllocateBuffer(
- width_, height_, old_layer_count, format_, old_usage, &slot);
+ width_, height_, old_layer_count, format_, old_usage);
if (!allocate_status) {
ALOGE("DvrWriteBufferQueue::Dequeue: Failed to allocate buffer: %s",
allocate_status.GetErrorMessage().c_str());
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index 0c10907..4693c7f 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -238,6 +238,8 @@
float pressure);
typedef int (*DvrVirtualTouchpadButtonStatePtr)(DvrVirtualTouchpad* client,
int touchpad, int buttons);
+typedef int (*DvrVirtualTouchpadScrollPtr)(DvrVirtualTouchpad* client,
+ int touchpad, float x, float y);
// dvr_hardware_composer_client.h
typedef struct DvrHwcClient DvrHwcClient;
diff --git a/libs/vr/libdvr/include/dvr/dvr_api_entries.h b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
index 802a0f7..ae5ef18 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api_entries.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api_entries.h
@@ -141,3 +141,9 @@
DVR_V1_API_ENTRY(HwcFrameGetLayerVisibleRegion);
DVR_V1_API_ENTRY(HwcFrameGetLayerNumDamagedRegions);
DVR_V1_API_ENTRY(HwcFrameGetLayerDamagedRegion);
+
+// New entries added at the end to allow the DVR platform library API
+// to be updated before updating VrCore.
+
+// Virtual touchpad client
+DVR_V1_API_ENTRY(VirtualTouchpadScroll);
diff --git a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
index f2ae09e..5158612 100644
--- a/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_buffer_queue-test.cpp
@@ -56,13 +56,10 @@
}
void AllocateBuffers(size_t buffer_count) {
- size_t out_slot;
- for (size_t i = 0; i < buffer_count; i++) {
- auto status = write_queue_->producer_queue()->AllocateBuffer(
- kBufferWidth, kBufferHeight, kLayerCount, kBufferFormat, kBufferUsage,
- &out_slot);
- ASSERT_TRUE(status.ok());
- }
+ auto status = write_queue_->producer_queue()->AllocateBuffers(
+ kBufferWidth, kBufferHeight, kLayerCount, kBufferFormat, kBufferUsage,
+ buffer_count);
+ ASSERT_TRUE(status.ok());
}
void HandleBufferAvailable() {
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
index ab08cac..aa306d8 100644
--- a/services/sensorservice/SensorList.cpp
+++ b/services/sensorservice/SensorList.cpp
@@ -124,14 +124,15 @@
forEachSensor([&result] (const Sensor& s) -> bool {
result.appendFormat(
"%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
- ") | perm: %s\n",
+ ") | perm: %s | flags: 0x%08x\n",
s.getHandle(),
s.getName().string(),
s.getVendor().string(),
s.getVersion(),
s.getStringType().string(),
s.getType(),
- s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a");
+ s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a",
+ static_cast<int>(s.getFlags()));
result.append("\t");
const int reportingMode = s.getReportingMode();
@@ -173,9 +174,14 @@
result.appendFormat("non-wakeUp | ");
}
+ if (s.isDataInjectionSupported()) {
+ result.appendFormat("data-injection, ");
+ }
+
if (s.isDynamicSensor()) {
result.appendFormat("dynamic, ");
}
+
if (s.hasAdditionalInfo()) {
result.appendFormat("has-additional-info, ");
}
@@ -190,7 +196,6 @@
if (s.isDirectChannelTypeSupported(SENSOR_DIRECT_MEM_TYPE_GRALLOC)) {
result.append("gralloc, ");
}
- result.appendFormat("flag =0x%08x", static_cast<int>(s.getFlags()));
result.append("\n");
}
return true;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index edc0140..13472df 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -225,6 +225,9 @@
property_get("ro.sf.disable_triple_buffer", value, "1");
mLayerTripleBufferingDisabled = atoi(value);
ALOGI_IF(mLayerTripleBufferingDisabled, "Disabling Triple Buffering");
+
+ property_get("persist.sys.sf.color_saturation", value, "1.0");
+ mSaturation = atof(value);
}
void SurfaceFlinger::onFirstRef()
@@ -3846,10 +3849,11 @@
status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- if (CC_UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
- IPCThreadState* ipc = IPCThreadState::self();
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int uid = ipc->getCallingUid();
+ if (CC_UNLIKELY(uid != AID_SYSTEM
+ && !PermissionCache::checkCallingPermission(sHardwareTest))) {
const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
ALOGE("Permission Denial: "
"can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
diff --git a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
index eb152ed..3ab77a7 100644
--- a/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/DvrVirtualTouchpadClient.cpp
@@ -40,6 +40,11 @@
return FromC(client)->ButtonState(touchpad, buttons);
}
+int dvrVirtualTouchpadScroll(DvrVirtualTouchpad* client, int touchpad, float x,
+ float y) {
+ return FromC(client)->Scroll(touchpad, x, y);
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/services/vr/virtual_touchpad/EvdevInjector.cpp b/services/vr/virtual_touchpad/EvdevInjector.cpp
index a4ccdd0..7fad379 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.cpp
+++ b/services/vr/virtual_touchpad/EvdevInjector.cpp
@@ -168,6 +168,25 @@
return ConfigureAbs(ABS_MT_SLOT, 0, slots, 0, 0);
}
+int EvdevInjector::ConfigureRel(uint16_t rel_type) {
+ ALOGV("ConfigureRel 0x%" PRIX16 "", rel_type);
+ if (rel_type < 0 || rel_type >= REL_CNT) {
+ ALOGE("EV_REL type 0x%" PRIX16 " out of range [0,0x%X)", rel_type, REL_CNT);
+ return Error(ERROR_REL_RANGE);
+ }
+ if (const int status = RequireState(State::CONFIGURING)) {
+ return status;
+ }
+ if (const int status = EnableEventType(EV_REL)) {
+ return status;
+ }
+ if (const int status = uinput_->IoctlSetInt(UI_SET_RELBIT, rel_type)) {
+ ALOGE("failed to enable EV_REL 0x%" PRIX16 "", rel_type);
+ return Error(status);
+ }
+ return 0;
+}
+
int EvdevInjector::ConfigureEnd() {
ALOGV("ConfigureEnd:");
ALOGV(" name=\"%s\"", uidev_.name);
@@ -236,6 +255,10 @@
return Send(EV_ABS, code, value);
}
+int EvdevInjector::SendRel(uint16_t code, int32_t value) {
+ return Send(EV_REL, code, value);
+}
+
int EvdevInjector::SendMultiTouchSlot(int32_t slot) {
if (latest_slot_ != slot) {
if (const int status = SendAbs(ABS_MT_SLOT, slot)) {
diff --git a/services/vr/virtual_touchpad/EvdevInjector.h b/services/vr/virtual_touchpad/EvdevInjector.h
index c69dbef..e87c959 100644
--- a/services/vr/virtual_touchpad/EvdevInjector.h
+++ b/services/vr/virtual_touchpad/EvdevInjector.h
@@ -30,6 +30,7 @@
ERROR_KEY_RANGE = -3, // |KEY_*|/|BTN_*| code out of range.
ERROR_ABS_RANGE = -4, // |ABS_*| code out of range.
ERROR_SEQUENCING = -5, // Configure/Send out of order.
+ ERROR_REL_RANGE = -6, // |REL_*| code out of range.
};
// Key event |value| is not defined in <linux/input.h>.
@@ -87,6 +88,10 @@
// Configure multitouch coordinate range.
int ConfigureMultiTouchXY(int32_t x0, int32_t y0, int32_t x1, int32_t y1);
+ // Configure a relative axis.
+ // @param rel_type One of the |REL_*| constants from <linux/input.h>.
+ int ConfigureRel(uint16_t rel_type);
+
// Complete configuration and create the input device.
int ConfigureEnd();
@@ -96,6 +101,7 @@
int SendSynReport();
int SendKey(uint16_t code, int32_t value);
int SendAbs(uint16_t code, int32_t value);
+ int SendRel(uint16_t code, int32_t value);
int SendMultiTouchSlot(int32_t slot);
int SendMultiTouchXY(int32_t slot, int32_t id, int32_t x, int32_t y);
int SendMultiTouchLift(int32_t slot);
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
index c7c8184..00e4ce6 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadClient.cpp
@@ -60,6 +60,13 @@
return service_->buttonState(touchpad, buttons).transactionError();
}
+ status_t Scroll(int touchpad, float x, float y) override {
+ if (service_ == nullptr) {
+ return NO_INIT;
+ }
+ return service_->scroll(touchpad, x, y).transactionError();
+ }
+
void dumpInternal(String8& result) override {
result.append("[virtual touchpad]\n");
result.appendFormat("connected = %s\n\n",
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
index f0bdcd9..ae56bf6 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.cpp
@@ -28,6 +28,22 @@
static constexpr int32_t kHeight = 0x10000;
static constexpr int32_t kSlots = 2;
+int32_t scale_relative_scroll(float x) {
+ // Guilty with an explanation, your honor.
+ // Ideally we should be able to communicate the full incoming precision
+ // to InputFlinger, through the evdev int32_t value, by scaling by a
+ // large factor, i.e. 2²³ for IEEE single precision floating point.
+ // However, although InputFlinger has |wheelVelocityControlParameters|,
+ // those parameters are currently hard coded, with a scale factor of 1.0.
+ // The observed evdev value for a physical mouse scroll wheel is usually
+ // ±1, with higher values up to ±4 for a very fast spin. So we imitate
+ // that. If the incoming value is not actually 0, the resulting magnitude
+ // should be at least 1, so that small movements are not lost.
+ // Adding IDC configurability of |VelocityControlParameters| may be
+ // desirable in the future.
+ return copysignf(ceilf(fabs(4.0f * x)), x);
+}
+
} // anonymous namespace
std::unique_ptr<VirtualTouchpad> VirtualTouchpadEvdev::Create() {
@@ -162,6 +178,32 @@
return touchpad.injector->GetError();
}
+int VirtualTouchpadEvdev::Scroll(int touchpad_id, float x, float y) {
+ if (touchpad_id < 0 || touchpad_id >= kTouchpads) {
+ return EINVAL;
+ }
+ if ((x < -1.0f) || (x > 1.0f) || (y < -1.0f) || (y > 1.0f)) {
+ return EINVAL;
+ }
+ Touchpad& touchpad = touchpad_[touchpad_id];
+ if (!touchpad.injector) {
+ return EvdevInjector::ERROR_SEQUENCING;
+ }
+ touchpad.injector->ResetError();
+ const int32_t scaled_x = scale_relative_scroll(x);
+ const int32_t scaled_y = scale_relative_scroll(y);
+ if (scaled_x) {
+ touchpad.injector->SendRel(REL_HWHEEL, scaled_x);
+ }
+ if (scaled_y) {
+ touchpad.injector->SendRel(REL_WHEEL, scaled_y);
+ }
+ if (scaled_x || scaled_y) {
+ touchpad.injector->SendSynReport();
+ }
+ return touchpad.injector->GetError();
+}
+
void VirtualTouchpadEvdev::dumpInternal(String8& result) {
for (int i = 0; i < kTouchpads; ++i) {
const auto& touchpad = touchpad_[i];
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
index 2fb8ff3..c9578bf 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadEvdev.h
@@ -21,6 +21,7 @@
status_t Detach() override;
status_t Touch(int touchpad, float x, float y, float pressure) override;
status_t ButtonState(int touchpad, int buttons) override;
+ status_t Scroll(int touchpad, float x, float y) override;
void dumpInternal(String8& result) override;
protected:
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
index 81edd32..523f890 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.cpp
@@ -87,6 +87,16 @@
return binder::Status::ok();
}
+binder::Status VirtualTouchpadService::scroll(int touchpad, float x, float y) {
+ if (!CheckPermissions()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ if (const status_t error = touchpad_->Scroll(touchpad, x, y)) {
+ return binder::Status::fromStatusT(error);
+ }
+ return binder::Status::ok();
+}
+
status_t VirtualTouchpadService::dump(
int fd, const Vector<String16>& args[[gnu::unused]]) {
String8 result;
diff --git a/services/vr/virtual_touchpad/VirtualTouchpadService.h b/services/vr/virtual_touchpad/VirtualTouchpadService.h
index cf236f9..2c46209 100644
--- a/services/vr/virtual_touchpad/VirtualTouchpadService.h
+++ b/services/vr/virtual_touchpad/VirtualTouchpadService.h
@@ -23,6 +23,7 @@
binder::Status detach() override;
binder::Status touch(int touchpad, float x, float y, float pressure) override;
binder::Status buttonState(int touchpad, int buttons) override;
+ binder::Status scroll(int touchpad, float x, float y) override;
// Implements BBinder::dump().
status_t dump(int fd, const Vector<String16>& args) override;
diff --git a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
index 9cfb186..256203c 100644
--- a/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
+++ b/services/vr/virtual_touchpad/aidl/android/dvr/VirtualTouchpadService.aidl
@@ -34,4 +34,15 @@
* @param buttons A union of MotionEvent BUTTON_* values.
*/
void buttonState(int touchpad, int buttons) = 3;
+
+ /**
+ * Generate a simulated scroll event.
+ *
+ * @param touchpad Selects touchpad.
+ * @param x Horizontal scroll increment.
+ * @param y Vertical scroll increment.
+ *
+ * Scroll values are in the range [-1.0, 1.0].
+ */
+ void scroll(int touchpad, float x, float y) = 4;
}
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpad.h b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
index da3a0b7..99b72fc 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpad.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpad.h
@@ -61,6 +61,16 @@
//
virtual status_t ButtonState(int touchpad, int buttons) = 0;
+ // Generate a simulated scroll event.
+ //
+ // @param touchpad Touchpad selector index.
+ // @param x Horizontal scroll increment.
+ // @param y Vertical scroll increment.
+ // Values must be in the range [-1.0, 1.0].
+ // @returns OK on success.
+ //
+ virtual status_t Scroll(int touchpad, float x, float y) = 0;
+
// Report state for 'dumpsys'.
virtual void dumpInternal(String8& result) = 0;
diff --git a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
index 23fb9f8..7d73f06 100644
--- a/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
+++ b/services/vr/virtual_touchpad/include/VirtualTouchpadClient.h
@@ -17,6 +17,7 @@
status_t Detach() override;
status_t Touch(int touchpad, float x, float y, float pressure) override;
status_t ButtonState(int touchpad, int buttons) override;
+ status_t Scroll(int touchpad, float x, float y) override;
void dumpInternal(String8& result) override;
protected:
diff --git a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
index 15e6687..09fb1cc 100644
--- a/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
+++ b/services/vr/virtual_touchpad/include/dvr/virtual_touchpad_client.h
@@ -61,6 +61,17 @@
int dvrVirtualTouchpadButtonState(DvrVirtualTouchpad* client, int touchpad,
int buttons);
+// Generate a simulated scroll event.
+//
+// @param client Pointer to the virtual touchpad client.
+// @param touchpad Selects touchpad.
+// @param x Horizontal scroll increment.
+// @param y Vertical scroll increment.
+// @return Zero on success, status_t-style error code on failure.
+//
+int dvrVirtualTouchpadScroll(DvrVirtualTouchpad* client, int touchpad, float x,
+ float y);
+
#ifdef __cplusplus
} // extern "C"
#endif