Merge changes I2b89dce1,I5412eae0,I2e428ec1 into pi-dev
* changes:
EGL: Fix over zealous colorspace implementation
SF: Update to composer@2.2 implementation
EGL: Plumb HDR metadata
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index d8bbdbb..371533c 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1506,6 +1506,12 @@
RunDumpsys("TELEPHONY SERVICES", {"activity", "service", "TelephonyDebugService"});
printf("========================================================\n");
+ printf("== Checkins\n");
+ printf("========================================================\n");
+
+ RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"});
+
+ printf("========================================================\n");
printf("== dumpstate: done (id %d)\n", ds.id_);
printf("========================================================\n");
}
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 8fe9dfb..6db09a9 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -395,25 +395,16 @@
}
BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint32_t usage, size_t user_metadata_size)
- : BufferProducer(width, height, format, usage, usage, user_metadata_size) {}
-
-BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t user_metadata_size)
+ uint64_t usage, size_t user_metadata_size)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
ALOGD_IF(TRACE,
"BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
- "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
- " user_metadata_size=%zu",
- event_fd(), width, height, format, producer_usage, consumer_usage,
- user_metadata_size);
+ "usage=%" PRIx64 " user_metadata_size=%zu",
+ event_fd(), width, height, format, usage, user_metadata_size);
- // (b/37881101) Deprecate producer/consumer usage
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, (producer_usage | consumer_usage),
- user_metadata_size);
+ width, height, format, usage, user_metadata_size);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -431,26 +422,18 @@
}
}
-BufferProducer::BufferProducer(uint32_t usage, size_t size)
- : BufferProducer(usage, usage, size) {}
-
-BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
- size_t size)
+BufferProducer::BufferProducer(uint64_t usage, size_t size)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
- ALOGD_IF(TRACE,
- "BufferProducer::BufferProducer: producer_usage=%" PRIx64
- " consumer_usage=%" PRIx64 " size=%zu",
- producer_usage, consumer_usage, size);
+ ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%" PRIx64 " size=%zu",
+ usage, size);
const int width = static_cast<int>(size);
const int height = 1;
const int format = HAL_PIXEL_FORMAT_BLOB;
const size_t user_metadata_size = 0;
- // (b/37881101) Deprecate producer/consumer usage
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, (producer_usage | consumer_usage),
- user_metadata_size);
+ width, height, format, usage, user_metadata_size);
if (!status) {
ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
status.GetErrorMessage().c_str());
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index 8a4440f..c791250 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -111,10 +111,6 @@
uint32_t usage() const { return buffer_.usage(); }
uint32_t layer_count() const { return buffer_.layer_count(); }
- // TODO(b/37881101) Clean up producer/consumer usage.
- uint64_t producer_usage() const { return buffer_.usage(); }
- uint64_t consumer_usage() const { return buffer_.usage(); }
-
uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
@@ -230,14 +226,10 @@
// Constructs a buffer with the given geometry and parameters.
BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint32_t usage, size_t metadata_size = 0);
- BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint64_t producer_usage, uint64_t consumer_usage,
- size_t metadata_size);
+ uint64_t usage, size_t metadata_size = 0);
// Constructs a blob (flat) buffer with the given usage flags.
- BufferProducer(uint32_t usage, size_t size);
- BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
+ BufferProducer(uint64_t usage, size_t size);
// Imports the given file handle to a producer channel, taking ownership.
explicit BufferProducer(LocalChannelHandle channel);
diff --git a/libs/vr/libdvr/tests/dvr_api_test.h b/libs/vr/libdvr/tests/dvr_api_test.h
index 648af75..d8359e7 100644
--- a/libs/vr/libdvr/tests/dvr_api_test.h
+++ b/libs/vr/libdvr/tests/dvr_api_test.h
@@ -3,8 +3,6 @@
#include <gtest/gtest.h>
-#define ASSERT_NOT_NULL(x) ASSERT_TRUE((x) != nullptr)
-
/** DvrTestBase loads the libdvr.so at runtime and get the Dvr API version 1. */
class DvrApiTest : public ::testing::Test {
protected:
@@ -17,11 +15,11 @@
// https://github.com/android-ndk/ndk/issues/360
flags |= RTLD_NODELETE;
platform_handle_ = dlopen("libdvr.so", flags);
- ASSERT_NOT_NULL(platform_handle_) << "Dvr shared library missing.";
+ ASSERT_NE(nullptr, platform_handle_) << "Dvr shared library missing.";
auto dvr_get_api = reinterpret_cast<decltype(&dvrGetApi)>(
dlsym(platform_handle_, "dvrGetApi"));
- ASSERT_NOT_NULL(dvr_get_api) << "Platform library missing dvrGetApi.";
+ ASSERT_NE(nullptr, dvr_get_api) << "Platform library missing dvrGetApi.";
ASSERT_EQ(dvr_get_api(&api_, sizeof(api_), /*version=*/1), 0)
<< "Unable to find compatible Dvr API.";
diff --git a/libs/vr/libdvr/tests/dvr_display-test.cpp b/libs/vr/libdvr/tests/dvr_display-test.cpp
index 1165573..c72f940 100644
--- a/libs/vr/libdvr/tests/dvr_display-test.cpp
+++ b/libs/vr/libdvr/tests/dvr_display-test.cpp
@@ -16,20 +16,58 @@
class DvrDisplayTest : public DvrApiTest {
protected:
+ void SetUp() override {
+ DvrApiTest::SetUp();
+ int ret = api_.GetNativeDisplayMetrics(sizeof(display_metrics_),
+ &display_metrics_);
+ ASSERT_EQ(ret, 0) << "Failed to get display metrics.";
+ ALOGD(
+ "display_width: %d, display_height: %d, display_x_dpi: %d, "
+ "display_y_dpi: %d, vsync_period_ns: %d.",
+ display_metrics_.display_width, display_metrics_.display_height,
+ display_metrics_.display_x_dpi, display_metrics_.display_y_dpi,
+ display_metrics_.vsync_period_ns);
+ }
+
void TearDown() override {
if (write_queue_ != nullptr) {
api_.WriteBufferQueueDestroy(write_queue_);
write_queue_ = nullptr;
}
+ if (direct_surface_ != nullptr) {
+ api_.SurfaceDestroy(direct_surface_);
+ direct_surface_ = nullptr;
+ }
DvrApiTest::TearDown();
}
+ /* Convert a write buffer to an android hardware buffer and fill in
+ * color_textures evenly to the buffer.
+ * AssertionError if the width of the buffer is not equal to the input width,
+ * AssertionError if the height of the buffer is not equal to the input
+ * height.
+ */
+ void FillWriteBuffer(DvrWriteBuffer* write_buffer,
+ const std::vector<uint32_t>& color_textures,
+ uint32_t width, uint32_t height);
+
+ // Write buffer queue properties.
+ static constexpr uint64_t kUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
+ AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
+ AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
+ uint32_t kFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ static constexpr size_t kMetadataSize = 0;
+ static constexpr int kTimeoutMs = 1000; // Time for getting buffer.
+ uint32_t kLayerCount = 1;
DvrWriteBufferQueue* write_queue_ = nullptr;
+ DvrSurface* direct_surface_ = nullptr;
+
+ // Device display properties.
+ DvrNativeDisplayMetrics display_metrics_;
};
-TEST_F(DvrDisplayTest, DisplaySingleColor) {
- // Create direct surface.
- DvrSurface* direct_surface = nullptr;
+TEST_F(DvrDisplayTest, DisplayWithOneBuffer) {
+ // Create a direct surface.
std::vector<DvrSurfaceAttribute> direct_surface_attributes = {
{.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
.value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
@@ -43,73 +81,32 @@
};
int ret =
api_.SurfaceCreate(direct_surface_attributes.data(),
- direct_surface_attributes.size(), &direct_surface);
+ direct_surface_attributes.size(), &direct_surface_);
ASSERT_EQ(ret, 0) << "Failed to create direct surface.";
- // Get screen dimension.
- DvrNativeDisplayMetrics display_metrics;
- ret = api_.GetNativeDisplayMetrics(sizeof(display_metrics), &display_metrics);
- ASSERT_EQ(ret, 0) << "Failed to get display metrics.";
- ALOGD(
- "display_width: %d, display_height: %d, display_x_dpi: %d, "
- "display_y_dpi: %d, vsync_period_ns: %d.",
- display_metrics.display_width, display_metrics.display_height,
- display_metrics.display_x_dpi, display_metrics.display_y_dpi,
- display_metrics.vsync_period_ns);
-
// Create a buffer queue with the direct surface.
- constexpr uint32_t kLayerCount = 1;
- constexpr uint64_t kUsage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
- AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT |
- AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
- constexpr uint32_t kFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
constexpr size_t kCapacity = 1;
- constexpr size_t kMetadataSize = 0;
- uint32_t width = display_metrics.display_width;
- uint32_t height = display_metrics.display_height;
+ uint32_t width = display_metrics_.display_width;
+ uint32_t height = display_metrics_.display_height;
ret = api_.SurfaceCreateWriteBufferQueue(
- direct_surface, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+ direct_surface_, width, height, kFormat, kLayerCount, kUsage, kCapacity,
kMetadataSize, &write_queue_);
EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
- ASSERT_NOT_NULL(write_queue_) << "Write buffer queue should not be null.";
+ ASSERT_NE(nullptr, write_queue_) << "Write buffer queue should not be null.";
// Get buffer from WriteBufferQueue.
DvrWriteBuffer* write_buffer = nullptr;
- constexpr int kTimeoutMs = 1000;
DvrNativeBufferMetadata out_meta;
int out_fence_fd = -1;
ret = api_.WriteBufferQueueGainBuffer(write_queue_, kTimeoutMs, &write_buffer,
&out_meta, &out_fence_fd);
EXPECT_EQ(0, ret) << "Failed to get the buffer.";
- ASSERT_NOT_NULL(write_buffer) << "Gained buffer should not be null.";
+ ASSERT_NE(nullptr, write_buffer) << "Gained buffer should not be null.";
- // Convert to an android hardware buffer.
- AHardwareBuffer* ah_buffer{nullptr};
- ret = api_.WriteBufferGetAHardwareBuffer(write_buffer, &ah_buffer);
- EXPECT_EQ(0, ret) << "Failed to get a hardware buffer from the write buffer.";
- ASSERT_NOT_NULL(ah_buffer) << "AHardware buffer should not be null.";
-
- // Change the content of the android hardware buffer.
- void* buffer_data{nullptr};
- int32_t fence = -1;
- ret = AHardwareBuffer_lock(ah_buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
- fence, nullptr, &buffer_data);
- EXPECT_EQ(0, ret) << "Failed to lock the hardware buffer.";
- ASSERT_NOT_NULL(buffer_data) << "Buffer data should not be null.";
-
- uint32_t color_texture = 0xff0000ff; // Red color in RGBA.
- for (uint32_t i = 0; i < width * height; ++i) {
- memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) +
- i * sizeof(color_texture)),
- &color_texture, sizeof(color_texture));
- }
-
- fence = -1;
- ret = AHardwareBuffer_unlock(ah_buffer, &fence);
- EXPECT_EQ(0, ret) << "Failed to unlock the hardware buffer.";
-
- // Release the android hardware buffer.
- AHardwareBuffer_release(ah_buffer);
+ // Color the write buffer.
+ FillWriteBuffer(write_buffer,
+ {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000},
+ width, height);
// Post buffer.
int ready_fence_fd = -1;
@@ -118,4 +115,237 @@
EXPECT_EQ(0, ret) << "Failed to post the buffer.";
sleep(5); // For visual check on the device under test.
+ // Should observe three primary colors on the screen center.
+}
+
+TEST_F(DvrDisplayTest, DisplayWithDoubleBuffering) {
+ // Create a direct surface.
+ std::vector<DvrSurfaceAttribute> direct_surface_attributes = {
+ {.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+ .value.bool_value = true},
+ {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
+ .value.int32_value = 10},
+ {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+ .value.bool_value = true},
+ };
+ int ret =
+ api_.SurfaceCreate(direct_surface_attributes.data(),
+ direct_surface_attributes.size(), &direct_surface_);
+ ASSERT_EQ(ret, 0) << "Failed to create direct surface.";
+
+ // Create a buffer queue with the direct surface.
+ constexpr size_t kCapacity = 2;
+ uint32_t width = display_metrics_.display_width;
+ uint32_t height = display_metrics_.display_height;
+ ret = api_.SurfaceCreateWriteBufferQueue(
+ direct_surface_, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+ kMetadataSize, &write_queue_);
+ EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
+ ASSERT_NE(nullptr, write_queue_) << "Write buffer queue should not be null.";
+
+ int num_display_cycles_in_5s = 5 / (display_metrics_.vsync_period_ns / 1e9);
+ ALOGD("The number of display cycles: %d", num_display_cycles_in_5s);
+ int bufferhub_id_prev_write_buffer = -1;
+ for (int i = 0; i < num_display_cycles_in_5s; ++i) {
+ // Get a buffer from the WriteBufferQueue.
+ DvrWriteBuffer* write_buffer = nullptr;
+ DvrNativeBufferMetadata out_meta;
+ int out_fence_fd = -1;
+ ret = api_.WriteBufferQueueGainBuffer(
+ write_queue_, kTimeoutMs, &write_buffer, &out_meta, &out_fence_fd);
+ EXPECT_EQ(0, ret) << "Failed to get the a write buffer.";
+ ASSERT_NE(nullptr, write_buffer) << "The gained buffer should not be null.";
+
+ int bufferhub_id = api_.WriteBufferGetId(write_buffer);
+ ALOGD("Display cycle: %d, bufferhub id of the write buffer: %d", i,
+ bufferhub_id);
+ EXPECT_NE(bufferhub_id_prev_write_buffer, bufferhub_id)
+ << "Double buffering should be using the two buffers in turns, not "
+ "reusing the same write buffer.";
+ bufferhub_id_prev_write_buffer = bufferhub_id;
+
+ // Color the write buffer.
+ if (i % 2) {
+ FillWriteBuffer(write_buffer, {0xffff0000, 0xff00ff00, 0xff0000ff}, width,
+ height);
+ } else {
+ FillWriteBuffer(write_buffer, {0xff00ff00, 0xff0000ff, 0xffff0000}, width,
+ height);
+ }
+
+ // Post the write buffer.
+ int ready_fence_fd = -1;
+ ret = api_.WriteBufferQueuePostBuffer(write_queue_, write_buffer, &out_meta,
+ ready_fence_fd);
+ EXPECT_EQ(0, ret) << "Failed to post the buffer.";
+ }
+ // Should observe blinking screen in secondary colors
+ // although it is actually displaying primary colors.
+}
+
+TEST_F(DvrDisplayTest, DisplayWithTwoHardwareLayers) {
+ // Create the direct_surface_0 of z order 10 and direct_surface_1 of z
+ // order 11.
+ DvrSurface* direct_surface_0 = nullptr;
+ std::vector<DvrSurfaceAttribute> direct_surface_0_attributes = {
+ {.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+ .value.bool_value = true},
+ {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
+ .value.int32_value = 10},
+ {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+ .value.bool_value = true},
+ };
+ int ret =
+ api_.SurfaceCreate(direct_surface_0_attributes.data(),
+ direct_surface_0_attributes.size(), &direct_surface_0);
+ EXPECT_EQ(ret, 0) << "Failed to create direct surface.";
+
+ DvrSurface* direct_surface_1 = nullptr;
+ std::vector<DvrSurfaceAttribute> direct_surface_1_attributes = {
+ {.key = DVR_SURFACE_ATTRIBUTE_DIRECT,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+ .value.bool_value = true},
+ {.key = DVR_SURFACE_ATTRIBUTE_Z_ORDER,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_INT32,
+ .value.int32_value = 11},
+ {.key = DVR_SURFACE_ATTRIBUTE_VISIBLE,
+ .value.type = DVR_SURFACE_ATTRIBUTE_TYPE_BOOL,
+ .value.bool_value = true},
+ };
+ ret =
+ api_.SurfaceCreate(direct_surface_1_attributes.data(),
+ direct_surface_1_attributes.size(), &direct_surface_1);
+ EXPECT_EQ(ret, 0) << "Failed to create direct surface.";
+
+ // Create a buffer queue for each of the direct surfaces.
+ constexpr size_t kCapacity = 1;
+ uint32_t width = display_metrics_.display_width;
+ uint32_t height = display_metrics_.display_height;
+
+ DvrWriteBufferQueue* write_queue_0 = nullptr;
+ ret = api_.SurfaceCreateWriteBufferQueue(
+ direct_surface_0, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+ kMetadataSize, &write_queue_0);
+ EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
+ EXPECT_NE(nullptr, write_queue_0) << "Write buffer queue should not be null.";
+
+ DvrWriteBufferQueue* write_queue_1 = nullptr;
+ ret = api_.SurfaceCreateWriteBufferQueue(
+ direct_surface_1, width, height, kFormat, kLayerCount, kUsage, kCapacity,
+ kMetadataSize, &write_queue_1);
+ EXPECT_EQ(0, ret) << "Failed to create buffer queue.";
+ EXPECT_NE(nullptr, write_queue_1) << "Write buffer queue should not be null.";
+
+ // Get a buffer from each of the write buffer queues.
+ DvrWriteBuffer* write_buffer_0 = nullptr;
+ DvrNativeBufferMetadata out_meta_0;
+ int out_fence_fd = -1;
+ ret = api_.WriteBufferQueueGainBuffer(
+ write_queue_0, kTimeoutMs, &write_buffer_0, &out_meta_0, &out_fence_fd);
+ EXPECT_EQ(0, ret) << "Failed to get the buffer.";
+ EXPECT_NE(nullptr, write_buffer_0) << "Gained buffer should not be null.";
+
+ DvrWriteBuffer* write_buffer_1 = nullptr;
+ DvrNativeBufferMetadata out_meta_1;
+ out_fence_fd = -1;
+ ret = api_.WriteBufferQueueGainBuffer(
+ write_queue_1, kTimeoutMs, &write_buffer_1, &out_meta_1, &out_fence_fd);
+ EXPECT_EQ(0, ret) << "Failed to get the buffer.";
+ EXPECT_NE(nullptr, write_buffer_1) << "Gained buffer should not be null.";
+
+ // Color the write buffers.
+ FillWriteBuffer(write_buffer_0, {0xffff0000, 0xff00ff00, 0xff0000ff}, width,
+ height);
+ FillWriteBuffer(write_buffer_1, {0x7f00ff00, 0x7f0000ff, 0x7fff0000}, width,
+ height);
+
+ // Post buffers.
+ int ready_fence_fd = -1;
+ ret = api_.WriteBufferQueuePostBuffer(write_queue_0, write_buffer_0,
+ &out_meta_0, ready_fence_fd);
+ EXPECT_EQ(0, ret) << "Failed to post the buffer.";
+
+ ready_fence_fd = -1;
+ ret = api_.WriteBufferQueuePostBuffer(write_queue_1, write_buffer_1,
+ &out_meta_1, ready_fence_fd);
+ EXPECT_EQ(0, ret) << "Failed to post the buffer.";
+
+ sleep(5); // For visual check on the device under test.
+ // Should observe three secondary colors.
+
+ // Test finished. Clean up buffers and surfaces.
+ if (write_queue_0 != nullptr) {
+ api_.WriteBufferQueueDestroy(write_queue_0);
+ write_queue_0 = nullptr;
+ }
+ if (write_queue_1 != nullptr) {
+ api_.WriteBufferQueueDestroy(write_queue_1);
+ write_queue_1 = nullptr;
+ }
+ if (direct_surface_0 != nullptr) {
+ api_.SurfaceDestroy(direct_surface_0);
+ }
+ if (direct_surface_1 != nullptr) {
+ api_.SurfaceDestroy(direct_surface_1);
+ }
+}
+
+void DvrDisplayTest::FillWriteBuffer(
+ DvrWriteBuffer* write_buffer, const std::vector<uint32_t>& color_textures,
+ uint32_t width, uint32_t height) {
+ uint32_t num_colors = color_textures.size();
+ // Convert the first write buffer to an android hardware buffer.
+ AHardwareBuffer* ah_buffer = nullptr;
+ int ret = api_.WriteBufferGetAHardwareBuffer(write_buffer, &ah_buffer);
+ ASSERT_EQ(0, ret) << "Failed to get a hardware buffer from the write buffer.";
+ ASSERT_NE(nullptr, ah_buffer) << "AHardware buffer should not be null.";
+ AHardwareBuffer_Desc ah_buffer_describe;
+ AHardwareBuffer_describe(ah_buffer, &ah_buffer_describe);
+ ASSERT_EQ(ah_buffer_describe.format, kFormat)
+ << "The format of the android hardware buffer is wrong.";
+ ASSERT_EQ(ah_buffer_describe.layers, kLayerCount)
+ << "The obtained android hardware buffer should have 2 layers.";
+ ASSERT_EQ(ah_buffer_describe.width, width)
+ << "The obtained android hardware buffer width is wrong.";
+ ASSERT_EQ(ah_buffer_describe.height, height)
+ << "The obtained android hardware buffer height is wrong.";
+ // Change the content of the android hardware buffer.
+ void* buffer_data = nullptr;
+ int32_t fence = -1;
+ ret = AHardwareBuffer_lock(ah_buffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN,
+ fence, nullptr, &buffer_data);
+ ASSERT_EQ(0, ret) << "Failed to lock the hardware buffer.";
+ ASSERT_NE(nullptr, buffer_data) << "Buffer data should not be null.";
+
+ uint32_t num_pixels = width * height / num_colors;
+ for (uint32_t color_index = 0; color_index < num_colors - 1; ++color_index) {
+ uint32_t color_texture = color_textures[color_index];
+ for (uint32_t i = 0; i < num_pixels; ++i) {
+ memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) +
+ (i + num_pixels * color_index) *
+ sizeof(color_texture)),
+ &color_texture, sizeof(color_texture));
+ }
+ }
+ uint32_t color_texture = color_textures[num_colors - 1];
+ uint32_t num_colored_pixels = num_pixels * (num_colors - 1);
+ num_pixels = width * height - num_colored_pixels;
+ for (uint32_t i = 0; i < num_pixels; ++i) {
+ memcpy(reinterpret_cast<void*>(reinterpret_cast<int64_t>(buffer_data) +
+ (i + num_colored_pixels) *
+ sizeof(color_texture)),
+ &color_texture, sizeof(color_texture));
+ }
+ fence = -1;
+ ret = AHardwareBuffer_unlock(ah_buffer, &fence);
+ EXPECT_EQ(0, ret) << "Failed to unlock the hardware buffer.";
+
+ // Release the android hardware buffer.
+ AHardwareBuffer_release(ah_buffer);
}
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index c32ffb9..2bd0a19 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -24,6 +24,7 @@
#include <cutils/properties.h>
#include <hardware/sensors.h>
#include <hardware_legacy/power.h>
+#include <log/log.h>
#include <openssl/digest.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
@@ -1093,10 +1094,15 @@
// check specific to memory type
switch(type) {
case SENSOR_DIRECT_MEM_TYPE_ASHMEM: { // channel backed by ashmem
+ if (resource->numFds < 1) {
+ ALOGE("Ashmem direct channel requires a memory region to be supplied");
+ android_errorWriteLog(0x534e4554, "70986337"); // SafetyNet
+ return nullptr;
+ }
int fd = resource->data[0];
int size2 = ashmem_get_size_region(fd);
// check size consistency
- if (size2 < static_cast<int>(size)) {
+ if (size2 < static_cast<int64_t>(size)) {
ALOGE("Ashmem direct channel size %" PRIu32 " greater than shared memory size %d",
size, size2);
return nullptr;