Merge "Remove DetachedBufferHandle from libui"
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 174ab21..b6038f9 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -2693,6 +2693,13 @@
return false;
}
+ // Return false for empty class path since it may otherwise return true below if profiles is
+ // empty.
+ if (classpath.empty()) {
+ PLOG(ERROR) << "Class path is empty";
+ return false;
+ }
+
// Open and create the snapshot profile.
unique_fd snapshot_fd = open_spnashot_profile(AID_SYSTEM, package_name, profile_name);
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 5fbb3b2..647fe86 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -13,13 +13,20 @@
// limitations under the License.
ndk_headers {
- name: "libnativewindow_headers",
+ name: "libnativewindow_ndk_headers",
from: "include/android",
to: "android",
srcs: ["include/android/*.h"],
license: "NOTICE",
}
+// TODO(b/118715870): cleanup header files
+cc_library_headers {
+ name: "libnativewindow_headers",
+ export_include_dirs: ["include"],
+ vendor_available: false,
+}
+
ndk_library {
name: "libnativewindow",
symbol_file: "libnativewindow.map.txt",
@@ -70,6 +77,7 @@
header_libs: [
"libnativebase_headers",
+ "libnativewindow_headers",
],
// headers we include in our public headers
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 108b005..a247e60 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -36,8 +36,8 @@
} // namespace
using dvr::BufferHubDefs::IsBufferGained;
+using dvr::BufferHubDefs::kFirstClientBitMask;
using dvr::BufferHubDefs::kMetadataHeaderSize;
-using dvr::BufferHubDefs::kProducerStateBit;
using frameworks::bufferhub::V1_0::IBufferHub;
using hardware::hidl_handle;
using hidl::base::V1_0::IBase;
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index b248ece..73ca69b 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -28,8 +28,8 @@
using android::dvr::BufferHubDefs::IsBufferPosted;
using android::dvr::BufferHubDefs::IsBufferReleased;
using android::dvr::BufferHubDefs::kConsumerStateMask;
+using android::dvr::BufferHubDefs::kFirstClientBitMask;
using android::dvr::BufferHubDefs::kMetadataHeaderSize;
-using android::dvr::BufferHubDefs::kProducerStateBit;
using android::pdx::LocalChannelHandle;
using android::pdx::LocalHandle;
using android::pdx::Status;
@@ -61,14 +61,14 @@
ASSERT_TRUE(c2.get() != nullptr);
// Producer state mask is unique, i.e. 1.
- EXPECT_EQ(p->client_state_mask(), kProducerStateBit);
+ EXPECT_EQ(p->client_state_mask(), kFirstClientBitMask);
// Consumer state mask cannot have producer bit on.
- EXPECT_EQ(c->client_state_mask() & kProducerStateBit, 0U);
+ EXPECT_EQ(c->client_state_mask() & kFirstClientBitMask, 0U);
// Consumer state mask must be a single, i.e. power of 2.
EXPECT_NE(c->client_state_mask(), 0U);
EXPECT_EQ(c->client_state_mask() & (c->client_state_mask() - 1), 0U);
// Consumer state mask cannot have producer bit on.
- EXPECT_EQ(c2->client_state_mask() & kProducerStateBit, 0U);
+ EXPECT_EQ(c2->client_state_mask() & kFirstClientBitMask, 0U);
// Consumer state mask must be a single, i.e. power of 2.
EXPECT_NE(c2->client_state_mask(), 0U);
EXPECT_EQ(c2->client_state_mask() & (c2->client_state_mask() - 1), 0U);
@@ -189,7 +189,7 @@
EXPECT_EQ(client_state_masks & cs[i]->client_state_mask(), 0U);
client_state_masks |= cs[i]->client_state_mask();
}
- EXPECT_EQ(client_state_masks, kProducerStateBit | kConsumerStateMask);
+ EXPECT_EQ(client_state_masks, kFirstClientBitMask | kConsumerStateMask);
// The 64th creation will fail with out-of-memory error.
auto state = p->CreateConsumer();
@@ -204,7 +204,7 @@
// The released state mask will be reused.
EXPECT_EQ(client_state_masks & cs[i]->client_state_mask(), 0U);
client_state_masks |= cs[i]->client_state_mask();
- EXPECT_EQ(client_state_masks, kProducerStateBit | kConsumerStateMask);
+ EXPECT_EQ(client_state_masks, kFirstClientBitMask | kConsumerStateMask);
}
}
@@ -890,6 +890,7 @@
int b1_id = b1->id();
EXPECT_TRUE(b1->IsValid());
EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
+ EXPECT_NE(b1->client_state_mask(), 0ULL);
auto status_or_handle = b1->Duplicate();
EXPECT_TRUE(status_or_handle);
@@ -907,6 +908,7 @@
ASSERT_TRUE(b2 != nullptr);
EXPECT_TRUE(b2->IsValid());
EXPECT_EQ(b2->user_metadata_size(), kUserMetadataSize);
+ EXPECT_NE(b2->client_state_mask(), 0ULL);
int b2_id = b2->id();
@@ -915,10 +917,6 @@
EXPECT_EQ(b1_id, b2_id);
// We use client_state_mask() to tell those two instances apart.
EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
- EXPECT_NE(b1->client_state_mask(), 0ULL);
- EXPECT_NE(b2->client_state_mask(), 0ULL);
- EXPECT_NE(b1->client_state_mask(), kProducerStateBit);
- EXPECT_NE(b2->client_state_mask(), kProducerStateBit);
// Both buffer instances should be in gained state.
EXPECT_TRUE(IsBufferGained(b1->buffer_state()));
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index 83d6951..8e630ec 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -59,7 +59,8 @@
uint64_t fence_state = fence_state_->load(std::memory_order_acquire);
// If there is an acquire fence from producer, we need to return it.
- if (fence_state & BufferHubDefs::kProducerStateBit) {
+ // The producer state bit mask is kFirstClientBitMask for now.
+ if (fence_state & BufferHubDefs::kFirstClientBitMask) {
*out_fence = shared_acquire_fence_.Duplicate();
}
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
index 80a00be..650da97 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
@@ -26,14 +26,14 @@
// MSB LSB
// | |
// v v
-// [P|C62|...|C1|C0]
-// Gain'ed state: [0|..|0|0] -> Exclusively Writable.
-// Post'ed state: [1|..|0|0]
-// Acquired'ed state: [1|..|X|X] -> At least one bit is set in lower 63 bits
-// Released'ed state: [0|..|X|X] -> At least one bit is set in lower 63 bits
+// [C62|...|C1|C0|P]
+// Gain'ed state: [..|0|0|0] -> Exclusively Writable.
+// Post'ed state: [..|0|0|1]
+// Acquired'ed state: [..|X|X|1] -> At least one bit is set in higher 63 bits
+// Released'ed state: [..|X|X|0] -> At least one bit is set in higher 63 bits
static constexpr int kMaxNumberOfClients = 64;
-static constexpr uint64_t kProducerStateBit = 1ULL << 63;
-static constexpr uint64_t kConsumerStateMask = (1ULL << 63) - 1;
+static constexpr uint64_t kFirstClientBitMask = 1ULL;
+static constexpr uint64_t kConsumerStateMask = ~kFirstClientBitMask;
static inline void ModifyBufferState(std::atomic<uint64_t>* buffer_state,
uint64_t clear_mask, uint64_t set_mask) {
@@ -49,15 +49,15 @@
static inline bool IsBufferPosted(uint64_t state,
uint64_t consumer_bit = kConsumerStateMask) {
- return (state & kProducerStateBit) && !(state & consumer_bit);
+ return (state & kFirstClientBitMask) && !(state & consumer_bit);
}
static inline bool IsBufferAcquired(uint64_t state) {
- return (state & kProducerStateBit) && (state & kConsumerStateMask);
+ return (state & kFirstClientBitMask) && (state & kConsumerStateMask);
}
static inline bool IsBufferReleased(uint64_t state) {
- return !(state & kProducerStateBit) && (state & kConsumerStateMask);
+ return !(state & kFirstClientBitMask) && (state & kConsumerStateMask);
}
static inline uint64_t FindNextAvailableClientStateMask(uint64_t bits) {
@@ -65,7 +65,7 @@
}
static inline uint64_t FindFirstClearedBit() {
- return FindNextAvailableClientStateMask(kProducerStateBit);
+ return FindNextAvailableClientStateMask(kFirstClientBitMask);
}
struct __attribute__((packed, aligned(8))) MetadataHeader {
@@ -123,7 +123,7 @@
// State mask of the buffer client. Each BufferHubBuffer client backed by the
// same buffer channel has uniqued state bit among its siblings. For a
- // producer buffer the bit must be kProducerStateBit; for a consumer the bit
+ // producer buffer the bit must be kFirstClientBitMask; for a consumer the bit
// must be one of the kConsumerStateMask.
uint64_t client_state_mask() const { return client_state_mask_; }
uint64_t metadata_size() const { return metadata_size_; }
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 10517c5..f36e169 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -102,8 +102,9 @@
return error;
// Set the producer bit atomically to transit into posted state.
+ // The producer state bit mask is kFirstClientBitMask for now.
BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
- BufferHubDefs::kProducerStateBit);
+ BufferHubDefs::kFirstClientBitMask);
return 0;
}
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index f246077..a9e873a 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -25,6 +25,7 @@
"libhidltransport",
"liblog",
"libutils",
+ "libnativewindow",
],
include_dirs: [
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
index 5927dc1..459b135 100644
--- a/opengl/tests/EGLTest/EGL_test.cpp
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -775,4 +775,169 @@
EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
}
+
+TEST_F(EGLTest, EGLInvalidColorspaceAttribute) {
+ EGLConfig config;
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
+}
+
+TEST_F(EGLTest, EGLUnsupportedColorspaceFormatCombo) {
+ EGLint numConfigs;
+ EGLConfig config;
+ EGLBoolean success;
+
+ const EGLint attrs[] = {
+ // clang-format off
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 16,
+ EGL_GREEN_SIZE, 16,
+ EGL_BLUE_SIZE, 16,
+ EGL_ALPHA_SIZE, 16,
+ EGL_COLOR_COMPONENT_TYPE_EXT, EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ EGL_NONE,
+ // clang-format on
+ };
+ success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+ ASSERT_EQ(EGL_UNSIGNED_TRUE, success);
+ ASSERT_EQ(1, numConfigs);
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ const EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_BAD_MATCH, eglGetError());
+ ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
+}
+
+TEST_F(EGLTest, EGLCreateWindowFailAndSucceed) {
+ EGLConfig config;
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_BACK_BUFFER,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ ASSERT_EQ(EGL_NO_SURFACE, eglSurface);
+
+ // Now recreate surface with a valid colorspace. Ensure proper cleanup is done
+ // in the first failed attempt (e.g. native_window_api_disconnect).
+ winAttrs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
+ eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
+
+TEST_F(EGLTest, EGLCreateWindowTwoColorspaces) {
+ EGLConfig config;
+
+ ASSERT_NO_FATAL_FAILURE(get8BitConfig(config));
+
+ struct DummyConsumer : public BnConsumerListener {
+ void onFrameAvailable(const BufferItem& /* item */) override {}
+ void onBuffersReleased() override {}
+ void onSidebandStreamChanged() override {}
+ };
+
+ // Create a EGLSurface
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ consumer->consumerConnect(new DummyConsumer, false);
+ sp<Surface> mSTC = new Surface(producer);
+ sp<ANativeWindow> mANW = mSTC;
+
+ const EGLint winAttrs[] = {
+ // clang-format off
+ EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_DISPLAY_P3_EXT,
+ EGL_NONE,
+ // clang-format on
+ };
+
+ EGLSurface eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), winAttrs);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ android_dataspace dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
+ ASSERT_EQ(dataspace, HAL_DATASPACE_DISPLAY_P3);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+
+ // Now create with default attribute (EGL_GL_COLORSPACE_LINEAR_KHR)
+ eglSurface = eglCreateWindowSurface(mEglDisplay, config, mANW.get(), NULL);
+ ASSERT_EQ(EGL_SUCCESS, eglGetError());
+ ASSERT_NE(EGL_NO_SURFACE, eglSurface);
+
+ dataspace = static_cast<android_dataspace>(ANativeWindow_getBuffersDataSpace(mANW.get()));
+ // Make sure the dataspace has been reset to UNKNOWN
+ ASSERT_NE(dataspace, HAL_DATASPACE_DISPLAY_P3);
+
+ EXPECT_TRUE(eglDestroySurface(mEglDisplay, eglSurface));
+}
}
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 162065b..241eee7 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -100,6 +100,12 @@
active_clients_bit_mask_ =
new (&metadata_header_->active_clients_bit_mask) std::atomic<uint64_t>(0);
+ // Producer channel is never created after consumer channel, and one buffer
+ // only have one fixed producer for now. Thus, it is correct to assume
+ // producer state bit is kFirstClientBitMask for now.
+ active_clients_bit_mask_->store(BufferHubDefs::kFirstClientBitMask,
+ std::memory_order_release);
+
acquire_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
release_fence_fd_.Reset(epoll_create1(EPOLL_CLOEXEC));
if (!acquire_fence_fd_ || !release_fence_fd_) {
@@ -171,7 +177,7 @@
BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
// Derive the mask of signaled buffers in this producer / consumer set.
- uint64_t signaled_mask = signaled() ? BufferHubDefs::kProducerStateBit : 0;
+ uint64_t signaled_mask = signaled() ? BufferHubDefs::kFirstClientBitMask : 0;
for (const ConsumerChannel* consumer : consumer_channels_) {
signaled_mask |= consumer->signaled() ? consumer->client_state_mask() : 0;
}
@@ -239,7 +245,7 @@
ATRACE_NAME("ProducerChannel::OnGetBuffer");
ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d, state=%" PRIx64 ".",
buffer_id(), buffer_state_->load(std::memory_order_acquire));
- return {GetBuffer(BufferHubDefs::kProducerStateBit)};
+ return {GetBuffer(BufferHubDefs::kFirstClientBitMask)};
}
Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
@@ -264,8 +270,7 @@
uint64_t current_active_clients_bit_mask =
active_clients_bit_mask_->load(std::memory_order_acquire);
uint64_t client_state_mask = BufferHubDefs::FindNextAvailableClientStateMask(
- current_active_clients_bit_mask | orphaned_consumer_bit_mask_ |
- BufferHubDefs::kProducerStateBit);
+ current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
if (client_state_mask == 0ULL) {
ALOGE(
"ProducerChannel::CreateConsumer: reached the maximum mumber of "
@@ -284,8 +289,8 @@
if (!active_clients_bit_mask_->compare_exchange_weak(
current_active_clients_bit_mask, updated_active_clients_bit_mask,
std::memory_order_acq_rel, std::memory_order_acquire)) {
- ALOGE("Current active clients bit mask is changed to %" PRIu64
- ", which was expected to be %" PRIu64 ".",
+ ALOGE("Current active clients bit mask is changed to %" PRIx64
+ ", which was expected to be %" PRIx64 ".",
updated_active_clients_bit_mask, current_active_clients_bit_mask);
return ErrorStatus(EBUSY);
}
@@ -504,7 +509,7 @@
// has to done by BufferHub as it requries synchronization among all
// consumers.
BufferHubDefs::ModifyBufferState(buffer_state_,
- BufferHubDefs::kProducerStateBit, 0ULL);
+ BufferHubDefs::kFirstClientBitMask, 0ULL);
ALOGD_IF(TRACE,
"ProducerChannel::OnConsumerRelease: releasing last consumer: "
"buffer_id=%d state=%" PRIx64 ".",