Merge "Move active clients mask to an atomic uint64_t in shared memory."
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 5acc09d..e185cbe 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -57,10 +57,21 @@
export_aidl_headers: true,
},
srcs: [
- "binder/android/os/IDumpstate.aidl",
+ "binder/android/os/DumpstateOptions.cpp",
+ ":dumpstate_aidl",
+ ],
+ export_include_dirs: ["binder"],
+}
+
+filegroup {
+ name: "dumpstate_aidl",
+ srcs: [
"binder/android/os/IDumpstateListener.aidl",
"binder/android/os/IDumpstateToken.aidl",
+ //"binder/android/os/DumpstateOptions.aidl",
+ "binder/android/os/IDumpstate.aidl",
],
+ path: "binder",
}
cc_defaults {
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index 49a78e7..260ea4b 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -77,6 +77,13 @@
return binder::Status::ok();
}
+binder::Status DumpstateService::startBugreport(int, const sp<IDumpstateListener>&,
+ const DumpstateOptions&, int32_t* returned_id) {
+ // TODO: fork to handle the bugreport request and return the process id or a request id here.
+ *returned_id = -1;
+ return binder::Status::ok();
+}
+
status_t DumpstateService::dump(int fd, const Vector<String16>&) {
dprintf(fd, "id: %d\n", ds_.id_);
dprintf(fd, "pid: %d\n", ds_.pid_);
diff --git a/cmds/dumpstate/DumpstateService.h b/cmds/dumpstate/DumpstateService.h
index 7bca24a..131aff3 100644
--- a/cmds/dumpstate/DumpstateService.h
+++ b/cmds/dumpstate/DumpstateService.h
@@ -41,6 +41,9 @@
bool getSectionDetails,
sp<IDumpstateToken>* returned_token) override;
+ binder::Status startBugreport(int fd, const sp<IDumpstateListener>& listener,
+ const DumpstateOptions& options, int32_t* returned_id) override;
+
private:
Dumpstate& ds_;
std::mutex lock_;
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl b/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
new file mode 100644
index 0000000..c1a7f15
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.aidl
@@ -0,0 +1,23 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * Specifies arguments for IDumpstate.
+ * {@hide}
+ */
+parcelable DumpstateOptions cpp_header "android/os/DumpstateOptions.h";
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp b/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
new file mode 100644
index 0000000..5654190
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.cpp
@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/os/DumpstateOptions.h>
+
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+
+namespace android {
+namespace os {
+
+status_t DumpstateOptions::readFromParcel(const ::android::Parcel* parcel) {
+ if (status_t err = parcel->readBool(&get_section_details)) {
+ return err;
+ }
+ if (status_t err = parcel->readUtf8FromUtf16(&name)) {
+ return err;
+ }
+ return android::OK;
+}
+
+status_t DumpstateOptions::writeToParcel(::android::Parcel* parcel) const {
+ if (status_t err = parcel->writeBool(get_section_details)) {
+ return err;
+ }
+ if (status_t err = parcel->writeUtf8AsUtf16(name)) {
+ return err;
+ }
+ return android::OK;
+}
+
+} // namespace os
+} // namespace android
diff --git a/cmds/dumpstate/binder/android/os/DumpstateOptions.h b/cmds/dumpstate/binder/android/os/DumpstateOptions.h
new file mode 100644
index 0000000..a748e3c
--- /dev/null
+++ b/cmds/dumpstate/binder/android/os/DumpstateOptions.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_DUMPSTATE_OPTIONS_H_
+#define ANDROID_OS_DUMPSTATE_OPTIONS_H_
+
+#include <binder/Parcelable.h>
+
+namespace android {
+namespace os {
+
+struct DumpstateOptions : public android::Parcelable {
+ // If true the caller can get callbacks with per-section progress details.
+ bool get_section_details = false;
+
+ // Name of the caller.
+ std::string name;
+
+ status_t writeToParcel(android::Parcel* parcel) const override;
+ status_t readFromParcel(const android::Parcel* parcel) override;
+};
+
+} // namespace os
+} // namespace android
+
+#endif // ANDROID_OS_DUMPSTATE_OPTIONS_H_
diff --git a/cmds/dumpstate/binder/android/os/IDumpstate.aidl b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
index 9b11b96..68a4f21 100644
--- a/cmds/dumpstate/binder/android/os/IDumpstate.aidl
+++ b/cmds/dumpstate/binder/android/os/IDumpstate.aidl
@@ -18,6 +18,7 @@
import android.os.IDumpstateListener;
import android.os.IDumpstateToken;
+import android.os.DumpstateOptions;
/**
* Binder interface for the currently running dumpstate process.
@@ -25,6 +26,8 @@
*/
interface IDumpstate {
+
+ // TODO: remove method once startBugReport is used by Shell.
/*
* Sets the listener for this dumpstate progress.
*
@@ -35,4 +38,11 @@
*/
IDumpstateToken setListener(@utf8InCpp String name, IDumpstateListener listener,
boolean getSectionDetails);
+
+ /*
+ * Starts a bugreport in a child process.
+ *
+ * Returns an identifier of the bugreport process running in the background.
+ */
+ int startBugreport(int fd, IDumpstateListener listener, in DumpstateOptions options);
}
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index f237e69..c222c16 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -207,6 +207,8 @@
* null. The exact cookie must also be used to unlink this transaction (see AIBinder_linkToDeath).
* This function may return a binder transaction failure. The cookie can be used both for
* identification and holding user data.
+ *
+ * If binder is local, this will return STATUS_INVALID_OPERATION.
*/
binder_status_t AIBinder_linkToDeath(AIBinder* binder, AIBinder_DeathRecipient* recipient,
void* cookie) __INTRODUCED_IN(29);
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 06d597c..3dac037 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -18,8 +18,8 @@
#include <gui/BufferHubProducer.h>
#include <inttypes.h>
#include <log/log.h>
-#include <private/dvr/detached_buffer.h>
#include <system/window.h>
+#include <ui/BufferHubBuffer.h>
#include <ui/DetachedBufferHandle.h>
namespace android {
@@ -400,14 +400,14 @@
ALOGE("attachBuffer: DetachedBufferHandle cannot be NULL.");
return BAD_VALUE;
}
- auto detached_buffer = DetachedBuffer::Import(std::move(detached_handle->handle()));
+ auto detached_buffer = BufferHubBuffer::Import(std::move(detached_handle->handle()));
if (detached_buffer == nullptr) {
- ALOGE("attachBuffer: DetachedBuffer cannot be NULL.");
+ ALOGE("attachBuffer: BufferHubBuffer cannot be NULL.");
return BAD_VALUE;
}
auto status_or_handle = detached_buffer->Promote();
if (!status_or_handle.ok()) {
- ALOGE("attachBuffer: Failed to promote a DetachedBuffer into a BufferProducer, error=%d.",
+ ALOGE("attachBuffer: Failed to promote a BufferHubBuffer into a BufferProducer, error=%d.",
status_or_handle.error());
return BAD_VALUE;
}
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 1605050..24b1986 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -54,6 +54,8 @@
srcs: [
"ColorSpace.cpp",
+ "BufferHubBuffer.cpp",
+ "BufferHubMetadata.cpp",
"DebugUtils.cpp",
"Fence.cpp",
"FenceTime.cpp",
@@ -91,6 +93,7 @@
"libutils",
"libutilscallstack",
"liblog",
+ "libpdx_default_transport", // TODO(b/112338294): Remove this once BufferHub moved to use Binder.
],
export_shared_lib_headers: [
@@ -103,8 +106,27 @@
"libmath",
],
+ // bufferhub is not used when building libgui for vendors
+ target: {
+ vendor: {
+ exclude_srcs: [
+ "BufferHubBuffer.cpp",
+ "BufferHubMetadata.cpp",
+ ],
+ exclude_header_libs: [
+ "libbufferhub_headers",
+ "libdvr_headers",
+ ],
+ exclude_shared_libs: [
+ "libpdx_default_transport",
+ ],
+ },
+ },
+
header_libs: [
"libbase_headers",
+ "libbufferhub_headers",
+ "libdvr_headers",
"libnativebase_headers",
"libhardware_headers",
"libui_headers",
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
new file mode 100644
index 0000000..606386c
--- /dev/null
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// We would eliminate the clang warnings introduced by libdpx.
+// TODO(b/112338294): Remove those once BufferHub moved to use Binder
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#pragma clang diagnostic ignored "-Wdouble-promotion"
+#pragma clang diagnostic ignored "-Wgnu-case-range"
+#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
+#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
+#pragma clang diagnostic ignored "-Wnested-anon-types"
+#pragma clang diagnostic ignored "-Wpacked"
+#pragma clang diagnostic ignored "-Wshadow"
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#pragma clang diagnostic ignored "-Wswitch-enum"
+#pragma clang diagnostic ignored "-Wundefined-func-template"
+#pragma clang diagnostic ignored "-Wunused-template"
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#include <pdx/default_transport/client_channel.h>
+#include <pdx/default_transport/client_channel_factory.h>
+#include <pdx/file_handle.h>
+#include <private/dvr/bufferhub_rpc.h>
+#pragma clang diagnostic pop
+
+#include <ui/BufferHubBuffer.h>
+#include <ui/DetachedBufferHandle.h>
+
+#include <poll.h>
+
+using android::dvr::BufferHubMetadata;
+using android::dvr::BufferTraits;
+using android::dvr::DetachedBufferRPC;
+using android::dvr::NativeHandleWrapper;
+
+// TODO(b/112338294): Remove PDX dependencies from libui.
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Status;
+using android::pdx::default_transport::ClientChannel;
+using android::pdx::default_transport::ClientChannelFactory;
+
+namespace android {
+
+namespace {
+
+// TODO(b/112338294): Remove this string literal after refactoring BufferHub
+// to use Binder.
+static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
+
+} // namespace
+
+BufferHubClient::BufferHubClient() : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
+
+BufferHubClient::BufferHubClient(LocalChannelHandle mChannelHandle)
+ : Client(ClientChannel::Create(std::move(mChannelHandle))) {}
+
+BufferHubClient::~BufferHubClient() {}
+
+bool BufferHubClient::IsValid() const {
+ return IsConnected() && GetChannelHandle().valid();
+}
+
+LocalChannelHandle BufferHubClient::TakeChannelHandle() {
+ if (IsConnected()) {
+ return std::move(GetChannelHandle());
+ } else {
+ return {};
+ }
+}
+
+BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
+ uint32_t format, uint64_t usage, size_t mUserMetadataSize) {
+ ATRACE_CALL();
+ ALOGD("BufferHubBuffer::BufferHubBuffer: width=%u height=%u layerCount=%u, format=%u "
+ "usage=%" PRIx64 " mUserMetadataSize=%zu",
+ width, height, layerCount, format, usage, mUserMetadataSize);
+
+ auto status =
+ mClient.InvokeRemoteMethod<DetachedBufferRPC::Create>(width, height, layerCount, format,
+ usage, mUserMetadataSize);
+ if (!status) {
+ ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to create detached buffer: %s",
+ status.GetErrorMessage().c_str());
+ mClient.Close(-status.error());
+ }
+
+ const int ret = ImportGraphicBuffer();
+ if (ret < 0) {
+ ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to import buffer: %s", strerror(-ret));
+ mClient.Close(ret);
+ }
+}
+
+BufferHubBuffer::BufferHubBuffer(LocalChannelHandle mChannelHandle)
+ : mClient(std::move(mChannelHandle)) {
+ const int ret = ImportGraphicBuffer();
+ if (ret < 0) {
+ ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to import buffer: %s", strerror(-ret));
+ mClient.Close(ret);
+ }
+}
+
+int BufferHubBuffer::ImportGraphicBuffer() {
+ ATRACE_CALL();
+
+ auto status = mClient.InvokeRemoteMethod<DetachedBufferRPC::Import>();
+ if (!status) {
+ ALOGE("BufferHubBuffer::BufferHubBuffer: Failed to import GraphicBuffer: %s",
+ status.GetErrorMessage().c_str());
+ return -status.error();
+ }
+
+ BufferTraits<LocalHandle> bufferTraits = status.take();
+ if (bufferTraits.id() < 0) {
+ ALOGE("BufferHubBuffer::BufferHubBuffer: Received an invalid id!");
+ return -EIO;
+ }
+
+ // Stash the buffer id to replace the value in mId.
+ const int bufferId = bufferTraits.id();
+
+ // Import the metadata.
+ mMetadata = BufferHubMetadata::Import(bufferTraits.take_metadata_handle());
+
+ if (!mMetadata.IsValid()) {
+ ALOGE("BufferHubBuffer::ImportGraphicBuffer: invalid metadata.");
+ return -ENOMEM;
+ }
+
+ if (mMetadata.metadata_size() != bufferTraits.metadata_size()) {
+ ALOGE("BufferHubBuffer::ImportGraphicBuffer: metadata buffer too small: "
+ "%zu, expected: %" PRIu64 ".",
+ mMetadata.metadata_size(), bufferTraits.metadata_size());
+ return -ENOMEM;
+ }
+
+ size_t metadataSize = static_cast<size_t>(bufferTraits.metadata_size());
+ if (metadataSize < dvr::BufferHubDefs::kMetadataHeaderSize) {
+ ALOGE("BufferHubBuffer::ImportGraphicBuffer: metadata too small: %zu", metadataSize);
+ return -EINVAL;
+ }
+
+ // Import the buffer: We only need to hold on the native_handle_t here so that
+ // GraphicBuffer instance can be created in future.
+ mBufferHandle = bufferTraits.take_buffer_handle();
+
+ // If all imports succeed, replace the previous buffer and id.
+ mId = bufferId;
+ mBfferStateBit = bufferTraits.buffer_state_bit();
+
+ // TODO(b/112012161) Set up shared fences.
+ ALOGD("BufferHubBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64 ".", id(),
+ mMetadata.metadata_header()->buffer_state.load(std::memory_order_acquire));
+ return 0;
+}
+
+int BufferHubBuffer::Poll(int timeoutMs) {
+ ATRACE_CALL();
+
+ pollfd p = {mClient.event_fd(), POLLIN, 0};
+ return poll(&p, 1, timeoutMs);
+}
+
+Status<LocalChannelHandle> BufferHubBuffer::Promote() {
+ ATRACE_CALL();
+
+ // TODO(b/112338294) remove after migrate producer buffer to binder
+ ALOGW("BufferHubBuffer::Promote: not supported operation during migration");
+ return {};
+
+ ALOGD("BufferHubBuffer::Promote: id=%d.", mId);
+
+ auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
+ if (statusOrHandle.ok()) {
+ // Invalidate the buffer.
+ mBufferHandle = {};
+ } else {
+ ALOGE("BufferHubBuffer::Promote: Failed to promote buffer (id=%d): %s.", mId,
+ statusOrHandle.GetErrorMessage().c_str());
+ }
+ return statusOrHandle;
+}
+
+Status<LocalChannelHandle> BufferHubBuffer::Duplicate() {
+ ATRACE_CALL();
+ ALOGD("BufferHubBuffer::Duplicate: id=%d.", mId);
+
+ auto statusOrHandle = mClient.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
+
+ if (!statusOrHandle.ok()) {
+ ALOGE("BufferHubBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.", mId,
+ statusOrHandle.GetErrorMessage().c_str());
+ }
+ return statusOrHandle;
+}
+
+} // namespace android
diff --git a/libs/ui/BufferHubMetadata.cpp b/libs/ui/BufferHubMetadata.cpp
new file mode 100644
index 0000000..b0c4510
--- /dev/null
+++ b/libs/ui/BufferHubMetadata.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <cutils/ashmem.h>
+#include <log/log.h>
+#include <ui/BufferHubMetadata.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+static const int kAshmemProt = PROT_READ | PROT_WRITE;
+
+} // namespace
+
+using BufferHubDefs::kMetadataHeaderSize;
+using BufferHubDefs::MetadataHeader;
+
+/* static */
+BufferHubMetadata BufferHubMetadata::Create(size_t userMetadataSize) {
+ // The size the of metadata buffer is used as the "width" parameter during allocation. Thus it
+ // cannot overflow uint32_t.
+ if (userMetadataSize >= (std::numeric_limits<uint32_t>::max() - kMetadataHeaderSize)) {
+ ALOGE("BufferHubMetadata::Create: metadata size too big: %zu.", userMetadataSize);
+ return {};
+ }
+
+ const size_t metadataSize = userMetadataSize + kMetadataHeaderSize;
+ int fd = ashmem_create_region(/*name=*/"BufferHubMetadata", metadataSize);
+ if (fd < 0) {
+ ALOGE("BufferHubMetadata::Create: failed to create ashmem region.");
+ return {};
+ }
+
+ // Hand over the ownership of the fd to a pdx::LocalHandle immediately after the successful
+ // return of ashmem_create_region. The ashmemHandle is going to own the fd and to prevent fd
+ // leaks during error handling.
+ pdx::LocalHandle ashmemHandle{fd};
+
+ if (ashmem_set_prot_region(ashmemHandle.Get(), kAshmemProt) != 0) {
+ ALOGE("BufferHubMetadata::Create: failed to set protect region.");
+ return {};
+ }
+
+ return BufferHubMetadata::Import(std::move(ashmemHandle));
+}
+
+/* static */
+BufferHubMetadata BufferHubMetadata::Import(pdx::LocalHandle ashmemHandle) {
+ if (!ashmem_valid(ashmemHandle.Get())) {
+ ALOGE("BufferHubMetadata::Import: invalid ashmem fd.");
+ return {};
+ }
+
+ size_t metadataSize = static_cast<size_t>(ashmem_get_size_region(ashmemHandle.Get()));
+ size_t userMetadataSize = metadataSize - kMetadataHeaderSize;
+
+ // Note that here the buffer state is mapped from shared memory as an atomic object. The
+ // std::atomic's constructor will not be called so that the original value stored in the memory
+ // region can be preserved.
+ auto metadataHeader = static_cast<MetadataHeader*>(mmap(nullptr, metadataSize, kAshmemProt,
+ MAP_SHARED, ashmemHandle.Get(),
+ /*offset=*/0));
+ if (metadataHeader == nullptr) {
+ ALOGE("BufferHubMetadata::Import: failed to map region.");
+ return {};
+ }
+
+ return BufferHubMetadata(userMetadataSize, std::move(ashmemHandle), metadataHeader);
+}
+
+BufferHubMetadata::BufferHubMetadata(size_t userMetadataSize, pdx::LocalHandle ashmemHandle,
+ MetadataHeader* metadataHeader)
+ : mUserMetadataSize(userMetadataSize),
+ mAshmemHandle(std::move(ashmemHandle)),
+ mMetadataHeader(metadataHeader) {}
+
+BufferHubMetadata::~BufferHubMetadata() {
+ if (mMetadataHeader != nullptr) {
+ int ret = munmap(mMetadataHeader, metadata_size());
+ ALOGE_IF(ret != 0,
+ "BufferHubMetadata::~BufferHubMetadata: failed to unmap ashmem, error=%d.", errno);
+ mMetadataHeader = nullptr;
+ }
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index 0382479..c50d1d0 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -376,6 +376,10 @@
status_t GraphicBuffer::unflatten(
void const*& buffer, size_t& size, int const*& fds, size_t& count) {
+ if (size < 12 * sizeof(int)) {
+ android_errorWriteLog(0x534e4554, "114223584");
+ return NO_MEMORY;
+ }
int const* buf = static_cast<int const*>(buffer);
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
new file mode 100644
index 0000000..e8ae244
--- /dev/null
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BUFFER_HUB_BUFFER_H_
+#define ANDROID_BUFFER_HUB_BUFFER_H_
+
+// We would eliminate the clang warnings introduced by libdpx.
+// TODO(b/112338294): Remove those once BufferHub moved to use Binder
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#pragma clang diagnostic ignored "-Wdouble-promotion"
+#pragma clang diagnostic ignored "-Wgnu-case-range"
+#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
+#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
+#pragma clang diagnostic ignored "-Wnested-anon-types"
+#pragma clang diagnostic ignored "-Wpacked"
+#pragma clang diagnostic ignored "-Wshadow"
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#pragma clang diagnostic ignored "-Wswitch-enum"
+#pragma clang diagnostic ignored "-Wundefined-func-template"
+#pragma clang diagnostic ignored "-Wunused-template"
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#include <pdx/client.h>
+#include <private/dvr/buffer_hub_defs.h>
+#include <private/dvr/native_handle_wrapper.h>
+#pragma clang diagnostic pop
+
+#include <ui/BufferHubMetadata.h>
+
+namespace android {
+
+class BufferHubClient : public pdx::Client {
+public:
+ BufferHubClient();
+ virtual ~BufferHubClient();
+ explicit BufferHubClient(pdx::LocalChannelHandle mChannelHandle);
+
+ bool IsValid() const;
+ pdx::LocalChannelHandle TakeChannelHandle();
+
+ using pdx::Client::Close;
+ using pdx::Client::event_fd;
+ using pdx::Client::GetChannel;
+ using pdx::Client::InvokeRemoteMethod;
+};
+
+class BufferHubBuffer {
+public:
+ // Allocates a standalone BufferHubBuffer not associated with any producer consumer set.
+ static std::unique_ptr<BufferHubBuffer> Create(uint32_t width, uint32_t height,
+ uint32_t layerCount, uint32_t format,
+ uint64_t usage, size_t mUserMetadataSize) {
+ return std::unique_ptr<BufferHubBuffer>(
+ new BufferHubBuffer(width, height, layerCount, format, usage, mUserMetadataSize));
+ }
+
+ // Imports the given channel handle to a BufferHubBuffer, taking ownership.
+ static std::unique_ptr<BufferHubBuffer> Import(pdx::LocalChannelHandle mChannelHandle) {
+ return std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(std::move(mChannelHandle)));
+ }
+
+ BufferHubBuffer(const BufferHubBuffer&) = delete;
+ void operator=(const BufferHubBuffer&) = delete;
+
+ // Gets ID of the buffer client. All BufferHubBuffer clients derived from the same buffer in
+ // bufferhubd share the same buffer id.
+ int id() const { return mId; }
+
+ const native_handle_t* DuplicateHandle() { return mBufferHandle.DuplicateHandle(); }
+
+ // Returns the current value of MetadataHeader::buffer_state.
+ uint64_t buffer_state() {
+ return mMetadata.metadata_header()->buffer_state.load(std::memory_order_acquire);
+ }
+
+ // A state mask which is unique to a buffer hub client among all its siblings sharing the same
+ // concrete graphic buffer.
+ uint64_t buffer_state_bit() const { return mBfferStateBit; }
+
+ size_t user_metadata_size() const { return mMetadata.user_metadata_size(); }
+
+ // Returns true if the buffer holds an open PDX channels towards bufferhubd.
+ bool IsConnected() const { return mClient.IsValid(); }
+
+ // Returns true if the buffer holds an valid native buffer handle that's availble for the client
+ // to read from and/or write into.
+ bool IsValid() const { return mBufferHandle.IsValid(); }
+
+ // Returns the event mask for all the events that are pending on this buffer (see sys/poll.h for
+ // all possible bits).
+ pdx::Status<int> GetEventMask(int events) {
+ if (auto* channel = mClient.GetChannel()) {
+ return channel->GetEventMask(events);
+ } else {
+ return pdx::ErrorStatus(EINVAL);
+ }
+ }
+
+ // Polls the fd for |timeoutMs| milliseconds (-1 for infinity).
+ int Poll(int timeoutMs);
+
+ // Promotes a BufferHubBuffer to become a ProducerBuffer. Once promoted the BufferHubBuffer
+ // channel will be closed automatically on successful IPC return. Further IPCs towards this
+ // channel will return error.
+ pdx::Status<pdx::LocalChannelHandle> Promote();
+
+ // Creates a BufferHubBuffer client from an existing one. The new client will
+ // share the same underlying gralloc buffer and ashmem region for metadata.
+ pdx::Status<pdx::LocalChannelHandle> Duplicate();
+
+private:
+ BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
+ uint64_t usage, size_t mUserMetadataSize);
+
+ BufferHubBuffer(pdx::LocalChannelHandle mChannelHandle);
+
+ int ImportGraphicBuffer();
+
+ // Global id for the buffer that is consistent across processes.
+ int mId;
+ uint64_t mBfferStateBit;
+
+ // Wrapps the gralloc buffer handle of this buffer.
+ dvr::NativeHandleWrapper<pdx::LocalHandle> mBufferHandle;
+
+ // An ashmem-based metadata object. The same shared memory are mapped to the
+ // bufferhubd daemon and all buffer clients.
+ dvr::BufferHubMetadata mMetadata;
+
+ // PDX backend.
+ BufferHubClient mClient;
+};
+
+} // namespace android
+
+#endif // ANDROID_BUFFER_HUB_BUFFER_H_
diff --git a/libs/ui/include/ui/BufferHubMetadata.h b/libs/ui/include/ui/BufferHubMetadata.h
new file mode 100644
index 0000000..46adc6a
--- /dev/null
+++ b/libs/ui/include/ui/BufferHubMetadata.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BUFFER_HUB_METADATA_H_
+#define ANDROID_BUFFER_HUB_METADATA_H_
+
+// We would eliminate the clang warnings introduced by libdpx.
+// TODO(b/112338294): Remove those once BufferHub moved to use Binder
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#pragma clang diagnostic ignored "-Wdouble-promotion"
+#pragma clang diagnostic ignored "-Wgnu-case-range"
+#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
+#pragma clang diagnostic ignored "-Winconsistent-missing-destructor-override"
+#pragma clang diagnostic ignored "-Wnested-anon-types"
+#pragma clang diagnostic ignored "-Wpacked"
+#pragma clang diagnostic ignored "-Wshadow"
+#pragma clang diagnostic ignored "-Wsign-conversion"
+#pragma clang diagnostic ignored "-Wswitch-enum"
+#pragma clang diagnostic ignored "-Wundefined-func-template"
+#pragma clang diagnostic ignored "-Wunused-template"
+#pragma clang diagnostic ignored "-Wweak-vtables"
+#include <pdx/file_handle.h>
+#include <private/dvr/buffer_hub_defs.h>
+#pragma clang diagnostic pop
+
+namespace android {
+namespace dvr {
+
+class BufferHubMetadata {
+public:
+ // Creates a new BufferHubMetadata backed by an ashmem region.
+ //
+ // @param userMetadataSize Size in bytes of the user defined metadata. The entire metadata
+ // shared memory region to be allocated is the size of canonical
+ // BufferHubDefs::MetadataHeader plus userMetadataSize.
+ static BufferHubMetadata Create(size_t userMetadataSize);
+
+ // Imports an existing BufferHubMetadata from an ashmem FD.
+ //
+ // TODO(b/112338294): Refactor BufferHub to use Binder as its internal IPC backend instead of
+ // UDS.
+ //
+ // @param ashmemHandle Ashmem file handle representing an ashmem region.
+ static BufferHubMetadata Import(pdx::LocalHandle ashmemHandle);
+
+ BufferHubMetadata() = default;
+
+ BufferHubMetadata(BufferHubMetadata&& other) { *this = std::move(other); }
+
+ ~BufferHubMetadata();
+
+ BufferHubMetadata& operator=(BufferHubMetadata&& other) {
+ if (this != &other) {
+ mUserMetadataSize = other.mUserMetadataSize;
+ other.mUserMetadataSize = 0;
+
+ mAshmemHandle = std::move(other.mAshmemHandle);
+
+ // The old raw mMetadataHeader pointer must be cleared, otherwise the destructor will
+ // automatically mummap() the shared memory.
+ mMetadataHeader = other.mMetadataHeader;
+ other.mMetadataHeader = nullptr;
+ }
+ return *this;
+ }
+
+ // Returns true if the metadata is valid, i.e. the metadata has a valid ashmem fd and the ashmem
+ // has been mapped into virtual address space.
+ bool IsValid() const { return mAshmemHandle.IsValid() && mMetadataHeader != nullptr; }
+
+ size_t user_metadata_size() const { return mUserMetadataSize; }
+ size_t metadata_size() const { return mUserMetadataSize + BufferHubDefs::kMetadataHeaderSize; }
+
+ const pdx::LocalHandle& ashmem_handle() const { return mAshmemHandle; }
+ BufferHubDefs::MetadataHeader* metadata_header() { return mMetadataHeader; }
+
+private:
+ BufferHubMetadata(size_t userMetadataSize, pdx::LocalHandle ashmemHandle,
+ BufferHubDefs::MetadataHeader* metadataHeader);
+
+ BufferHubMetadata(const BufferHubMetadata&) = delete;
+ void operator=(const BufferHubMetadata&) = delete;
+
+ size_t mUserMetadataSize = 0;
+ pdx::LocalHandle mAshmemHandle;
+ BufferHubDefs::MetadataHeader* mMetadataHeader = nullptr;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_BUFFER_HUB_METADATA_H_
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index aef6428..6e73960 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -34,3 +34,11 @@
srcs: ["GraphicBuffer_test.cpp"],
cflags: ["-Wall", "-Werror"],
}
+
+cc_test {
+ name: "BufferHubMetadata_test",
+ header_libs: ["libbufferhub_headers", "libdvr_headers"],
+ shared_libs: ["libpdx_default_transport", "libui", "libutils"],
+ srcs: ["BufferHubMetadata_test.cpp"],
+ cflags: ["-Wall", "-Werror"],
+}
diff --git a/libs/vr/libbufferhub/buffer_hub_metadata-test.cpp b/libs/ui/tests/BufferHubMetadata_test.cpp
similarity index 97%
rename from libs/vr/libbufferhub/buffer_hub_metadata-test.cpp
rename to libs/ui/tests/BufferHubMetadata_test.cpp
index 8c1c01c..4209392 100644
--- a/libs/vr/libbufferhub/buffer_hub_metadata-test.cpp
+++ b/libs/ui/tests/BufferHubMetadata_test.cpp
@@ -15,7 +15,7 @@
*/
#include <gtest/gtest.h>
-#include <private/dvr/buffer_hub_metadata.h>
+#include <ui/BufferHubMetadata.h>
using android::dvr::BufferHubDefs::IsBufferGained;
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index d174d35..ba5cfcd 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -12,20 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+cc_library_headers {
+ name: "libbufferhub_headers",
+ export_include_dirs: ["include"],
+ vendor_available: true, // TODO(b/112338314): Does shouldn't be available to vendor.
+}
+
sourceFiles = [
"buffer_hub_base.cpp",
- "buffer_hub_metadata.cpp",
"buffer_hub_rpc.cpp",
"consumer_buffer.cpp",
- "detached_buffer.cpp",
"ion_buffer.cpp",
"producer_buffer.cpp",
]
-localIncludeFiles = [
- "include",
-]
-
sharedLibraries = [
"libbase",
"libbinder",
@@ -39,6 +39,7 @@
]
headerLibraries = [
+ "libbufferhub_headers",
"libdvr_headers",
"libnativebase_headers",
]
@@ -52,13 +53,16 @@
"-Wall",
"-Werror",
],
- export_include_dirs: localIncludeFiles,
shared_libs: sharedLibraries,
header_libs: headerLibraries,
name: "libbufferhub",
export_header_lib_headers: [
+ "libbufferhub_headers",
"libnativebase_headers",
],
+
+ // TODO(b/117568153): Temporarily opt out using libcrt.
+ no_libcrt: true,
}
cc_test {
@@ -67,12 +71,7 @@
shared_libs: sharedLibraries,
header_libs: headerLibraries,
name: "buffer_hub-test",
-}
-cc_test {
- srcs: ["buffer_hub_metadata-test.cpp"],
- static_libs: ["libbufferhub"],
- shared_libs: sharedLibraries,
- header_libs: headerLibraries,
- name: "buffer_hub_metadata-test",
+ // TODO(b/117568153): Temporarily opt out using libcrt.
+ no_libcrt: true,
}
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index a77dbf1..b477f1a 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -2,9 +2,9 @@
#include <poll.h>
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/bufferhub_rpc.h>
-#include <private/dvr/detached_buffer.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
+#include <ui/BufferHubBuffer.h>
#include <ui/DetachedBufferHandle.h>
#include <mutex>
@@ -19,10 +19,10 @@
return result; \
})()
+using android::BufferHubBuffer;
using android::GraphicBuffer;
using android::sp;
using android::dvr::ConsumerBuffer;
-using android::dvr::DetachedBuffer;
using android::dvr::ProducerBuffer;
using android::dvr::BufferHubDefs::IsBufferAcquired;
using android::dvr::BufferHubDefs::IsBufferGained;
@@ -41,7 +41,6 @@
const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
const int kUsage = 0;
const size_t kUserMetadataSize = 0;
-const uint64_t kContext = 42;
const size_t kMaxConsumerCount = 63;
const int kPollTimeoutMs = 100;
@@ -79,22 +78,19 @@
EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
- EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
+ EXPECT_EQ(0, p->Post(LocalHandle()));
// New state: producer not available, consumers available.
EXPECT_EQ(0, RETRY_EINTR(p->Poll(kPollTimeoutMs)));
EXPECT_EQ(1, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
- uint64_t context;
LocalHandle fence;
- EXPECT_EQ(0, c->Acquire(&fence, &context));
- EXPECT_EQ(kContext, context);
+ EXPECT_EQ(0, c->Acquire(&fence));
EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
EXPECT_EQ(1, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
- EXPECT_EQ(0, c2->Acquire(&fence, &context));
- EXPECT_EQ(kContext, context);
+ EXPECT_EQ(0, c2->Acquire(&fence));
EXPECT_EQ(0, RETRY_EINTR(c2->Poll(kPollTimeoutMs)));
EXPECT_EQ(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
@@ -147,7 +143,7 @@
ASSERT_EQ(0, epoll_wait(epoll_fd.Get(), events.data(), events.size(), 0));
// Post the producer and check for consumer signal.
- EXPECT_EQ(0, p->Post({}, kContext));
+ EXPECT_EQ(0, p->Post({}));
ASSERT_EQ(1, epoll_wait(epoll_fd.Get(), events.data(), events.size(),
kPollTimeoutMs));
ASSERT_TRUE(events[0].events & EPOLLIN);
@@ -229,10 +225,10 @@
EXPECT_EQ(-EALREADY, p->Gain(&fence));
// Post in gained state should succeed.
- EXPECT_EQ(0, p->Post(LocalHandle(), kContext));
+ EXPECT_EQ(0, p->Post(LocalHandle()));
// Post, release, and gain in posted state should fail.
- EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
+ EXPECT_EQ(-EBUSY, p->Post(LocalHandle()));
EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
EXPECT_EQ(-EBUSY, p->Gain(&fence));
@@ -241,7 +237,7 @@
// Acquire, post, and gain in acquired state should fail.
EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
- EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
+ EXPECT_EQ(-EBUSY, p->Post(LocalHandle()));
EXPECT_EQ(-EBUSY, p->Gain(&fence));
// Release in acquired state should succeed.
@@ -251,7 +247,7 @@
// Release, acquire, and post in released state should fail.
EXPECT_EQ(-EBUSY, c->Release(LocalHandle()));
EXPECT_EQ(-EBUSY, c->Acquire(&fence, &context));
- EXPECT_EQ(-EBUSY, p->Post(LocalHandle(), kContext));
+ EXPECT_EQ(-EBUSY, p->Post(LocalHandle()));
// Gain in released state should succeed.
EXPECT_EQ(0, p->Gain(&fence));
@@ -490,17 +486,14 @@
std::unique_ptr<ConsumerBuffer> c =
ConsumerBuffer::Import(p->CreateConsumer());
ASSERT_TRUE(c.get() != nullptr);
-
Metadata m = {1, 3};
- EXPECT_EQ(0, p->Post(LocalHandle(), m));
+ EXPECT_EQ(0, p->Post(LocalHandle(), &m, sizeof(Metadata)));
EXPECT_LE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
-
LocalHandle fence;
Metadata m2 = {};
EXPECT_EQ(0, c->Acquire(&fence, &m2));
EXPECT_EQ(m.field1, m2.field1);
EXPECT_EQ(m.field2, m2.field2);
-
EXPECT_EQ(0, c->Release(LocalHandle()));
EXPECT_LT(0, RETRY_EINTR(p->Poll(0)));
}
@@ -525,13 +518,12 @@
// It is illegal to post metadata larger than originally requested during
// buffer allocation.
OverSizedMetadata evil_meta = {};
- EXPECT_NE(0, p->Post(LocalHandle(), evil_meta));
+ EXPECT_NE(0, p->Post(LocalHandle(), &evil_meta, sizeof(OverSizedMetadata)));
EXPECT_GE(0, RETRY_EINTR(c->Poll(kPollTimeoutMs)));
// It is ok to post metadata smaller than originally requested during
// buffer allocation.
- int64_t sequence = 42;
- EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
+ EXPECT_EQ(0, p->Post(LocalHandle()));
}
TEST_F(LibBufferHubTest, TestAcquireWithWrongMetaSize) {
@@ -552,7 +544,7 @@
ASSERT_TRUE(c.get() != nullptr);
Metadata m = {1, 3};
- EXPECT_EQ(0, p->Post(LocalHandle(), m));
+ EXPECT_EQ(0, p->Post(LocalHandle(), &m, sizeof(m)));
LocalHandle fence;
int64_t sequence;
@@ -577,7 +569,7 @@
ASSERT_TRUE(c.get() != nullptr);
int64_t sequence = 3;
- EXPECT_EQ(0, p->Post(LocalHandle(), sequence));
+ EXPECT_EQ(0, p->Post(LocalHandle(), &sequence, sizeof(sequence)));
LocalHandle fence;
EXPECT_EQ(0, c->Acquire(&fence));
@@ -606,7 +598,7 @@
ASSERT_TRUE(c.get() != nullptr);
int64_t sequence = 3;
- EXPECT_NE(0, p->Post(LocalHandle(), sequence));
+ EXPECT_NE(0, p->Post(LocalHandle(), &sequence, sizeof(sequence)));
}
namespace {
@@ -792,8 +784,9 @@
// is gone.
EXPECT_EQ(s3.error(), EPIPE);
- // Detached buffer handle can be use to construct a new DetachedBuffer object.
- auto d = DetachedBuffer::Import(std::move(handle));
+ // Detached buffer handle can be use to construct a new BufferHubBuffer
+ // object.
+ auto d = BufferHubBuffer::Import(std::move(handle));
EXPECT_FALSE(handle.valid());
EXPECT_TRUE(d->IsConnected());
EXPECT_TRUE(d->IsValid());
@@ -801,17 +794,17 @@
EXPECT_EQ(d->id(), p_id);
}
-TEST_F(LibBufferHubTest, TestCreateDetachedBufferFails) {
+TEST_F(LibBufferHubTest, TestCreateBufferHubBufferFails) {
// Buffer Creation will fail: BLOB format requires height to be 1.
- auto b1 = DetachedBuffer::Create(kWidth, /*height=2*/ 2, kLayerCount,
- /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage,
- kUserMetadataSize);
+ auto b1 = BufferHubBuffer::Create(kWidth, /*height=2*/ 2, kLayerCount,
+ /*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage,
+ kUserMetadataSize);
EXPECT_FALSE(b1->IsConnected());
EXPECT_FALSE(b1->IsValid());
// Buffer Creation will fail: user metadata size too large.
- auto b2 = DetachedBuffer::Create(
+ auto b2 = BufferHubBuffer::Create(
kWidth, kHeight, kLayerCount, kFormat, kUsage,
/*user_metadata_size=*/std::numeric_limits<size_t>::max());
@@ -819,7 +812,7 @@
EXPECT_FALSE(b2->IsValid());
// Buffer Creation will fail: user metadata size too large.
- auto b3 = DetachedBuffer::Create(
+ auto b3 = BufferHubBuffer::Create(
kWidth, kHeight, kLayerCount, kFormat, kUsage,
/*user_metadata_size=*/std::numeric_limits<size_t>::max() -
kMetadataHeaderSize);
@@ -828,20 +821,20 @@
EXPECT_FALSE(b3->IsValid());
}
-TEST_F(LibBufferHubTest, TestCreateDetachedBuffer) {
- auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
- kUsage, kUserMetadataSize);
+TEST_F(LibBufferHubTest, TestCreateBufferHubBuffer) {
+ auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, kUserMetadataSize);
EXPECT_TRUE(b1->IsConnected());
EXPECT_TRUE(b1->IsValid());
EXPECT_NE(b1->id(), 0);
}
-TEST_F(LibBufferHubTest, TestPromoteDetachedBuffer) {
+TEST_F(LibBufferHubTest, TestPromoteBufferHubBuffer) {
// TODO(b/112338294) rewrite test after migration
return;
- auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
- kUsage, kUserMetadataSize);
+ auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, kUserMetadataSize);
int b1_id = b1->id();
EXPECT_TRUE(b1->IsValid());
@@ -887,8 +880,9 @@
LocalChannelHandle h1 = status_or_handle.take();
EXPECT_TRUE(h1.valid());
- // Detached buffer handle can be use to construct a new DetachedBuffer object.
- auto b1 = DetachedBuffer::Import(std::move(h1));
+ // Detached buffer handle can be use to construct a new BufferHubBuffer
+ // object.
+ auto b1 = BufferHubBuffer::Import(std::move(h1));
EXPECT_FALSE(h1.valid());
EXPECT_TRUE(b1->IsValid());
int b1_id = b1->id();
@@ -915,9 +909,9 @@
EXPECT_TRUE(IsBufferGained(p2->buffer_state()));
}
-TEST_F(LibBufferHubTest, TestDuplicateDetachedBuffer) {
- auto b1 = DetachedBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
- kUsage, kUserMetadataSize);
+TEST_F(LibBufferHubTest, TestDuplicateBufferHubBuffer) {
+ auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, kUserMetadataSize);
int b1_id = b1->id();
EXPECT_TRUE(b1->IsValid());
EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
@@ -933,7 +927,7 @@
LocalChannelHandle h2 = status_or_handle.take();
EXPECT_TRUE(h2.valid());
- std::unique_ptr<DetachedBuffer> b2 = DetachedBuffer::Import(std::move(h2));
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(std::move(h2));
EXPECT_FALSE(h2.valid());
ASSERT_TRUE(b2 != nullptr);
EXPECT_TRUE(b2->IsValid());
diff --git a/libs/vr/libbufferhub/buffer_hub_base.cpp b/libs/vr/libbufferhub/buffer_hub_base.cpp
index 2746dfb..bc6aece 100644
--- a/libs/vr/libbufferhub/buffer_hub_base.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_base.cpp
@@ -216,10 +216,6 @@
return ret;
}
-int BufferHubBase::GetBlobReadOnlyPointer(size_t size, void** addr) {
- return GetBlobReadWritePointer(size, addr);
-}
-
void BufferHubBase::GetBlobFds(int* fds, size_t* fds_count,
size_t max_fds_count) const {
size_t numFds = static_cast<size_t>(native_handle()->numFds);
diff --git a/libs/vr/libbufferhub/buffer_hub_metadata.cpp b/libs/vr/libbufferhub/buffer_hub_metadata.cpp
deleted file mode 100644
index 788c22c..0000000
--- a/libs/vr/libbufferhub/buffer_hub_metadata.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <sys/mman.h>
-
-#include <cutils/ashmem.h>
-#include <log/log.h>
-#include <private/dvr/buffer_hub_metadata.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-static const int kAshmemProt = PROT_READ | PROT_WRITE;
-
-} // namespace
-
-using BufferHubDefs::kMetadataHeaderSize;
-using BufferHubDefs::MetadataHeader;
-
-/* static */
-BufferHubMetadata BufferHubMetadata::Create(size_t user_metadata_size) {
- // The size the of metadata buffer is used as the "width" parameter during
- // allocation. Thus it cannot overflow uint32_t.
- if (user_metadata_size >=
- (std::numeric_limits<uint32_t>::max() - kMetadataHeaderSize)) {
- ALOGE("BufferHubMetadata::Create: metadata size too big: %zu.",
- user_metadata_size);
- return {};
- }
-
- const size_t metadata_size = user_metadata_size + kMetadataHeaderSize;
- int fd = ashmem_create_region(/*name=*/"BufferHubMetadata", metadata_size);
- if (fd < 0) {
- ALOGE("BufferHubMetadata::Create: failed to create ashmem region.");
- return {};
- }
-
- // Hand over the ownership of the fd to a pdx::LocalHandle immediately after
- // the successful return of ashmem_create_region. The ashmem_handle is going
- // to own the fd and to prevent fd leaks during error handling.
- pdx::LocalHandle ashmem_handle{fd};
-
- if (ashmem_set_prot_region(ashmem_handle.Get(), kAshmemProt) != 0) {
- ALOGE("BufferHubMetadata::Create: failed to set protect region.");
- return {};
- }
-
- return BufferHubMetadata::Import(std::move(ashmem_handle));
-}
-
-/* static */
-BufferHubMetadata BufferHubMetadata::Import(pdx::LocalHandle ashmem_handle) {
- if (!ashmem_valid(ashmem_handle.Get())) {
- ALOGE("BufferHubMetadata::Import: invalid ashmem fd.");
- return {};
- }
-
- size_t metadata_size = ashmem_get_size_region(ashmem_handle.Get());
- size_t user_metadata_size = metadata_size - kMetadataHeaderSize;
-
- // Note that here the buffer state is mapped from shared memory as an atomic
- // object. The std::atomic's constructor will not be called so that the
- // original value stored in the memory region can be preserved.
- auto metadata_header = static_cast<MetadataHeader*>(
- mmap(nullptr, metadata_size, kAshmemProt, MAP_SHARED, ashmem_handle.Get(),
- /*offset=*/0));
- if (metadata_header == nullptr) {
- ALOGE("BufferHubMetadata::Import: failed to map region.");
- return {};
- }
-
- return BufferHubMetadata(user_metadata_size, std::move(ashmem_handle),
- metadata_header);
-}
-
-BufferHubMetadata::BufferHubMetadata(size_t user_metadata_size,
- pdx::LocalHandle ashmem_handle,
- MetadataHeader* metadata_header)
- : user_metadata_size_(user_metadata_size),
- ashmem_handle_(std::move(ashmem_handle)),
- metadata_header_(metadata_header) {}
-
-BufferHubMetadata::~BufferHubMetadata() {
- if (metadata_header_ != nullptr) {
- int ret = munmap(metadata_header_, metadata_size());
- ALOGE_IF(ret != 0,
- "BufferHubMetadata::~BufferHubMetadata: failed to unmap ashmem, "
- "error=%d.",
- errno);
- metadata_header_ = nullptr;
- }
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libbufferhub/detached_buffer.cpp b/libs/vr/libbufferhub/detached_buffer.cpp
deleted file mode 100644
index 795ad19..0000000
--- a/libs/vr/libbufferhub/detached_buffer.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-#include <pdx/default_transport/client_channel.h>
-#include <pdx/default_transport/client_channel_factory.h>
-#include <pdx/file_handle.h>
-#include <private/dvr/bufferhub_rpc.h>
-#include <private/dvr/detached_buffer.h>
-#include <ui/DetachedBufferHandle.h>
-
-#include <poll.h>
-
-using android::pdx::LocalChannelHandle;
-using android::pdx::LocalHandle;
-using android::pdx::Status;
-using android::pdx::default_transport::ClientChannel;
-using android::pdx::default_transport::ClientChannelFactory;
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-// TODO(b/112338294): Remove this string literal after refactoring BufferHub
-// to use Binder.
-static constexpr char kBufferHubClientPath[] = "system/buffer_hub/client";
-
-} // namespace
-
-BufferHubClient::BufferHubClient()
- : Client(ClientChannelFactory::Create(kBufferHubClientPath)) {}
-
-BufferHubClient::BufferHubClient(LocalChannelHandle channel_handle)
- : Client(ClientChannel::Create(std::move(channel_handle))) {}
-
-bool BufferHubClient::IsValid() const {
- return IsConnected() && GetChannelHandle().valid();
-}
-
-LocalChannelHandle BufferHubClient::TakeChannelHandle() {
- if (IsConnected()) {
- return std::move(GetChannelHandle());
- } else {
- return {};
- }
-}
-
-DetachedBuffer::DetachedBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage, size_t user_metadata_size) {
- ATRACE_NAME("DetachedBuffer::DetachedBuffer");
- ALOGD_IF(TRACE,
- "DetachedBuffer::DetachedBuffer: width=%u height=%u layer_count=%u, "
- "format=%u usage=%" PRIx64 " user_metadata_size=%zu",
- width, height, layer_count, format, usage, user_metadata_size);
-
- auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Create>(
- width, height, layer_count, format, usage, user_metadata_size);
- if (!status) {
- ALOGE(
- "DetachedBuffer::DetachedBuffer: Failed to create detached buffer: %s",
- status.GetErrorMessage().c_str());
- client_.Close(-status.error());
- }
-
- const int ret = ImportGraphicBuffer();
- if (ret < 0) {
- ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
- strerror(-ret));
- client_.Close(ret);
- }
-}
-
-DetachedBuffer::DetachedBuffer(LocalChannelHandle channel_handle)
- : client_(std::move(channel_handle)) {
- const int ret = ImportGraphicBuffer();
- if (ret < 0) {
- ALOGE("DetachedBuffer::DetachedBuffer: Failed to import buffer: %s",
- strerror(-ret));
- client_.Close(ret);
- }
-}
-
-int DetachedBuffer::ImportGraphicBuffer() {
- ATRACE_NAME("DetachedBuffer::ImportGraphicBuffer");
-
- auto status = client_.InvokeRemoteMethod<DetachedBufferRPC::Import>();
- if (!status) {
- ALOGE("DetachedBuffer::DetachedBuffer: Failed to import GraphicBuffer: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- }
-
- BufferTraits<LocalHandle> buffer_traits = status.take();
- if (buffer_traits.id() < 0) {
- ALOGE("DetachedBuffer::DetachedBuffer: Received an invalid id!");
- return -EIO;
- }
-
- // Stash the buffer id to replace the value in id_.
- const int buffer_id = buffer_traits.id();
-
- // Import the metadata.
- metadata_ = BufferHubMetadata::Import(buffer_traits.take_metadata_handle());
-
- if (!metadata_.IsValid()) {
- ALOGE("DetachedBuffer::ImportGraphicBuffer: invalid metadata.");
- return -ENOMEM;
- }
-
- if (metadata_.metadata_size() != buffer_traits.metadata_size()) {
- ALOGE(
- "DetachedBuffer::ImportGraphicBuffer: metadata buffer too small: "
- "%zu, expected: %" PRIu64 ".",
- metadata_.metadata_size(), buffer_traits.metadata_size());
- return -ENOMEM;
- }
-
- size_t metadata_buf_size = buffer_traits.metadata_size();
- if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
- ALOGE("DetachedBuffer::ImportGraphicBuffer: metadata too small: %zu",
- metadata_buf_size);
- return -EINVAL;
- }
-
- // Import the buffer: We only need to hold on the native_handle_t here so that
- // GraphicBuffer instance can be created in future.
- buffer_handle_ = buffer_traits.take_buffer_handle();
-
- // If all imports succeed, replace the previous buffer and id.
- id_ = buffer_id;
- buffer_state_bit_ = buffer_traits.buffer_state_bit();
-
- // TODO(b/112012161) Set up shared fences.
- ALOGD_IF(TRACE,
- "DetachedBuffer::ImportGraphicBuffer: id=%d, buffer_state=%" PRIx64
- ".",
- id(),
- metadata_.metadata_header()->buffer_state.load(
- std::memory_order_acquire));
- return 0;
-}
-
-int DetachedBuffer::Poll(int timeout_ms) {
- ATRACE_NAME("DetachedBuffer::Poll");
- pollfd p = {client_.event_fd(), POLLIN, 0};
- return poll(&p, 1, timeout_ms);
-}
-
-Status<LocalChannelHandle> DetachedBuffer::Promote() {
- // TODO(b/112338294) remove after migrate producer buffer to binder
- ALOGW("DetachedBuffer::Promote: not supported operation during migration");
- return {};
-
- ATRACE_NAME("DetachedBuffer::Promote");
- ALOGD_IF(TRACE, "DetachedBuffer::Promote: id=%d.", id_);
-
- auto status_or_handle =
- client_.InvokeRemoteMethod<DetachedBufferRPC::Promote>();
- if (status_or_handle.ok()) {
- // Invalidate the buffer.
- buffer_handle_ = {};
- } else {
- ALOGE("DetachedBuffer::Promote: Failed to promote buffer (id=%d): %s.", id_,
- status_or_handle.GetErrorMessage().c_str());
- }
- return status_or_handle;
-}
-
-Status<LocalChannelHandle> DetachedBuffer::Duplicate() {
- ATRACE_NAME("DetachedBuffer::Duplicate");
- ALOGD_IF(TRACE, "DetachedBuffer::Duplicate: id=%d.", id_);
-
- auto status_or_handle =
- client_.InvokeRemoteMethod<DetachedBufferRPC::Duplicate>();
-
- if (!status_or_handle.ok()) {
- ALOGE("DetachedBuffer::Duplicate: Failed to duplicate buffer (id=%d): %s.",
- id_, status_or_handle.GetErrorMessage().c_str());
- }
- return status_or_handle;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
index 0180462..282be46 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -39,11 +39,6 @@
// after calling this method.
int GetBlobReadWritePointer(size_t size, void** addr);
- // Gets a blob buffer that was created with ProducerBuffer::CreateBlob.
- // Locking and Unlocking is handled internally. There's no need to Unlock
- // after calling this method.
- int GetBlobReadOnlyPointer(size_t size, void** addr);
-
// Returns a dup'd file descriptor for accessing the blob shared memory. The
// caller takes ownership of the file descriptor and must close it or pass on
// ownership. Some GPU API extensions can take file descriptors to bind shared
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_metadata.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_metadata.h
deleted file mode 100644
index 980ade7..0000000
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_metadata.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_DVR_BUFFER_HUB_METADATA_H_
-#define ANDROID_DVR_BUFFER_HUB_METADATA_H_
-
-#include <pdx/file_handle.h>
-#include <private/dvr/buffer_hub_defs.h>
-
-namespace android {
-namespace dvr {
-
-class BufferHubMetadata {
- public:
- // Creates a new BufferHubMetadata backed by an ashmem region.
- //
- // @param user_metadata_size Size in bytes of the user defined metadata. The
- // entire metadata shared memory region to be allocated is the size of
- // canonical BufferHubDefs::MetadataHeader plus user_metadata_size.
- static BufferHubMetadata Create(size_t user_metadata_size);
-
- // Imports an existing BufferHubMetadata from an ashmem FD.
- //
- // TODO(b/112338294): Refactor BufferHub to use Binder as its internal IPC
- // backend instead of UDS.
- //
- // @param ashmem_handle Ashmem file handle representing an ashmem region.
- static BufferHubMetadata Import(pdx::LocalHandle ashmem_handle);
-
- BufferHubMetadata() = default;
-
- BufferHubMetadata(BufferHubMetadata&& other) { *this = std::move(other); }
-
- ~BufferHubMetadata();
-
- BufferHubMetadata& operator=(BufferHubMetadata&& other) {
- if (this != &other) {
- user_metadata_size_ = other.user_metadata_size_;
- other.user_metadata_size_ = 0;
-
- ashmem_handle_ = std::move(other.ashmem_handle_);
-
- // The old raw metadata_header_ pointer must be cleared, otherwise the
- // destructor will automatically mummap() the shared memory.
- metadata_header_ = other.metadata_header_;
- other.metadata_header_ = nullptr;
- }
- return *this;
- }
-
- // Returns true if the metadata is valid, i.e. the metadata has a valid ashmem
- // fd and the ashmem has been mapped into virtual address space.
- bool IsValid() const {
- return ashmem_handle_.IsValid() && metadata_header_ != nullptr;
- }
-
- size_t user_metadata_size() const { return user_metadata_size_; }
- size_t metadata_size() const {
- return user_metadata_size_ + BufferHubDefs::kMetadataHeaderSize;
- }
-
- const pdx::LocalHandle& ashmem_handle() const { return ashmem_handle_; }
- BufferHubDefs::MetadataHeader* metadata_header() { return metadata_header_; }
-
- private:
- BufferHubMetadata(size_t user_metadata_size, pdx::LocalHandle ashmem_handle,
- BufferHubDefs::MetadataHeader* metadata_header);
-
- BufferHubMetadata(const BufferHubMetadata&) = delete;
- void operator=(const BufferHubMetadata&) = delete;
-
- size_t user_metadata_size_ = 0;
- pdx::LocalHandle ashmem_handle_;
- BufferHubDefs::MetadataHeader* metadata_header_ = nullptr;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_BUFFER_HUB_METADATA_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h b/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
deleted file mode 100644
index ff61145..0000000
--- a/libs/vr/libbufferhub/include/private/dvr/detached_buffer.h
+++ /dev/null
@@ -1,123 +0,0 @@
-#ifndef ANDROID_DVR_DETACHED_BUFFER_H_
-#define ANDROID_DVR_DETACHED_BUFFER_H_
-
-#include <pdx/client.h>
-#include <private/dvr/buffer_hub_defs.h>
-#include <private/dvr/buffer_hub_metadata.h>
-#include <private/dvr/ion_buffer.h>
-
-namespace android {
-namespace dvr {
-
-class BufferHubClient : public pdx::Client {
- public:
- BufferHubClient();
- explicit BufferHubClient(pdx::LocalChannelHandle channel_handle);
-
- bool IsValid() const;
- pdx::LocalChannelHandle TakeChannelHandle();
-
- using pdx::Client::Close;
- using pdx::Client::event_fd;
- using pdx::Client::GetChannel;
- using pdx::Client::InvokeRemoteMethod;
-};
-
-class DetachedBuffer {
- public:
- // Allocates a standalone DetachedBuffer not associated with any producer
- // consumer set.
- static std::unique_ptr<DetachedBuffer> Create(uint32_t width, uint32_t height,
- uint32_t layer_count,
- uint32_t format, uint64_t usage,
- size_t user_metadata_size) {
- return std::unique_ptr<DetachedBuffer>(new DetachedBuffer(
- width, height, layer_count, format, usage, user_metadata_size));
- }
-
- // Imports the given channel handle to a DetachedBuffer, taking ownership.
- static std::unique_ptr<DetachedBuffer> Import(
- pdx::LocalChannelHandle channel_handle) {
- return std::unique_ptr<DetachedBuffer>(
- new DetachedBuffer(std::move(channel_handle)));
- }
-
- DetachedBuffer(const DetachedBuffer&) = delete;
- void operator=(const DetachedBuffer&) = delete;
-
- // Gets ID of the buffer client. All DetachedBuffer clients derived from the
- // same buffer in bufferhubd share the same buffer id.
- int id() const { return id_; }
-
- const native_handle_t* DuplicateHandle() {
- return buffer_handle_.DuplicateHandle();
- }
-
- // Returns the current value of MetadataHeader::buffer_state.
- uint64_t buffer_state() {
- return metadata_.metadata_header()->buffer_state.load(
- std::memory_order_acquire);
- }
-
- // A state mask which is unique to a buffer hub client among all its siblings
- // sharing the same concrete graphic buffer.
- uint64_t buffer_state_bit() const { return buffer_state_bit_; }
-
- size_t user_metadata_size() const { return metadata_.user_metadata_size(); }
-
- // Returns true if the buffer holds an open PDX channels towards bufferhubd.
- bool IsConnected() const { return client_.IsValid(); }
-
- // Returns true if the buffer holds an valid native buffer handle that's
- // availble for the client to read from and/or write into.
- bool IsValid() const { return buffer_handle_.IsValid(); }
-
- // Returns the event mask for all the events that are pending on this buffer
- // (see sys/poll.h for all possible bits).
- pdx::Status<int> GetEventMask(int events) {
- if (auto* channel = client_.GetChannel()) {
- return channel->GetEventMask(events);
- } else {
- return pdx::ErrorStatus(EINVAL);
- }
- }
-
- // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
- int Poll(int timeout_ms);
-
- // Promotes a DetachedBuffer to become a ProducerBuffer. Once promoted the
- // DetachedBuffer channel will be closed automatically on successful IPC
- // return. Further IPCs towards this channel will return error.
- pdx::Status<pdx::LocalChannelHandle> Promote();
-
- // Creates a DetachedBuffer client from an existing one. The new client will
- // share the same underlying gralloc buffer and ashmem region for metadata.
- pdx::Status<pdx::LocalChannelHandle> Duplicate();
-
- private:
- DetachedBuffer(uint32_t width, uint32_t height, uint32_t layer_count,
- uint32_t format, uint64_t usage, size_t user_metadata_size);
-
- DetachedBuffer(pdx::LocalChannelHandle channel_handle);
-
- int ImportGraphicBuffer();
-
- // Global id for the buffer that is consistent across processes.
- int id_;
- uint64_t buffer_state_bit_;
-
- // Wrapps the gralloc buffer handle of this buffer.
- NativeHandleWrapper<pdx::LocalHandle> buffer_handle_;
-
- // An ashmem-based metadata object. The same shared memory are mapped to the
- // bufferhubd daemon and all buffer clients.
- BufferHubMetadata metadata_;
-
- // PDX backend.
- BufferHubClient client_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_DETACHED_BUFFER_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
index b5e1c5b..d2d4d1e 100644
--- a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
@@ -50,12 +50,6 @@
return Post(ready_fence, nullptr, 0);
}
- template <typename Meta, typename = typename std::enable_if<
- !std::is_void<Meta>::value>::type>
- int Post(const LocalHandle& ready_fence, const Meta& meta) {
- return Post(ready_fence, &meta, sizeof(meta));
- }
-
// Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
// must be waited on before using the buffer. If it is not valid then the
// buffer is free for immediate use. This call will only succeed if the buffer
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 9f72c05..20894e3 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -59,6 +59,9 @@
static_libs: staticLibraries,
shared_libs: sharedLibraries,
header_libs: headerLibraries,
+
+ // TODO(b/117568153): Temporarily opt out using libcrt.
+ no_libcrt: true,
}
subdirs = ["benchmarks", "tests"]
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index 3260447..357dffe 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -49,6 +49,9 @@
"-g",
],
name: "dvr_api-test",
+
+ // TODO(b/117568153): Temporarily opt out using libcrt.
+ no_libcrt: true,
}
cc_test {
diff --git a/libs/vr/libvrflinger/tests/vrflinger_test.cpp b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
index e1c7adb..1d5740f 100644
--- a/libs/vr/libvrflinger/tests/vrflinger_test.cpp
+++ b/libs/vr/libvrflinger/tests/vrflinger_test.cpp
@@ -218,10 +218,7 @@
ASSERT_GE(buffer.get()->Unlock(), 0);
- ASSERT_GE(buffer.get()->Post(/*ready_fence=*/pdx::LocalHandle(),
- /*meta=*/nullptr,
- /*user_metadata_size=*/0),
- 0);
+ ASSERT_GE(buffer.get()->Post(/*ready_fence=*/pdx::LocalHandle()), 0);
ASSERT_EQ(
surface_flinger_connection->WaitForVrFlinger(/*wait_active=*/true),
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index 4acc085..710d75a 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -228,7 +228,7 @@
}
constexpr size_t size = DvrVsyncPoseBuffer::kSize * sizeof(DvrPoseAsync);
void* addr = nullptr;
- int ret = buffer->GetBlobReadOnlyPointer(size, &addr);
+ int ret = buffer->GetBlobReadWritePointer(size, &addr);
if (ret < 0 || !addr) {
ALOGE("Pose failed to map ring buffer: ret:%d, addr:%p", ret, addr);
return -EIO;
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 5aa03a7..cd227ca 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -274,6 +274,7 @@
void Loader::init_api(void* dso,
char const * const * api,
+ char const * const * ref_api,
__eglMustCastToProperFunctionPointerType* curr,
getProcAddressType getProcAddress)
{
@@ -283,6 +284,15 @@
char scrap[SIZE];
while (*api) {
char const * name = *api;
+ if (ref_api) {
+ char const * ref_name = *ref_api;
+ if (std::strcmp(name, ref_name) != 0) {
+ *curr++ = nullptr;
+ ref_api++;
+ continue;
+ }
+ }
+
__eglMustCastToProperFunctionPointerType f =
(__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
if (f == nullptr) {
@@ -327,6 +337,7 @@
}
*curr++ = f;
api++;
+ if (ref_api) ref_api++;
}
}
@@ -670,14 +681,14 @@
}
if (mask & GLESv1_CM) {
- init_api(dso, gl_names,
+ init_api(dso, gl_names_1, gl_names,
(__eglMustCastToProperFunctionPointerType*)
&cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
getProcAddress);
}
if (mask & GLESv2) {
- init_api(dso, gl_names,
+ init_api(dso, gl_names, nullptr,
(__eglMustCastToProperFunctionPointerType*)
&cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
getProcAddress);
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 93c33a8..9cc73f3 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -29,7 +29,7 @@
class Loader {
typedef __eglMustCastToProperFunctionPointerType (* getProcAddressType)(const char*);
-
+
enum {
EGL = 0x01,
GLESv1_CM = 0x02,
@@ -43,25 +43,26 @@
int set(void* hnd, int32_t api);
void* dso[3];
};
-
+
getProcAddressType getProcAddress;
public:
static Loader& getInstance();
~Loader();
-
+
void* open(egl_connection_t* cnx);
void close(void* driver);
-
+
private:
Loader();
void *load_driver(const char* kind, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))
- void init_api(void* dso,
- char const * const * api,
- __eglMustCastToProperFunctionPointerType* curr,
- getProcAddressType getProcAddress);
+ void init_api(void* dso,
+ char const * const * api,
+ char const * const * ref_api,
+ __eglMustCastToProperFunctionPointerType* curr,
+ getProcAddressType getProcAddress);
};
// ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 01795e0..8870d5f 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -263,6 +263,11 @@
nullptr
};
+char const * const gl_names_1[] = {
+ #include "../entries_gles1.in"
+ nullptr
+};
+
char const * const egl_names[] = {
#include "egl_entries.in"
nullptr
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 1a88678..d8606d3 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -66,6 +66,7 @@
extern "C" void gl_noop();
extern char const * const gl_names[];
+extern char const * const gl_names_1[];
extern char const * const egl_names[];
extern char const * const platform_names[];
diff --git a/opengl/libs/entries_gles1.in b/opengl/libs/entries_gles1.in
new file mode 100644
index 0000000..c9be593
--- /dev/null
+++ b/opengl/libs/entries_gles1.in
@@ -0,0 +1,298 @@
+GL_ENTRY(void, glActiveTexture, GLenum texture)
+GL_ENTRY(void, glAlphaFunc, GLenum func, GLfloat ref)
+GL_ENTRY(void, glAlphaFuncx, GLenum func, GLfixed ref)
+GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLfixed ref)
+GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
+GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
+GL_ENTRY(void, glBindRenderbufferOES, GLenum target, GLuint renderbuffer)
+GL_ENTRY(void, glBindTexture, GLenum target, GLuint texture)
+GL_ENTRY(void, glBindVertexArrayOES, GLuint array)
+GL_ENTRY(void, glBlendEquationOES, GLenum mode)
+GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
+GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
+GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
+GL_ENTRY(void, glClear, GLbitfield mask)
+GL_ENTRY(void, glClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glClearColorx, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glClearColorxOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glClearDepthf, GLfloat d)
+GL_ENTRY(void, glClearDepthfOES, GLclampf depth)
+GL_ENTRY(void, glClearDepthx, GLfixed depth)
+GL_ENTRY(void, glClearDepthxOES, GLfixed depth)
+GL_ENTRY(void, glClearStencil, GLint s)
+GL_ENTRY(void, glClientActiveTexture, GLenum texture)
+GL_ENTRY(GLenum, glClientWaitSyncAPPLE, GLsync sync, GLbitfield flags, GLuint64 timeout)
+GL_ENTRY(void, glClipPlanef, GLenum p, const GLfloat *eqn)
+GL_ENTRY(void, glClipPlanefIMG, GLenum p, const GLfloat *eqn)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexIMG, GLenum p, const GLfixed *eqn)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glCopyTextureLevelsAPPLE, GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount)
+GL_ENTRY(void, glCullFace, GLenum mode)
+GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint *framebuffers)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint *renderbuffers)
+GL_ENTRY(void, glDeleteSyncAPPLE, GLsync sync)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint *arrays)
+GL_ENTRY(void, glDepthFunc, GLenum func)
+GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangef, GLfloat n, GLfloat f)
+GL_ENTRY(void, glDepthRangefOES, GLclampf n, GLclampf f)
+GL_ENTRY(void, glDepthRangex, GLfixed n, GLfixed f)
+GL_ENTRY(void, glDepthRangexOES, GLfixed n, GLfixed f)
+GL_ENTRY(void, glDisable, GLenum cap)
+GL_ENTRY(void, glDisableClientState, GLenum array)
+GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum *attachments)
+GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void *indices)
+GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
+GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
+GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
+GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
+GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
+GL_ENTRY(void, glEnable, GLenum cap)
+GL_ENTRY(void, glEnableClientState, GLenum array)
+GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
+GL_ENTRY(void, glEndTilingQCOM, GLbitfield preserveMask)
+GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, void **params)
+GL_ENTRY(void, glExtGetBuffersQCOM, GLuint *buffers, GLint maxBuffers, GLint *numBuffers)
+GL_ENTRY(void, glExtGetFramebuffersQCOM, GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers)
+GL_ENTRY(void, glExtGetProgramBinarySourceQCOM, GLuint program, GLenum shadertype, GLchar *source, GLint *length)
+GL_ENTRY(void, glExtGetProgramsQCOM, GLuint *programs, GLint maxPrograms, GLint *numPrograms)
+GL_ENTRY(void, glExtGetRenderbuffersQCOM, GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers)
+GL_ENTRY(void, glExtGetShadersQCOM, GLuint *shaders, GLint maxShaders, GLint *numShaders)
+GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
+GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels)
+GL_ENTRY(void, glExtGetTexturesQCOM, GLuint *textures, GLint maxTextures, GLint *numTextures)
+GL_ENTRY(GLboolean, glExtIsProgramBinaryQCOM, GLuint program)
+GL_ENTRY(void, glExtTexObjectStateOverrideiQCOM, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(GLsync, glFenceSyncAPPLE, GLenum condition, GLbitfield flags)
+GL_ENTRY(void, glFinish, void)
+GL_ENTRY(void, glFinishFenceNV, GLuint fence)
+GL_ENTRY(void, glFlush, void)
+GL_ENTRY(void, glFlushMappedBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length)
+GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferTexture2DMultisampleEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
+GL_ENTRY(void, glFramebufferTexture2DMultisampleIMG, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
+GL_ENTRY(void, glFramebufferTexture2DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+GL_ENTRY(void, glFrontFace, GLenum mode)
+GL_ENTRY(void, glFrustumf, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
+GL_ENTRY(void, glFrustumfOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
+GL_ENTRY(void, glFrustumx, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
+GL_ENTRY(void, glFrustumxOES, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint *framebuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint *renderbuffers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint *arrays)
+GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *data)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void **params)
+GL_ENTRY(void, glGetClipPlanef, GLenum plane, GLfloat *equation)
+GL_ENTRY(void, glGetClipPlanefOES, GLenum plane, GLfloat *equation)
+GL_ENTRY(void, glGetClipPlanex, GLenum plane, GLfixed *equation)
+GL_ENTRY(void, glGetClipPlanexOES, GLenum plane, GLfixed *equation)
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
+GL_ENTRY(GLenum, glGetError, void)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *data)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint *params)
+GL_ENTRY(GLenum, glGetGraphicsResetStatusEXT, void)
+GL_ENTRY(void, glGetInteger64vAPPLE, GLenum pname, GLint64 *params)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *data)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(const GLubyte *, glGetString, GLenum name)
+GL_ENTRY(void, glGetSyncivAPPLE, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+GL_ENTRY(void, glGetTexEnvfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnviv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetnUniformfvEXT, GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+GL_ENTRY(void, glGetnUniformivEXT, GLuint program, GLint location, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glHint, GLenum target, GLenum mode)
+GL_ENTRY(void, glInsertEventMarkerEXT, GLsizei length, const GLchar *marker)
+GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
+GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
+GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsRenderbufferOES, GLuint renderbuffer)
+GL_ENTRY(GLboolean, glIsSyncAPPLE, GLsync sync)
+GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(GLboolean, glIsVertexArrayOES, GLuint array)
+GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLineWidth, GLfloat width)
+GL_ENTRY(void, glLineWidthx, GLfixed width)
+GL_ENTRY(void, glLineWidthxOES, GLfixed width)
+GL_ENTRY(void, glLoadIdentity, void)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
+GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void *, glMapBufferOES, GLenum target, GLenum access)
+GL_ENTRY(void *, glMapBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glMatrixMode, GLenum mode)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount)
+GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+GL_ENTRY(void, glMultiTexCoord4x, GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glMultiTexCoord4xOES, GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
+GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glOrthof, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
+GL_ENTRY(void, glOrthofOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
+GL_ENTRY(void, glOrthox, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
+GL_ENTRY(void, glOrthoxOES, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
+GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointSize, GLfloat size)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glPointSizex, GLfixed size)
+GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPopGroupMarkerEXT, void)
+GL_ENTRY(void, glPopMatrix, void)
+GL_ENTRY(void, glPushGroupMarkerEXT, GLsizei length, const GLchar *marker)
+GL_ENTRY(void, glPushMatrix, void)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed *mantissa, GLint *exponent)
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels)
+GL_ENTRY(void, glReadnPixelsEXT, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+GL_ENTRY(void, glRenderbufferStorageMultisampleAPPLE, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageMultisampleEXT, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageMultisampleIMG, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glResolveMultisampleFramebufferAPPLE, void)
+GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glSampleCoverage, GLfloat value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
+GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
+GL_ENTRY(void, glShadeModel, GLenum mode)
+GL_ENTRY(void, glStartTilingQCOM, GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask)
+GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glStencilMask, GLuint mask)
+GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
+GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
+GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
+GL_ENTRY(void, glTexStorage2DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glTexStorage3DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
+GL_ENTRY(void, glTextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glTextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
+GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
+GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glWaitSyncAPPLE, GLsync sync, GLbitfield flags, GLuint64 timeout)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const void *pointer)
diff --git a/opengl/tools/glgen2/glgen.py b/opengl/tools/glgen2/glgen.py
index fa981a8..86fa28f 100755
--- a/opengl/tools/glgen2/glgen.py
+++ b/opengl/tools/glgen2/glgen.py
@@ -250,6 +250,27 @@
for opts in TRAMPOLINE_OPTIONS:
registry.apiGen(opts)
+ # Generate a GLESv1_CM entries separately to avoid extra driver loading time
+ apigen = ApiGenerator()
+ registry.setGenerator(apigen)
+ API_OPTIONS = [
+ # Generate non-extension versions of each API first, then extensions,
+ # so that if an extension enum was later standardized, we see the non-
+ # suffixed version first.
+ reg.GeneratorOptions(
+ apiname = 'gles1',
+ profile = 'common'),
+ reg.GeneratorOptions(
+ apiname = 'gles1',
+ profile = 'common',
+ emitversions = None,
+ defaultExtensions = 'gles1')]
+ for opts in API_OPTIONS:
+ registry.apiGen(opts)
+ apigen.finish()
+ with open('../../libs/entries_gles1.in', 'w') as f:
+ apigen.writeEntries(f)
+
apigen = ApiGenerator()
registry.setGenerator(apigen)
API_OPTIONS = [
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 2bbfb1b..f75b0b6 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -340,7 +340,8 @@
mDisplayId = displayId;
}
- void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId) {
+ void consumeEvent(int32_t expectedEventType, int32_t expectedDisplayId,
+ int32_t expectedFlags = 0) {
uint32_t consumeSeq;
InputEvent* event;
status_t status = mConsumer->consume(&mEventFactory, false /*consumeBatches*/, -1,
@@ -351,10 +352,29 @@
ASSERT_TRUE(event != nullptr)
<< mName.c_str() << ": consumer should have returned non-NULL event.";
ASSERT_EQ(expectedEventType, event->getType())
- << mName.c_str() << ": consumer type should same as expected one.";
+ << mName.c_str() << ": event type should match.";
ASSERT_EQ(expectedDisplayId, event->getDisplayId())
- << mName.c_str() << ": consumer displayId should same as expected one.";
+ << mName.c_str() << ": event displayId should be the same as expected.";
+
+ int32_t flags;
+ switch (expectedEventType) {
+ case AINPUT_EVENT_TYPE_KEY: {
+ KeyEvent* typedEvent = static_cast<KeyEvent*>(event);
+ flags = typedEvent->getFlags();
+ break;
+ }
+ case AINPUT_EVENT_TYPE_MOTION: {
+ MotionEvent* typedEvent = static_cast<MotionEvent*>(event);
+ flags = typedEvent->getFlags();
+ break;
+ }
+ default: {
+ FAIL() << mName.c_str() << ": invalid event type: " << expectedEventType;
+ }
+ }
+ ASSERT_EQ(expectedFlags, flags)
+ << mName.c_str() << ": event flags should be the same as expected.";
status = mConsumer->sendFinishedSignal(consumeSeq, true /*handled*/);
ASSERT_EQ(OK, status)
@@ -556,8 +576,8 @@
mDispatcher->setInputWindows(inputWindowHandles_Second, SECOND_DISPLAY_ID);
// Expect old focus should receive a cancel event.
- windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE);
- // TODO(b/111361570): Validate that the event here was marked as canceled.
+ windowInSecondary->consumeEvent(AINPUT_EVENT_TYPE_KEY, ADISPLAY_ID_NONE,
+ AKEY_EVENT_FLAG_CANCELED);
// Test inject a key down, should timeout because of no target window.
ASSERT_EQ(INPUT_EVENT_INJECTION_TIMED_OUT, injectKeyDown(mDispatcher))
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index f499f06..8c8915c 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -98,54 +98,7 @@
mContentsChangedListener = listener;
}
-// We need to determine the time when a buffer acquired now will be
-// displayed. This can be calculated:
-// time when previous buffer's actual-present fence was signaled
-// + current display refresh rate * HWC latency
-// + a little extra padding
-//
-// Buffer producers are expected to set their desired presentation time
-// based on choreographer time stamps, which (coming from vsync events)
-// will be slightly later then the actual-present timing. If we get a
-// desired-present time that is unintentionally a hair after the next
-// vsync, we'll hold the frame when we really want to display it. We
-// need to take the offset between actual-present and reported-vsync
-// into account.
-//
-// If the system is configured without a DispSync phase offset for the app,
-// we also want to throw in a bit of padding to avoid edge cases where we
-// just barely miss. We want to do it here, not in every app. A major
-// source of trouble is the app's use of the display's ideal refresh time
-// (via Display.getRefreshRate()), which could be off of the actual refresh
-// by a few percent, with the error multiplied by the number of frames
-// between now and when the buffer should be displayed.
-//
-// If the refresh reported to the app has a phase offset, we shouldn't need
-// to tweak anything here.
-nsecs_t BufferLayerConsumer::computeExpectedPresent(const DispSync& dispSync) {
- // The HWC doesn't currently have a way to report additional latency.
- // Assume that whatever we submit now will appear right after the flip.
- // For a smart panel this might be 1. This is expressed in frames,
- // rather than time, because we expect to have a constant frame delay
- // regardless of the refresh rate.
- const uint32_t hwcLatency = 0;
-
- // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
- const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency);
-
- // The DispSync time is already adjusted for the difference between
- // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
- // we don't need to factor that in here. Pad a little to avoid
- // weird effects if apps might be requesting times right on the edge.
- nsecs_t extraPadding = 0;
- if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
- extraPadding = 1000000; // 1ms (6% of 60Hz)
- }
-
- return nextRefresh + extraPadding;
-}
-
-status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
+status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
bool* autoRefresh, bool* queuedBuffer,
uint64_t maxFrameNumber,
const sp<Fence>& releaseFence) {
@@ -169,7 +122,7 @@
// Acquire the next buffer.
// In asynchronous mode the list is guaranteed to be one buffer
// deep, while in synchronous mode we use the oldest buffer.
- status_t err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber);
+ status_t err = acquireBufferLocked(&item, expectedPresentTime, maxFrameNumber);
if (err != NO_ERROR) {
if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
err = NO_ERROR;
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index dc00487..e174680 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -80,8 +80,6 @@
// ConsumerBase::setFrameAvailableListener().
void setContentsChangedListener(const wp<ContentsChangedListener>& listener);
- nsecs_t computeExpectedPresent(const DispSync& dispSync);
-
// updateTexImage acquires the most recently queued buffer, and sets the
// image contents of the target texture to it.
//
@@ -93,8 +91,8 @@
// Unlike the GLConsumer version, this version takes a functor that may be
// used to reject the newly acquired buffer. It also does not bind the
// RenderEngine texture until bindTextureImage is called.
- status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync, bool* autoRefresh,
- bool* queuedBuffer, uint64_t maxFrameNumber,
+ status_t updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
+ bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber,
const sp<Fence>& releaseFence);
// See BufferLayerConsumer::bindTextureImageLocked().
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 6822298..ab9a2f8 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -79,7 +79,7 @@
return mQueuedFrames;
}
-bool BufferQueueLayer::shouldPresentNow(const DispSync& dispSync) const {
+bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
if (getSidebandStreamChanged() || getAutoRefresh()) {
return true;
}
@@ -91,7 +91,6 @@
Mutex::Autolock lock(mQueueItemLock);
const int64_t addedTime = mQueueItems[0].mTimestamp;
- const nsecs_t expectedPresentTime = mConsumer->computeExpectedPresent(dispSync);
// Ignore timestamps more than a second in the future
const bool isPlausible = addedTime < (expectedPresentTime + s2ns(1));
@@ -232,8 +231,9 @@
getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
getTransformToDisplayInverse(), mFreezeGeometryUpdates);
status_t updateResult =
- mConsumer->updateTexImage(&r, *mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived, releaseFence);
+ mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync->expectedPresentTime(),
+ &mAutoRefresh, &queuedBuffer, mLastFrameNumberReceived,
+ releaseFence);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index dcf39ee..c239a00 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -55,7 +55,7 @@
int32_t getQueuedFrameCount() const override;
- bool shouldPresentNow(const DispSync& dispSync) const override;
+ bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 2ecf71c..c817fb0 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -56,7 +56,7 @@
return;
}
-bool BufferStateLayer::shouldPresentNow(const DispSync& /*dispSync*/) const {
+bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {
if (getSidebandStreamChanged() || getAutoRefresh()) {
return true;
}
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index db11110..b134fc5 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -39,7 +39,7 @@
void setTransformHint(uint32_t orientation) const override;
void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
- bool shouldPresentNow(const DispSync& dispSync) const override;
+ bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
bool getTransformToDisplayInverse() const override;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 3eb8327..e2d1178 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -395,7 +395,7 @@
virtual void abandon() {}
- virtual bool shouldPresentNow(const DispSync& /*dispSync*/) const { return false; }
+ virtual bool shouldPresentNow(nsecs_t /*expectedPresentTime*/) const { return false; }
virtual void setTransformHint(uint32_t /*orientation*/) const { }
/*
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 54a1b51..cba9181 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -44,10 +44,6 @@
namespace impl {
-// Setting this to true enables verbose tracing that can be used to debug
-// vsync event model or phase issues.
-static const bool kTraceDetailedInfo = false;
-
// Setting this to true adds a zero-phase tracer for correlating with hardware
// vsync events
static const bool kEnableZeroPhaseTracer = false;
@@ -62,19 +58,20 @@
#define LOG_TAG "DispSyncThread"
class DispSyncThread : public Thread {
public:
- explicit DispSyncThread(const char* name)
+ DispSyncThread(const char* name, bool showTraceDetailedInfo)
: mName(name),
mStop(false),
mPeriod(0),
mPhase(0),
mReferenceTime(0),
mWakeupLatency(0),
- mFrameNumber(0) {}
+ mFrameNumber(0),
+ mTraceDetailedInfo(showTraceDetailedInfo) {}
virtual ~DispSyncThread() {}
void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mPeriod = period;
mPhase = phase;
@@ -86,7 +83,7 @@
}
void stop() {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
mStop = true;
mCond.signal();
@@ -104,7 +101,7 @@
{ // Scope for lock
Mutex::Autolock lock(mMutex);
- if (kTraceDetailedInfo) {
+ if (mTraceDetailedInfo) {
ATRACE_INT64("DispSync:Frame", mFrameNumber);
}
ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
@@ -128,7 +125,7 @@
bool isWakeup = false;
if (now < targetTime) {
- if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
+ if (mTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
if (targetTime == INT64_MAX) {
ALOGV("[%s] Waiting forever", mName);
@@ -154,7 +151,7 @@
if (isWakeup) {
mWakeupLatency = ((mWakeupLatency * 63) + (now - targetTime)) / 64;
mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
- if (kTraceDetailedInfo) {
+ if (mTraceDetailedInfo) {
ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
}
@@ -172,7 +169,7 @@
}
status_t addEventListener(const char* name, nsecs_t phase, DispSync::Callback* callback) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -198,7 +195,7 @@
}
status_t removeEventListener(DispSync::Callback* callback) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (std::vector<EventListener>::iterator it = mEventListeners.begin();
@@ -214,7 +211,7 @@
}
status_t changePhaseOffset(DispSync::Callback* callback, nsecs_t phase) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
Mutex::Autolock lock(mMutex);
for (auto& eventListener : mEventListeners) {
@@ -254,7 +251,7 @@
};
nsecs_t computeNextEventTimeLocked(nsecs_t now) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
ALOGV("[%s] computeNextEventTimeLocked", mName);
nsecs_t nextEventTime = INT64_MAX;
for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -270,7 +267,7 @@
}
std::vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName, ns2us(now));
std::vector<CallbackInvocation> callbackInvocations;
@@ -293,7 +290,7 @@
}
nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener, nsecs_t baseTime) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")", mName, listener.mName,
ns2us(baseTime));
@@ -344,7 +341,7 @@
}
void fireCallbackInvocations(const std::vector<CallbackInvocation>& callbacks) {
- if (kTraceDetailedInfo) ATRACE_CALL();
+ if (mTraceDetailedInfo) ATRACE_CALL();
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
}
@@ -365,6 +362,9 @@
Mutex mMutex;
Condition mCond;
+
+ // Flag to turn on logging in systrace.
+ const bool mTraceDetailedInfo;
};
#undef LOG_TAG
@@ -383,8 +383,13 @@
bool mParity;
};
-DispSync::DispSync(const char* name)
- : mName(name), mRefreshSkipCount(0), mThread(new DispSyncThread(name)) {}
+DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0) {
+ // This flag offers the ability to turn on systrace logging from the shell.
+ char value[PROPERTY_VALUE_MAX];
+ property_get("debug.sf.dispsync_trace_detailed_info", value, "0");
+ mTraceDetailedInfo = atoi(value);
+ mThread = new DispSyncThread(name, mTraceDetailedInfo);
+}
DispSync::~DispSync() {}
@@ -403,7 +408,7 @@
reset();
beginResync();
- if (kTraceDetailedInfo && kEnableZeroPhaseTracer) {
+ if (mTraceDetailedInfo && kEnableZeroPhaseTracer) {
mZeroPhaseTracer = std::make_unique<ZeroPhaseTracer>();
addEventListener("ZeroPhaseTracer", 0, mZeroPhaseTracer.get());
}
@@ -588,7 +593,7 @@
ALOGV("[%s] Adjusting mPhase -> %" PRId64, mName, ns2us(mPhase));
}
- if (kTraceDetailedInfo) {
+ if (mTraceDetailedInfo) {
ATRACE_INT64("DispSync:Period", mPeriod);
ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
}
@@ -647,7 +652,7 @@
"No present times for model error.");
}
- if (kTraceDetailedInfo) {
+ if (mTraceDetailedInfo) {
ATRACE_INT64("DispSync:Error", mError);
}
}
@@ -726,6 +731,54 @@
result.appendFormat("current monotonic time: %" PRId64 "\n", now);
}
+// TODO(b/113612090): Figure out how much of this is still relevant.
+// We need to determine the time when a buffer acquired now will be
+// displayed. This can be calculated:
+// time when previous buffer's actual-present fence was signaled
+// + current display refresh rate * HWC latency
+// + a little extra padding
+//
+// Buffer producers are expected to set their desired presentation time
+// based on choreographer time stamps, which (coming from vsync events)
+// will be slightly later then the actual-present timing. If we get a
+// desired-present time that is unintentionally a hair after the next
+// vsync, we'll hold the frame when we really want to display it. We
+// need to take the offset between actual-present and reported-vsync
+// into account.
+//
+// If the system is configured without a DispSync phase offset for the app,
+// we also want to throw in a bit of padding to avoid edge cases where we
+// just barely miss. We want to do it here, not in every app. A major
+// source of trouble is the app's use of the display's ideal refresh time
+// (via Display.getRefreshRate()), which could be off of the actual refresh
+// by a few percent, with the error multiplied by the number of frames
+// between now and when the buffer should be displayed.
+//
+// If the refresh reported to the app has a phase offset, we shouldn't need
+// to tweak anything here.
+nsecs_t DispSync::expectedPresentTime() {
+ // The HWC doesn't currently have a way to report additional latency.
+ // Assume that whatever we submit now will appear right after the flip.
+ // For a smart panel this might be 1. This is expressed in frames,
+ // rather than time, because we expect to have a constant frame delay
+ // regardless of the refresh rate.
+ const uint32_t hwcLatency = 0;
+
+ // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
+ const nsecs_t nextRefresh = computeNextRefresh(hwcLatency);
+
+ // The DispSync time is already adjusted for the difference between
+ // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
+ // we don't need to factor that in here. Pad a little to avoid
+ // weird effects if apps might be requesting times right on the edge.
+ nsecs_t extraPadding = 0;
+ if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
+ extraPadding = 1000000; // 1ms (6% of 60Hz)
+ }
+
+ return nextRefresh + extraPadding;
+}
+
} // namespace impl
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/DispSync.h b/services/surfaceflinger/Scheduler/DispSync.h
index b3aef2d..5b511f4 100644
--- a/services/surfaceflinger/Scheduler/DispSync.h
+++ b/services/surfaceflinger/Scheduler/DispSync.h
@@ -57,6 +57,7 @@
virtual status_t changePhaseOffset(Callback* callback, nsecs_t phase) = 0;
virtual nsecs_t computeNextRefresh(int periodOffset) const = 0;
virtual void setIgnorePresentFences(bool ignore) = 0;
+ virtual nsecs_t expectedPresentTime() = 0;
virtual void dump(String8& result) const = 0;
};
@@ -164,6 +165,9 @@
// true from addPresentFence() and addResyncSample().
void setIgnorePresentFences(bool ignore) override;
+ // Determine the expected present time when a buffer acquired now will be displayed.
+ nsecs_t expectedPresentTime();
+
// dump appends human-readable debug info to the result string.
void dump(String8& result) const override;
@@ -237,6 +241,9 @@
bool mIgnorePresentFences;
std::unique_ptr<Callback> mZeroPhaseTracer;
+
+ // Flag to turn on logging in systrace.
+ bool mTraceDetailedInfo = false;
};
} // namespace impl
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 37b32ed..5744266 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3039,7 +3039,8 @@
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (layer->hasReadyFrame()) {
frameQueued = true;
- if (layer->shouldPresentNow(*mPrimaryDispSync)) {
+ const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+ if (layer->shouldPresentNow(expectedPresentTime)) {
mLayersWithQueuedFrames.push_back(layer);
} else {
layer->useEmptyDamage();
diff --git a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
index 46d6558..495b3f2 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockDispSync.h
@@ -43,6 +43,7 @@
MOCK_METHOD2(changePhaseOffset, status_t(Callback*, nsecs_t));
MOCK_CONST_METHOD1(computeNextRefresh, nsecs_t(int));
MOCK_METHOD1(setIgnorePresentFences, void(bool));
+ MOCK_METHOD0(expectedPresentTime, nsecs_t());
MOCK_CONST_METHOD1(dump, void(String8&));
};
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index ae955fb..c35ddd4 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -49,6 +49,9 @@
static_libs: [
"libbufferhub",
],
+
+ // TODO(b/117568153): Temporarily opt out using libcrt.
+ no_libcrt: true,
}
cc_binary {
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_node.h b/services/vr/bufferhubd/include/private/dvr/buffer_node.h
index ebab97c..d6c6105 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_node.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_node.h
@@ -1,8 +1,8 @@
#ifndef ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_
#define ANDROID_DVR_BUFFERHUBD_BUFFER_NODE_H_
-#include <private/dvr/buffer_hub_metadata.h>
#include <private/dvr/ion_buffer.h>
+#include <ui/BufferHubMetadata.h>
namespace android {
namespace dvr {
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
index 92bda78..bf8ea5b 100644
--- a/services/vr/bufferhubd/tests/Android.bp
+++ b/services/vr/bufferhubd/tests/Android.bp
@@ -20,4 +20,7 @@
"libui",
"libutils",
],
+
+ // TODO(b/117568153): Temporarily opt out using libcrt.
+ no_libcrt: true,
}
\ No newline at end of file