Merge "Fix gralloc direct channel bug and polish log messages" into oc-dev
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 5c04f6c..dfc3e58 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -25,7 +25,6 @@
namespace android {
GLHelper::GLHelper() :
- mGraphicBufferAlloc(new GraphicBufferAlloc()),
mDisplay(EGL_NO_DISPLAY),
mContext(EGL_NO_CONTEXT),
mDummySurface(EGL_NO_SURFACE),
@@ -203,7 +202,7 @@
sp<GLConsumer>* glConsumer, EGLSurface* surface) {
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, mGraphicBufferAlloc);
+ BufferQueue::createBufferQueue(&producer, &consumer);
sp<GLConsumer> glc = new GLConsumer(consumer, name,
GL_TEXTURE_EXTERNAL_OES, false, true);
glc->setDefaultBufferSize(w, h);
diff --git a/cmds/flatland/GLHelper.h b/cmds/flatland/GLHelper.h
index 7a9e9e3..d09463a 100644
--- a/cmds/flatland/GLHelper.h
+++ b/cmds/flatland/GLHelper.h
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-#include <gui/GraphicBufferAlloc.h>
#include <gui/GLConsumer.h>
#include <gui/Surface.h>
#include <gui/SurfaceControl.h>
@@ -75,8 +74,6 @@
bool setUpShaders(const ShaderDesc* shaderDescs, size_t numShaders);
- sp<GraphicBufferAlloc> mGraphicBufferAlloc;
-
EGLDisplay mDisplay;
EGLContext mContext;
EGLSurface mDummySurface;
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index c47b0c8..ec1e543 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -16,7 +16,6 @@
#define ATRACE_TAG ATRACE_TAG_ALWAYS
-#include <gui/GraphicBufferAlloc.h>
#include <gui/Surface.h>
#include <gui/SurfaceControl.h>
#include <gui/GLConsumer.h>
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index be1a434..1d21b3c 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -24,6 +24,7 @@
LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
LOCAL_SRC_FILES := otapreopt.cpp globals.cpp utils.cpp dexopt.cpp
+LOCAL_HEADER_LIBRARIES := dex2oat_headers
LOCAL_SHARED_LIBRARIES := \
libbase \
libcutils \
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 82b8cc2..e8e6b56 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -33,6 +33,7 @@
#include <android-base/strings.h>
#include <cutils/fs.h>
#include <cutils/properties.h>
+#include <dex2oat_return_codes.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
@@ -576,7 +577,11 @@
}
// If the dexopt failed, we may have a stale boot image from a previous OTA run.
- // Try to delete and retry.
+ // Then regenerate and retry.
+ if (WEXITSTATUS(dexopt_result) !=
+ static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime)) {
+ return dexopt_result;
+ }
if (!PrepareBootImage(/* force */ true)) {
LOG(ERROR) << "Forced boot image creating failed. Original error return was "
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 49605be..dab3236 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -547,7 +547,7 @@
TEST_F(UtilsTest, CreatePrimaryCurrentProfile) {
std::string expected =
- create_primary_current_profile_package_dir_path(1, "com.example") + "/primary.prof";
+ create_primary_current_profile_package_dir_path(0, "com.example") + "/primary.prof";
EXPECT_EQ(expected,
create_current_profile_path(/*user*/0, "com.example", /*is_secondary*/false));
}
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 4c57361..33bc43c 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -296,7 +296,7 @@
continue;
}
- vintf::ManifestHal *hal = manifest.getHal(fqName.package());
+ vintf::ManifestHal *hal = manifest.getAnyHal(fqName.package());
if (hal == nullptr) {
if (!manifest.add(vintf::ManifestHal{
.format = vintf::HalFormat::HIDL,
@@ -306,7 +306,7 @@
mErr << "Warning: cannot add hal '" << fqInstanceName << "'" << std::endl;
continue;
}
- hal = manifest.getHal(fqName.package());
+ hal = manifest.getAnyHal(fqName.package());
}
if (hal == nullptr) {
mErr << "Warning: cannot get hal '" << fqInstanceName
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 68d39db..39d92a7 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -38,7 +38,7 @@
cc_binary {
name: "vndservicemanager",
defaults: ["servicemanager_flags"],
- proprietary: true,
+ vendor: true,
srcs: [
"service_manager.c",
"binder.c",
@@ -46,6 +46,7 @@
cflags: [
"-DVENDORSERVICEMANAGER=1",
],
- shared_libs: ["libcutils", "libselinux"],
+ shared_libs: ["libcutils"],
+ static_libs: ["libselinux"],
init_rc: ["vndservicemanager.rc"],
}
diff --git a/cmds/vr/vrscreencap/Android.mk b/cmds/vr/vrscreencap/Android.mk
index bd0b224..804afc9 100644
--- a/cmds/vr/vrscreencap/Android.mk
+++ b/cmds/vr/vrscreencap/Android.mk
@@ -6,6 +6,7 @@
vrscreencap.cpp
LOCAL_STATIC_LIBRARIES := \
+ libbufferhub \
libdisplay \
libimageio \
libpdx_default_transport \
@@ -14,7 +15,8 @@
libcutils \
liblog \
libpng \
- libsync
+ libsync \
+ libui \
LOCAL_MODULE := vrscreencap
diff --git a/data/etc/android.hardware.nfc.hce.xml b/data/etc/android.hardware.nfc.hce.xml
index 10b96b1..95da181 100644
--- a/data/etc/android.hardware.nfc.hce.xml
+++ b/data/etc/android.hardware.nfc.hce.xml
@@ -18,4 +18,5 @@
NFC card emulation -->
<permissions>
<feature name="android.hardware.nfc.hce" />
+ <feature name="android.hardware.nfc.any" />
</permissions>
diff --git a/data/etc/android.hardware.nfc.hcef.xml b/data/etc/android.hardware.nfc.hcef.xml
index 0d03023..b86890d 100644
--- a/data/etc/android.hardware.nfc.hcef.xml
+++ b/data/etc/android.hardware.nfc.hcef.xml
@@ -18,4 +18,5 @@
NFC-F card emulation -->
<permissions>
<feature name="android.hardware.nfc.hcef" />
+ <feature name="android.hardware.nfc.any" />
</permissions>
diff --git a/data/etc/android.hardware.nfc.xml b/data/etc/android.hardware.nfc.xml
index 81c4a84..5201fa2 100644
--- a/data/etc/android.hardware.nfc.xml
+++ b/data/etc/android.hardware.nfc.xml
@@ -18,4 +18,5 @@
using Near-Field Communications (NFC). -->
<permissions>
<feature name="android.hardware.nfc" />
+ <feature name="android.hardware.nfc.any" />
</permissions>
diff --git a/data/etc/android.software.autofill.xml b/data/etc/android.software.autofill.xml
new file mode 100644
index 0000000..c510d0c
--- /dev/null
+++ b/data/etc/android.software.autofill.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<permissions>
+ <feature name="android.software.autofill" />
+</permissions>
diff --git a/data/etc/android.software.cts.xml b/data/etc/android.software.cts.xml
new file mode 100644
index 0000000..0414c9a
--- /dev/null
+++ b/data/etc/android.software.cts.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+
+<permissions>
+ <!-- This is Android and fully CTS compatible. Basically this is for CTS tests to use. -->
+ <feature name="android.software.cts" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 9229f82..0d5d206 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -49,6 +49,7 @@
<feature name="android.software.activities_on_secondary_displays" />
<feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
+ <feature name="android.software.autofill" />
<!-- Feature to specify if the device supports adding device admins. -->
<feature name="android.software.device_admin" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 64e32ff..9b88648 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -49,6 +49,7 @@
<feature name="android.software.activities_on_secondary_displays" />
<feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
+ <feature name="android.software.autofill" />
<!-- Feature to specify if the device supports adding device admins. -->
<feature name="android.software.device_admin" />
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 186f62c..cdb3fff 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -484,8 +484,9 @@
*
* Configure sensor direct report on a direct channel: set rate to value other than
* {@link ASENSOR_DIRECT_RATE_STOP} so that sensor event can be directly
- * written into the shared memory region used for creating the buffer; set rate to
- * {@link ASENSOR_DIRECT_RATE_STOP} will stop the sensor direct report.
+ * written into the shared memory region used for creating the buffer. It returns a positive token
+ * which can be used for identify sensor events from different sensors on success. Calling with rate
+ * {@link ASENSOR_DIRECT_RATE_STOP} will stop direct report of the sensor specified in the channel.
*
* To stop all active sensor direct report configured to a channel, set sensor to NULL and rate to
* {@link ASENSOR_DIRECT_RATE_STOP}.
@@ -513,7 +514,7 @@
* {@link ASensorManager_createSharedMemoryDirectChannel} or
* {@link ASensorManager_createHardwareBufferDirectChannel}.
*
- * \return 0 for success or negative integer for failure.
+ * \return positive token for success or negative error code.
*/
int ASensorManager_configureDirectReport(
ASensorManager* manager, ASensor const* sensor, int channelId, int rate);
diff --git a/include/binder b/include/binder
new file mode 120000
index 0000000..35a022a
--- /dev/null
+++ b/include/binder
@@ -0,0 +1 @@
+../libs/binder/include/binder/
\ No newline at end of file
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index c95c535..bd62d85 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -23,10 +23,6 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/IConsumerListener.h>
-// These are only required to keep other parts of the framework with incomplete
-// dependencies building successfully
-#include <gui/IGraphicBufferAlloc.h>
-
namespace android {
class BufferQueue {
@@ -81,11 +77,9 @@
// needed gralloc buffers.
static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
- const sp<IGraphicBufferAlloc>& allocator = NULL,
bool consumerIsSurfaceFlinger = false);
-private:
- BufferQueue(); // Create through createBufferQueue
+ BufferQueue() = delete; // Create through createBufferQueue
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index da574ec..1e22d28 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -110,7 +110,7 @@
virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
// setConsumerName sets the name used in logging
- virtual void setConsumerName(const String8& name);
+ status_t setConsumerName(const String8& name) override;
// setDefaultBufferFormat allows the BufferQueue to create
// GraphicBuffers of a defaultFormat if no format is specified
@@ -135,7 +135,7 @@
virtual status_t setTransformHint(uint32_t hint);
// Retrieve the sideband buffer stream, if any.
- virtual sp<NativeHandle> getSidebandStream() const;
+ status_t getSidebandStream(sp<NativeHandle>* outStream) const override;
// See IGraphicBufferConsumer::getOccupancyHistory
virtual status_t getOccupancyHistory(bool forceFlush,
@@ -145,7 +145,7 @@
virtual status_t discardFreeBuffers() override;
// dump our state in a String
- virtual void dumpState(String8& result, const char* prefix) const;
+ status_t dumpState(const String8& prefix, String8* outResult) const override;
// Functions required for backwards compatibility.
// These will be modified/renamed in IGraphicBufferConsumer and will be
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index b1c730a..cfe716f 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -51,7 +51,6 @@
namespace android {
class IConsumerListener;
-class IGraphicBufferAlloc;
class IProducerListener;
class BufferQueueCore : public virtual RefBase {
@@ -79,14 +78,13 @@
typedef Vector<BufferItem> Fifo;
// BufferQueueCore manages a pool of gralloc memory slots to be used by
- // producers and consumers. allocator is used to allocate all the needed
- // gralloc buffers.
- BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator = NULL);
+ // producers and consumers.
+ BufferQueueCore();
virtual ~BufferQueueCore();
private:
// Dump our state in a string
- void dumpState(String8& result, const char* prefix) const;
+ void dumpState(const String8& prefix, String8* outResult) const;
// getMinUndequeuedBufferCountLocked returns the minimum number of buffers
// that must remain in a state other than DEQUEUED. The async parameter
@@ -143,10 +141,6 @@
void validateConsistencyLocked() const;
#endif
- // mAllocator is the connection to SurfaceFlinger that is used to allocate
- // new GraphicBuffer objects.
- sp<IGraphicBufferAlloc> mAllocator;
-
// mMutex is the mutex used to prevent concurrent access to the member
// variables of BufferQueueCore objects. It must be locked whenever any
// member variable is accessed.
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 92251ed..9716be4 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -54,8 +54,7 @@
static constexpr auto EVENT_COUNT =
static_cast<size_t>(FrameEvent::EVENT_COUNT);
static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
- static constexpr nsecs_t TIMESTAMP_PENDING =
- std::numeric_limits<nsecs_t>::max();
+ static constexpr nsecs_t TIMESTAMP_PENDING = -2;
static inline bool isValidTimestamp(nsecs_t time) {
return time != TIMESTAMP_PENDING;
diff --git a/include/gui/GraphicBufferAlloc.h b/include/gui/GraphicBufferAlloc.h
deleted file mode 100644
index 54c9829..0000000
--- a/include/gui/GraphicBufferAlloc.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2012 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_GUI_GRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-#include <ui/PixelFormat.h>
-#include <utils/Errors.h>
-
-namespace android {
-
-class GraphicBuffer;
-
-/*
- * Concrete implementation of the IGraphicBufferAlloc interface.
- *
- * This can create GraphicBuffer instance across processes. This is mainly used
- * by surfaceflinger.
- */
-
-class GraphicBufferAlloc : public BnGraphicBufferAlloc {
-public:
- GraphicBufferAlloc();
- virtual ~GraphicBufferAlloc();
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
- uint32_t height, PixelFormat format, uint32_t layerCount,
- uint64_t producerUsage, uint64_t consumerUsage,
- std::string requestorName, status_t* error) override;
-};
-
-
-} // namespace android
-
-#endif // ANDROID_GUI_GRAPHIC_BUFFER_ALLOC_H
diff --git a/include/gui/IGraphicBufferAlloc.h b/include/gui/IGraphicBufferAlloc.h
deleted file mode 100644
index 1e578cc..0000000
--- a/include/gui/IGraphicBufferAlloc.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2011 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_GUI_IGRAPHIC_BUFFER_ALLOC_H
-#define ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/IInterface.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/PixelFormat.h>
-#include <utils/RefBase.h>
-
-#include <string>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class IGraphicBufferAlloc : public IInterface
-{
-public:
- DECLARE_META_INTERFACE(GraphicBufferAlloc)
-
- /* Create a new GraphicBuffer for the client to use.
- */
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
- uint64_t consumerUsage, std::string requestorName,
- status_t* error) = 0;
-
- sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t layerCount, uint32_t usage,
- status_t* error) {
- return createGraphicBuffer(w, h, format, layerCount, usage,
- usage, "<Unknown>", error);
- }
-
- sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t layerCount, uint32_t usage,
- std::string requestorName, status_t* error) {
- return createGraphicBuffer(w, h, format, layerCount, usage,
- usage, requestorName, error);
- }
-
- sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
- PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
- uint64_t consumerUsage, status_t* error) {
- return createGraphicBuffer(w, h, format, layerCount, producerUsage,
- consumerUsage, "<Unknown>", error);
- }
-};
-
-// ----------------------------------------------------------------------------
-
-class BnGraphicBufferAlloc : public BnInterface<IGraphicBufferAlloc>
-{
-public:
- virtual status_t onTransact(uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------------
-
-}; // namespace android
-
-#endif // ANDROID_GUI_IGRAPHIC_BUFFER_ALLOC_H
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 60b7d24..63254ed 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -14,27 +14,21 @@
* limitations under the License.
*/
-#ifndef ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H
-#define ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Timers.h>
-
-#include <binder/IInterface.h>
-
-#include <ui/PixelFormat.h>
+#pragma once
#include <gui/OccupancyTracker.h>
+#include <binder/IInterface.h>
+#include <binder/SafeInterface.h>
+
#include <EGL/egl.h>
#include <EGL/eglext.h>
+#include <ui/PixelFormat.h>
+
+#include <utils/Errors.h>
+
namespace android {
-// ----------------------------------------------------------------------------
class BufferItem;
class Fence;
@@ -43,11 +37,12 @@
class NativeHandle;
class IGraphicBufferConsumer : public IInterface {
-
public:
+ DECLARE_META_INTERFACE(GraphicBufferConsumer)
+
enum {
- // Returned by releaseBuffer, after which the consumer must
- // free any references to the just-released buffer that it might have.
+ // Returned by releaseBuffer, after which the consumer must free any references to the
+ // just-released buffer that it might have.
STALE_BUFFER_SLOT = 1,
// Returned by dequeueBuffer if there are no pending buffers available.
NO_BUFFER_AVAILABLE,
@@ -55,88 +50,79 @@
PRESENT_LATER,
};
- // acquireBuffer attempts to acquire ownership of the next pending buffer in
- // the BufferQueue. If no buffer is pending then it returns
- // NO_BUFFER_AVAILABLE. If a buffer is successfully acquired, the
- // information about the buffer is returned in BufferItem.
+ // acquireBuffer attempts to acquire ownership of the next pending buffer in the BufferQueue.
+ // If no buffer is pending then it returns NO_BUFFER_AVAILABLE. If a buffer is successfully
+ // acquired, the information about the buffer is returned in BufferItem.
//
- // If the buffer returned had previously been
- // acquired then the BufferItem::mGraphicBuffer field of buffer is set to
- // NULL and it is assumed that the consumer still holds a reference to the
+ // If the buffer returned had previously been acquired then the BufferItem::mGraphicBuffer field
+ // of buffer is set to NULL and it is assumed that the consumer still holds a reference to the
// buffer.
//
- // If presentWhen is non-zero, it indicates the time when the buffer will
- // be displayed on screen. If the buffer's timestamp is farther in the
- // future, the buffer won't be acquired, and PRESENT_LATER will be
- // returned. The presentation time is in nanoseconds, and the time base
+ // If presentWhen is non-zero, it indicates the time when the buffer will be displayed on
+ // screen. If the buffer's timestamp is farther in the future, the buffer won't be acquired, and
+ // PRESENT_LATER will be returned. The presentation time is in nanoseconds, and the time base
// is CLOCK_MONOTONIC.
//
- // If maxFrameNumber is non-zero, it indicates that acquireBuffer should
- // only return a buffer with a frame number less than or equal to
- // maxFrameNumber. If no such frame is available (such as when a buffer has
- // been replaced but the consumer has not received the onFrameReplaced
- // callback), then PRESENT_LATER will be returned.
+ // If maxFrameNumber is non-zero, it indicates that acquireBuffer should only return a buffer
+ // with a frame number less than or equal to maxFrameNumber. If no such frame is available
+ // (such as when a buffer has been replaced but the consumer has not received the
+ // onFrameReplaced callback), then PRESENT_LATER will be returned.
//
// Return of NO_ERROR means the operation completed as normal.
//
- // Return of a positive value means the operation could not be completed
- // at this time, but the user should try again later:
+ // Return of a positive value means the operation could not be completed at this time, but the
+ // user should try again later:
// * NO_BUFFER_AVAILABLE - no buffer is pending (nothing queued by producer)
// * PRESENT_LATER - the buffer's timestamp is farther in the future
//
// Return of a negative value means an error has occurred:
// * INVALID_OPERATION - too many buffers have been acquired
virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
- uint64_t maxFrameNumber = 0) = 0;
+ uint64_t maxFrameNumber = 0) = 0;
- // detachBuffer attempts to remove all ownership of the buffer in the given
- // slot from the buffer queue. If this call succeeds, the slot will be
- // freed, and there will be no way to obtain the buffer from this interface.
- // The freed slot will remain unallocated until either it is selected to
- // hold a freshly allocated buffer in dequeueBuffer or a buffer is attached
- // to the slot. The buffer must have already been acquired.
+ // detachBuffer attempts to remove all ownership of the buffer in the given slot from the buffer
+ // queue. If this call succeeds, the slot will be freed, and there will be no way to obtain the
+ // buffer from this interface. The freed slot will remain unallocated until either it is
+ // selected to hold a freshly allocated buffer in dequeueBuffer or a buffer is attached to the
+ // slot. The buffer must have already been acquired.
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - the given slot number is invalid, either because it is
- // out of the range [0, NUM_BUFFER_SLOTS) or because the slot
- // it refers to is not currently acquired.
+ // * BAD_VALUE - the given slot number is invalid, either because it is out of the range
+ // [0, NUM_BUFFER_SLOTS) or because the slot it refers to is not
+ // currently acquired.
virtual status_t detachBuffer(int slot) = 0;
- // attachBuffer attempts to transfer ownership of a buffer to the buffer
- // queue. If this call succeeds, it will be as if this buffer was acquired
- // from the returned slot number. As such, this call will fail if attaching
- // this buffer would cause too many buffers to be simultaneously acquired.
+ // attachBuffer attempts to transfer ownership of a buffer to the BufferQueue. If this call
+ // succeeds, it will be as if this buffer was acquired from the returned slot number. As such,
+ // this call will fail if attaching this buffer would cause too many buffers to be
+ // simultaneously acquired.
//
- // If the buffer is successfully attached, its frameNumber is initialized
- // to 0. This must be passed into the releaseBuffer call or else the buffer
- // will be deallocated as stale.
+ // If the buffer is successfully attached, its frameNumber is initialized to 0. This must be
+ // passed into the releaseBuffer call or else the buffer will be deallocated as stale.
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * BAD_VALUE - outSlot or buffer were NULL, or the generation number of
- // the buffer did not match the buffer queue.
- // * INVALID_OPERATION - cannot attach the buffer because it would cause too
- // many buffers to be acquired.
+ // * BAD_VALUE - outSlot or buffer were NULL, or the generation number of the buffer did not
+ // match the BufferQueue.
+ // * INVALID_OPERATION - cannot attach the buffer because it would cause too many buffers
+ // to be acquired.
// * NO_MEMORY - no free slots available
- virtual status_t attachBuffer(int *outSlot,
- const sp<GraphicBuffer>& buffer) = 0;
+ virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) = 0;
- // releaseBuffer releases a buffer slot from the consumer back to the
- // BufferQueue. This may be done while the buffer's contents are still
- // being accessed. The fence will signal when the buffer is no longer
- // in use. frameNumber is used to indentify the exact buffer returned.
+ // releaseBuffer releases a buffer slot from the consumer back to the BufferQueue. This may be
+ // done while the buffer's contents are still being accessed. The fence will signal when the
+ // buffer is no longer in use. frameNumber is used to identify the exact buffer returned.
//
- // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free
- // any references to the just-released buffer that it might have, as if it
- // had received a onBuffersReleased() call with a mask set for the released
- // buffer.
+ // If releaseBuffer returns STALE_BUFFER_SLOT, then the consumer must free any references to the
+ // just-released buffer that it might have, as if it had received a onBuffersReleased() call
+ // with a mask set for the released buffer.
//
- // Note that the dependencies on EGL will be removed once we switch to using
- // the Android HW Sync HAL.
+ // Note that the dependencies on EGL will be removed once we switch to using the Android HW
+ // Sync HAL.
//
// Return of NO_ERROR means the operation completed as normal.
//
- // Return of a positive value means the operation could not be completed
- // at this time, but the user should try again later:
+ // Return of a positive value means the operation could not be completed at this time, but the
+ // user should try again later:
// * STALE_BUFFER_SLOT - see above (second paragraph)
//
// Return of a negative value means an error has occurred:
@@ -144,159 +130,157 @@
// * the buffer slot was invalid
// * the fence was NULL
// * the buffer slot specified is not in the acquired state
- virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
- EGLDisplay display, EGLSyncKHR fence,
- const sp<Fence>& releaseFence) = 0;
+ virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display,
+ EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0;
- // consumerConnect connects a consumer to the BufferQueue. Only one
- // consumer may be connected, and when that consumer disconnects the
- // BufferQueue is placed into the "abandoned" state, causing most
- // interactions with the BufferQueue by the producer to fail.
- // controlledByApp indicates whether the consumer is controlled by
- // the application.
+ status_t releaseHelper(int buf, uint64_t frameNumber, const sp<Fence>& releaseFence) {
+ return releaseBuffer(buf, frameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
+ }
+ // This is explicitly *not* the actual signature of IGBC::releaseBuffer, but:
+ // 1) We have no easy way to send the EGL objects across Binder
+ // 2) This has always been broken, probably because
+ // 3) IGBC is rarely remoted
+ // For now, we will choose to bury our heads in the sand and ignore this problem until such time
+ // as we can finally finish converting away from EGL sync to native Android sync
+ using ReleaseBuffer = decltype(&IGraphicBufferConsumer::releaseHelper);
+
+ // consumerConnect connects a consumer to the BufferQueue. Only one consumer may be connected,
+ // and when that consumer disconnects the BufferQueue is placed into the "abandoned" state,
+ // causing most interactions with the BufferQueue by the producer to fail. controlledByApp
+ // indicates whether the consumer is controlled by the application.
//
// consumer may not be NULL.
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned
+ // * NO_INIT - the BufferQueue has been abandoned
// * BAD_VALUE - a NULL consumer was provided
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0;
+ virtual status_t consumerConnect(const sp<IConsumerListener>& consumer,
+ bool controlledByApp) = 0;
- // consumerDisconnect disconnects a consumer from the BufferQueue. All
- // buffers will be freed and the BufferQueue is placed in the "abandoned"
- // state, causing most interactions with the BufferQueue by the producer to
- // fail.
+ // consumerDisconnect disconnects a consumer from the BufferQueue. All buffers will be freed and
+ // the BufferQueue is placed in the "abandoned" state, causing most interactions with the
+ // BufferQueue by the producer to fail.
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - no consumer is currently connected
virtual status_t consumerDisconnect() = 0;
- // getReleasedBuffers sets the value pointed to by slotMask to a bit set.
- // Each bit index with a 1 corresponds to a released buffer slot with that
- // index value. In particular, a released buffer is one that has
- // been released by the BufferQueue but have not yet been released by the consumer.
+ // getReleasedBuffers sets the value pointed to by slotMask to a bit set. Each bit index with a
+ // 1 corresponds to a released buffer slot with that index value. In particular, a released
+ // buffer is one that has been released by the BufferQueue but has not yet been released by
+ // the consumer.
//
// This should be called from the onBuffersReleased() callback.
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned.
+ // * NO_INIT - the BufferQueue has been abandoned.
virtual status_t getReleasedBuffers(uint64_t* slotMask) = 0;
- // setDefaultBufferSize is used to set the size of buffers returned by
- // dequeueBuffer when a width and height of zero is requested. Default
- // is 1x1.
+ // setDefaultBufferSize is used to set the size of buffers returned by dequeueBuffer when a
+ // width and height of zero is requested. Default is 1x1.
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - either w or h was zero
virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
- // setMaxBufferCount sets the maximum value for the number of buffers used
- // in the buffer queue (the initial default is NUM_BUFFER_SLOTS). If a call
- // to setMaxAcquiredBufferCount (by the consumer), or a call to setAsyncMode
- // or setMaxDequeuedBufferCount (by the producer), would cause this value to
- // be exceeded then that call will fail. This call will fail if a producer
+ // setMaxBufferCount sets the maximum value for the number of buffers used in the BufferQueue
+ // (the initial default is NUM_BUFFER_SLOTS). If a call to setMaxAcquiredBufferCount (by the
+ // consumer), or a call to setAsyncMode or setMaxDequeuedBufferCount (by the producer), would
+ // cause this value to be exceeded then that call will fail. This call will fail if a producer
// is connected to the BufferQueue.
//
- // The count must be between 1 and NUM_BUFFER_SLOTS, inclusive. The count
- // cannot be less than maxAcquiredBufferCount.
+ // The count must be between 1 and NUM_BUFFER_SLOTS, inclusive. The count cannot be less than
+ // maxAcquiredBufferCount.
//
// Return of a value other than NO_ERROR means an error has occurred:
// * BAD_VALUE - one of the below conditions occurred:
- // * bufferCount was out of range (see above).
- // * failure to adjust the number of available slots.
+ // * bufferCount was out of range (see above).
+ // * failure to adjust the number of available slots.
// * INVALID_OPERATION - attempting to call this after a producer connected.
virtual status_t setMaxBufferCount(int bufferCount) = 0;
- // setMaxAcquiredBufferCount sets the maximum number of buffers that can
- // be acquired by the consumer at one time (default 1). If this method
- // succeeds, any new buffer slots will be both unallocated and owned by the
- // BufferQueue object (i.e. they are not owned by the producer or consumer).
- // Calling this may also cause some buffer slots to be emptied.
+ // setMaxAcquiredBufferCount sets the maximum number of buffers that can be acquired by the
+ // consumer at one time (default 1). If this method succeeds, any new buffer slots will be both
+ // unallocated and owned by the BufferQueue object (i.e. they are not owned by the producer or
+ // consumer). Calling this may also cause some buffer slots to be emptied.
//
- // This function should not be called with a value of maxAcquiredBuffers
- // that is less than the number of currently acquired buffer slots. Doing so
- // will result in a BAD_VALUE error.
+ // This function should not be called with a value of maxAcquiredBuffers that is less than the
+ // number of currently acquired buffer slots. Doing so will result in a BAD_VALUE error.
//
- // maxAcquiredBuffers must be (inclusive) between 1 and
- // MAX_MAX_ACQUIRED_BUFFERS. It also cannot cause the maxBufferCount value
- // to be exceeded.
+ // maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS. It also cannot
+ // cause the maxBufferCount value to be exceeded.
//
// Return of a value other than NO_ERROR means an error has occurred:
- // * NO_INIT - the buffer queue has been abandoned
+ // * NO_INIT - the BufferQueue has been abandoned
// * BAD_VALUE - one of the below conditions occurred:
- // * maxAcquiredBuffers was out of range (see above).
- // * failure to adjust the number of available slots.
- // * client would have more than the requested number of
- // acquired buffers after this call
+ // * maxAcquiredBuffers was out of range (see above).
+ // * failure to adjust the number of available slots.
+ // * client would have more than the requested number of acquired buffers after
+ // this call
// * INVALID_OPERATION - attempting to call this after a producer connected.
virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0;
// setConsumerName sets the name used in logging
- virtual void setConsumerName(const String8& name) = 0;
+ virtual status_t setConsumerName(const String8& name) = 0;
- // setDefaultBufferFormat allows the BufferQueue to create
- // GraphicBuffers of a defaultFormat if no format is specified
- // in dequeueBuffer.
- // The initial default is PIXEL_FORMAT_RGBA_8888.
+ // setDefaultBufferFormat allows the BufferQueue to create GraphicBuffers of a defaultFormat if
+ // no format is specified in dequeueBuffer. The initial default is PIXEL_FORMAT_RGBA_8888.
//
// Return of a value other than NO_ERROR means an unknown error has occurred.
virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) = 0;
- // setDefaultBufferDataSpace is a request to the producer to provide buffers
- // of the indicated dataSpace. The producer may ignore this request.
- // The initial default is HAL_DATASPACE_UNKNOWN.
+ // setDefaultBufferDataSpace is a request to the producer to provide buffers of the indicated
+ // dataSpace. The producer may ignore this request. The initial default is
+ // HAL_DATASPACE_UNKNOWN.
//
// Return of a value other than NO_ERROR means an unknown error has occurred.
- virtual status_t setDefaultBufferDataSpace(
- android_dataspace defaultDataSpace) = 0;
+ virtual status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) = 0;
- // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer.
- // These are merged with the bits passed to dequeueBuffer. The values are
- // enumerated in gralloc.h, e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
+ // setConsumerUsageBits will turn on additional usage bits for dequeueBuffer. These are merged
+ // with the bits passed to dequeueBuffer. The values are enumerated in gralloc.h,
+ // e.g. GRALLOC_USAGE_HW_RENDER; the default is 0.
//
// Return of a value other than NO_ERROR means an unknown error has occurred.
virtual status_t setConsumerUsageBits(uint32_t usage) = 0;
- // setTransformHint bakes in rotation to buffers so overlays can be used.
- // The values are enumerated in window.h, e.g.
- // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform).
+ // setTransformHint bakes in rotation to buffers so overlays can be used. The values are
+ // enumerated in window.h, e.g. NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0
+ // (no transform).
//
// Return of a value other than NO_ERROR means an unknown error has occurred.
virtual status_t setTransformHint(uint32_t hint) = 0;
// Retrieve the sideband buffer stream, if any.
- virtual sp<NativeHandle> getSidebandStream() const = 0;
+ virtual status_t getSidebandStream(sp<NativeHandle>* outStream) const = 0;
- // Retrieves any stored segments of the occupancy history of this
- // BufferQueue and clears them. Optionally closes out the pending segment if
- // forceFlush is true.
+ // Retrieves any stored segments of the occupancy history of this BufferQueue and clears them.
+ // Optionally closes out the pending segment if forceFlush is true.
virtual status_t getOccupancyHistory(bool forceFlush,
- std::vector<OccupancyTracker::Segment>* outHistory) = 0;
+ std::vector<OccupancyTracker::Segment>* outHistory) = 0;
- // discardFreeBuffers releases all currently-free buffers held by the queue,
- // in order to reduce the memory consumption of the queue to the minimum
- // possible without discarding data.
+ // discardFreeBuffers releases all currently-free buffers held by the BufferQueue, in order to
+ // reduce the memory consumption of the BufferQueue to the minimum possible without
+ // discarding data.
virtual status_t discardFreeBuffers() = 0;
// dump state into a string
- virtual void dumpState(String8& result, const char* prefix) const = 0;
+ virtual status_t dumpState(const String8& prefix, String8* outResult) const = 0;
-public:
- DECLARE_META_INTERFACE(GraphicBufferConsumer)
+ // Provide backwards source compatibility
+ void dumpState(String8& result, const char* prefix) {
+ String8 returned;
+ dumpState(String8(prefix), &returned);
+ result.append(returned);
+ }
};
-// ----------------------------------------------------------------------------
-
-class BnGraphicBufferConsumer : public BnInterface<IGraphicBufferConsumer>
-{
+class BnGraphicBufferConsumer : public SafeBnInterface<IGraphicBufferConsumer> {
public:
- virtual status_t onTransact( uint32_t code,
- const Parcel& data,
- Parcel* reply,
- uint32_t flags = 0);
+ BnGraphicBufferConsumer()
+ : SafeBnInterface<IGraphicBufferConsumer>("BnGraphicBufferConsumer") {}
+
+ status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags = 0) override;
};
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_GUI_IGRAPHICBUFFERCONSUMER_H
+} // namespace android
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 2fbe07a..1112973 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -41,7 +41,6 @@
struct DisplayStatInfo;
class HdrCapabilities;
class IDisplayEventConnection;
-class IGraphicBufferAlloc;
class IGraphicBufferProducer;
class ISurfaceComposerClient;
class Rect;
@@ -89,10 +88,6 @@
virtual sp<ISurfaceComposerClient> createScopedConnection(
const sp<IGraphicBufferProducer>& parent) = 0;
- /* create a graphic buffer allocator
- */
- virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc() = 0;
-
/* return an IDisplayEventConnection */
virtual sp<IDisplayEventConnection> createDisplayEventConnection() = 0;
@@ -126,6 +121,11 @@
virtual bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& surface) const = 0;
+ /* Returns the frame timestamps supported by SurfaceFlinger.
+ */
+ virtual status_t getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const = 0;
+
/* set display power mode. depending on the mode, it can either trigger
* screen on, off or low power mode and wait for it to complete.
* requires ACCESS_SURFACE_FLINGER permission.
@@ -200,7 +200,7 @@
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
CREATE_CONNECTION,
- CREATE_GRAPHIC_BUFFER_ALLOC,
+ UNUSED, // formerly CREATE_GRAPHIC_BUFFER_ALLOC
CREATE_DISPLAY_EVENT_CONNECTION,
CREATE_DISPLAY,
DESTROY_DISPLAY,
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 88ef010..8b1d106 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -426,6 +426,10 @@
uint64_t mNextFrameNumber = 1;
uint64_t mLastFrameNumber = 0;
+ // Mutable because ANativeWindow::query needs this class const.
+ mutable bool mQueriedSupportedTimestamps;
+ mutable bool mFrameTimestampsSupportsPresent;
+
// A cached copy of the FrameEventHistory maintained by the consumer.
bool mEnableFrameTimestamps = false;
std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 394425a..ec310cf 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -146,6 +146,8 @@
status_t setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent);
status_t setLayer(const sp<IBinder>& id, int32_t layer);
+ status_t setRelativeLayer(const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t layer);
status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f);
status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy);
status_t setPosition(const sp<IBinder>& id, float x, float y);
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 3cff7df..712a323 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -62,6 +62,27 @@
status_t setLayerStack(uint32_t layerStack);
status_t setLayer(int32_t layer);
+
+ // Sets a Z order relative to the Surface specified by "relativeTo" but
+ // without becoming a full child of the relative. Z-ordering works exactly
+ // as if it were a child however.
+ //
+ // As a nod to sanity, only non-child surfaces may have a relative Z-order.
+ //
+ // This overrides any previous and is overriden by any future calls
+ // to setLayer.
+ //
+ // If the relative dissapears, the Surface will have no layer and be
+ // invisible, until the next time set(Relative)Layer is called.
+ //
+ // TODO: This is probably a hack. Currently it exists only to work around
+ // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type
+ // which allows inserting a window between a SurfaceView and it's main application
+ // window. However, since we are using child windows for the SurfaceView, but not using
+ // child windows elsewhere in O, the WindowManager can't set the layer appropriately.
+ // This is only used by the "TvInputService" and following the port of ViewRootImpl
+ // to child surfaces, we can then port this and remove this method.
+ status_t setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer);
status_t setPosition(float x, float y);
status_t setSize(uint32_t w, uint32_t h);
status_t hide();
diff --git a/include/media/cas/CasAPI.h b/include/media/cas/CasAPI.h
index 0e88019..67f4511 100644
--- a/include/media/cas/CasAPI.h
+++ b/include/media/cas/CasAPI.h
@@ -81,23 +81,12 @@
virtual status_t setPrivateData(
const CasData &privateData) = 0;
- // Open a session for descrambling a program. The session will receive the
- // ECM stream corresponding to the CA_PID for the program.
- virtual status_t openSession(
- uint16_t program_number,
- CasSessionId *sessionId) = 0;
-
- // Open a session for descrambling an elementary stream inside a program.
- // The session will receive the ECM stream corresponding to the CA_PID for
- // the stream.
- virtual status_t openSession(
- uint16_t program_number,
- uint16_t elementary_PID,
- CasSessionId *sessionId) = 0;
+ // Open a session for descrambling a program, or one or more elementary
+ // streams.
+ virtual status_t openSession(CasSessionId *sessionId) = 0;
// Close a previously opened session.
- virtual status_t closeSession(
- const CasSessionId &sessionId) = 0;
+ virtual status_t closeSession(const CasSessionId &sessionId) = 0;
// Provide the CA private data from a CA_descriptor in the program map
// table to a CasPlugin.
diff --git a/include/private/binder b/include/private/binder
new file mode 120000
index 0000000..09e9076
--- /dev/null
+++ b/include/private/binder
@@ -0,0 +1 @@
+../../libs/binder/include/private/binder
\ No newline at end of file
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index 20f51a5..307c764 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -58,7 +58,8 @@
eOverrideScalingModeChanged = 0x00000800,
eGeometryAppliesWithResize = 0x00001000,
eReparentChildren = 0x00002000,
- eDetachChildren = 0x00004000
+ eDetachChildren = 0x00004000,
+ eRelativeLayerChanged = 0x00008000
};
layer_state_t()
@@ -104,6 +105,8 @@
sp<IGraphicBufferProducer> barrierGbp;
+ sp<IBinder> relativeLayerHandle;
+
// non POD must be last. see write/read
Region transparentRegion;
};
diff --git a/include/ui/Gralloc2.h b/include/ui/Gralloc2.h
new file mode 100644
index 0000000..c59d327
--- /dev/null
+++ b/include/ui/Gralloc2.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2016 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_UI_GRALLOC2_H
+#define ANDROID_UI_GRALLOC2_H
+
+#include <string>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <system/window.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+namespace Gralloc2 {
+
+using hardware::graphics::allocator::V2_0::IAllocator;
+using hardware::graphics::common::V1_0::BufferUsage;
+using hardware::graphics::common::V1_0::PixelFormat;
+using hardware::graphics::mapper::V2_0::BufferDescriptor;
+using hardware::graphics::mapper::V2_0::Error;
+using hardware::graphics::mapper::V2_0::IMapper;
+using hardware::graphics::mapper::V2_0::YCbCrLayout;
+
+// A wrapper to IMapper
+class Mapper {
+public:
+ Mapper();
+
+ // this will be removed and Mapper will be always valid
+ bool valid() const { return (mMapper != nullptr); }
+
+ Error createDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) const;
+
+ // Import a buffer that is from another HAL, another process, or is
+ // cloned.
+ //
+ // The returned handle must be freed with freeBuffer.
+ Error importBuffer(const hardware::hidl_handle& rawHandle,
+ buffer_handle_t* outBufferHandle) const;
+
+ void freeBuffer(buffer_handle_t bufferHandle) const;
+
+ // The ownership of acquireFence is always transferred to the callee, even
+ // on errors.
+ Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, void** outData) const;
+
+ // The ownership of acquireFence is always transferred to the callee, even
+ // on errors.
+ Error lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, YCbCrLayout* outLayout) const;
+
+ // unlock returns a fence sync object (or -1) and the fence sync object is
+ // owned by the caller
+ int unlock(buffer_handle_t bufferHandle) const;
+
+private:
+ sp<IMapper> mMapper;
+};
+
+// A wrapper to IAllocator
+class Allocator {
+public:
+ // An allocator relies on a mapper, and that mapper must be alive at all
+ // time.
+ Allocator(const Mapper& mapper);
+
+ // this will be removed and Allocator will be always valid
+ bool valid() const { return (mAllocator != nullptr); }
+
+ std::string dumpDebugInfo() const;
+
+ /*
+ * The returned buffers are already imported and must not be imported
+ * again. outBufferHandles must point to a space that can contain at
+ * least "count" buffer_handle_t.
+ */
+ Error allocate(BufferDescriptor descriptor, uint32_t count,
+ uint32_t* outStride, buffer_handle_t* outBufferHandles) const;
+
+ Error allocate(BufferDescriptor descriptor,
+ uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+ {
+ return allocate(descriptor, 1, outStride, outBufferHandle);
+ }
+
+ Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t count,
+ uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+ {
+ BufferDescriptor descriptor;
+ Error error = mMapper.createDescriptor(descriptorInfo, &descriptor);
+ if (error == Error::NONE) {
+ error = allocate(descriptor, count, outStride, outBufferHandles);
+ }
+ return error;
+ }
+
+ Error allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ uint32_t* outStride, buffer_handle_t* outBufferHandle) const
+ {
+ return allocate(descriptorInfo, 1, outStride, outBufferHandle);
+ }
+
+private:
+ const Mapper& mMapper;
+ sp<IAllocator> mAllocator;
+};
+
+} // namespace Gralloc2
+
+} // namespace android
+
+#endif // ANDROID_UI_GRALLOC2_H
diff --git a/include/ui/GrallocAllocator.h b/include/ui/GrallocAllocator.h
deleted file mode 100644
index dd0f9e0..0000000
--- a/include/ui/GrallocAllocator.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2016 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_UI_GRALLOC_ALLOCATOR_H
-#define ANDROID_UI_GRALLOC_ALLOCATOR_H
-
-#include <string>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <utils/StrongPointer.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::allocator::V2_0::BufferDescriptor;
-using hardware::graphics::allocator::V2_0::Buffer;
-using hardware::graphics::allocator::V2_0::IAllocator;
-using hardware::graphics::allocator::V2_0::IAllocatorClient;
-using hardware::graphics::common::V1_0::PixelFormat;
-
-// Allocator is a wrapper to IAllocator, a proxy to server-side allocator.
-class Allocator {
-public:
- Allocator();
-
- // this will be removed and Allocator will be always valid
- bool valid() const { return (mAllocator != nullptr); }
-
- std::string dumpDebugInfo() const;
-
- Error createBufferDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
- BufferDescriptor* outDescriptor) const;
- void destroyBufferDescriptor(BufferDescriptor descriptor) const;
-
- Error allocate(BufferDescriptor descriptor, Buffer* outBuffer) const;
- void free(Buffer buffer) const;
-
- Error exportHandle(BufferDescriptor descriptor, Buffer buffer,
- native_handle_t** outBufferHandle) const;
-
-private:
- sp<IAllocator> mAllocator;
- sp<IAllocatorClient> mClient;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_ALLOCATOR_H
diff --git a/include/ui/GrallocMapper.h b/include/ui/GrallocMapper.h
deleted file mode 100644
index 5a0d64b..0000000
--- a/include/ui/GrallocMapper.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2016 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_UI_GRALLOC_MAPPER_H
-#define ANDROID_UI_GRALLOC_MAPPER_H
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <system/window.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-using hardware::graphics::allocator::V2_0::Error;
-using hardware::graphics::allocator::V2_0::ProducerUsage;
-using hardware::graphics::allocator::V2_0::ConsumerUsage;
-using hardware::graphics::common::V1_0::PixelFormat;
-using hardware::graphics::mapper::V2_0::FlexLayout;
-using hardware::graphics::mapper::V2_0::BackingStore;
-using hardware::graphics::mapper::V2_0::IMapper;
-
-// Mapper is a wrapper to IMapper, a client-side graphics buffer mapper.
-class Mapper {
-public:
- Mapper();
-
- // this will be removed and Mapper will be always valid
- bool valid() const { return (mMapper != nullptr); }
-
- Error retain(buffer_handle_t handle) const;
- void release(buffer_handle_t handle) const;
-
- Error getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const;
- Error getFormat(buffer_handle_t handle, int32_t* outFormat) const;
- Error getLayerCount(buffer_handle_t handle, uint32_t* outLayerCount) const;
- Error getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const;
- Error getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const;
- Error getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const;
- Error getStride(buffer_handle_t handle, uint32_t* outStride) const;
-
- Error lock(buffer_handle_t handle, uint64_t producerUsage,
- uint64_t consumerUsage, const IMapper::Rect& accessRegion,
- int acquireFence, void** outData) const;
- Error lock(buffer_handle_t handle, uint64_t producerUsage,
- uint64_t consumerUsage, const IMapper::Rect& accessRegion,
- int acquireFence, FlexLayout* outLayout) const;
- int unlock(buffer_handle_t handle) const;
-
-private:
- sp<IMapper> mMapper;
-};
-
-} // namespace Gralloc2
-
-} // namespace android
-
-#endif // ANDROID_UI_GRALLOC_MAPPER_H
diff --git a/include/ui/GraphicBufferAllocator.h b/include/ui/GraphicBufferAllocator.h
index e97122b..95eb8fd 100644
--- a/include/ui/GraphicBufferAllocator.h
+++ b/include/ui/GraphicBufferAllocator.h
@@ -96,8 +96,8 @@
GraphicBufferAllocator();
~GraphicBufferAllocator();
- const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
GraphicBufferMapper& mMapper;
+ const std::unique_ptr<const Gralloc2::Allocator> mAllocator;
std::unique_ptr<Gralloc1::Loader> mLoader;
std::unique_ptr<Gralloc1::Device> mDevice;
diff --git a/include/ui/GraphicBufferMapper.h b/include/ui/GraphicBufferMapper.h
index b6d4021..d69f8fc 100644
--- a/include/ui/GraphicBufferMapper.h
+++ b/include/ui/GraphicBufferMapper.h
@@ -47,31 +47,15 @@
public:
static inline GraphicBufferMapper& get() { return getInstance(); }
- // This may NOT work on devices without a valid Gralloc2::Mapper.
- status_t registerBuffer(buffer_handle_t handle);
+ // The imported outHandle must be freed with freeBuffer when no longer
+ // needed. rawHandle is owned by the caller.
+ status_t importBuffer(buffer_handle_t rawHandle,
+ buffer_handle_t* outHandle);
- status_t registerBuffer(const GraphicBuffer* buffer);
+ // This is temporary and will be removed soon
+ status_t importBuffer(const GraphicBuffer* buffer);
- status_t unregisterBuffer(buffer_handle_t handle);
-
- status_t getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const;
-
- status_t getFormat(buffer_handle_t handle, int32_t* outFormat) const;
-
- status_t getLayerCount(buffer_handle_t handle,
- uint32_t* outLayerCount) const;
-
- status_t getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const;
-
- status_t getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const;
-
- status_t getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const;
-
- status_t getStride(buffer_handle_t handle, uint32_t* outStride) const;
+ status_t freeBuffer(buffer_handle_t handle);
status_t lock(buffer_handle_t handle,
uint32_t usage, const Rect& bounds, void** vaddr);
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index b225128..204fdb5 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -12,9 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+cc_library_headers {
+ name: "libbinder_headers",
+ export_include_dirs: ["include"],
+}
+
cc_library {
name: "libbinder",
+ // for vndbinder
+ vendor_available: true,
+
srcs: [
"AppOpsManager.cpp",
"Binder.cpp",
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 3aeff2e..c7a0f43 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -23,6 +23,7 @@
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
+#include <utils/CallStack.h>
#include <private/binder/Static.h>
@@ -136,7 +137,12 @@
unsigned n;
for (n = 0; n < 5; n++){
if (n > 0) {
- ALOGI("Waiting for service %s...", String8(name).string());
+ if (!strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder")) {
+ ALOGI("Waiting for vendor service %s...", String8(name).string());
+ CallStack stack(LOG_TAG);
+ } else {
+ ALOGI("Waiting for service %s...", String8(name).string());
+ }
sleep(1);
}
sp<IBinder> svc = checkService(name);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index da94305..39bb078 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -553,6 +553,14 @@
return err;
}
+int Parcel::compareData(const Parcel& other) {
+ size_t size = dataSize();
+ if (size != other.dataSize()) {
+ return size < other.dataSize() ? -1 : 1;
+ }
+ return memcmp(data(), other.data(), size);
+}
+
bool Parcel::allowFds() const
{
return mAllowFds;
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 5c4cfe2..add5e74 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -79,6 +79,11 @@
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
+ // Allow for initWithDriver to be called repeatedly with the same
+ // driver.
+ if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
+ return gProcess;
+ }
LOG_ALWAYS_FATAL("ProcessState was already initialized.");
}
gProcess = new ProcessState(driver);
@@ -317,6 +322,10 @@
androidSetThreadName( makeBinderThreadName().string() );
}
+String8 ProcessState::getDriverName() {
+ return mDriverName;
+}
+
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
@@ -346,7 +355,8 @@
}
ProcessState::ProcessState(const char *driver)
- : mDriverFD(open_driver(driver))
+ : mDriverName(String8(driver))
+ , mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
@@ -367,6 +377,7 @@
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
+ mDriverName.clear();
}
}
diff --git a/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
similarity index 100%
rename from include/binder/AppOpsManager.h
rename to libs/binder/include/binder/AppOpsManager.h
diff --git a/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
similarity index 100%
rename from include/binder/Binder.h
rename to libs/binder/include/binder/Binder.h
diff --git a/include/binder/BinderService.h b/libs/binder/include/binder/BinderService.h
similarity index 100%
rename from include/binder/BinderService.h
rename to libs/binder/include/binder/BinderService.h
diff --git a/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
similarity index 100%
rename from include/binder/BpBinder.h
rename to libs/binder/include/binder/BpBinder.h
diff --git a/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
similarity index 100%
rename from include/binder/BufferedTextOutput.h
rename to libs/binder/include/binder/BufferedTextOutput.h
diff --git a/include/binder/Debug.h b/libs/binder/include/binder/Debug.h
similarity index 100%
rename from include/binder/Debug.h
rename to libs/binder/include/binder/Debug.h
diff --git a/include/binder/IActivityManager.h b/libs/binder/include/binder/IActivityManager.h
similarity index 100%
rename from include/binder/IActivityManager.h
rename to libs/binder/include/binder/IActivityManager.h
diff --git a/include/binder/IAppOpsCallback.h b/libs/binder/include/binder/IAppOpsCallback.h
similarity index 100%
rename from include/binder/IAppOpsCallback.h
rename to libs/binder/include/binder/IAppOpsCallback.h
diff --git a/include/binder/IAppOpsService.h b/libs/binder/include/binder/IAppOpsService.h
similarity index 100%
rename from include/binder/IAppOpsService.h
rename to libs/binder/include/binder/IAppOpsService.h
diff --git a/include/binder/IBatteryStats.h b/libs/binder/include/binder/IBatteryStats.h
similarity index 100%
rename from include/binder/IBatteryStats.h
rename to libs/binder/include/binder/IBatteryStats.h
diff --git a/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
similarity index 100%
rename from include/binder/IBinder.h
rename to libs/binder/include/binder/IBinder.h
diff --git a/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
similarity index 100%
rename from include/binder/IInterface.h
rename to libs/binder/include/binder/IInterface.h
diff --git a/include/binder/IMediaResourceMonitor.h b/libs/binder/include/binder/IMediaResourceMonitor.h
similarity index 100%
rename from include/binder/IMediaResourceMonitor.h
rename to libs/binder/include/binder/IMediaResourceMonitor.h
diff --git a/include/binder/IMemory.h b/libs/binder/include/binder/IMemory.h
similarity index 100%
rename from include/binder/IMemory.h
rename to libs/binder/include/binder/IMemory.h
diff --git a/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
similarity index 100%
rename from include/binder/IPCThreadState.h
rename to libs/binder/include/binder/IPCThreadState.h
diff --git a/include/binder/IPermissionController.h b/libs/binder/include/binder/IPermissionController.h
similarity index 100%
rename from include/binder/IPermissionController.h
rename to libs/binder/include/binder/IPermissionController.h
diff --git a/include/binder/IProcessInfoService.h b/libs/binder/include/binder/IProcessInfoService.h
similarity index 100%
rename from include/binder/IProcessInfoService.h
rename to libs/binder/include/binder/IProcessInfoService.h
diff --git a/include/binder/IResultReceiver.h b/libs/binder/include/binder/IResultReceiver.h
similarity index 100%
rename from include/binder/IResultReceiver.h
rename to libs/binder/include/binder/IResultReceiver.h
diff --git a/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h
similarity index 100%
rename from include/binder/IServiceManager.h
rename to libs/binder/include/binder/IServiceManager.h
diff --git a/include/binder/IShellCallback.h b/libs/binder/include/binder/IShellCallback.h
similarity index 100%
rename from include/binder/IShellCallback.h
rename to libs/binder/include/binder/IShellCallback.h
diff --git a/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
similarity index 100%
rename from include/binder/IpPrefix.h
rename to libs/binder/include/binder/IpPrefix.h
diff --git a/include/binder/Map.h b/libs/binder/include/binder/Map.h
similarity index 100%
rename from include/binder/Map.h
rename to libs/binder/include/binder/Map.h
diff --git a/include/binder/MemoryBase.h b/libs/binder/include/binder/MemoryBase.h
similarity index 100%
rename from include/binder/MemoryBase.h
rename to libs/binder/include/binder/MemoryBase.h
diff --git a/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
similarity index 100%
rename from include/binder/MemoryDealer.h
rename to libs/binder/include/binder/MemoryDealer.h
diff --git a/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
similarity index 100%
rename from include/binder/MemoryHeapBase.h
rename to libs/binder/include/binder/MemoryHeapBase.h
diff --git a/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
similarity index 99%
rename from include/binder/Parcel.h
rename to libs/binder/include/binder/Parcel.h
index cf2fa47..5d36526 100644
--- a/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -72,6 +72,8 @@
status_t appendFrom(const Parcel *parcel,
size_t start, size_t len);
+ int compareData(const Parcel& other);
+
bool allowFds() const;
bool pushAllowFds(bool allowFds);
void restoreAllowFds(bool lastValue);
diff --git a/include/binder/Parcelable.h b/libs/binder/include/binder/Parcelable.h
similarity index 100%
rename from include/binder/Parcelable.h
rename to libs/binder/include/binder/Parcelable.h
diff --git a/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
similarity index 100%
rename from include/binder/PermissionCache.h
rename to libs/binder/include/binder/PermissionCache.h
diff --git a/include/binder/PersistableBundle.h b/libs/binder/include/binder/PersistableBundle.h
similarity index 100%
rename from include/binder/PersistableBundle.h
rename to libs/binder/include/binder/PersistableBundle.h
diff --git a/include/binder/ProcessInfoService.h b/libs/binder/include/binder/ProcessInfoService.h
similarity index 100%
rename from include/binder/ProcessInfoService.h
rename to libs/binder/include/binder/ProcessInfoService.h
diff --git a/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
similarity index 97%
rename from include/binder/ProcessState.h
rename to libs/binder/include/binder/ProcessState.h
index 05e9d09..1ef045d 100644
--- a/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -69,6 +69,8 @@
status_t setThreadPoolMaxThreadCount(size_t maxThreads);
void giveThreadPoolName();
+ String8 getDriverName();
+
private:
friend class IPCThreadState;
@@ -86,6 +88,7 @@
handle_entry* lookupHandleLocked(int32_t handle);
+ String8 mDriverName;
int mDriverFD;
void* mVMStart;
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 44c1352..3bfd462 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -26,6 +26,8 @@
#include <utils/CallStack.h>
#endif
+#include <utils/NativeHandle.h>
+
#include <functional>
#include <type_traits>
@@ -44,6 +46,19 @@
status_t write(Parcel* parcel, bool b) const {
return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
}
+ template <typename E>
+ typename std::enable_if<std::is_enum<E>::value, status_t>::type read(const Parcel& parcel,
+ E* e) const {
+ typename std::underlying_type<E>::type u{};
+ status_t result = read(parcel, &u);
+ *e = static_cast<E>(u);
+ return result;
+ }
+ template <typename E>
+ typename std::enable_if<std::is_enum<E>::value, status_t>::type write(Parcel* parcel,
+ E e) const {
+ return write(parcel, static_cast<typename std::underlying_type<E>::type>(e));
+ }
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
@@ -55,6 +70,17 @@
return callParcel("write(Flattenable)", [&]() { return parcel->write(t); });
}
template <typename T>
+ typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
+ const Parcel& parcel, sp<T>* t) const {
+ *t = new T{};
+ return callParcel("read(sp<Flattenable>)", [&]() { return parcel.read(*(t->get())); });
+ }
+ template <typename T>
+ typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
+ Parcel* parcel, const sp<T>& t) const {
+ return callParcel("write(sp<Flattenable>)", [&]() { return parcel->write(*(t.get())); });
+ }
+ template <typename T>
typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); });
@@ -64,6 +90,18 @@
Parcel* parcel, const T& t) const {
return callParcel("write(LightFlattenable)", [&]() { return parcel->write(t); });
}
+ template <typename NH>
+ typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type read(
+ const Parcel& parcel, NH* nh) {
+ *nh = NativeHandle::create(parcel.readNativeHandle(), true);
+ return NO_ERROR;
+ }
+ template <typename NH>
+ typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type write(
+ Parcel* parcel, const NH& nh) {
+ return callParcel("write(sp<NativeHandle>)",
+ [&]() { return parcel->writeNativeHandle(nh->handle()); });
+ }
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
@@ -81,7 +119,8 @@
return callParcel("writeString8", [&]() { return parcel->writeString8(str); });
}
template <typename T>
- status_t read(const Parcel& parcel, sp<T>* pointer) const {
+ typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type read(
+ const Parcel& parcel, sp<T>* pointer) const {
return callParcel("readNullableStrongBinder",
[&]() { return parcel.readNullableStrongBinder(pointer); });
}
@@ -92,10 +131,27 @@
[&]() { return parcel->writeStrongBinder(pointer); });
}
template <typename T>
+ typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type read(
+ const Parcel& parcel, sp<T>* pointer) const {
+ return callParcel("readNullableStrongBinder[IInterface]",
+ [&]() { return parcel.readNullableStrongBinder(pointer); });
+ }
+ template <typename T>
typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& interface) const {
return write(parcel, IInterface::asBinder(interface));
}
+ template <typename T>
+ typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
+ const Parcel& parcel, std::vector<T>* v) const {
+ return callParcel("readParcelableVector", [&]() { return parcel.readParcelableVector(v); });
+ }
+ template <typename T>
+ typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
+ Parcel* parcel, const std::vector<T>& v) const {
+ return callParcel("writeParcelableVector",
+ [&]() { return parcel->writeParcelableVector(v); });
+ }
// Templates to handle integral types. We use a struct template to require that the called
// function exactly matches the signedness and size of the argument (e.g., the argument isn't
@@ -121,6 +177,24 @@
}
};
template <typename I>
+ struct HandleInt<true, 8, I> {
+ static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
+ return handler.callParcel("readInt64", [&]() { return parcel.readInt64(i); });
+ }
+ static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
+ return handler.callParcel("writeInt64", [&]() { return parcel->writeInt64(i); });
+ }
+ };
+ template <typename I>
+ struct HandleInt<false, 8, I> {
+ static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
+ return handler.callParcel("readUint64", [&]() { return parcel.readUint64(i); });
+ }
+ static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
+ return handler.callParcel("writeUint64", [&]() { return parcel->writeUint64(i); });
+ }
+ };
+ template <typename I>
typename std::enable_if<std::is_integral<I>::value, status_t>::type read(const Parcel& parcel,
I* i) const {
return HandleInt<std::is_signed<I>::value, sizeof(I), I>::read(*this, parcel, i);
diff --git a/include/binder/Status.h b/libs/binder/include/binder/Status.h
similarity index 100%
rename from include/binder/Status.h
rename to libs/binder/include/binder/Status.h
diff --git a/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
similarity index 100%
rename from include/binder/TextOutput.h
rename to libs/binder/include/binder/TextOutput.h
diff --git a/include/binder/Value.h b/libs/binder/include/binder/Value.h
similarity index 100%
rename from include/binder/Value.h
rename to libs/binder/include/binder/Value.h
diff --git a/include/private/binder/ParcelValTypes.h b/libs/binder/include/private/binder/ParcelValTypes.h
similarity index 100%
rename from include/private/binder/ParcelValTypes.h
rename to libs/binder/include/private/binder/ParcelValTypes.h
diff --git a/include/private/binder/Static.h b/libs/binder/include/private/binder/Static.h
similarity index 100%
rename from include/private/binder/Static.h
rename to libs/binder/include/private/binder/Static.h
diff --git a/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
similarity index 100%
rename from include/private/binder/binder_module.h
rename to libs/binder/include/private/binder/binder_module.h
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 1ee4b6f..853ca16 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -100,6 +100,7 @@
shared_libs: [
"libbinder",
+ "libcutils",
"liblog",
"libutils",
],
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index d1f63a7..6a16e24 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -28,13 +28,26 @@
#include <gtest/gtest.h>
#pragma clang diagnostic pop
+#include <utils/LightRefBase.h>
+#include <utils/NativeHandle.h>
+
+#include <cutils/native_handle.h>
+
#include <optional>
+#include <sys/eventfd.h>
+
using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
namespace android {
namespace tests {
+enum class TestEnum : uint32_t {
+ INVALID = 0,
+ INITIAL = 1,
+ FINAL = 2,
+};
+
// This class serves two purposes:
// 1) It ensures that the implementation doesn't require copying or moving the data (for
// efficiency purposes)
@@ -90,6 +103,48 @@
int32_t value = 0;
};
+// It seems like this should be able to inherit from TestFlattenable (to avoid duplicating code),
+// but the SafeInterface logic can't easily be extended to find an indirect Flattenable<T>
+// base class
+class TestLightRefBaseFlattenable : public Flattenable<TestLightRefBaseFlattenable>,
+ public LightRefBase<TestLightRefBaseFlattenable> {
+public:
+ TestLightRefBaseFlattenable() = default;
+ explicit TestLightRefBaseFlattenable(int32_t v) : value(v) {}
+
+ // Flattenable protocol
+ size_t getFlattenedSize() const { return sizeof(value); }
+ size_t getFdCount() const { return 0; }
+ status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
+ FlattenableUtils::write(buffer, size, value);
+ return NO_ERROR;
+ }
+ status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
+ FlattenableUtils::read(buffer, size, value);
+ return NO_ERROR;
+ }
+
+ int32_t value = 0;
+};
+
+class TestParcelable : public Parcelable {
+public:
+ TestParcelable() = default;
+ explicit TestParcelable(int32_t value) : mValue(value) {}
+ TestParcelable(const TestParcelable& other) : TestParcelable(other.mValue) {}
+ TestParcelable(TestParcelable&& other) : TestParcelable(other.mValue) {}
+
+ // Parcelable interface
+ status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
+ status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }
+
+ int32_t getValue() const { return mValue; }
+ void setValue(int32_t value) { mValue = value; }
+
+private:
+ int32_t mValue = 0;
+};
+
class ExitOnDeath : public IBinder::DeathRecipient {
public:
~ExitOnDeath() override = default;
@@ -161,13 +216,19 @@
SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
ReturnsNoMemory,
LogicalNot,
+ ModifyEnum,
IncrementFlattenable,
IncrementLightFlattenable,
+ IncrementLightRefBaseFlattenable,
+ IncrementNativeHandle,
IncrementNoCopyNoMove,
+ IncrementParcelableVector,
ToUpper,
CallMeBack,
IncrementInt32,
IncrementUint32,
+ IncrementInt64,
+ IncrementUint64,
IncrementTwo,
Last,
};
@@ -181,15 +242,23 @@
// These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
virtual status_t logicalNot(bool a, bool* notA) const = 0;
+ virtual status_t modifyEnum(TestEnum a, TestEnum* b) const = 0;
virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
virtual status_t increment(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const = 0;
+ virtual status_t increment(const sp<TestLightRefBaseFlattenable>& a,
+ sp<TestLightRefBaseFlattenable>* aPlusOne) const = 0;
+ virtual status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const = 0;
virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
+ virtual status_t increment(const std::vector<TestParcelable>& a,
+ std::vector<TestParcelable>* aPlusOne) const = 0;
virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
// As mentioned above, sp<IBinder> is already tested by setDeathToken
virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
+ virtual status_t increment(int64_t a, int64_t* aPlusOne) const = 0;
+ virtual status_t increment(uint64_t a, uint64_t* aPlusOne) const = 0;
// This tests that input/output parameter interleaving works correctly
virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
@@ -213,6 +282,10 @@
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
}
+ status_t modifyEnum(TestEnum a, TestEnum* b) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ return callRemote<decltype(&ISafeInterfaceTest::modifyEnum)>(Tag::ModifyEnum, a, b);
+ }
status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
using Signature =
status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
@@ -226,12 +299,31 @@
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne);
}
+ status_t increment(const sp<TestLightRefBaseFlattenable>& a,
+ sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
+ using Signature = status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
+ sp<TestLightRefBaseFlattenable>*) const;
+ return callRemote<Signature>(Tag::IncrementLightRefBaseFlattenable, a, aPlusOne);
+ }
+ status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ using Signature =
+ status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&, sp<NativeHandle>*) const;
+ return callRemote<Signature>(Tag::IncrementNativeHandle, a, aPlusOne);
+ }
status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
NoCopyNoMove* aPlusOne) const;
return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
}
+ status_t increment(const std::vector<TestParcelable>& a,
+ std::vector<TestParcelable>* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ using Signature = status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
+ std::vector<TestParcelable>*);
+ return callRemote<Signature>(Tag::IncrementParcelableVector, a, aPlusOne);
+ }
status_t toUpper(const String8& str, String8* upperStr) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
@@ -251,6 +343,16 @@
using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
return callRemote<Signature>(Tag::IncrementUint32, a, aPlusOne);
}
+ status_t increment(int64_t a, int64_t* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
+ return callRemote<Signature>(Tag::IncrementInt64, a, aPlusOne);
+ }
+ status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
+ return callRemote<Signature>(Tag::IncrementUint64, a, aPlusOne);
+ }
status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature =
@@ -290,6 +392,11 @@
*notA = !a;
return NO_ERROR;
}
+ status_t modifyEnum(TestEnum a, TestEnum* b) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ *b = (a == TestEnum::INITIAL) ? TestEnum::FINAL : TestEnum::INVALID;
+ return NO_ERROR;
+ }
status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
aPlusOne->value = a.value + 1;
@@ -301,11 +408,42 @@
aPlusOne->value = a.value + 1;
return NO_ERROR;
}
+ status_t increment(const sp<TestLightRefBaseFlattenable>& a,
+ sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ *aPlusOne = new TestLightRefBaseFlattenable(a->value + 1);
+ return NO_ERROR;
+ }
+ status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ native_handle* rawHandle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
+ if (rawHandle == nullptr) return NO_MEMORY;
+
+ // Copy the fd over directly
+ rawHandle->data[0] = dup(a->handle()->data[0]);
+
+ // Increment the int
+ rawHandle->data[1] = a->handle()->data[1] + 1;
+
+ // This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
+ // the native_handle when it goes out of scope
+ *aPlusOne = NativeHandle::create(rawHandle, true);
+ return NO_ERROR;
+ }
status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
aPlusOne->setValue(a.getValue() + 1);
return NO_ERROR;
}
+ status_t increment(const std::vector<TestParcelable>& a,
+ std::vector<TestParcelable>* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ aPlusOne->resize(a.size());
+ for (size_t i = 0; i < a.size(); ++i) {
+ (*aPlusOne)[i].setValue(a[i].getValue() + 1);
+ }
+ return NO_ERROR;
+ }
status_t toUpper(const String8& str, String8* upperStr) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*upperStr = str;
@@ -326,6 +464,16 @@
*aPlusOne = a + 1;
return NO_ERROR;
}
+ status_t increment(int64_t a, int64_t* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ *aPlusOne = a + 1;
+ return NO_ERROR;
+ }
+ status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ *aPlusOne = a + 1;
+ return NO_ERROR;
+ }
status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = a + 1;
@@ -349,6 +497,9 @@
case ISafeInterfaceTest::Tag::LogicalNot: {
return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
}
+ case ISafeInterfaceTest::Tag::ModifyEnum: {
+ return callLocal(data, reply, &ISafeInterfaceTest::modifyEnum);
+ }
case ISafeInterfaceTest::Tag::IncrementFlattenable: {
using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
TestFlattenable* aPlusOne) const;
@@ -360,11 +511,28 @@
TestLightFlattenable* aPlusOne) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
+ case ISafeInterfaceTest::Tag::IncrementLightRefBaseFlattenable: {
+ using Signature =
+ status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
+ sp<TestLightRefBaseFlattenable>*) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+ }
+ case ISafeInterfaceTest::Tag::IncrementNativeHandle: {
+ using Signature = status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&,
+ sp<NativeHandle>*) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+ }
case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: {
using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
NoCopyNoMove* aPlusOne) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
+ case ISafeInterfaceTest::Tag::IncrementParcelableVector: {
+ using Signature =
+ status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
+ std::vector<TestParcelable>*) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+ }
case ISafeInterfaceTest::Tag::ToUpper: {
return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
}
@@ -379,6 +547,14 @@
using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
+ case ISafeInterfaceTest::Tag::IncrementInt64: {
+ using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+ }
+ case ISafeInterfaceTest::Tag::IncrementUint64: {
+ using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+ }
case ISafeInterfaceTest::Tag::IncrementTwo: {
using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
int32_t*) const;
@@ -465,6 +641,14 @@
ASSERT_EQ(!b, notB);
}
+TEST_F(SafeInterfaceTest, TestModifyEnum) {
+ const TestEnum a = TestEnum::INITIAL;
+ TestEnum b = TestEnum::INVALID;
+ status_t result = mSafeInterfaceTest->modifyEnum(a, &b);
+ ASSERT_EQ(NO_ERROR, result);
+ ASSERT_EQ(TestEnum::FINAL, b);
+}
+
TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
const TestFlattenable a{1};
TestFlattenable aPlusOne{0};
@@ -481,6 +665,56 @@
ASSERT_EQ(a.value + 1, aPlusOne.value);
}
+TEST_F(SafeInterfaceTest, TestIncrementLightRefBaseFlattenable) {
+ sp<TestLightRefBaseFlattenable> a = new TestLightRefBaseFlattenable{1};
+ sp<TestLightRefBaseFlattenable> aPlusOne;
+ status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+ ASSERT_EQ(NO_ERROR, result);
+ ASSERT_NE(nullptr, aPlusOne.get());
+ ASSERT_EQ(a->value + 1, aPlusOne->value);
+}
+
+namespace { // Anonymous namespace
+
+bool fdsAreEquivalent(int a, int b) {
+ struct stat statA {};
+ struct stat statB {};
+ if (fstat(a, &statA) != 0) return false;
+ if (fstat(b, &statB) != 0) return false;
+ return (statA.st_dev == statB.st_dev) && (statA.st_ino == statB.st_ino);
+}
+
+} // Anonymous namespace
+
+TEST_F(SafeInterfaceTest, TestIncrementNativeHandle) {
+ // Create an fd we can use to send and receive from the remote process
+ base::unique_fd eventFd{eventfd(0 /*initval*/, 0 /*flags*/)};
+ ASSERT_NE(-1, eventFd);
+
+ // Determine the maximum number of fds this process can have open
+ struct rlimit limit {};
+ ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &limit));
+ uint32_t maxFds = static_cast<uint32_t>(limit.rlim_cur);
+
+ // Perform this test enough times to rule out fd leaks
+ for (uint32_t iter = 0; iter < (2 * maxFds); ++iter) {
+ native_handle* handle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
+ ASSERT_NE(nullptr, handle);
+ handle->data[0] = dup(eventFd.get());
+ handle->data[1] = 1;
+
+ // This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
+ // the native_handle when it goes out of scope
+ sp<NativeHandle> a = NativeHandle::create(handle, true);
+
+ sp<NativeHandle> aPlusOne;
+ status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+ ASSERT_EQ(NO_ERROR, result);
+ ASSERT_TRUE(fdsAreEquivalent(a->handle()->data[0], aPlusOne->handle()->data[0]));
+ ASSERT_EQ(a->handle()->data[1] + 1, aPlusOne->handle()->data[1]);
+ }
+}
+
TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
const NoCopyNoMove a{1};
NoCopyNoMove aPlusOne{0};
@@ -489,6 +723,16 @@
ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
}
+TEST_F(SafeInterfaceTest, TestIncremementParcelableVector) {
+ const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
+ std::vector<TestParcelable> aPlusOne;
+ status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+ ASSERT_EQ(a.size(), aPlusOne.size());
+ for (size_t i = 0; i < a.size(); ++i) {
+ ASSERT_EQ(a[i].getValue() + 1, aPlusOne[i].getValue());
+ }
+}
+
TEST_F(SafeInterfaceTest, TestToUpper) {
const String8 str{"Hello, world!"};
String8 upperStr;
@@ -544,6 +788,22 @@
ASSERT_EQ(a + 1, aPlusOne);
}
+TEST_F(SafeInterfaceTest, TestIncrementInt64) {
+ const int64_t a = 1;
+ int64_t aPlusOne = 0;
+ status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+ ASSERT_EQ(NO_ERROR, result);
+ ASSERT_EQ(a + 1, aPlusOne);
+}
+
+TEST_F(SafeInterfaceTest, TestIncrementUint64) {
+ const uint64_t a = 1;
+ uint64_t aPlusOne = 0;
+ status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+ ASSERT_EQ(NO_ERROR, result);
+ ASSERT_EQ(a + 1, aPlusOne);
+}
+
TEST_F(SafeInterfaceTest, TestIncrementTwo) {
const int32_t a = 1;
int32_t aPlusOne = 0;
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index fe9e05a..13f03b1 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -40,7 +40,7 @@
// GOOD_SYNC_MIN is considered as good
#define GOOD_SYNC_MIN (0.6)
-#define DUMP_PRICISION 3
+#define DUMP_PRESICION 2
string trace_path = "/sys/kernel/debug/tracing";
@@ -246,10 +246,11 @@
double worst = (double)m_worst / 1.0E6;
double average = (double)m_total_time / m_transactions / 1.0E6;
// FIXME: libjson?
- cout << std::setprecision(DUMP_PRICISION) << "{ \"avg\":" << setw(5) << left
- << average << ", \"wst\":" << setw(5) << left << worst
- << ", \"bst\":" << setw(5) << left << best << ", \"miss\":" << setw(5)
- << left << m_miss << ", \"meetR\":" << setw(3) << left
+ int W = DUMP_PRESICION + 2;
+ cout << setprecision(DUMP_PRESICION) << "{ \"avg\":" << setw(W) << left
+ << average << ",\"wst\":" << setw(W) << left << worst
+ << ",\"bst\":" << setw(W) << left << best << ",\"miss\":" << left
+ << m_miss << ",\"meetR\":" << left << setprecision(DUMP_PRESICION + 3)
<< (1.0 - (double)m_miss / m_transactions) << "}";
}
};
@@ -272,8 +273,15 @@
}
}
+typedef struct {
+ void* result;
+ int target;
+} thread_priv_t;
+
static void* thread_start(void* p) {
- Results* results_fifo = (Results*)p;
+ thread_priv_t* priv = (thread_priv_t*)p;
+ int target = priv->target;
+ Results* results_fifo = (Results*)priv->result;
Parcel data, reply;
Tick sta, end;
@@ -281,7 +289,7 @@
thread_dump("fifo-caller");
sta = tickNow();
- status_t ret = workers[0]->transact(BINDER_NOP, data, &reply);
+ status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
end = tickNow();
results_fifo->add_time(tickNano(sta, end));
@@ -291,16 +299,19 @@
}
// create a fifo thread to transact and wait it to finished
-static void thread_transaction(Results* results_fifo) {
+static void thread_transaction(int target, Results* results_fifo) {
+ thread_priv_t thread_priv;
void* dummy;
pthread_t thread;
pthread_attr_t attr;
struct sched_param param;
+ thread_priv.target = target;
+ thread_priv.result = results_fifo;
ASSERT(!pthread_attr_init(&attr));
ASSERT(!pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
ASSERT(!pthread_attr_setschedparam(&attr, ¶m));
- ASSERT(!pthread_create(&thread, &attr, &thread_start, results_fifo));
+ ASSERT(!pthread_create(&thread, &attr, &thread_start, &thread_priv));
ASSERT(!pthread_join(thread, &dummy));
}
@@ -316,7 +327,9 @@
sp<IServiceManager> serviceMgr = defaultServiceManager();
sp<BinderWorkerService> service = new BinderWorkerService;
serviceMgr->addService(generateServiceName(num), service);
+ // init done
p.signal();
+ // wait for kick-off
p.wait();
// If client/server pairs, then half the workers are
@@ -338,7 +351,7 @@
int target = num % server_count;
// 1. transaction by fifo thread
- thread_transaction(&results_fifo);
+ thread_transaction(target, &results_fifo);
parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
thread_dump("other-caller");
@@ -356,6 +369,7 @@
p.wait();
p.send(&dummy);
+ // wait for kill
p.wait();
// Client for each pair dump here
if (is_client(num)) {
@@ -367,10 +381,10 @@
<< "\"S\":" << (no_trans - no_sync) << ",\"I\":" << no_trans << ","
<< "\"R\":" << sync_ratio << "," << endl;
- cout << " \"other_ms\":";
+ cout << " \"other_ms\":";
results_other.dump();
cout << "," << endl;
- cout << " \"fifo_ms\": ";
+ cout << " \"fifo_ms\": ";
results_fifo.dump();
cout << endl;
cout << "}," << endl;
@@ -463,12 +477,17 @@
for (int i = 0; i < no_process; i++) {
pipes.push_back(make_process(i, iterations, no_process, payload_size));
}
+ // wait for init done
wait_all(pipes);
+ // kick-off iterations
signal_all(pipes);
+ // wait for completion
wait_all(pipes);
+ // start to send result
signal_all(pipes);
for (int i = 0; i < no_process; i++) {
int status;
+ // kill
pipes[i].signal();
wait(&status);
// the exit status is number of transactions without priority inheritance
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 90ab286..5eafb2c 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -79,11 +79,9 @@
"DisplayEventReceiver.cpp",
"FrameTimestamps.cpp",
"GLConsumer.cpp",
- "GraphicBufferAlloc.cpp",
"GuiConfig.cpp",
"IDisplayEventConnection.cpp",
"IConsumerListener.cpp",
- "IGraphicBufferAlloc.cpp",
"IGraphicBufferConsumer.cpp",
"IGraphicBufferProducer.cpp",
"IProducerListener.cpp",
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 13692eb..4151212 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -79,14 +79,13 @@
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
- const sp<IGraphicBufferAlloc>& allocator,
bool consumerIsSurfaceFlinger) {
LOG_ALWAYS_FATAL_IF(outProducer == NULL,
"BufferQueue: outProducer must not be NULL");
LOG_ALWAYS_FATAL_IF(outConsumer == NULL,
"BufferQueue: outConsumer must not be NULL");
- sp<BufferQueueCore> core(new BufferQueueCore(allocator));
+ sp<BufferQueueCore> core(new BufferQueueCore());
LOG_ALWAYS_FATAL_IF(core == NULL,
"BufferQueue: failed to create BufferQueueCore");
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index d66aa1a..cd8e696 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -675,12 +675,13 @@
return NO_ERROR;
}
-void BufferQueueConsumer::setConsumerName(const String8& name) {
+status_t BufferQueueConsumer::setConsumerName(const String8& name) {
ATRACE_CALL();
BQ_LOGV("setConsumerName: '%s'", name.string());
Mutex::Autolock lock(mCore->mMutex);
mCore->mConsumerName = name;
mConsumerName = name;
+ return NO_ERROR;
}
status_t BufferQueueConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
@@ -716,9 +717,10 @@
return NO_ERROR;
}
-sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const {
+status_t BufferQueueConsumer::getSidebandStream(sp<NativeHandle>* outStream) const {
Mutex::Autolock lock(mCore->mMutex);
- return mCore->mSidebandStream;
+ *outStream = mCore->mSidebandStream;
+ return NO_ERROR;
}
status_t BufferQueueConsumer::getOccupancyHistory(bool forceFlush,
@@ -734,20 +736,22 @@
return NO_ERROR;
}
-void BufferQueueConsumer::dumpState(String8& result, const char* prefix) const {
+status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const {
const IPCThreadState* ipc = IPCThreadState::self();
const pid_t pid = ipc->getCallingPid();
const uid_t uid = ipc->getCallingUid();
if ((uid != AID_SHELL)
&& !PermissionCache::checkPermission(String16(
"android.permission.DUMP"), pid, uid)) {
- result.appendFormat("Permission Denial: can't dump BufferQueueConsumer "
+ outResult->appendFormat("Permission Denial: can't dump BufferQueueConsumer "
"from pid=%d, uid=%d\n", pid, uid);
android_errorWriteWithInfoLog(0x534e4554, "27046057",
static_cast<int32_t>(uid), NULL, 0);
- } else {
- mCore->dumpState(result, prefix);
+ return PERMISSION_DENIED;
}
+
+ mCore->dumpState(prefix, outResult);
+ return NO_ERROR;
}
} // namespace android
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index d653db8..cd94253 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -33,9 +33,7 @@
#include <gui/BufferItem.h>
#include <gui/BufferQueueCore.h>
-#include <gui/GraphicBufferAlloc.h>
#include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferAlloc.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
#include <private/gui/ComposerService.h>
@@ -54,8 +52,7 @@
return id | counter++;
}
-BufferQueueCore::BufferQueueCore(const sp<IGraphicBufferAlloc>& allocator) :
- mAllocator(allocator),
+BufferQueueCore::BufferQueueCore() :
mMutex(),
mIsAbandoned(false),
mConsumerControlledByApp(false),
@@ -97,30 +94,6 @@
mLastQueuedSlot(INVALID_BUFFER_SLOT),
mUniqueId(getUniqueId())
{
- if (allocator == NULL) {
-
-#ifdef HAVE_NO_SURFACE_FLINGER
- // Without a SurfaceFlinger, allocate in-process. This only makes
- // sense in systems with static SELinux configurations and no
- // applications (since applications need dynamic SELinux policy).
- mAllocator = new GraphicBufferAlloc();
-#else
- // Run time check for headless, where we also allocate in-process.
- char value[PROPERTY_VALUE_MAX];
- property_get("config.headless", value, "0");
- if (atoi(value) == 1) {
- mAllocator = new GraphicBufferAlloc();
- } else {
- sp<ISurfaceComposer> composer(ComposerService::getComposerService());
- mAllocator = composer->createGraphicBufferAlloc();
- }
-#endif // HAVE_NO_SURFACE_FLINGER
-
- if (mAllocator == NULL) {
- BQ_LOGE("createGraphicBufferAlloc failed");
- }
- }
-
int numStartingBuffers = getMaxBufferCountLocked();
for (int s = 0; s < numStartingBuffers; s++) {
mFreeSlots.insert(s);
@@ -133,7 +106,7 @@
BufferQueueCore::~BufferQueueCore() {}
-void BufferQueueCore::dumpState(String8& result, const char* prefix) const {
+void BufferQueueCore::dumpState(const String8& prefix, String8* outResult) const {
Mutex::Autolock lock(mMutex);
String8 fifo;
@@ -148,10 +121,10 @@
++current;
}
- result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
+ outResult->appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
"mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
"mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
- "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
+ "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix.string(),
mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
@@ -161,28 +134,28 @@
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
// A dequeued buffer might be null if it's still being allocated
if (buffer.get()) {
- result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
- "[%4ux%4u:%4u,%3X]\n", prefix,
+ outResult->appendFormat("%s%s[%02d:%p] state=%-8s, %p "
+ "[%4ux%4u:%4u,%3X]\n", prefix.string(),
(mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
buffer.get(), mSlots[s].mBufferState.string(),
buffer->handle, buffer->width, buffer->height,
buffer->stride, buffer->format);
} else {
- result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
+ outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
buffer.get(), mSlots[s].mBufferState.string());
}
}
for (int s : mFreeBuffers) {
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
- result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
- prefix, s, buffer.get(), mSlots[s].mBufferState.string(),
+ outResult->appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
+ prefix.string(), s, buffer.get(), mSlots[s].mBufferState.string(),
buffer->handle, buffer->width, buffer->height, buffer->stride,
buffer->format);
}
for (int s : mFreeSlots) {
const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
- result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
+ outResult->appendFormat("%s [%02d:%p] state=%-8s\n", prefix.string(), s,
buffer.get(), mSlots[s].mBufferState.string());
}
}
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index aef231a..a540ab9 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -34,7 +34,6 @@
#include <gui/BufferQueueProducer.h>
#include <gui/GLConsumer.h>
#include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferAlloc.h>
#include <gui/IProducerListener.h>
#include <utils/Log.h>
@@ -454,8 +453,7 @@
mSlots[found].mBufferState.dequeue();
if ((buffer == NULL) ||
- buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT,
- usage))
+ buffer->needsReallocation(width, height, format, BQ_LAYER_COUNT, usage))
{
mSlots[found].mAcquireCalled = false;
mSlots[found].mGraphicBuffer = NULL;
@@ -503,11 +501,13 @@
} // Autolock scope
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
- status_t error;
BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
- sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
- width, height, format, BQ_LAYER_COUNT, usage,
- {mConsumerName.string(), mConsumerName.size()}, &error));
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
+ width, height, format, BQ_LAYER_COUNT, usage, usage,
+ {mConsumerName.string(), mConsumerName.size()});
+
+ status_t error = graphicBuffer->initCheck();
+
{ // Autolock scope
Mutex::Autolock lock(mCore->mMutex);
@@ -1337,11 +1337,12 @@
Vector<sp<GraphicBuffer>> buffers;
for (size_t i = 0; i < newBufferCount; ++i) {
- status_t result = NO_ERROR;
- sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
+ sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
allocWidth, allocHeight, allocFormat, BQ_LAYER_COUNT,
- allocUsage, {mConsumerName.string(), mConsumerName.size()},
- &result));
+ allocUsage, allocUsage, {mConsumerName.string(), mConsumerName.size()});
+
+ status_t result = graphicBuffer->initCheck();
+
if (result != NO_ERROR) {
BQ_LOGE("allocateBuffers: failed to allocate buffer (%u x %u, format"
" %u, usage %u)", width, height, format, usage);
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index d4e4dc3..5c6158c 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -30,7 +30,6 @@
#include <cutils/atomic.h>
#include <gui/BufferItem.h>
-#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/ConsumerBase.h>
@@ -270,7 +269,9 @@
result.appendFormat("%smAbandoned=%d\n", prefix, int(mAbandoned));
if (!mAbandoned) {
- mConsumer->dumpState(result, prefix);
+ String8 consumerState;
+ mConsumer->dumpState(String8(prefix), &consumerState);
+ result.append(consumerState);
}
}
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 55e0d26..c654f08 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -31,7 +31,6 @@
#include <gui/BufferItem.h>
#include <gui/GLConsumer.h>
-#include <gui/IGraphicBufferAlloc.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
diff --git a/libs/gui/GraphicBufferAlloc.cpp b/libs/gui/GraphicBufferAlloc.cpp
deleted file mode 100644
index cc7d403..0000000
--- a/libs/gui/GraphicBufferAlloc.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- **
- ** Copyright 2012 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 <gui/GraphicBufferAlloc.h>
-
-#include <log/log.h>
-
-
-namespace android {
-
-GraphicBufferAlloc::GraphicBufferAlloc() = default;
-GraphicBufferAlloc::~GraphicBufferAlloc() = default;
-
-sp<GraphicBuffer> GraphicBufferAlloc::createGraphicBuffer(uint32_t width,
- uint32_t height, PixelFormat format, uint32_t layerCount,
- uint64_t producerUsage, uint64_t consumerUsage,
- std::string requestorName, status_t* error) {
- sp<GraphicBuffer> graphicBuffer(new GraphicBuffer(
- width, height, format, layerCount, producerUsage, consumerUsage,
- std::move(requestorName)));
- status_t err = graphicBuffer->initCheck();
- *error = err;
- if (err != 0 || graphicBuffer->handle == 0) {
- if (err == NO_MEMORY) {
- GraphicBuffer::dumpAllocationsToSystemLog();
- }
- ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
- width, height, layerCount, strerror(-err),
- graphicBuffer->handle);
- graphicBuffer.clear();
- }
- return graphicBuffer;
-}
-
-} // namespace android
diff --git a/libs/gui/IGraphicBufferAlloc.cpp b/libs/gui/IGraphicBufferAlloc.cpp
deleted file mode 100644
index 21a0dd5..0000000
--- a/libs/gui/IGraphicBufferAlloc.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-// tag as surfaceflinger
-#define LOG_TAG "SurfaceFlinger"
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <binder/Parcel.h>
-
-#include <ui/GraphicBuffer.h>
-
-#include <gui/IGraphicBufferAlloc.h>
-
-// ---------------------------------------------------------------------------
-
-namespace android {
-
-enum {
- CREATE_GRAPHIC_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
-};
-
-class BpGraphicBufferAlloc : public BpInterface<IGraphicBufferAlloc>
-{
-public:
- explicit BpGraphicBufferAlloc(const sp<IBinder>& impl)
- : BpInterface<IGraphicBufferAlloc>(impl)
- {
- }
-
- virtual ~BpGraphicBufferAlloc();
-
- virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t width,
- uint32_t height, PixelFormat format, uint32_t layerCount,
- uint64_t producerUsage, uint64_t consumerUsage,
- std::string requestorName, status_t* error) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferAlloc::getInterfaceDescriptor());
- data.writeUint32(width);
- data.writeUint32(height);
- data.writeInt32(static_cast<int32_t>(format));
- data.writeUint32(layerCount);
- data.writeUint64(producerUsage);
- data.writeUint64(consumerUsage);
- if (requestorName.empty()) {
- requestorName += "[PID ";
- requestorName += std::to_string(getpid());
- requestorName += ']';
- }
- data.writeUtf8AsUtf16(requestorName);
- remote()->transact(CREATE_GRAPHIC_BUFFER, data, &reply);
- sp<GraphicBuffer> graphicBuffer;
- status_t result = reply.readInt32();
- if (result == NO_ERROR) {
- graphicBuffer = new GraphicBuffer();
- result = reply.read(*graphicBuffer);
- if (result != NO_ERROR) {
- graphicBuffer.clear();
- }
- // reply.readStrongBinder();
- // here we don't even have to read the BufferReference from
- // the parcel, it'll die with the parcel.
- }
- *error = result;
- return graphicBuffer;
- }
-};
-
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpGraphicBufferAlloc::~BpGraphicBufferAlloc() {}
-
-IMPLEMENT_META_INTERFACE(GraphicBufferAlloc, "android.ui.IGraphicBufferAlloc");
-
-// ----------------------------------------------------------------------
-
-status_t BnGraphicBufferAlloc::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- // codes that don't require permission check
-
- // BufferReference just keeps a strong reference to a GraphicBuffer until it
- // is destroyed (that is, until no local or remote process have a reference
- // to it).
- class BufferReference : public BBinder {
- sp<GraphicBuffer> mBuffer;
- public:
- explicit BufferReference(const sp<GraphicBuffer>& buffer) : mBuffer(buffer) {}
- };
-
-
- switch (code) {
- case CREATE_GRAPHIC_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferAlloc, data, reply);
- uint32_t width = data.readUint32();
- uint32_t height = data.readUint32();
- PixelFormat format = static_cast<PixelFormat>(data.readInt32());
- uint32_t layerCount = data.readUint32();
- uint64_t producerUsage = data.readUint64();
- uint64_t consumerUsage = data.readUint64();
- status_t error = NO_ERROR;
- std::string requestorName;
- data.readUtf8FromUtf16(&requestorName);
- sp<GraphicBuffer> result = createGraphicBuffer(width, height,
- format, layerCount, producerUsage, consumerUsage,
- requestorName, &error);
- reply->writeInt32(error);
- if (result != 0) {
- reply->write(*result);
- // We add a BufferReference to this parcel to make sure the
- // buffer stays alive until the GraphicBuffer object on
- // the other side has been created.
- // This is needed so that the buffer handle can be
- // registered before the buffer is destroyed on implementations
- // that do not use file-descriptors to track their buffers.
- reply->writeStrongBinder( new BufferReference(result) );
- }
- return NO_ERROR;
- }
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-}; // namespace android
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index ef770e8..568c318 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -14,28 +14,24 @@
* limitations under the License.
*/
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Errors.h>
-#include <utils/NativeHandle.h>
-#include <utils/String8.h>
-
-#include <binder/Parcel.h>
-#include <binder/IInterface.h>
+#include <gui/IGraphicBufferConsumer.h>
#include <gui/BufferItem.h>
#include <gui/IConsumerListener.h>
-#include <gui/IGraphicBufferConsumer.h>
-#include <ui/GraphicBuffer.h>
+#include <binder/Parcel.h>
+
#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
-#include <system/window.h>
+#include <utils/NativeHandle.h>
+#include <utils/String8.h>
namespace android {
-enum {
+namespace { // Anonymous namespace
+
+enum class Tag : uint32_t {
ACQUIRE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
DETACH_BUFFER,
ATTACH_BUFFER,
@@ -54,439 +50,173 @@
GET_SIDEBAND_STREAM,
GET_OCCUPANCY_HISTORY,
DISCARD_FREE_BUFFERS,
- DUMP,
+ DUMP_STATE,
+ LAST = DUMP_STATE,
};
+} // Anonymous namespace
-class BpGraphicBufferConsumer : public BpInterface<IGraphicBufferConsumer>
-{
+class BpGraphicBufferConsumer : public SafeBpInterface<IGraphicBufferConsumer> {
public:
explicit BpGraphicBufferConsumer(const sp<IBinder>& impl)
- : BpInterface<IGraphicBufferConsumer>(impl)
- {
+ : SafeBpInterface<IGraphicBufferConsumer>(impl, "BpGraphicBufferConsumer") {}
+
+ ~BpGraphicBufferConsumer() override;
+
+ status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
+ uint64_t maxFrameNumber) override {
+ using Signature = decltype(&IGraphicBufferConsumer::acquireBuffer);
+ return callRemote<Signature>(Tag::ACQUIRE_BUFFER, buffer, presentWhen, maxFrameNumber);
}
- virtual ~BpGraphicBufferConsumer();
-
- virtual status_t acquireBuffer(BufferItem *buffer, nsecs_t presentWhen,
- uint64_t maxFrameNumber) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt64(presentWhen);
- data.writeUint64(maxFrameNumber);
- status_t result = remote()->transact(ACQUIRE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.read(*buffer);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t detachBuffer(int slot) override {
+ using Signature = decltype(&IGraphicBufferConsumer::detachBuffer);
+ return callRemote<Signature>(Tag::DETACH_BUFFER, slot);
}
- virtual status_t detachBuffer(int slot) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(slot);
- status_t result = remote()->transact(DETACH_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readInt32();
- return result;
+ status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) override {
+ using Signature = decltype(&IGraphicBufferConsumer::attachBuffer);
+ return callRemote<Signature>(Tag::ATTACH_BUFFER, slot, buffer);
}
- virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.write(*buffer.get());
- status_t result = remote()->transact(ATTACH_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- *slot = reply.readInt32();
- result = reply.readInt32();
- return result;
+ status_t releaseBuffer(int buf, uint64_t frameNumber,
+ EGLDisplay display __attribute__((unused)),
+ EGLSyncKHR fence __attribute__((unused)),
+ const sp<Fence>& releaseFence) override {
+ return callRemote<ReleaseBuffer>(Tag::RELEASE_BUFFER, buf, frameNumber, releaseFence);
}
- virtual status_t releaseBuffer(int buf, uint64_t frameNumber,
- EGLDisplay display __attribute__((unused)), EGLSyncKHR fence __attribute__((unused)),
- const sp<Fence>& releaseFence) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(buf);
- data.writeInt64(static_cast<int64_t>(frameNumber));
- data.write(*releaseFence);
- status_t result = remote()->transact(RELEASE_BUFFER, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) override {
+ using Signature = decltype(&IGraphicBufferConsumer::consumerConnect);
+ return callRemote<Signature>(Tag::CONSUMER_CONNECT, consumer, controlledByApp);
}
- virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeStrongBinder(IInterface::asBinder(consumer));
- data.writeInt32(controlledByApp);
- status_t result = remote()->transact(CONSUMER_CONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t consumerDisconnect() override {
+ return callRemote<decltype(&IGraphicBufferConsumer::consumerDisconnect)>(
+ Tag::CONSUMER_DISCONNECT);
}
- virtual status_t consumerDisconnect() {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(CONSUMER_DISCONNECT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t getReleasedBuffers(uint64_t* slotMask) override {
+ using Signature = decltype(&IGraphicBufferConsumer::getReleasedBuffers);
+ return callRemote<Signature>(Tag::GET_RELEASED_BUFFERS, slotMask);
}
- virtual status_t getReleasedBuffers(uint64_t* slotMask) {
- Parcel data, reply;
- if (slotMask == NULL) {
- ALOGE("getReleasedBuffers: slotMask must not be NULL");
- return BAD_VALUE;
- }
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- status_t result = remote()->transact(GET_RELEASED_BUFFERS, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- *slotMask = static_cast<uint64_t>(reply.readInt64());
- return reply.readInt32();
+ status_t setDefaultBufferSize(uint32_t width, uint32_t height) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferSize);
+ return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_SIZE, width, height);
}
- virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeUint32(width);
- data.writeUint32(height);
- status_t result = remote()->transact(SET_DEFAULT_BUFFER_SIZE, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t setMaxBufferCount(int bufferCount) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setMaxBufferCount);
+ return callRemote<Signature>(Tag::SET_MAX_BUFFER_COUNT, bufferCount);
}
- virtual status_t setMaxBufferCount(int bufferCount) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(bufferCount);
- status_t result = remote()->transact(SET_MAX_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setMaxAcquiredBufferCount);
+ return callRemote<Signature>(Tag::SET_MAX_ACQUIRED_BUFFER_COUNT, maxAcquiredBuffers);
}
- virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(maxAcquiredBuffers);
- status_t result = remote()->transact(SET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t setConsumerName(const String8& name) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setConsumerName);
+ return callRemote<Signature>(Tag::SET_CONSUMER_NAME, name);
}
- virtual void setConsumerName(const String8& name) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeString8(name);
- remote()->transact(SET_CONSUMER_NAME, data, &reply);
+ status_t setDefaultBufferFormat(PixelFormat defaultFormat) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferFormat);
+ return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_FORMAT, defaultFormat);
}
- virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(static_cast<int32_t>(defaultFormat));
- status_t result = remote()->transact(SET_DEFAULT_BUFFER_FORMAT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setDefaultBufferDataSpace);
+ return callRemote<Signature>(Tag::SET_DEFAULT_BUFFER_DATA_SPACE, defaultDataSpace);
}
- virtual status_t setDefaultBufferDataSpace(
- android_dataspace defaultDataSpace) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeInt32(static_cast<int32_t>(defaultDataSpace));
- status_t result = remote()->transact(SET_DEFAULT_BUFFER_DATA_SPACE,
- data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t setConsumerUsageBits(uint32_t usage) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setConsumerUsageBits);
+ return callRemote<Signature>(Tag::SET_CONSUMER_USAGE_BITS, usage);
}
- virtual status_t setConsumerUsageBits(uint32_t usage) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeUint32(usage);
- status_t result = remote()->transact(SET_CONSUMER_USAGE_BITS, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t setTransformHint(uint32_t hint) override {
+ using Signature = decltype(&IGraphicBufferConsumer::setTransformHint);
+ return callRemote<Signature>(Tag::SET_TRANSFORM_HINT, hint);
}
- virtual status_t setTransformHint(uint32_t hint) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeUint32(hint);
- status_t result = remote()->transact(SET_TRANSFORM_HINT, data, &reply);
- if (result != NO_ERROR) {
- return result;
- }
- return reply.readInt32();
+ status_t getSidebandStream(sp<NativeHandle>* outStream) const override {
+ using Signature = decltype(&IGraphicBufferConsumer::getSidebandStream);
+ return callRemote<Signature>(Tag::GET_SIDEBAND_STREAM, outStream);
}
- virtual sp<NativeHandle> getSidebandStream() const {
- Parcel data, reply;
- status_t err;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- if ((err = remote()->transact(GET_SIDEBAND_STREAM, data, &reply)) != NO_ERROR) {
- return NULL;
- }
- sp<NativeHandle> stream;
- if (reply.readInt32()) {
- stream = NativeHandle::create(reply.readNativeHandle(), true);
- }
- return stream;
+ status_t getOccupancyHistory(bool forceFlush,
+ std::vector<OccupancyTracker::Segment>* outHistory) override {
+ using Signature = decltype(&IGraphicBufferConsumer::getOccupancyHistory);
+ return callRemote<Signature>(Tag::GET_OCCUPANCY_HISTORY, forceFlush, outHistory);
}
- virtual status_t getOccupancyHistory(bool forceFlush,
- std::vector<OccupancyTracker::Segment>* outHistory) {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- status_t error = data.writeBool(forceFlush);
- if (error != NO_ERROR) {
- return error;
- }
- error = remote()->transact(GET_OCCUPANCY_HISTORY, data,
- &reply);
- if (error != NO_ERROR) {
- return error;
- }
- error = reply.readParcelableVector(outHistory);
- if (error != NO_ERROR) {
- return error;
- }
- status_t result = NO_ERROR;
- error = reply.readInt32(&result);
- if (error != NO_ERROR) {
- return error;
- }
- return result;
+ status_t discardFreeBuffers() override {
+ return callRemote<decltype(&IGraphicBufferConsumer::discardFreeBuffers)>(
+ Tag::DISCARD_FREE_BUFFERS);
}
- virtual status_t discardFreeBuffers() {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- status_t error = remote()->transact(DISCARD_FREE_BUFFERS, data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
- int32_t result = NO_ERROR;
- error = reply.readInt32(&result);
- if (error != NO_ERROR) {
- return error;
- }
- return result;
- }
-
- virtual void dumpState(String8& result, const char* prefix) const {
- Parcel data, reply;
- data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
- data.writeString8(result);
- data.writeString8(String8(prefix ? prefix : ""));
- remote()->transact(DUMP, data, &reply);
- reply.readString8();
+ status_t dumpState(const String8& prefix, String8* outResult) const override {
+ using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
+ return callRemote<Signature>(Tag::DUMP_STATE, prefix, outResult);
}
};
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpGraphicBufferConsumer::~BpGraphicBufferConsumer() {}
+// Out-of-line virtual method definition to trigger vtable emission in this translation unit
+// (see clang warning -Wweak-vtables)
+BpGraphicBufferConsumer::~BpGraphicBufferConsumer() = default;
IMPLEMENT_META_INTERFACE(GraphicBufferConsumer, "android.gui.IGraphicBufferConsumer");
-// ----------------------------------------------------------------------
-
-status_t BnGraphicBufferConsumer::onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
- switch(code) {
- case ACQUIRE_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- BufferItem item;
- int64_t presentWhen = data.readInt64();
- uint64_t maxFrameNumber = data.readUint64();
- status_t result = acquireBuffer(&item, presentWhen, maxFrameNumber);
- status_t err = reply->write(item);
- if (err) return err;
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case DETACH_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- int slot = data.readInt32();
- int result = detachBuffer(slot);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case ATTACH_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- sp<GraphicBuffer> buffer = new GraphicBuffer();
- data.read(*buffer.get());
- int slot = -1;
- int result = attachBuffer(&slot, buffer);
- reply->writeInt32(slot);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case RELEASE_BUFFER: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- int buf = data.readInt32();
- uint64_t frameNumber = static_cast<uint64_t>(data.readInt64());
- sp<Fence> releaseFence = new Fence();
- status_t err = data.read(*releaseFence);
- if (err) return err;
- status_t result = releaseBuffer(buf, frameNumber,
- EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, releaseFence);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case CONSUMER_CONNECT: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- sp<IConsumerListener> consumer = IConsumerListener::asInterface( data.readStrongBinder() );
- bool controlledByApp = data.readInt32();
- status_t result = consumerConnect(consumer, controlledByApp);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case CONSUMER_DISCONNECT: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- status_t result = consumerDisconnect();
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case GET_RELEASED_BUFFERS: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint64_t slotMask = 0;
- status_t result = getReleasedBuffers(&slotMask);
- reply->writeInt64(static_cast<int64_t>(slotMask));
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_DEFAULT_BUFFER_SIZE: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t width = data.readUint32();
- uint32_t height = data.readUint32();
- status_t result = setDefaultBufferSize(width, height);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_MAX_BUFFER_COUNT: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- int bufferCount = data.readInt32();
- status_t result = setMaxBufferCount(bufferCount);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_MAX_ACQUIRED_BUFFER_COUNT: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- int maxAcquiredBuffers = data.readInt32();
- status_t result = setMaxAcquiredBufferCount(maxAcquiredBuffers);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_CONSUMER_NAME: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- setConsumerName( data.readString8() );
- return NO_ERROR;
- }
- case SET_DEFAULT_BUFFER_FORMAT: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- PixelFormat defaultFormat = static_cast<PixelFormat>(data.readInt32());
- status_t result = setDefaultBufferFormat(defaultFormat);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_DEFAULT_BUFFER_DATA_SPACE: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- android_dataspace defaultDataSpace =
- static_cast<android_dataspace>(data.readInt32());
- status_t result = setDefaultBufferDataSpace(defaultDataSpace);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_CONSUMER_USAGE_BITS: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t usage = data.readUint32();
- status_t result = setConsumerUsageBits(usage);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_TRANSFORM_HINT: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- uint32_t hint = data.readUint32();
- status_t result = setTransformHint(hint);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case GET_SIDEBAND_STREAM: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- sp<NativeHandle> stream = getSidebandStream();
- reply->writeInt32(static_cast<int32_t>(stream != NULL));
- if (stream != NULL) {
- reply->writeNativeHandle(stream->handle());
- }
- return NO_ERROR;
- }
- case GET_OCCUPANCY_HISTORY: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- bool forceFlush = false;
- status_t error = data.readBool(&forceFlush);
- if (error != NO_ERROR) {
- return error;
- }
- std::vector<OccupancyTracker::Segment> history;
- status_t result = getOccupancyHistory(forceFlush, &history);
- error = reply->writeParcelableVector(history);
- if (error != NO_ERROR) {
- return error;
- }
- error = reply->writeInt32(result);
- if (error != NO_ERROR) {
- return error;
- }
- return NO_ERROR;
- }
- case DISCARD_FREE_BUFFERS: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- status_t result = discardFreeBuffers();
- status_t error = reply->writeInt32(result);
- return error;
- }
- case DUMP: {
- CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
- String8 result = data.readString8();
- String8 prefix = data.readString8();
- static_cast<IGraphicBufferConsumer*>(this)->dumpState(result, prefix);
- reply->writeString8(result);
- return NO_ERROR;
+status_t BnGraphicBufferConsumer::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+ uint32_t flags) {
+ if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+ auto tag = static_cast<Tag>(code);
+ switch (tag) {
+ case Tag::ACQUIRE_BUFFER:
+ return callLocal(data, reply, &IGraphicBufferConsumer::acquireBuffer);
+ case Tag::DETACH_BUFFER:
+ return callLocal(data, reply, &IGraphicBufferConsumer::detachBuffer);
+ case Tag::ATTACH_BUFFER:
+ return callLocal(data, reply, &IGraphicBufferConsumer::attachBuffer);
+ case Tag::RELEASE_BUFFER:
+ return callLocal(data, reply, &IGraphicBufferConsumer::releaseHelper);
+ case Tag::CONSUMER_CONNECT:
+ return callLocal(data, reply, &IGraphicBufferConsumer::consumerConnect);
+ case Tag::CONSUMER_DISCONNECT:
+ return callLocal(data, reply, &IGraphicBufferConsumer::consumerDisconnect);
+ case Tag::GET_RELEASED_BUFFERS:
+ return callLocal(data, reply, &IGraphicBufferConsumer::getReleasedBuffers);
+ case Tag::SET_DEFAULT_BUFFER_SIZE:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferSize);
+ case Tag::SET_MAX_BUFFER_COUNT:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setMaxBufferCount);
+ case Tag::SET_MAX_ACQUIRED_BUFFER_COUNT:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setMaxAcquiredBufferCount);
+ case Tag::SET_CONSUMER_NAME:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setConsumerName);
+ case Tag::SET_DEFAULT_BUFFER_FORMAT:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferFormat);
+ case Tag::SET_DEFAULT_BUFFER_DATA_SPACE:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setDefaultBufferDataSpace);
+ case Tag::SET_CONSUMER_USAGE_BITS:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setConsumerUsageBits);
+ case Tag::SET_TRANSFORM_HINT:
+ return callLocal(data, reply, &IGraphicBufferConsumer::setTransformHint);
+ case Tag::GET_SIDEBAND_STREAM:
+ return callLocal(data, reply, &IGraphicBufferConsumer::getSidebandStream);
+ case Tag::GET_OCCUPANCY_HISTORY:
+ return callLocal(data, reply, &IGraphicBufferConsumer::getOccupancyHistory);
+ case Tag::DISCARD_FREE_BUFFERS:
+ return callLocal(data, reply, &IGraphicBufferConsumer::discardFreeBuffers);
+ case Tag::DUMP_STATE: {
+ using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const;
+ return callLocal<Signature>(data, reply, &IGraphicBufferConsumer::dumpState);
}
}
- return BBinder::onTransact(code, data, reply, flags);
}
-}; // namespace android
+} // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 5a32d05..2516fb8 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,7 +25,6 @@
#include <binder/IServiceManager.h>
#include <gui/IDisplayEventConnection.h>
-#include <gui/IGraphicBufferAlloc.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
@@ -72,14 +71,6 @@
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
- virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc()
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::CREATE_GRAPHIC_BUFFER_ALLOC, data, &reply);
- return interface_cast<IGraphicBufferAlloc>(reply.readStrongBinder());
- }
-
virtual void setTransactionState(
const Vector<ComposerState>& state,
const Vector<DisplayState>& displays,
@@ -166,6 +157,50 @@
return result != 0;
}
+ virtual status_t getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const {
+ if (!outSupported) {
+ return UNEXPECTED_NULL;
+ }
+ outSupported->clear();
+
+ Parcel data, reply;
+
+ status_t err = data.writeInterfaceToken(
+ ISurfaceComposer::getInterfaceDescriptor());
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ err = remote()->transact(
+ BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS,
+ data, &reply);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ int32_t result = 0;
+ err = reply.readInt32(&result);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ std::vector<int32_t> supported;
+ err = reply.readInt32Vector(&supported);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ outSupported->reserve(supported.size());
+ for (int32_t s : supported) {
+ outSupported->push_back(static_cast<FrameEvent>(s));
+ }
+ return NO_ERROR;
+ }
+
virtual sp<IDisplayEventConnection> createDisplayEventConnection()
{
Parcel data, reply;
@@ -461,12 +496,6 @@
reply->writeStrongBinder(b);
return NO_ERROR;
}
- case CREATE_GRAPHIC_BUFFER_ALLOC: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> b = IInterface::asBinder(createGraphicBufferAlloc());
- reply->writeStrongBinder(b);
- return NO_ERROR;
- }
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -536,6 +565,25 @@
reply->writeInt32(result);
return NO_ERROR;
}
+ case GET_SUPPORTED_FRAME_TIMESTAMPS: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+ std::vector<FrameEvent> supportedTimestamps;
+ status_t result = getSupportedFrameTimestamps(&supportedTimestamps);
+ status_t err = reply->writeInt32(result);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ if (result != NO_ERROR) {
+ return result;
+ }
+
+ std::vector<int32_t> supported;
+ supported.reserve(supportedTimestamps.size());
+ for (FrameEvent s : supportedTimestamps) {
+ supported.push_back(static_cast<int32_t>(s));
+ }
+ return reply->writeInt32Vector(supported);
+ }
case CREATE_DISPLAY_EVENT_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IDisplayEventConnection> connection(createDisplayEventConnection());
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2461cba..9b06e63 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -44,6 +44,7 @@
output.writeUint64(frameNumber);
output.writeInt32(overrideScalingMode);
output.writeStrongBinder(IInterface::asBinder(barrierGbp));
+ output.writeStrongBinder(relativeLayerHandle);
output.write(transparentRegion);
return NO_ERROR;
}
@@ -75,6 +76,7 @@
overrideScalingMode = input.readInt32();
barrierGbp =
interface_cast<IGraphicBufferProducer>(input.readStrongBinder());
+ relativeLayerHandle = input.readStrongBinder();
input.read(transparentRegion);
return NO_ERROR;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 1149b89..a6d9e66 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -52,6 +52,8 @@
mAutoRefresh(false),
mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
mSharedBufferHasBeenQueued(false),
+ mQueriedSupportedTimestamps(false),
+ mFrameTimestampsSupportsPresent(false),
mEnableFrameTimestamps(false),
mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
{
@@ -209,8 +211,8 @@
bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) &&
!e->hasDisplayPresentInfo();
- // LastRefreshStart, DequeueReady, and Release are never
- // available for the last frame.
+ // LastRefreshStart, DequeueReady, and Release are never available for the
+ // last frame.
bool checkForLastRefreshStart = (outLastRefreshStartTime != nullptr) &&
!e->hasLastRefreshStartInfo() &&
(e->frameNumber != lastFrameNumber);
@@ -227,14 +229,26 @@
static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
if (dst != nullptr) {
- *dst = FrameEvents::isValidTimestamp(src) ? src : 0;
+ // We always get valid timestamps for these eventually.
+ *dst = (src == FrameEvents::TIMESTAMP_PENDING) ?
+ NATIVE_WINDOW_TIMESTAMP_PENDING : src;
}
}
-static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+static void getFrameTimestampFence(nsecs_t *dst,
+ const std::shared_ptr<FenceTime>& src, bool fenceShouldBeKnown) {
if (dst != nullptr) {
+ if (!fenceShouldBeKnown) {
+ *dst = NATIVE_WINDOW_TIMESTAMP_PENDING;
+ return;
+ }
+
nsecs_t signalTime = src->getSignalTime();
- *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+ *dst = (signalTime == Fence::SIGNAL_TIME_PENDING) ?
+ NATIVE_WINDOW_TIMESTAMP_PENDING :
+ (signalTime == Fence::SIGNAL_TIME_INVALID) ?
+ NATIVE_WINDOW_TIMESTAMP_INVALID :
+ signalTime;
}
}
@@ -252,6 +266,12 @@
return INVALID_OPERATION;
}
+ // Verify the requested timestamps are supported.
+ querySupportedTimestampsLocked();
+ if (outDisplayPresentTime != nullptr && !mFrameTimestampsSupportsPresent) {
+ return BAD_VALUE;
+ }
+
FrameEvents* events = mFrameEventHistory->getFrame(frameNumber);
if (events == nullptr) {
// If the entry isn't available in the producer, it's definitely not
@@ -282,12 +302,15 @@
getFrameTimestamp(outLastRefreshStartTime, events->lastRefreshStartTime);
getFrameTimestamp(outDequeueReadyTime, events->dequeueReadyTime);
- getFrameTimestampFence(outAcquireTime, events->acquireFence);
- getFrameTimestampFence(
- outGpuCompositionDoneTime, events->gpuCompositionDoneFence);
- getFrameTimestampFence(
- outDisplayPresentTime, events->displayPresentFence);
- getFrameTimestampFence(outReleaseTime, events->releaseFence);
+ getFrameTimestampFence(outAcquireTime, events->acquireFence,
+ events->hasAcquireInfo());
+ getFrameTimestampFence(outGpuCompositionDoneTime,
+ events->gpuCompositionDoneFence,
+ events->hasGpuCompositionDoneInfo());
+ getFrameTimestampFence(outDisplayPresentTime, events->displayPresentFence,
+ events->hasDisplayPresentInfo());
+ getFrameTimestampFence(outReleaseTime, events->releaseFence,
+ events->hasReleaseInfo());
return NO_ERROR;
}
@@ -739,6 +762,29 @@
return err;
}
+void Surface::querySupportedTimestampsLocked() const {
+ // mMutex must be locked when calling this method.
+
+ if (mQueriedSupportedTimestamps) {
+ return;
+ }
+ mQueriedSupportedTimestamps = true;
+
+ std::vector<FrameEvent> supportedFrameTimestamps;
+ status_t err = composerService()->getSupportedFrameTimestamps(
+ &supportedFrameTimestamps);
+
+ if (err != NO_ERROR) {
+ return;
+ }
+
+ for (auto sft : supportedFrameTimestamps) {
+ if (sft == FrameEvent::DISPLAY_PRESENT) {
+ mFrameTimestampsSupportsPresent = true;
+ }
+ }
+}
+
int Surface::query(int what, int* value) const {
ATRACE_CALL();
ALOGV("Surface::query");
@@ -800,6 +846,11 @@
static_cast<int>(durationUs);
return NO_ERROR;
}
+ case NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT: {
+ querySupportedTimestampsLocked();
+ *value = mFrameTimestampsSupportsPresent ? 1 : 0;
+ return NO_ERROR;
+ }
case NATIVE_WINDOW_IS_VALID: {
*value = mGraphicBufferProducer != nullptr ? 1 : 0;
return NO_ERROR;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 56c7586..8c83843 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -149,6 +149,8 @@
uint32_t w, uint32_t h);
status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
int32_t z);
+ status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t z);
status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
uint32_t flags, uint32_t mask);
status_t setTransparentRegionHint(
@@ -343,6 +345,20 @@
return NO_ERROR;
}
+status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client,
+ const sp<IBinder>& id, const sp<IBinder>& relativeTo,
+ int32_t z) {
+ Mutex::Autolock _l(mLock);
+ layer_state_t* s = getLayerStateLocked(client, id);
+ if (!s) {
+ return BAD_INDEX;
+ }
+ s->what |= layer_state_t::eRelativeLayerChanged;
+ s->relativeLayerHandle = relativeTo;
+ s->z = z;
+ return NO_ERROR;
+}
+
status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
const sp<IBinder>& id, uint32_t flags,
uint32_t mask) {
@@ -760,6 +776,11 @@
return getComposer().setLayer(this, id, z);
}
+status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id,
+ const sp<IBinder>& relativeTo, int32_t z) {
+ return getComposer().setRelativeLayer(this, id, relativeTo, z);
+}
+
status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
return getComposer().setFlags(this, id,
layer_state_t::eLayerHidden,
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 7a68f11..bf8a815 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -102,11 +102,19 @@
if (err < 0) return err;
return mClient->setLayerStack(mHandle, layerStack);
}
+
status_t SurfaceControl::setLayer(int32_t layer) {
status_t err = validate();
if (err < 0) return err;
return mClient->setLayer(mHandle, layer);
}
+
+status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) {
+ status_t err = validate();
+ if (err < 0) return err;
+ return mClient->setRelativeLayer(mHandle, relativeTo, layer);
+}
+
status_t SurfaceControl::setPosition(float x, float y) {
status_t err = validate();
if (err < 0) return err;
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 55e6fbf..893c0a6 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -1057,7 +1057,7 @@
// Check no free buffers in dump
String8 dumpString;
- mConsumer->dumpState(dumpString, nullptr);
+ mConsumer->dumpState(String8{}, &dumpString);
// Parse the dump to ensure that all buffer slots that are FREE also
// have a null GraphicBuffer
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index ce11486..08d6715 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -368,14 +368,15 @@
public:
~FakeSurfaceComposer() override {}
+ void setSupportsPresent(bool supportsPresent) {
+ mSupportsPresent = supportsPresent;
+ }
+
sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
sp<ISurfaceComposerClient> createScopedConnection(
const sp<IGraphicBufferProducer>& /* parent */) override {
return nullptr;
}
- sp<IGraphicBufferAlloc> createGraphicBufferAlloc() override {
- return nullptr;
- }
sp<IDisplayEventConnection> createDisplayEventConnection() override {
return nullptr;
}
@@ -391,6 +392,26 @@
const sp<IGraphicBufferProducer>& /*surface*/) const override {
return false;
}
+
+ status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported)
+ const override {
+ *outSupported = {
+ FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE
+ };
+ if (mSupportsPresent) {
+ outSupported->push_back(
+ FrameEvent::DISPLAY_PRESENT);
+ }
+ return NO_ERROR;
+ }
+
void setPowerMode(const sp<IBinder>& /*display*/, int /*mode*/) override {}
status_t getDisplayConfigs(const sp<IBinder>& /*display*/,
Vector<DisplayInfo>* /*configs*/) override { return NO_ERROR; }
@@ -435,7 +456,6 @@
private:
bool mSupportsPresent{true};
- bool mSupportsRetire{true};
};
class FakeProducerFrameEventHistory : public ProducerFrameEventHistory {
@@ -864,6 +884,28 @@
EXPECT_EQ(4, mFakeConsumer->mGetFrameTimestampsCount);
}
+TEST_F(GetFrameTimestampsTest, QueryPresentSupported) {
+ bool displayPresentSupported = true;
+ mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+ // Verify supported bits are forwarded.
+ int supportsPresent = -1;
+ mWindow.get()->query(mWindow.get(),
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+ EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
+TEST_F(GetFrameTimestampsTest, QueryPresentNotSupported) {
+ bool displayPresentSupported = false;
+ mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+
+ // Verify supported bits are forwarded.
+ int supportsPresent = -1;
+ mWindow.get()->query(mWindow.get(),
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &supportsPresent);
+ EXPECT_EQ(displayPresentSupported, supportsPresent);
+}
+
TEST_F(GetFrameTimestampsTest, SnapToNextTickBasic) {
nsecs_t phase = 4000;
nsecs_t interval = 1000;
@@ -1139,8 +1181,8 @@
EXPECT_EQ(mFrames[1].mRefreshes[0].kGpuCompositionDoneTime,
outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
- EXPECT_EQ(0, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
}
// This test verifies the acquire fence recorded by the consumer is not sent
@@ -1163,7 +1205,7 @@
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[0].kRequestedPresentTime, outRequestedPresentTime);
- EXPECT_EQ(0, outAcquireTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
// Signal acquire fences. Verify a sync call still isn't necessary.
mFrames[0].signalQueueFences();
@@ -1192,7 +1234,7 @@
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(mFrames[1].kRequestedPresentTime, outRequestedPresentTime);
- EXPECT_EQ(0, outAcquireTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outAcquireTime);
// Signal acquire fences. Verify a sync call still isn't necessary.
mFrames[1].signalQueueFences();
@@ -1228,8 +1270,8 @@
// Verify a request for no timestamps doesn't result in a sync call.
int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
int result = native_window_get_frame_timestamps(mWindow.get(), fId2,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr);
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr);
EXPECT_EQ(NO_ERROR, result);
EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
}
@@ -1265,10 +1307,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Verify available timestamps are correct for frame 1 again, before any
// fence has been signaled.
@@ -1283,10 +1325,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Signal the fences for frame 1.
mFrames[0].signalRefreshFences();
@@ -1342,10 +1384,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
// Signal the fences for frame 1.
mFrames[0].signalRefreshFences();
@@ -1363,7 +1405,7 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kPresentTime, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
EXPECT_EQ(mFrames[0].kReleaseTime, outReleaseTime);
@@ -1371,7 +1413,7 @@
// This test verifies that if the certain timestamps can't possibly exist for
// the most recent frame, then a sync call is not done.
-TEST_F(GetFrameTimestampsTest, NoRetireOrReleaseNoSync) {
+TEST_F(GetFrameTimestampsTest, NoReleaseNoSync) {
enableFrameTimestamps();
// Dequeue and queue frame 1.
@@ -1401,10 +1443,10 @@
EXPECT_EQ(mFrames[0].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[0].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[0].mRefreshes[2].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
- EXPECT_EQ(0, outDisplayPresentTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDisplayPresentTime);
EXPECT_EQ(mFrames[0].kDequeueReadyTime, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
mFrames[0].signalRefreshFences();
mFrames[0].signalReleaseFences();
@@ -1425,10 +1467,33 @@
EXPECT_EQ(mFrames[1].kLatchTime, outLatchTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kStartTime, outFirstRefreshStartTime);
EXPECT_EQ(mFrames[1].mRefreshes[1].kStartTime, outLastRefreshStartTime);
- EXPECT_EQ(0, outGpuCompositionDoneTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_INVALID, outGpuCompositionDoneTime);
EXPECT_EQ(mFrames[1].mRefreshes[0].kPresentTime, outDisplayPresentTime);
- EXPECT_EQ(0, outDequeueReadyTime);
- EXPECT_EQ(0, outReleaseTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outDequeueReadyTime);
+ EXPECT_EQ(NATIVE_WINDOW_TIMESTAMP_PENDING, outReleaseTime);
+}
+
+// This test verifies there are no sync calls for present times
+// when they aren't supported and that an error is returned.
+
+TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) {
+ enableFrameTimestamps();
+ mSurface->mFakeSurfaceComposer->setSupportsPresent(false);
+
+ // Dequeue and queue frame 1.
+ const uint64_t fId1 = getNextFrameId();
+ dequeueAndQueue(0);
+
+ // Verify a query for the Present times do not trigger a sync call if they
+ // are not supported.
+ resetTimestamps();
+ int oldCount = mFakeConsumer->mGetFrameTimestampsCount;
+ int result = native_window_get_frame_timestamps(mWindow.get(), fId1,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ &outDisplayPresentTime, nullptr, nullptr);
+ EXPECT_EQ(oldCount, mFakeConsumer->mGetFrameTimestampsCount);
+ EXPECT_EQ(BAD_VALUE, result);
+ EXPECT_EQ(-1, outDisplayPresentTime);
}
}
diff --git a/libs/hwc2on1adapter/Android.bp b/libs/hwc2on1adapter/Android.bp
index 438d3f5..5d7f660 100644
--- a/libs/hwc2on1adapter/Android.bp
+++ b/libs/hwc2on1adapter/Android.bp
@@ -14,6 +14,7 @@
cc_library_shared {
name: "libhwc2on1adapter",
+ vendor_available: true,
clang: true,
cppflags: [
diff --git a/libs/hwc2on1adapter/HWC2On1Adapter.cpp b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
index e35bfc9..8c6ef69 100644
--- a/libs/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/libs/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -2246,6 +2246,11 @@
mHwc1SupportsBackgroundColor = true;
}
}
+
+ // Some devices might have HWC1 retire fences that accurately emulate
+ // HWC2 present fences when they are deferred, but it's not very reliable.
+ // To be safe, we indicate PresentFenceIsNotReliable for all HWC1 devices.
+ mCapabilities.insert(Capability::PresentFenceIsNotReliable);
}
HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id) {
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index a38b4dc..5812831 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -33,7 +33,7 @@
#include <private/android/AHardwareBufferHelpers.h>
-static constexpr int kDataBufferSize = 64 * sizeof(int); // 64 ints
+static constexpr int kFdBufferSize = 128 * sizeof(int); // 128 ints
using namespace android;
@@ -70,7 +70,7 @@
if (err == NO_MEMORY) {
GraphicBuffer::dumpAllocationsToSystemLog();
}
- ALOGE("GraphicBufferAlloc::createGraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
+ ALOGE("GraphicBuffer(w=%u, h=%u, lc=%u) failed (%s), handle=%p",
desc->width, desc->height, desc->layers, strerror(-err), gbuffer->handle);
return err;
}
@@ -169,7 +169,7 @@
iov[0].iov_base = data.get();
iov[0].iov_len = flattenedSize;
- char buf[CMSG_SPACE(kDataBufferSize)];
+ char buf[CMSG_SPACE(kFdBufferSize)];
struct msghdr msg = {
.msg_control = buf,
.msg_controllen = sizeof(buf),
@@ -197,11 +197,13 @@
int AHardwareBuffer_recvHandleFromUnixSocket(int socketFd, AHardwareBuffer** outBuffer) {
if (!outBuffer) return BAD_VALUE;
- char dataBuf[CMSG_SPACE(kDataBufferSize)];
- char fdBuf[CMSG_SPACE(kDataBufferSize)];
+ static constexpr int kMessageBufferSize = 4096 * sizeof(int);
+
+ std::unique_ptr<char[]> dataBuf(new char[kMessageBufferSize]);
+ char fdBuf[CMSG_SPACE(kFdBufferSize)];
struct iovec iov[1];
- iov[0].iov_base = dataBuf;
- iov[0].iov_len = sizeof(dataBuf);
+ iov[0].iov_base = dataBuf.get();
+ iov[0].iov_len = kMessageBufferSize;
struct msghdr msg = {
.msg_control = fdBuf,
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 90fb4b6..6c8221d 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -21,7 +21,7 @@
}
ndk_library {
- name: "libnativewindow.ndk",
+ name: "libnativewindow",
symbol_file: "libnativewindow.map.txt",
// Android O
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 63d1ad1..fb67a51 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -186,6 +186,12 @@
* if it is safe (i.e. no crash will occur) to call any method on it.
*/
NATIVE_WINDOW_IS_VALID = 17,
+
+ /*
+ * Returns 1 if NATIVE_WINDOW_GET_FRAME_TIMESTAMPS will return display
+ * present info, 0 if it won't.
+ */
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT = 18,
};
/* Valid operations for the (*perform)() hook.
@@ -305,6 +311,14 @@
*/
static const int64_t NATIVE_WINDOW_TIMESTAMP_AUTO = (-9223372036854775807LL-1);
+/* parameter for NATIVE_WINDOW_GET_FRAME_TIMESTAMPS
+ *
+ * Special timestamp value to indicate the timestamps aren't yet known or
+ * that they are invalid.
+ */
+static const int64_t NATIVE_WINDOW_TIMESTAMP_PENDING = -2;
+static const int64_t NATIVE_WINDOW_TIMESTAMP_INVALID = -1;
+
struct ANativeWindow
{
#ifdef __cplusplus
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 310d25e..ba37391 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -51,8 +51,7 @@
"FrameStats.cpp",
"Gralloc1.cpp",
"Gralloc1On0Adapter.cpp",
- "GrallocAllocator.cpp",
- "GrallocMapper.cpp",
+ "Gralloc2.cpp",
"GraphicBuffer.cpp",
"GraphicBufferAllocator.cpp",
"GraphicBufferMapper.cpp",
diff --git a/libs/ui/Gralloc1On0Adapter.cpp b/libs/ui/Gralloc1On0Adapter.cpp
index bd7c6a1..9ee9838 100644
--- a/libs/ui/Gralloc1On0Adapter.cpp
+++ b/libs/ui/Gralloc1On0Adapter.cpp
@@ -20,6 +20,9 @@
#include <ui/Gralloc1On0Adapter.h>
+#include <algorithm>
+#include <array>
+
#include <grallocusage/GrallocUsageConversion.h>
#include <hardware/gralloc.h>
@@ -67,13 +70,18 @@
void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount,
int32_t* outCapabilities)
{
+ constexpr std::array<int32_t, 2> supportedCapabilities = {{
+ GRALLOC1_CAPABILITY_ON_ADAPTER,
+ GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE,
+ }};
+
if (outCapabilities == nullptr) {
- *outCount = 1;
- return;
- }
- if (*outCount >= 1) {
- *outCapabilities = GRALLOC1_CAPABILITY_ON_ADAPTER;
- *outCount = 1;
+ *outCount = supportedCapabilities.size();
+ } else {
+ *outCount = std::min(*outCount, static_cast<uint32_t>(
+ supportedCapabilities.size()));
+ std::copy_n(supportedCapabilities.begin(),
+ *outCount, outCapabilities);
}
}
@@ -325,6 +333,9 @@
if (result != 0) {
ALOGE("gralloc0 unregister failed: %d", result);
}
+
+ native_handle_close(handle);
+ native_handle_delete(const_cast<native_handle_t*>(handle));
}
mBuffers.erase(handle);
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
new file mode 100644
index 0000000..75f5686
--- /dev/null
+++ b/libs/ui/Gralloc2.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#define LOG_TAG "Gralloc2"
+
+#include <ui/Gralloc2.h>
+
+#include <log/log.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wzero-length-array"
+#include <sync/sync.h>
+#pragma clang diagnostic pop
+
+namespace android {
+
+namespace Gralloc2 {
+
+static constexpr Error kTransactionError = Error::NO_RESOURCES;
+
+Mapper::Mapper()
+{
+ mMapper = IMapper::getService();
+ if (mMapper != nullptr && mMapper->isRemote()) {
+ LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
+ }
+}
+
+Error Mapper::createDescriptor(
+ const IMapper::BufferDescriptorInfo& descriptorInfo,
+ BufferDescriptor* outDescriptor) const
+{
+ Error error;
+ auto ret = mMapper->createDescriptor(descriptorInfo,
+ [&](const auto& tmpError, const auto& tmpDescriptor)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outDescriptor = tmpDescriptor;
+ });
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::importBuffer(const hardware::hidl_handle& rawHandle,
+ buffer_handle_t* outBufferHandle) const
+{
+ Error error;
+ auto ret = mMapper->importBuffer(rawHandle,
+ [&](const auto& tmpError, const auto& tmpBuffer)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outBufferHandle = static_cast<buffer_handle_t>(tmpBuffer);
+ });
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+void Mapper::freeBuffer(buffer_handle_t bufferHandle) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+ auto ret = mMapper->freeBuffer(buffer);
+
+ auto error = (ret.isOk()) ? static_cast<Error>(ret) : kTransactionError;
+ ALOGE_IF(error != Error::NONE, "freeBuffer(%p) failed with %d",
+ buffer, error);
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, void** outData) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ // put acquireFence in a hidl_handle
+ hardware::hidl_handle acquireFenceHandle;
+ NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+ if (acquireFence >= 0) {
+ auto h = native_handle_init(acquireFenceStorage, 1, 0);
+ h->data[0] = acquireFence;
+ acquireFenceHandle = h;
+ }
+
+ Error error;
+ auto ret = mMapper->lock(buffer, usage, accessRegion, acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpData)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outData = tmpData;
+ });
+
+ // we own acquireFence even on errors
+ if (acquireFence >= 0) {
+ close(acquireFence);
+ }
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+Error Mapper::lock(buffer_handle_t bufferHandle, uint64_t usage,
+ const IMapper::Rect& accessRegion,
+ int acquireFence, YCbCrLayout* outLayout) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ // put acquireFence in a hidl_handle
+ hardware::hidl_handle acquireFenceHandle;
+ NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+ if (acquireFence >= 0) {
+ auto h = native_handle_init(acquireFenceStorage, 1, 0);
+ h->data[0] = acquireFence;
+ acquireFenceHandle = h;
+ }
+
+ Error error;
+ auto ret = mMapper->lockYCbCr(buffer, usage, accessRegion,
+ acquireFenceHandle,
+ [&](const auto& tmpError, const auto& tmpLayout)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ *outLayout = tmpLayout;
+ });
+
+ // we own acquireFence even on errors
+ if (acquireFence >= 0) {
+ close(acquireFence);
+ }
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+int Mapper::unlock(buffer_handle_t bufferHandle) const
+{
+ auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+ int releaseFence = -1;
+ Error error;
+ auto ret = mMapper->unlock(buffer,
+ [&](const auto& tmpError, const auto& tmpReleaseFence)
+ {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ auto fenceHandle = tmpReleaseFence.getNativeHandle();
+ if (fenceHandle && fenceHandle->numFds == 1) {
+ int fd = dup(fenceHandle->data[0]);
+ if (fd >= 0) {
+ releaseFence = fd;
+ } else {
+ ALOGD("failed to dup unlock release fence");
+ sync_wait(fenceHandle->data[0], -1);
+ }
+ }
+ });
+
+ if (!ret.isOk()) {
+ error = kTransactionError;
+ }
+
+ if (error != Error::NONE) {
+ ALOGE("unlock(%p) failed with %d", buffer, error);
+ }
+
+ return releaseFence;
+}
+
+Allocator::Allocator(const Mapper& mapper)
+ : mMapper(mapper)
+{
+ if (mMapper.valid()) {
+ mAllocator = IAllocator::getService();
+ }
+}
+
+std::string Allocator::dumpDebugInfo() const
+{
+ std::string debugInfo;
+
+ mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) {
+ debugInfo = tmpDebugInfo.c_str();
+ });
+
+ return debugInfo;
+}
+
+Error Allocator::allocate(BufferDescriptor descriptor, uint32_t count,
+ uint32_t* outStride, buffer_handle_t* outBufferHandles) const
+{
+ Error error;
+ auto ret = mAllocator->allocate(descriptor, count,
+ [&](const auto& tmpError, const auto& tmpStride,
+ const auto& tmpBuffers) {
+ error = tmpError;
+ if (tmpError != Error::NONE) {
+ return;
+ }
+
+ // import buffers
+ for (uint32_t i = 0; i < count; i++) {
+ error = mMapper.importBuffer(tmpBuffers[i],
+ &outBufferHandles[i]);
+ if (error != Error::NONE) {
+ for (uint32_t j = 0; j < i; j++) {
+ mMapper.freeBuffer(outBufferHandles[j]);
+ outBufferHandles[j] = nullptr;
+ }
+ return;
+ }
+ }
+
+ *outStride = tmpStride;
+ });
+
+ return (ret.isOk()) ? error : kTransactionError;
+}
+
+} // namespace Gralloc2
+
+} // namespace android
diff --git a/libs/ui/GrallocAllocator.cpp b/libs/ui/GrallocAllocator.cpp
deleted file mode 100644
index 7af55e7..0000000
--- a/libs/ui/GrallocAllocator.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#define LOG_TAG "GrallocAllocator"
-
-#include <ui/GrallocAllocator.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-// assume NO_RESOURCES when Status::isOk returns false
-constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Allocator::Allocator()
-{
- mAllocator = IAllocator::getService();
- if (mAllocator != nullptr) {
- mAllocator->createClient(
- [&](const auto& tmpError, const auto& tmpClient) {
- if (tmpError == Error::NONE) {
- mClient = tmpClient;
- }
- });
- if (mClient == nullptr) {
- mAllocator.clear();
- }
- }
-}
-
-std::string Allocator::dumpDebugInfo() const
-{
- std::string info;
-
- mAllocator->dumpDebugInfo([&](const auto& tmpInfo) {
- info = tmpInfo.c_str();
- });
-
- return info;
-}
-
-Error Allocator::createBufferDescriptor(
- const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
- BufferDescriptor* outDescriptor) const
-{
- Error error = kDefaultError;
- mClient->createDescriptor(descriptorInfo,
- [&](const auto& tmpError, const auto& tmpDescriptor) {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outDescriptor = tmpDescriptor;
- });
-
- return error;
-}
-
-void Allocator::destroyBufferDescriptor(BufferDescriptor descriptor) const
-{
- mClient->destroyDescriptor(descriptor);
-}
-
-Error Allocator::allocate(BufferDescriptor descriptor,
- Buffer* outBuffer) const
-{
- hardware::hidl_vec<BufferDescriptor> descriptors;
- descriptors.setToExternal(&descriptor, 1);
-
- Error error = kDefaultError;
- auto status = mClient->allocate(descriptors,
- [&](const auto& tmpError, const auto& tmpBuffers) {
- error = tmpError;
- if (tmpError != Error::NONE) {
- return;
- }
-
- *outBuffer = tmpBuffers[0];
- });
-
- return error;
-}
-
-void Allocator::free(Buffer buffer) const
-{
- mClient->free(buffer);
-}
-
-Error Allocator::exportHandle(BufferDescriptor descriptor, Buffer buffer,
- native_handle_t** outBufferHandle) const
-{
- Error error = kDefaultError;
- auto status = mClient->exportHandle(descriptor, buffer,
- [&](const auto& tmpError, const auto& tmpBufferHandle) {
- error = tmpError;
- if (tmpError != Error::NONE) {
- return;
- }
-
- *outBufferHandle = native_handle_clone(tmpBufferHandle);
- if (!*outBufferHandle) {
- error = Error::NO_RESOURCES;
- }
- });
-
- return error;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GrallocMapper.cpp b/libs/ui/GrallocMapper.cpp
deleted file mode 100644
index 8095247..0000000
--- a/libs/ui/GrallocMapper.cpp
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright 2016 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.
- */
-
-#define LOG_TAG "GrallocMapper"
-
-#include <ui/GrallocMapper.h>
-
-#include <log/log.h>
-
-namespace android {
-
-namespace Gralloc2 {
-
-static constexpr Error kDefaultError = Error::NO_RESOURCES;
-
-Mapper::Mapper()
-{
- mMapper = IMapper::getService();
- if (mMapper != nullptr && mMapper->isRemote()) {
- LOG_ALWAYS_FATAL("gralloc-mapper must be in passthrough mode");
- }
-}
-
-Error Mapper::retain(buffer_handle_t handle) const
-{
- auto ret = mMapper->retain(handle);
- return (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
-}
-
-void Mapper::release(buffer_handle_t handle) const
-{
- auto ret = mMapper->release(handle);
-
- auto error = (ret.isOk()) ? static_cast<Error>(ret) : kDefaultError;
- ALOGE_IF(error != Error::NONE,
- "release(%p) failed with %d", handle, error);
-}
-
-Error Mapper::getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const
-{
- Error error = kDefaultError;
- mMapper->getDimensions(handle,
- [&](const auto& tmpError, const auto& tmpWidth,
- const auto& tmpHeight)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outWidth = tmpWidth;
- *outHeight = tmpHeight;
- });
-
- return error;
-}
-
-Error Mapper::getFormat(buffer_handle_t handle, int32_t* outFormat) const
-{
- Error error = kDefaultError;
- mMapper->getFormat(handle,
- [&](const auto& tmpError, const auto& tmpFormat)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outFormat = static_cast<int32_t>(tmpFormat);
- });
-
- return error;
-}
-
-Error Mapper::getLayerCount(buffer_handle_t handle,
- uint32_t* outLayerCount) const
-{
- Error error = kDefaultError;
- mMapper->getLayerCount(handle,
- [&](const auto& tmpError, const auto& tmpLayerCount)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outLayerCount = tmpLayerCount;
- });
-
- return error;
-}
-
-Error Mapper::getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const
-{
- Error error = kDefaultError;
- mMapper->getProducerUsageMask(handle,
- [&](const auto& tmpError, const auto& tmpProducerUsage)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outProducerUsage = tmpProducerUsage;
- });
-
- return error;
-}
-
-Error Mapper::getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const
-{
- Error error = kDefaultError;
- mMapper->getConsumerUsageMask(handle,
- [&](const auto& tmpError, const auto& tmpConsumerUsage)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outConsumerUsage = tmpConsumerUsage;
- });
-
- return error;
-}
-
-Error Mapper::getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const
-{
- Error error = kDefaultError;
- mMapper->getBackingStore(handle,
- [&](const auto& tmpError, const auto& tmpStore)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outBackingStore = tmpStore;
- });
-
- return error;
-}
-
-Error Mapper::getStride(buffer_handle_t handle, uint32_t* outStride) const
-{
- Error error = kDefaultError;
- mMapper->getStride(handle,
- [&](const auto& tmpError, const auto& tmpStride)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outStride = tmpStride;
- });
-
- return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
- uint64_t producerUsage,
- uint64_t consumerUsage,
- const IMapper::Rect& accessRegion,
- int acquireFence, void** outData) const
-{
- hardware::hidl_handle acquireFenceHandle;
-
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
- if (acquireFence >= 0) {
- auto h = native_handle_init(acquireFenceStorage, 1, 0);
- h->data[0] = acquireFence;
- acquireFenceHandle = h;
- }
-
- Error error = kDefaultError;
- mMapper->lock(handle, producerUsage, consumerUsage,
- accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpData)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outData = tmpData;
- });
-
- if (error == Error::NONE && acquireFence >= 0) {
- close(acquireFence);
- }
-
- return error;
-}
-
-Error Mapper::lock(buffer_handle_t handle,
- uint64_t producerUsage,
- uint64_t consumerUsage,
- const IMapper::Rect& accessRegion,
- int acquireFence, FlexLayout* outLayout) const
-{
- hardware::hidl_handle acquireFenceHandle;
-
- NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
- if (acquireFence >= 0) {
- auto h = native_handle_init(acquireFenceStorage, 1, 0);
- h->data[0] = acquireFence;
- acquireFenceHandle = h;
- }
-
- Error error = kDefaultError;
- mMapper->lockFlex(handle, producerUsage, consumerUsage,
- accessRegion, acquireFenceHandle,
- [&](const auto& tmpError, const auto& tmpLayout)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outLayout = tmpLayout;
- });
-
- if (error == Error::NONE && acquireFence >= 0) {
- close(acquireFence);
- }
-
- return error;
-}
-
-int Mapper::unlock(buffer_handle_t handle) const
-{
- int releaseFence = -1;
-
- Error error = kDefaultError;
- mMapper->unlock(handle,
- [&](const auto& tmpError, const auto& tmpReleaseFence)
- {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- auto fenceHandle = tmpReleaseFence.getNativeHandle();
- if (fenceHandle && fenceHandle->numFds == 1) {
- int fd = dup(fenceHandle->data[0]);
- if (fd >= 0) {
- releaseFence = fd;
- } else {
- error = Error::NO_RESOURCES;
- }
- } else {
- releaseFence = -1;
- }
- });
-
- if (error != Error::NONE) {
- ALOGE("unlock(%p) failed with %d", handle, error);
- releaseFence = -1;
- }
-
- return releaseFence;
-}
-
-} // namespace Gralloc2
-
-} // namespace android
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index d21758d..eb5c7b6 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -22,7 +22,7 @@
#include <grallocusage/GrallocUsageConversion.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/GraphicBufferMapper.h>
@@ -104,11 +104,7 @@
void GraphicBuffer::free_handle()
{
if (mOwner == ownHandle) {
- mBufferMapper.unregisterBuffer(handle);
- if (!mBufferMapper.getGrallocMapper().valid()) {
- native_handle_close(handle);
- native_handle_delete(const_cast<native_handle*>(handle));
- }
+ mBufferMapper.freeBuffer(handle);
} else if (mOwner == ownData) {
GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
allocator.free(handle);
@@ -217,7 +213,7 @@
mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
if (method == TAKE_UNREGISTERED_HANDLE) {
- status_t err = mBufferMapper.registerBuffer(this);
+ status_t err = mBufferMapper.importBuffer(this);
if (err != NO_ERROR) {
// clean up cloned handle
if (clone) {
@@ -451,7 +447,7 @@
mOwner = ownHandle;
if (handle != 0) {
- status_t err = mBufferMapper.registerBuffer(this);
+ status_t err = mBufferMapper.importBuffer(this);
if (err != NO_ERROR) {
width = height = stride = format = layerCount = usage = 0;
handle = NULL;
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index 3f18bbc..1f6c537 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -22,13 +22,14 @@
#include <stdio.h>
+#include <grallocusage/GrallocUsageConversion.h>
+
#include <log/log.h>
#include <utils/Singleton.h>
#include <utils/String8.h>
#include <utils/Trace.h>
-#include <ui/GrallocAllocator.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
#include <ui/GraphicBufferMapper.h>
namespace android {
@@ -41,8 +42,9 @@
GraphicBufferAllocator::alloc_rec_t> GraphicBufferAllocator::sAllocList;
GraphicBufferAllocator::GraphicBufferAllocator()
- : mAllocator(std::make_unique<Gralloc2::Allocator>()),
- mMapper(GraphicBufferMapper::getInstance())
+ : mMapper(GraphicBufferMapper::getInstance()),
+ mAllocator(std::make_unique<Gralloc2::Allocator>(
+ mMapper.getGrallocMapper()))
{
if (!mAllocator->valid()) {
mLoader = std::make_unique<Gralloc1::Loader>();
@@ -102,109 +104,6 @@
ALOGD("%s", s.string());
}
-namespace {
-
-class HalBuffer {
-public:
- HalBuffer(const Gralloc2::Allocator* allocator,
- uint32_t width, uint32_t height,
- PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
- uint64_t consumerUsage)
- : mAllocator(allocator), mBufferValid(false)
- {
- Gralloc2::IAllocatorClient::BufferDescriptorInfo info = {};
- info.width = width;
- info.height = height;
- info.format = static_cast<Gralloc2::PixelFormat>(format);
- info.layerCount = layerCount;
- info.producerUsageMask = producerUsage;
- info.consumerUsageMask = consumerUsage;
-
- Gralloc2::BufferDescriptor descriptor;
- auto error = mAllocator->createBufferDescriptor(info, &descriptor);
- if (error != Gralloc2::Error::NONE) {
- ALOGE("Failed to create desc (%u x %u) layerCount %u format %d producerUsage %" PRIx64
- " consumerUsage %" PRIx64 ": %d",
- width, height, layerCount, format, producerUsage,
- consumerUsage, error);
- return;
- }
-
- error = mAllocator->allocate(descriptor, &mBuffer);
- if (error == Gralloc2::Error::NOT_SHARED) {
- error = Gralloc2::Error::NONE;
- }
-
- if (error != Gralloc2::Error::NONE) {
- ALOGE("Failed to allocate (%u x %u) layerCount %u format %d producerUsage %" PRIx64
- " consumerUsage %" PRIx64 ": %d",
- width, height, layerCount, format, producerUsage,
- consumerUsage, error);
- mAllocator->destroyBufferDescriptor(descriptor);
- return;
- }
-
- error = mAllocator->exportHandle(descriptor, mBuffer, &mHandle);
- if (error != Gralloc2::Error::NONE) {
- ALOGE("Failed to export handle");
- mAllocator->free(mBuffer);
- mAllocator->destroyBufferDescriptor(descriptor);
- return;
- }
-
- mAllocator->destroyBufferDescriptor(descriptor);
-
- mBufferValid = true;
- }
-
- ~HalBuffer()
- {
- if (mBufferValid) {
- if (mHandle) {
- native_handle_close(mHandle);
- native_handle_delete(mHandle);
- }
-
- mAllocator->free(mBuffer);
- }
- }
-
- bool exportHandle(GraphicBufferMapper& mapper,
- buffer_handle_t* handle, uint32_t* stride)
- {
- if (!mBufferValid) {
- return false;
- }
-
- if (mapper.registerBuffer(mHandle)) {
- return false;
- }
-
- *handle = mHandle;
-
- auto error = mapper.getGrallocMapper().getStride(mHandle, stride);
- if (error != Gralloc2::Error::NONE) {
- ALOGW("Failed to get stride from buffer: %d", error);
- *stride = 0;
- }
-
- mHandle = nullptr;
- mAllocator->free(mBuffer);
- mBufferValid = false;
-
- return true;
- }
-
-private:
- const Gralloc2::Allocator* mAllocator;
-
- bool mBufferValid;
- Gralloc2::Buffer mBuffer;
- native_handle_t* mHandle;
-};
-
-} // namespace
-
status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
PixelFormat format, uint32_t layerCount, uint64_t producerUsage,
uint64_t consumerUsage, buffer_handle_t* handle, uint32_t* stride,
@@ -223,12 +122,18 @@
gralloc1_error_t error;
if (mAllocator->valid()) {
- HalBuffer buffer(mAllocator.get(), width, height, format, layerCount,
- producerUsage, consumerUsage);
- if (!buffer.exportHandle(mMapper, handle, stride)) {
+ Gralloc2::IMapper::BufferDescriptorInfo info = {};
+ info.width = width;
+ info.height = height;
+ info.layerCount = layerCount;
+ info.format = static_cast<Gralloc2::PixelFormat>(format);
+ info.usage = static_cast<uint64_t>(android_convertGralloc1To0Usage(
+ producerUsage, consumerUsage));
+ error = static_cast<gralloc1_error_t>(mAllocator->allocate(info,
+ stride, handle));
+ if (error != GRALLOC1_ERROR_NONE) {
return NO_MEMORY;
}
- error = GRALLOC1_ERROR_NONE;
} else {
auto descriptor = mDevice->createDescriptor();
error = descriptor->setDimensions(width, height);
@@ -310,8 +215,7 @@
gralloc1_error_t error;
if (mAllocator->valid()) {
- error = static_cast<gralloc1_error_t>(
- mMapper.unregisterBuffer(handle));
+ error = static_cast<gralloc1_error_t>(mMapper.freeBuffer(handle));
} else {
error = mDevice->release(handle);
}
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 656472f..87519bf 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -20,6 +20,8 @@
#include <ui/GraphicBufferMapper.h>
+#include <grallocusage/GrallocUsageConversion.h>
+
// We would eliminate the non-conforming zero-length array, but we can't since
// this is effectively included from the Linux kernel
#pragma clang diagnostic push
@@ -30,7 +32,7 @@
#include <utils/Log.h>
#include <utils/Trace.h>
-#include <ui/GrallocMapper.h>
+#include <ui/Gralloc2.h>
#include <ui/GraphicBuffer.h>
#include <system/graphics.h>
@@ -49,63 +51,84 @@
}
}
-
-
-status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::importBuffer(buffer_handle_t rawHandle,
+ buffer_handle_t* outHandle)
{
ATRACE_CALL();
+ Gralloc2::Error error;
+ if (mMapper->valid()) {
+ error = mMapper->importBuffer(hardware::hidl_handle(rawHandle),
+ outHandle);
+ } else {
+ error = Gralloc2::Error::UNSUPPORTED;
+ }
+
+ ALOGW_IF(error != Gralloc2::Error::NONE, "importBuffer(%p) failed: %d",
+ rawHandle, error);
+
+ return static_cast<status_t>(error);
+}
+
+status_t GraphicBufferMapper::importBuffer(const GraphicBuffer* buffer)
+{
+ ATRACE_CALL();
+
+ ANativeWindowBuffer* nativeBuffer = buffer->getNativeBuffer();
+ buffer_handle_t rawHandle = nativeBuffer->handle;
+
gralloc1_error_t error;
if (mMapper->valid()) {
- error = static_cast<gralloc1_error_t>(mMapper->retain(handle));
+ buffer_handle_t importedHandle;
+ error = static_cast<gralloc1_error_t>(mMapper->importBuffer(
+ hardware::hidl_handle(rawHandle), &importedHandle));
+ if (error == GRALLOC1_ERROR_NONE) {
+ nativeBuffer->handle = importedHandle;
+ }
} else {
- // This always returns GRALLOC1_BAD_HANDLE when handle is from a
- // remote process and mDevice is backed by Gralloc1On0Adapter.
- error = mDevice->retain(handle);
- if (error == GRALLOC1_ERROR_BAD_HANDLE &&
- mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) {
- ALOGE("registerBuffer by handle is not supported with "
- "Gralloc1On0Adapter");
+ native_handle_t* clonedHandle = native_handle_clone(rawHandle);
+ if (clonedHandle) {
+ nativeBuffer->handle = clonedHandle;
+ error = mDevice->retain(buffer);
+ if (error != GRALLOC1_ERROR_NONE) {
+ nativeBuffer->handle = rawHandle;
+ native_handle_close(clonedHandle);
+ native_handle_delete(clonedHandle);
+ }
+ } else {
+ error = GRALLOC1_ERROR_NO_RESOURCES;
}
}
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer)
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- error = static_cast<gralloc1_error_t>(
- mMapper->retain(buffer->getNativeBuffer()->handle));
- } else {
- error = mDevice->retain(buffer);
+ // the raw handle is owned by GraphicBuffer and is now replaced
+ if (error == GRALLOC1_ERROR_NONE) {
+ native_handle_close(rawHandle);
+ native_handle_delete(const_cast<native_handle_t*>(rawHandle));
}
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d",
- buffer->getNativeBuffer()->handle, error);
+ ALOGW_IF(error != GRALLOC1_ERROR_NONE, "importBuffer(%p) failed: %d",
+ rawHandle, error);
return error;
}
-status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
+status_t GraphicBufferMapper::freeBuffer(buffer_handle_t handle)
{
ATRACE_CALL();
gralloc1_error_t error;
if (mMapper->valid()) {
- mMapper->release(handle);
+ mMapper->freeBuffer(handle);
error = GRALLOC1_ERROR_NONE;
} else {
error = mDevice->release(handle);
+ if (!mDevice->hasCapability(GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE)) {
+ native_handle_close(handle);
+ native_handle_delete(const_cast<native_handle_t*>(handle));
+ }
}
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d",
+ ALOGW_IF(error != GRALLOC1_ERROR_NONE, "freeBuffer(%p): failed %d",
handle, error);
return error;
@@ -120,138 +143,13 @@
return outRect;
}
-
-status_t GraphicBufferMapper::getDimensions(buffer_handle_t handle,
- uint32_t* outWidth, uint32_t* outHeight) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getDimensions(handle, outWidth, outHeight);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getDimensions(handle, outWidth, outHeight);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getDimensions(%p, ...): failed %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getFormat(buffer_handle_t handle,
- int32_t* outFormat) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getFormat(handle, outFormat);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getFormat(handle, outFormat);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getFormat(%p, ...): failed %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getLayerCount(buffer_handle_t handle,
- uint32_t* outLayerCount) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getLayerCount(handle, outLayerCount);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getLayerCount(handle, outLayerCount);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getLayerCount(%p, ...): failed %d",
- handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getProducerUsage(buffer_handle_t handle,
- uint64_t* outProducerUsage) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getProducerUsage(handle, outProducerUsage);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getProducerUsage(handle, outProducerUsage);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE,
- "getProducerUsage(%p, ...): failed %d", handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getConsumerUsage(buffer_handle_t handle,
- uint64_t* outConsumerUsage) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getConsumerUsage(handle, outConsumerUsage);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getConsumerUsage(handle, outConsumerUsage);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE,
- "getConsumerUsage(%p, ...): failed %d", handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getBackingStore(buffer_handle_t handle,
- uint64_t* outBackingStore) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getBackingStore(handle, outBackingStore);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getBackingStore(handle, outBackingStore);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE,
- "getBackingStore(%p, ...): failed %d", handle, error);
-
- return error;
-}
-
-status_t GraphicBufferMapper::getStride(buffer_handle_t handle,
- uint32_t* outStride) const
-{
- ATRACE_CALL();
-
- gralloc1_error_t error;
- if (mMapper->valid()) {
- mMapper->getStride(handle, outStride);
- error = GRALLOC1_ERROR_NONE;
- } else {
- error = mDevice->getStride(handle, outStride);
- }
-
- ALOGW_IF(error != GRALLOC1_ERROR_NONE, "getStride(%p, ...): failed %d",
- handle, error);
-
- return error;
+static inline Gralloc2::IMapper::Rect asGralloc2Rect(const Rect& rect) {
+ Gralloc2::IMapper::Rect outRect{};
+ outRect.left = rect.left;
+ outRect.top = rect.top;
+ outRect.width = rect.width();
+ outRect.height = rect.height();
+ return outRect;
}
status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage,
@@ -289,15 +187,15 @@
{
ATRACE_CALL();
- gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
gralloc1_error_t error;
if (mMapper->valid()) {
- const Gralloc2::IMapper::Rect& accessRect =
- *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
- error = static_cast<gralloc1_error_t>(mMapper->lock(
- handle, producerUsage, consumerUsage, accessRect,
- fenceFd, vaddr));
+ const uint64_t usage =
+ static_cast<uint64_t>(android_convertGralloc1To0Usage(
+ producerUsage, consumerUsage));
+ error = static_cast<gralloc1_error_t>(mMapper->lock(handle,
+ usage, asGralloc2Rect(bounds), fenceFd, vaddr));
} else {
+ gralloc1_rect_t accessRegion = asGralloc1Rect(bounds);
sp<Fence> fence = new Fence(fenceFd);
error = mDevice->lock(handle,
static_cast<gralloc1_producer_usage_t>(producerUsage),
@@ -346,22 +244,19 @@
gralloc1_error_t error;
if (mMapper->valid()) {
- const Gralloc2::IMapper::Rect& accessRect =
- *reinterpret_cast<Gralloc2::IMapper::Rect*>(&accessRegion);
- Gralloc2::FlexLayout layout{};
- error = static_cast<gralloc1_error_t>(mMapper->lock(
- handle, usage, usage, accessRect, fenceFd, &layout));
-
+ Gralloc2::YCbCrLayout layout;
+ error = static_cast<gralloc1_error_t>(mMapper->lock(handle, usage,
+ asGralloc2Rect(bounds), fenceFd, &layout));
if (error == GRALLOC1_ERROR_NONE) {
- planes.resize(layout.planes.size());
- memcpy(planes.data(), layout.planes.data(),
- sizeof(planes[0]) * planes.size());
-
- flexLayout.format = static_cast<android_flex_format_t>(
- layout.format);
- flexLayout.num_planes = static_cast<uint32_t>(planes.size());
- flexLayout.planes = planes.data();
+ ycbcr->y = layout.y;
+ ycbcr->cb = layout.cb;
+ ycbcr->cr = layout.cr;
+ ycbcr->ystride = static_cast<size_t>(layout.yStride);
+ ycbcr->cstride = static_cast<size_t>(layout.cStride);
+ ycbcr->chroma_step = static_cast<size_t>(layout.chromaStep);
}
+
+ return error;
} else {
sp<Fence> fence = new Fence(fenceFd);
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index b55c212..6733505 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -25,9 +25,3 @@
shared_libs: ["libui"],
srcs: ["colorspace_test.cpp"],
}
-
-cc_test {
- name: "Gralloc1Mapper_test",
- shared_libs: ["libui", "libutils"],
- srcs: ["Gralloc1Mapper_test.cpp"],
-}
diff --git a/libs/ui/tests/Gralloc1Mapper_test.cpp b/libs/ui/tests/Gralloc1Mapper_test.cpp
deleted file mode 100644
index b7c9f0f..0000000
--- a/libs/ui/tests/Gralloc1Mapper_test.cpp
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#define LOG_TAG "Gralloc1Mapper_test"
-//#define LOG_NDEBUG 0
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
-#include <utils/Errors.h>
-
-#include <gtest/gtest.h>
-
-using namespace android;
-
-class Gralloc1MapperTest : public ::testing::Test
-{
-public:
- ~Gralloc1MapperTest() override = default;
-
-protected:
- void SetUp() override {
- buffer = new GraphicBuffer(4, 8, HAL_PIXEL_FORMAT_RGBA_8888, 1,
- GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN,
- GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, "Gralloc1MapperTest");
- ASSERT_NE(nullptr, buffer.get());
-
- handle = static_cast<buffer_handle_t>(buffer->handle);
-
- mapper = &GraphicBufferMapper::get();
- }
-
- sp<GraphicBuffer> buffer;
- buffer_handle_t handle;
- GraphicBufferMapper* mapper;
-};
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getDimensions) {
- uint32_t width = 0;
- uint32_t height = 0;
- status_t err = mapper->getDimensions(handle, &width, &height);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(4U, width);
- EXPECT_EQ(8U, height);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getFormat) {
- int32_t value = 0;
- status_t err = mapper->getFormat(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getLayerCount) {
- uint32_t value = 0;
- status_t err = mapper->getLayerCount(handle, &value);
- if (err != GRALLOC1_ERROR_UNSUPPORTED) {
- EXPECT_EQ(1U, value);
- }
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getProducerUsage) {
- uint64_t value = 0;
- status_t err = mapper->getProducerUsage(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getConsumerUsage) {
- uint64_t value = 0;
- status_t err = mapper->getConsumerUsage(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- EXPECT_EQ(GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, value);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getBackingStore) {
- uint64_t value = 0;
- status_t err = mapper->getBackingStore(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
-}
-
-TEST_F(Gralloc1MapperTest, Gralloc1MapperTest_getStride) {
- uint32_t value = 0;
- status_t err = mapper->getStride(handle, &value);
- ASSERT_EQ(GRALLOC1_ERROR_NONE, err);
- // The stride should be at least the width of the buffer.
- EXPECT_LE(4U, value);
-}
diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp
new file mode 100644
index 0000000..13af470
--- /dev/null
+++ b/libs/vr/libbroadcastring/Android.bp
@@ -0,0 +1,35 @@
+cc_library_static {
+ name: "libbroadcastring",
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ export_include_dirs: ["include"],
+ shared_libs: [
+ "libbase",
+ ],
+ export_shared_lib_headers: [
+ "libbase",
+ ],
+}
+
+cc_test {
+ name: "broadcast_ring_tests",
+ clang: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ ],
+ srcs: [
+ "broadcast_ring_test.cc",
+ ],
+ static_libs: [
+ "libbroadcastring",
+ ],
+ shared_libs: [
+ "libbase",
+ ],
+}
diff --git a/libs/vr/libbroadcastring/broadcast_ring_test.cc b/libs/vr/libbroadcastring/broadcast_ring_test.cc
new file mode 100644
index 0000000..dfdd4ef
--- /dev/null
+++ b/libs/vr/libbroadcastring/broadcast_ring_test.cc
@@ -0,0 +1,866 @@
+#include "libbroadcastring/broadcast_ring.h"
+
+#include <stdlib.h>
+#include <memory>
+#include <thread> // NOLINT
+#include <sys/mman.h>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+namespace {
+
+template <uint32_t N>
+struct alignas(8) Aligned {
+ char v[N];
+};
+
+template <uint32_t N>
+struct alignas(8) Sized {
+ Sized() { Clear(); }
+ explicit Sized(char c) { Fill(c); }
+ char v[sizeof(Aligned<N>)];
+ void Clear() { memset(v, 0, sizeof(v)); }
+ void Fill(char c) { memset(v, c, sizeof(v)); }
+ static Sized Pattern(uint8_t c) {
+ Sized sized;
+ for (size_t i = 0; i < sizeof(v); ++i) {
+ sized.v[i] = static_cast<char>(c + i);
+ }
+ return sized;
+ }
+ bool operator==(const Sized& right) const {
+ static_assert(sizeof(*this) == sizeof(v), "Size mismatch");
+ return !memcmp(v, right.v, sizeof(v));
+ }
+ template <typename SmallerSized>
+ SmallerSized Truncate() const {
+ SmallerSized val;
+ static_assert(sizeof(val.v) <= sizeof(v), "Cannot truncate to larger size");
+ memcpy(val.v, v, sizeof(val.v));
+ return val;
+ }
+};
+
+char FillChar(int val) { return static_cast<char>(val); }
+
+struct FakeMmap {
+ explicit FakeMmap(size_t size) : size(size), data(new char[size]) {}
+ size_t size;
+ std::unique_ptr<char[]> data;
+ void* mmap() { return static_cast<void*>(data.get()); }
+};
+
+template <typename Ring>
+FakeMmap CreateRing(Ring* ring, uint32_t count) {
+ FakeMmap mmap(Ring::MemorySize(count));
+ *ring = Ring::Create(mmap.mmap(), mmap.size, count);
+ return mmap;
+}
+
+template <typename RecordType, bool StaticSize = false,
+ uint32_t StaticCount = 0, uint32_t MaxReserved = 1,
+ uint32_t MinAvailable = 0>
+struct Traits {
+ using Record = RecordType;
+ static constexpr bool kUseStaticRecordSize = StaticSize;
+ static constexpr uint32_t kStaticRecordCount = StaticCount;
+ static constexpr uint32_t kMaxReservedRecords = MaxReserved;
+ static constexpr uint32_t kMinAvailableRecords = MinAvailable;
+ static constexpr uint32_t kMinRecordCount = MaxReserved + MinAvailable;
+};
+
+template <typename Record, bool StaticSize = false, uint32_t MaxReserved = 1,
+ uint32_t MinAvailable = 7>
+struct TraitsDynamic
+ : public Traits<Record, StaticSize, 0, MaxReserved, MinAvailable> {
+ using Ring = BroadcastRing<Record, TraitsDynamic>;
+ static uint32_t MinCount() { return MaxReserved + MinAvailable; }
+};
+
+template <typename Record, uint32_t StaticCount = 1, bool StaticSize = true,
+ uint32_t MaxReserved = 1, uint32_t MinAvailable = 0>
+struct TraitsStatic
+ : public Traits<Record, true, StaticCount, MaxReserved, MinAvailable> {
+ using Ring = BroadcastRing<Record, TraitsStatic>;
+ static uint32_t MinCount() { return StaticCount; }
+};
+
+using Dynamic_8_NxM = TraitsDynamic<Sized<8>>;
+using Dynamic_16_NxM = TraitsDynamic<Sized<16>>;
+using Dynamic_32_NxM = TraitsDynamic<Sized<32>>;
+using Dynamic_32_32xM = TraitsDynamic<Sized<32>, true>;
+using Dynamic_16_NxM_1plus0 = TraitsDynamic<Sized<16>, false, 1, 0>;
+using Dynamic_16_NxM_1plus1 = TraitsDynamic<Sized<16>, false, 1, 1>;
+using Dynamic_16_NxM_5plus11 = TraitsDynamic<Sized<16>, false, 5, 11>;
+using Dynamic_256_NxM_1plus0 = TraitsDynamic<Sized<256>, false, 1, 0>;
+
+using Static_8_8x1 = TraitsStatic<Sized<8>, 1>;
+using Static_8_8x16 = TraitsStatic<Sized<8>, 16>;
+using Static_16_16x8 = TraitsStatic<Sized<16>, 8>;
+using Static_16_16x16 = TraitsStatic<Sized<16>, 16>;
+using Static_16_16x32 = TraitsStatic<Sized<16>, 32>;
+using Static_32_Nx8 = TraitsStatic<Sized<32>, 8, false>;
+
+using TraitsList = ::testing::Types<Dynamic_8_NxM, //
+ Dynamic_16_NxM, //
+ Dynamic_32_NxM, //
+ Dynamic_32_32xM, //
+ Dynamic_16_NxM_1plus0, //
+ Dynamic_16_NxM_1plus1, //
+ Dynamic_16_NxM_5plus11, //
+ Dynamic_256_NxM_1plus0, //
+ Static_8_8x1, //
+ Static_8_8x16, //
+ Static_16_16x8, //
+ Static_16_16x16, //
+ Static_16_16x32, //
+ Static_32_Nx8>;
+
+} // namespace
+
+template <typename T>
+class BroadcastRingTest : public ::testing::Test {};
+
+TYPED_TEST_CASE(BroadcastRingTest, TraitsList);
+
+TYPED_TEST(BroadcastRingTest, Geometry) {
+ using Record = typename TypeParam::Record;
+ using Ring = typename TypeParam::Ring;
+ Ring ring;
+ auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+ EXPECT_EQ(Ring::Traits::MinCount(), ring.record_count());
+ EXPECT_EQ(sizeof(Record), ring.record_size());
+}
+
+TYPED_TEST(BroadcastRingTest, PutGet) {
+ using Record = typename TypeParam::Record;
+ using Ring = typename TypeParam::Ring;
+ Ring ring;
+ auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+ const uint32_t oldest_sequence_at_start = ring.GetOldestSequence();
+ const uint32_t next_sequence_at_start = ring.GetNextSequence();
+ {
+ uint32_t sequence = oldest_sequence_at_start;
+ Record record;
+ EXPECT_FALSE(ring.Get(&sequence, &record));
+ EXPECT_EQ(oldest_sequence_at_start, sequence);
+ EXPECT_EQ(Record(), record);
+ }
+ const Record original_record(0x1a);
+ ring.Put(original_record);
+ {
+ uint32_t sequence = next_sequence_at_start;
+ Record record;
+ EXPECT_TRUE(ring.Get(&sequence, &record));
+ EXPECT_EQ(next_sequence_at_start, sequence);
+ EXPECT_EQ(original_record, record);
+ }
+ {
+ uint32_t sequence = next_sequence_at_start + 1;
+ Record record;
+ EXPECT_FALSE(ring.Get(&sequence, &record));
+ EXPECT_EQ(next_sequence_at_start + 1, sequence);
+ EXPECT_EQ(Record(), record);
+ }
+}
+
+TYPED_TEST(BroadcastRingTest, FillOnce) {
+ using Record = typename TypeParam::Record;
+ using Ring = typename TypeParam::Ring;
+ Ring ring;
+ auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+ const uint32_t next_sequence_at_start = ring.GetNextSequence();
+ for (uint32_t i = 0; i < ring.record_count(); ++i)
+ ring.Put(Record(FillChar(i)));
+ for (uint32_t i = 0; i < ring.record_count(); ++i) {
+ const uint32_t expected_sequence = next_sequence_at_start + i;
+ const Record expected_record(FillChar(i));
+ {
+ uint32_t sequence = ring.GetOldestSequence() + i;
+ Record record;
+ EXPECT_TRUE(ring.Get(&sequence, &record));
+ EXPECT_EQ(expected_sequence, sequence);
+ EXPECT_EQ(expected_record, record);
+ }
+ }
+ {
+ uint32_t sequence = ring.GetOldestSequence() + ring.record_count();
+ Record record;
+ EXPECT_FALSE(ring.Get(&sequence, &record));
+ }
+}
+
+TYPED_TEST(BroadcastRingTest, FillTwice) {
+ using Record = typename TypeParam::Record;
+ using Ring = typename TypeParam::Ring;
+ Ring ring;
+ auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+ const uint32_t next_sequence_at_start = ring.GetNextSequence();
+ for (uint32_t i = 0; i < 2 * ring.record_count(); ++i) {
+ const Record newest_record(FillChar(i));
+ ring.Put(newest_record);
+
+ const uint32_t newest_sequence = next_sequence_at_start + i;
+ const uint32_t records_available = std::min(i + 1, ring.record_count());
+ const uint32_t oldest_sequence = newest_sequence - records_available + 1;
+ EXPECT_EQ(newest_sequence, ring.GetNewestSequence());
+ EXPECT_EQ(oldest_sequence, ring.GetOldestSequence());
+ EXPECT_EQ(newest_sequence + 1, ring.GetNextSequence());
+
+ for (uint32_t j = 0; j < records_available; ++j) {
+ const uint32_t sequence_jth_newest = newest_sequence - j;
+ const Record record_jth_newest(FillChar(i - j));
+
+ {
+ uint32_t sequence = sequence_jth_newest;
+ Record record;
+ EXPECT_TRUE(ring.Get(&sequence, &record));
+ EXPECT_EQ(sequence_jth_newest, sequence);
+ EXPECT_EQ(record_jth_newest, record);
+ }
+
+ {
+ uint32_t sequence = sequence_jth_newest;
+ Record record;
+ EXPECT_TRUE(ring.GetNewest(&sequence, &record));
+ EXPECT_EQ(newest_sequence, sequence);
+ EXPECT_EQ(newest_record, record);
+ }
+ }
+
+ const Record oldest_record(
+ FillChar(i + (oldest_sequence - newest_sequence)));
+ const uint32_t sequence_0th_overwritten = oldest_sequence - 1;
+ const uint32_t sequence_0th_future = newest_sequence + 1;
+ const uint32_t sequence_1st_future = newest_sequence + 2;
+
+ {
+ uint32_t sequence = sequence_0th_overwritten;
+ Record record;
+ EXPECT_TRUE(ring.Get(&sequence, &record));
+ EXPECT_EQ(oldest_sequence, sequence);
+ EXPECT_EQ(oldest_record, record);
+ }
+
+ {
+ uint32_t sequence = sequence_0th_overwritten;
+ Record record;
+ EXPECT_TRUE(ring.GetNewest(&sequence, &record));
+ EXPECT_EQ(newest_sequence, sequence);
+ EXPECT_EQ(newest_record, record);
+ }
+
+ {
+ uint32_t sequence = sequence_0th_future;
+ Record record;
+ EXPECT_FALSE(ring.Get(&sequence, &record));
+ EXPECT_EQ(sequence_0th_future, sequence);
+ EXPECT_EQ(Record(), record);
+ }
+
+ {
+ uint32_t sequence = sequence_0th_future;
+ Record record;
+ EXPECT_FALSE(ring.GetNewest(&sequence, &record));
+ EXPECT_EQ(sequence_0th_future, sequence);
+ EXPECT_EQ(Record(), record);
+ }
+
+ {
+ uint32_t sequence = sequence_1st_future;
+ Record record;
+ EXPECT_TRUE(ring.Get(&sequence, &record));
+ EXPECT_EQ(oldest_sequence, sequence);
+ EXPECT_EQ(oldest_record, record);
+ }
+
+ {
+ uint32_t sequence = sequence_1st_future;
+ Record record;
+ EXPECT_TRUE(ring.GetNewest(&sequence, &record));
+ EXPECT_EQ(newest_sequence, sequence);
+ EXPECT_EQ(newest_record, record);
+ }
+ }
+}
+
+TYPED_TEST(BroadcastRingTest, Import) {
+ using Record = typename TypeParam::Record;
+ using Ring = typename TypeParam::Ring;
+ Ring ring;
+ auto mmap = CreateRing(&ring, Ring::Traits::MinCount());
+
+ const uint32_t sequence_0 = ring.GetNextSequence();
+ const uint32_t sequence_1 = ring.GetNextSequence() + 1;
+ const Record record_0 = Record::Pattern(0x00);
+ const Record record_1 = Record::Pattern(0x80);
+ ring.Put(record_0);
+ ring.Put(record_1);
+
+ {
+ Ring imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) = Ring::Import(mmap.mmap(), mmap.size);
+ EXPECT_TRUE(import_ok);
+ EXPECT_EQ(ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(ring.record_count(), imported_ring.record_count());
+
+ if (ring.record_count() != 1) {
+ uint32_t sequence = sequence_0;
+ Record imported_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+ EXPECT_EQ(sequence_0, sequence);
+ EXPECT_EQ(record_0, imported_record);
+ }
+
+ {
+ uint32_t sequence = sequence_1;
+ Record imported_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+ EXPECT_EQ(sequence_1, sequence);
+ EXPECT_EQ(record_1, imported_record);
+ }
+ }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfStaticSizeMismatch) {
+ using OriginalRing = typename Static_16_16x16::Ring;
+ using RecordSizeMismatchRing = typename Static_8_8x16::Ring;
+ using RecordCountMismatchRing = typename Static_16_16x8::Ring;
+
+ OriginalRing original_ring;
+ auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+ {
+ using ImportedRing = RecordSizeMismatchRing;
+ ImportedRing imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), mmap.size);
+ EXPECT_FALSE(import_ok);
+ auto mmap_imported =
+ CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+ EXPECT_NE(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+ }
+
+ {
+ using ImportedRing = RecordCountMismatchRing;
+ ImportedRing imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), mmap.size);
+ EXPECT_FALSE(import_ok);
+ auto mmap_imported =
+ CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+ EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_NE(original_ring.record_count(), imported_ring.record_count());
+ }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfDynamicSizeGrows) {
+ using OriginalRing = typename Dynamic_8_NxM::Ring;
+ using RecordSizeGrowsRing = typename Dynamic_16_NxM::Ring;
+
+ OriginalRing original_ring;
+ auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+ {
+ using ImportedRing = RecordSizeGrowsRing;
+ ImportedRing imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), mmap.size);
+ EXPECT_FALSE(import_ok);
+ auto mmap_imported =
+ CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+ EXPECT_LT(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+ }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfCountTooSmall) {
+ using OriginalRing = typename Dynamic_16_NxM_1plus0::Ring;
+ using MinCountRing = typename Dynamic_16_NxM_1plus1::Ring;
+
+ OriginalRing original_ring;
+ auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+ {
+ using ImportedRing = MinCountRing;
+ ImportedRing imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), mmap.size);
+ EXPECT_FALSE(import_ok);
+ auto mmap_imported =
+ CreateRing(&imported_ring, ImportedRing::Traits::MinCount());
+ EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_LT(original_ring.record_count(), imported_ring.record_count());
+ }
+}
+
+TEST(BroadcastRingTest, ShouldFailImportIfMmapTooSmall) {
+ using OriginalRing = typename Dynamic_16_NxM::Ring;
+
+ OriginalRing original_ring;
+ auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+ {
+ using ImportedRing = OriginalRing;
+ ImportedRing imported_ring;
+ bool import_ok;
+ const size_t kMinSize =
+ ImportedRing::MemorySize(original_ring.record_count());
+ std::tie(imported_ring, import_ok) = ImportedRing::Import(mmap.mmap(), 0);
+ EXPECT_FALSE(import_ok);
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), kMinSize - 1);
+ EXPECT_FALSE(import_ok);
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), kMinSize);
+ EXPECT_TRUE(import_ok);
+ EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+ }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfDynamicSizeShrinks) {
+ using OriginalRing = typename Dynamic_16_NxM::Ring;
+ using RecordSizeShrinksRing = typename Dynamic_8_NxM::Ring;
+
+ OriginalRing original_ring;
+ auto mmap = CreateRing(&original_ring, OriginalRing::Traits::MinCount());
+
+ using OriginalRecord = typename OriginalRing::Record;
+ const uint32_t original_sequence_0 = original_ring.GetNextSequence();
+ const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
+ const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
+ const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
+ original_ring.Put(original_record_0);
+ original_ring.Put(original_record_1);
+
+ {
+ using ImportedRing = RecordSizeShrinksRing;
+ using ImportedRecord = typename ImportedRing::Record;
+ ImportedRing imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), mmap.size);
+ EXPECT_TRUE(import_ok);
+ EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+ EXPECT_GT(sizeof(OriginalRecord), sizeof(ImportedRecord));
+
+ {
+ uint32_t sequence = original_sequence_0;
+ ImportedRecord shrunk_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record));
+ EXPECT_EQ(original_sequence_0, sequence);
+ EXPECT_EQ(original_record_0.Truncate<ImportedRecord>(), shrunk_record);
+ }
+
+ {
+ uint32_t sequence = original_sequence_1;
+ ImportedRecord shrunk_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &shrunk_record));
+ EXPECT_EQ(original_sequence_1, sequence);
+ EXPECT_EQ(original_record_1.Truncate<ImportedRecord>(), shrunk_record);
+ }
+ }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfCompatibleDynamicToStatic) {
+ using OriginalRing = typename Dynamic_16_NxM::Ring;
+ using ImportedRing = typename Static_16_16x16::Ring;
+ using OriginalRecord = typename OriginalRing::Record;
+ using ImportedRecord = typename ImportedRing::Record;
+ using StaticRing = ImportedRing;
+
+ OriginalRing original_ring;
+ auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount());
+
+ const uint32_t original_sequence_0 = original_ring.GetNextSequence();
+ const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
+ const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
+ const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
+ original_ring.Put(original_record_0);
+ original_ring.Put(original_record_1);
+
+ {
+ ImportedRing imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), mmap.size);
+ EXPECT_TRUE(import_ok);
+ EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+
+ {
+ uint32_t sequence = original_sequence_0;
+ ImportedRecord imported_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+ EXPECT_EQ(original_sequence_0, sequence);
+ EXPECT_EQ(original_record_0, imported_record);
+ }
+
+ {
+ uint32_t sequence = original_sequence_1;
+ ImportedRecord imported_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+ EXPECT_EQ(original_sequence_1, sequence);
+ EXPECT_EQ(original_record_1, imported_record);
+ }
+ }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfCompatibleStaticToDynamic) {
+ using OriginalRing = typename Static_16_16x16::Ring;
+ using ImportedRing = typename Dynamic_16_NxM::Ring;
+ using OriginalRecord = typename OriginalRing::Record;
+ using ImportedRecord = typename ImportedRing::Record;
+ using StaticRing = OriginalRing;
+
+ OriginalRing original_ring;
+ auto mmap = CreateRing(&original_ring, StaticRing::Traits::MinCount());
+
+ const uint32_t original_sequence_0 = original_ring.GetNextSequence();
+ const uint32_t original_sequence_1 = original_ring.GetNextSequence() + 1;
+ const OriginalRecord original_record_0 = OriginalRecord::Pattern(0x00);
+ const OriginalRecord original_record_1 = OriginalRecord::Pattern(0x80);
+ original_ring.Put(original_record_0);
+ original_ring.Put(original_record_1);
+
+ {
+ ImportedRing imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) =
+ ImportedRing::Import(mmap.mmap(), mmap.size);
+ EXPECT_TRUE(import_ok);
+ EXPECT_EQ(original_ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(original_ring.record_count(), imported_ring.record_count());
+
+ {
+ uint32_t sequence = original_sequence_0;
+ ImportedRecord imported_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+ EXPECT_EQ(original_sequence_0, sequence);
+ EXPECT_EQ(original_record_0, imported_record);
+ }
+
+ {
+ uint32_t sequence = original_sequence_1;
+ ImportedRecord imported_record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &imported_record));
+ EXPECT_EQ(original_sequence_1, sequence);
+ EXPECT_EQ(original_record_1, imported_record);
+ }
+ }
+}
+
+TEST(BroadcastRingTest, ShouldImportIfReadonlyMmap) {
+ using Ring = Dynamic_32_NxM::Ring;
+ using Record = Ring::Record;
+
+ uint32_t record_count = Ring::Traits::MinCount();
+ size_t ring_size = Ring::MemorySize(record_count);
+
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
+ ASSERT_GE(mmap_size, ring_size);
+
+ void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ ASSERT_NE(MAP_FAILED, mmap_base);
+
+ Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
+ for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i)));
+
+ ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ));
+
+ {
+ Ring imported_ring;
+ bool import_ok;
+ std::tie(imported_ring, import_ok) = Ring::Import(mmap_base, mmap_size);
+ EXPECT_TRUE(import_ok);
+ EXPECT_EQ(ring.record_size(), imported_ring.record_size());
+ EXPECT_EQ(ring.record_count(), imported_ring.record_count());
+
+ uint32_t oldest_sequence = imported_ring.GetOldestSequence();
+ for (uint32_t i = 0; i < record_count; ++i) {
+ uint32_t sequence = oldest_sequence + i;
+ Record record;
+ EXPECT_TRUE(imported_ring.Get(&sequence, &record));
+ EXPECT_EQ(Record(FillChar(i)), record);
+ }
+ }
+
+ ASSERT_EQ(0, munmap(mmap_base, mmap_size));
+}
+
+TEST(BroadcastRingTest, ShouldDieIfPutReadonlyMmap) {
+ using Ring = Dynamic_32_NxM::Ring;
+ using Record = Ring::Record;
+
+ uint32_t record_count = Ring::Traits::MinCount();
+ size_t ring_size = Ring::MemorySize(record_count);
+
+ size_t page_size = sysconf(_SC_PAGESIZE);
+ size_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
+ ASSERT_GE(mmap_size, ring_size);
+
+ void* mmap_base = mmap(nullptr, mmap_size, PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ ASSERT_NE(MAP_FAILED, mmap_base);
+
+ Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
+ for (uint32_t i = 0; i < record_count; ++i) ring.Put(Record(FillChar(i)));
+
+ ASSERT_EQ(0, mprotect(mmap_base, mmap_size, PROT_READ));
+
+ EXPECT_DEATH_IF_SUPPORTED({ ring.Put(Record(7)); }, "");
+
+ ASSERT_EQ(0, munmap(mmap_base, mmap_size));
+}
+
+TEST(BroadcastRingTest, ShouldDieIfCreationMmapTooSmall) {
+ using Ring = Dynamic_32_NxM::Ring;
+ using Record = Ring::Record;
+
+ uint32_t record_count = Ring::Traits::MinCount();
+ size_t ring_size = Ring::MemorySize(record_count);
+ FakeMmap mmap(ring_size);
+
+ EXPECT_DEATH_IF_SUPPORTED({
+ Ring ring = Ring::Create(mmap.mmap(), ring_size - 1, record_count);
+ }, "");
+
+ Ring ring = Ring::Create(mmap.mmap(), ring_size, record_count);
+
+ ring.Put(Record(3));
+
+ {
+ uint32_t sequence = ring.GetNewestSequence();
+ Record record;
+ EXPECT_TRUE(ring.Get(&sequence, &record));
+ EXPECT_EQ(Record(3), record);
+ }
+}
+
+TEST(BroadcastRingTest, ShouldDieIfCreationMmapMisaligned) {
+ using Ring = Static_8_8x1::Ring;
+ using Record = Ring::Record;
+
+ constexpr int kAlign = Ring::mmap_alignment();
+ constexpr int kMisalign = kAlign / 2;
+ size_t ring_size = Ring::MemorySize();
+ std::unique_ptr<char[]> buf(new char[ring_size + kMisalign]);
+
+ EXPECT_DEATH_IF_SUPPORTED(
+ { Ring ring = Ring::Create(buf.get() + kMisalign, ring_size); }, "");
+
+ Ring ring = Ring::Create(buf.get(), ring_size);
+
+ ring.Put(Record(3));
+
+ {
+ uint32_t sequence = ring.GetNewestSequence();
+ Record record;
+ EXPECT_TRUE(ring.Get(&sequence, &record));
+ EXPECT_EQ(Record(3), record);
+ }
+}
+
+template <typename Ring>
+std::unique_ptr<std::thread> CopyTask(std::atomic<bool>* quit, void* in_base,
+ size_t in_size, void* out_base,
+ size_t out_size) {
+ return std::unique_ptr<std::thread>(
+ new std::thread([quit, in_base, in_size, out_base, out_size]() {
+ using Record = typename Ring::Record;
+
+ bool import_ok;
+ Ring in_ring;
+ Ring out_ring;
+ std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size);
+ ASSERT_TRUE(import_ok);
+ std::tie(out_ring, import_ok) = Ring::Import(out_base, out_size);
+ ASSERT_TRUE(import_ok);
+
+ uint32_t sequence = in_ring.GetOldestSequence();
+ while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) {
+ Record record;
+ if (in_ring.Get(&sequence, &record)) {
+ out_ring.Put(record);
+ sequence++;
+ }
+ }
+ }));
+}
+
+TEST(BroadcastRingTest, ThreadedCopySingle) {
+ using Ring = Dynamic_32_NxM::Ring;
+ using Record = Ring::Record;
+ Ring in_ring;
+ auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
+
+ Ring out_ring;
+ auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
+
+ std::atomic<bool> quit(false);
+ std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
+ &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
+
+ const Record out_record(0x1c);
+ out_ring.Put(out_record);
+
+ uint32_t in_sequence = in_ring.GetOldestSequence();
+ Record in_record;
+ while (!in_ring.Get(&in_sequence, &in_record)) {
+ // Do nothing.
+ }
+
+ EXPECT_EQ(out_record, in_record);
+ std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+ copy_task->join();
+}
+
+TEST(BroadcastRingTest, ThreadedCopyLossless) {
+ using Ring = Dynamic_32_NxM::Ring;
+ using Record = Ring::Record;
+ Ring in_ring;
+ auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
+
+ Ring out_ring;
+ auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
+
+ std::atomic<bool> quit(false);
+ std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
+ &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
+
+ constexpr uint32_t kRecordsToProcess = 10000;
+ uint32_t out_records = 0;
+ uint32_t in_records = 0;
+ uint32_t in_sequence = in_ring.GetNextSequence();
+ while (out_records < kRecordsToProcess || in_records < kRecordsToProcess) {
+ if (out_records < kRecordsToProcess &&
+ out_records - in_records < out_ring.record_count()) {
+ const Record out_record(FillChar(out_records));
+ out_ring.Put(out_record);
+ out_records++;
+ }
+
+ Record in_record;
+ while (in_ring.Get(&in_sequence, &in_record)) {
+ EXPECT_EQ(Record(FillChar(in_records)), in_record);
+ in_records++;
+ in_sequence++;
+ }
+ }
+
+ EXPECT_EQ(kRecordsToProcess, out_records);
+ EXPECT_EQ(kRecordsToProcess, in_records);
+
+ std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+ copy_task->join();
+}
+
+TEST(BroadcastRingTest, ThreadedCopyLossy) {
+ using Ring = Dynamic_32_NxM::Ring;
+ using Record = Ring::Record;
+ Ring in_ring;
+ auto in_mmap = CreateRing(&in_ring, Ring::Traits::MinCount());
+
+ Ring out_ring;
+ auto out_mmap = CreateRing(&out_ring, Ring::Traits::MinCount());
+
+ std::atomic<bool> quit(false);
+ std::unique_ptr<std::thread> copy_task = CopyTask<Ring>(
+ &quit, out_mmap.mmap(), out_mmap.size, in_mmap.mmap(), in_mmap.size);
+
+ constexpr uint32_t kRecordsToProcess = 100000;
+ uint32_t out_records = 0;
+ uint32_t in_records = 0;
+ uint32_t in_sequence = in_ring.GetNextSequence();
+ while (out_records < kRecordsToProcess) {
+ const Record out_record(FillChar(out_records));
+ out_ring.Put(out_record);
+ out_records++;
+
+ Record in_record;
+ if (in_ring.GetNewest(&in_sequence, &in_record)) {
+ EXPECT_EQ(Record(in_record.v[0]), in_record);
+ in_records++;
+ in_sequence++;
+ }
+ }
+
+ EXPECT_EQ(kRecordsToProcess, out_records);
+ EXPECT_GE(kRecordsToProcess, in_records);
+
+ std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+ copy_task->join();
+}
+
+template <typename Ring>
+std::unique_ptr<std::thread> CheckFillTask(std::atomic<bool>* quit,
+ void* in_base, size_t in_size) {
+ return std::unique_ptr<std::thread>(
+ new std::thread([quit, in_base, in_size]() {
+ using Record = typename Ring::Record;
+
+ bool import_ok;
+ Ring in_ring;
+ std::tie(in_ring, import_ok) = Ring::Import(in_base, in_size);
+ ASSERT_TRUE(import_ok);
+
+ uint32_t sequence = in_ring.GetOldestSequence();
+ while (!std::atomic_load_explicit(quit, std::memory_order_relaxed)) {
+ Record record;
+ if (in_ring.Get(&sequence, &record)) {
+ ASSERT_EQ(Record(record.v[0]), record);
+ sequence++;
+ }
+ }
+ }));
+}
+
+template <typename Ring>
+void ThreadedOverwriteTorture() {
+ using Record = typename Ring::Record;
+
+ // Maximize overwrites by having few records.
+ const int kMinRecordCount = 1;
+ const int kMaxRecordCount = 4;
+
+ for (int count = kMinRecordCount; count <= kMaxRecordCount; count *= 2) {
+ Ring out_ring;
+ auto out_mmap = CreateRing(&out_ring, count);
+
+ std::atomic<bool> quit(false);
+ std::unique_ptr<std::thread> check_task =
+ CheckFillTask<Ring>(&quit, out_mmap.mmap(), out_mmap.size);
+
+ constexpr int kIterations = 10000;
+ for (int i = 0; i < kIterations; ++i) {
+ const Record record(FillChar(i));
+ out_ring.Put(record);
+ }
+
+ std::atomic_store_explicit(&quit, true, std::memory_order_relaxed);
+ check_task->join();
+ }
+}
+
+TEST(BroadcastRingTest, ThreadedOverwriteTortureSmall) {
+ ThreadedOverwriteTorture<Dynamic_16_NxM_1plus0::Ring>();
+}
+
+TEST(BroadcastRingTest, ThreadedOverwriteTortureLarge) {
+ ThreadedOverwriteTorture<Dynamic_256_NxM_1plus0::Ring>();
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
new file mode 100644
index 0000000..69cb648
--- /dev/null
+++ b/libs/vr/libbroadcastring/include/libbroadcastring/broadcast_ring.h
@@ -0,0 +1,668 @@
+#ifndef ANDROID_DVR_BROADCAST_RING_H_
+#define ANDROID_DVR_BROADCAST_RING_H_
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <atomic>
+#include <limits>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "android-base/logging.h"
+
+#if ATOMIC_LONG_LOCK_FREE != 2 || ATOMIC_INT_LOCK_FREE != 2
+#error "This file requires lock free atomic uint32_t and long"
+#endif
+
+namespace android {
+namespace dvr {
+
+struct DefaultRingTraits {
+ // Set this to false to allow compatibly expanding the record size.
+ static constexpr bool kUseStaticRecordSize = false;
+
+ // Set this to a nonzero value to fix the number of records in the ring.
+ static constexpr uint32_t kStaticRecordCount = 0;
+
+ // Set this to the max number of records that can be written simultaneously.
+ static constexpr uint32_t kMaxReservedRecords = 1;
+
+ // Set this to the min number of records that must be readable.
+ static constexpr uint32_t kMinAvailableRecords = 1;
+};
+
+// Nonblocking ring suitable for concurrent single-writer, multi-reader access.
+//
+// Readers never block the writer and thus this is a nondeterministically lossy
+// transport in the absence of external synchronization. Don't use this as a
+// transport when deterministic behavior is required.
+//
+// Readers may have a read-only mapping; each reader's state is a single local
+// sequence number.
+//
+// The implementation takes care to avoid data races on record access.
+// Inconsistent data can only be returned if at least 2^32 records are written
+// during the read-side critical section.
+//
+// In addition, both readers and the writer are careful to avoid accesses
+// outside the bounds of the mmap area passed in during initialization even if
+// there is a misbehaving or malicious task with write access to the mmap area.
+//
+// When dynamic record size is enabled, readers use the record size in the ring
+// header when indexing the ring, so that it is possible to extend the record
+// type without breaking the read-side ABI.
+//
+// Avoid calling Put() in a tight loop; there should be significantly more time
+// between successive puts than it takes to read one record from memory to
+// ensure Get() completes quickly. This requirement should not be difficult to
+// achieve for most practical uses; 4kB puts at 10,000Hz is well below the
+// scaling limit on current mobile chips.
+//
+// Example Writer Usage:
+//
+// using Record = MyRecordType;
+// using Ring = BroadcastRing<Record>;
+//
+// uint32_t record_count = kMyDesiredCount;
+// uint32_t ring_size = Ring::MemorySize(record_count);
+//
+// size_t page_size = sysconf(_SC_PAGESIZE);
+// uint32_t mmap_size = (ring_size + (page_size - 1)) & ~(page_size - 1);
+//
+// // Allocate & map via your preferred mechanism, e.g.
+// int fd = open("/dev/shm/ring_test", O_CREAT|O_RDWR|O_CLOEXEC, 0600);
+// CHECK(fd >= 0);
+// CHECK(!ftruncate(fd, ring_size));
+// void *mmap_base = mmap(nullptr, mmap_size, PROT_READ|PROT_WRITE,
+// MAP_SHARED, fd, 0);
+// CHECK(mmap_base != MAP_FAILED);
+// close(fd);
+//
+// Ring ring = Ring::Create(mmap_base, mmap_size, record_count);
+//
+// while (!done)
+// ring.Put(BuildNextRecordBlocking());
+//
+// CHECK(!munmap(mmap_base, mmap_size));
+//
+// Example Reader Usage:
+//
+// using Record = MyRecordType;
+// using Ring = BroadcastRing<Record>;
+//
+// // Map via your preferred mechanism, e.g.
+// int fd = open("/dev/shm/ring_test", O_RDONLY|O_CLOEXEC);
+// CHECK(fd >= 0);
+// struct stat st;
+// CHECK(!fstat(fd, &st));
+// size_t mmap_size = st.st_size;
+// void *mmap_base = mmap(nullptr, mmap_size, PROT_READ,
+// MAP_SHARED, fd, 0);
+// CHECK(mmap_base != MAP_FAILED);
+// close(fd);
+//
+// Ring ring;
+// bool import_ok;
+// std::tie(ring, import_ok) = Ring::Import(mmap_base, mmap_size);
+// CHECK(import_ok);
+//
+// uint32_t sequence;
+//
+// // Choose starting point (using "0" is unpredictable but not dangerous)
+// sequence = ring.GetOldestSequence(); // The oldest available
+// sequence = ring.GetNewestSequence(); // The newest available
+// sequence = ring.GetNextSequence(); // The next one produced
+//
+// while (!done) {
+// Record record;
+//
+// if (you_want_to_process_all_available_records) {
+// while (ring.Get(&sequence, &record)) {
+// ProcessRecord(sequence, record);
+// sequence++;
+// }
+// } else if (you_want_to_skip_to_the_newest_record) {
+// if (ring.GetNewest(&sequence, &record)) {
+// ProcessRecord(sequence, record);
+// sequence++;
+// }
+// }
+//
+// DoSomethingExpensiveOrBlocking();
+// }
+//
+// CHECK(!munmap(mmap_base, mmap_size));
+//
+template <typename RecordType, typename BaseTraits = DefaultRingTraits>
+class BroadcastRing {
+ public:
+ using Record = RecordType;
+ struct Traits : public BaseTraits {
+ // Must have enough space for writers, plus enough space for readers.
+ static constexpr int kMinRecordCount =
+ BaseTraits::kMaxReservedRecords + BaseTraits::kMinAvailableRecords;
+
+ // Count of zero means dynamic, non-zero means static.
+ static constexpr bool kUseStaticRecordCount =
+ (BaseTraits::kStaticRecordCount != 0);
+
+ // If both record size and count are static then the overall size is too.
+ static constexpr bool kIsStaticSize =
+ BaseTraits::kUseStaticRecordSize && kUseStaticRecordCount;
+ };
+
+ static constexpr bool IsPowerOfTwo(uint32_t size) {
+ return (size & (size - 1)) == 0;
+ }
+
+ // Sanity check the options provided in Traits.
+ static_assert(Traits::kMinRecordCount >= 1, "Min record count too small");
+ static_assert(!Traits::kUseStaticRecordCount ||
+ Traits::kStaticRecordCount >= Traits::kMinRecordCount,
+ "Static record count is too small");
+ static_assert(!Traits::kStaticRecordCount ||
+ IsPowerOfTwo(Traits::kStaticRecordCount),
+ "Static record count is not a power of two");
+ static_assert(std::is_standard_layout<Record>::value,
+ "Record type must be standard layout");
+
+ BroadcastRing() {}
+
+ // Creates a new ring at |mmap| with |record_count| records.
+ //
+ // There must be at least |MemorySize(record_count)| bytes of space already
+ // allocated at |mmap|. The ring does not take ownership.
+ //
+ // Use this function for dynamically sized rings.
+ static BroadcastRing Create(void* mmap, size_t mmap_size,
+ uint32_t record_count) {
+ BroadcastRing ring(mmap);
+ CHECK(ring.ValidateGeometry(mmap_size, sizeof(Record), record_count));
+ ring.InitializeHeader(sizeof(Record), record_count);
+ return ring;
+ }
+
+ // Creates a new ring at |mmap|.
+ //
+ // There must be at least |MemorySize()| bytes of space already allocated at
+ // |mmap|. The ring does not take ownership.
+ //
+ // Use this function for statically sized rings.
+ static BroadcastRing Create(void* mmap, size_t mmap_size) {
+ static_assert(Traits::kUseStaticRecordCount,
+ "Wrong Create() function called for dynamic record count");
+ return Create(mmap, mmap_size, Traits::kStaticRecordCount);
+ }
+
+ // Imports an existing ring at |mmap|.
+ //
+ // Import may fail if the ring parameters in the mmap header are not sensible.
+ // In this case the returned boolean is false; make sure to check this value.
+ static std::tuple<BroadcastRing, bool> Import(void* mmap, size_t mmap_size) {
+ BroadcastRing ring(mmap);
+ uint32_t record_size = 0;
+ uint32_t record_count = 0;
+ if (mmap_size >= sizeof(Header)) {
+ record_size = std::atomic_load_explicit(&ring.header_mmap()->record_size,
+ std::memory_order_relaxed);
+ record_count = std::atomic_load_explicit(
+ &ring.header_mmap()->record_count, std::memory_order_relaxed);
+ }
+ bool ok = ring.ValidateGeometry(mmap_size, record_size, record_count);
+ return std::make_tuple(ring, ok);
+ }
+
+ ~BroadcastRing() {}
+
+ // Calculates the space necessary for a ring of size |record_count|.
+ //
+ // Use this function for dynamically sized rings.
+ static constexpr size_t MemorySize(uint32_t record_count) {
+ return sizeof(Header) + sizeof(Record) * record_count;
+ }
+
+ // Calculates the space necessary for a statically sized ring.
+ //
+ // Use this function for statically sized rings.
+ static constexpr size_t MemorySize() {
+ static_assert(
+ Traits::kUseStaticRecordCount,
+ "Wrong MemorySize() function called for dynamic record count");
+ return MemorySize(Traits::kStaticRecordCount);
+ }
+
+ // Writes a record to the ring.
+ //
+ // The oldest record is overwritten unless the ring is not already full.
+ void Put(const Record& record) {
+ const int kRecordCount = 1;
+ Reserve(kRecordCount);
+ Geometry geometry = GetGeometry();
+ PutRecordInternal(&record, record_mmap_writer(geometry.tail_index));
+ Publish(kRecordCount);
+ }
+
+ // Gets sequence number of the oldest currently available record.
+ uint32_t GetOldestSequence() const {
+ return std::atomic_load_explicit(&header_mmap()->head,
+ std::memory_order_relaxed);
+ }
+
+ // Gets sequence number of the first future record.
+ //
+ // If the returned value is passed to Get() and there is no concurrent Put(),
+ // Get() will return false.
+ uint32_t GetNextSequence() const {
+ return std::atomic_load_explicit(&header_mmap()->tail,
+ std::memory_order_relaxed);
+ }
+
+ // Gets sequence number of the newest currently available record.
+ uint32_t GetNewestSequence() const { return GetNextSequence() - 1; }
+
+ // Copies the oldest available record with sequence at least |*sequence| to
+ // |record|.
+ //
+ // Returns false if there is no recent enough record available.
+ //
+ // Updates |*sequence| with the sequence number of the record returned. To get
+ // the following record, increment this number by one.
+ //
+ // This function synchronizes with two other operations:
+ //
+ // (1) Load-Acquire of |tail|
+ //
+ // Together with the store-release in Publish(), this load-acquire
+ // ensures each store to a record in PutRecordInternal() happens-before
+ // any corresponding load in GetRecordInternal().
+ //
+ // i.e. the stores for the records with sequence numbers < |tail| have
+ // completed from our perspective
+ //
+ // (2) Acquire Fence between record access & final load of |head|
+ //
+ // Together with the release fence in Reserve(), this ensures that if
+ // GetRecordInternal() loads a value stored in some execution of
+ // PutRecordInternal(), then the store of |head| in the Reserve() that
+ // preceeded it happens-before our final load of |head|.
+ //
+ // i.e. if we read a record with sequence number >= |final_head| then
+ // no later store to that record has completed from our perspective
+ bool Get(uint32_t* sequence /*inout*/, Record* record /*out*/) const {
+ for (;;) {
+ uint32_t tail = std::atomic_load_explicit(&header_mmap()->tail,
+ std::memory_order_acquire);
+ uint32_t head = std::atomic_load_explicit(&header_mmap()->head,
+ std::memory_order_relaxed);
+
+ if (tail - head > record_count())
+ continue; // Concurrent modification; re-try.
+
+ if (*sequence - head > tail - head)
+ *sequence = head; // Out of window, skip forward to first available.
+
+ if (*sequence == tail) return false; // No new records available.
+
+ Geometry geometry =
+ CalculateGeometry(record_count(), record_size(), *sequence, tail);
+
+ // Compute address explicitly in case record_size > sizeof(Record).
+ RecordStorage* record_storage = record_mmap_reader(geometry.head_index);
+
+ GetRecordInternal(record_storage, record);
+
+ // NB: It is not sufficient to change this to a load-acquire of |head|.
+ std::atomic_thread_fence(std::memory_order_acquire);
+
+ uint32_t final_head = std::atomic_load_explicit(
+ &header_mmap()->head, std::memory_order_relaxed);
+
+ if (final_head - head > *sequence - head)
+ continue; // Concurrent modification; re-try.
+
+ // Note: Combining the above 4 comparisons gives:
+ // 0 <= final_head - head <= sequence - head < tail - head <= record_count
+ //
+ // We can also write this as:
+ // head <=* final_head <=* sequence <* tail <=* head + record_count
+ //
+ // where <* orders by difference from head: x <* y if x - head < y - head.
+ // This agrees with the order of sequence updates during "put" operations.
+ return true;
+ }
+ }
+
+ // Copies the newest available record with sequence at least |*sequence| to
+ // |record|.
+ //
+ // Returns false if there is no recent enough record available.
+ //
+ // Updates |*sequence| with the sequence number of the record returned. To get
+ // the following record, increment this number by one.
+ bool GetNewest(uint32_t* sequence, Record* record) const {
+ uint32_t newest_sequence = GetNewestSequence();
+ if (*sequence == newest_sequence + 1) return false;
+ *sequence = newest_sequence;
+ return Get(sequence, record);
+ }
+
+ uint32_t record_count() const { return record_count_internal(); }
+ uint32_t record_size() const { return record_size_internal(); }
+ static constexpr uint32_t mmap_alignment() { return alignof(Mmap); }
+
+ private:
+ struct Header {
+ // Record size for reading out of the ring. Writers always write the full
+ // length; readers may need to read a prefix of each record.
+ std::atomic<uint32_t> record_size;
+
+ // Number of records in the ring.
+ std::atomic<uint32_t> record_count;
+
+ // Readable region is [head % record_count, tail % record_count).
+ //
+ // The region in [tail % record_count, head % record_count) was either never
+ // populated or is being updated.
+ //
+ // These are sequences numbers, not indexes - indexes should be computed
+ // with a modulus.
+ //
+ // To ensure consistency:
+ //
+ // (1) Writes advance |head| past any updated records before writing to
+ // them, and advance |tail| after they are written.
+ // (2) Readers check |tail| before reading data and |head| after,
+ // making sure to discard any data that was written to concurrently.
+ std::atomic<uint32_t> head;
+ std::atomic<uint32_t> tail;
+ };
+
+ // Store using the standard word size.
+ using StorageType = long; // NOLINT
+
+ // Always require 8 byte alignment so that the same record sizes are legal on
+ // 32 and 64 bit builds.
+ static constexpr size_t kRecordAlignment = 8;
+ static_assert(kRecordAlignment % sizeof(StorageType) == 0,
+ "Bad record alignment");
+
+ struct RecordStorage {
+ // This is accessed with relaxed atomics to prevent data races on the
+ // contained data, which would be undefined behavior.
+ std::atomic<StorageType> data[sizeof(Record) / sizeof(StorageType)];
+ };
+
+ static_assert(sizeof(StorageType) *
+ std::extent<decltype(RecordStorage::data)>() ==
+ sizeof(Record),
+ "Record length must be a multiple of sizeof(StorageType)");
+
+ struct Geometry {
+ // Static geometry.
+ uint32_t record_count;
+ uint32_t record_size;
+
+ // Copy of atomic sequence counts.
+ uint32_t head;
+ uint32_t tail;
+
+ // First index of readable region.
+ uint32_t head_index;
+
+ // First index of writable region.
+ uint32_t tail_index;
+
+ // Number of records in readable region.
+ uint32_t count;
+
+ // Number of records in writable region.
+ uint32_t space;
+ };
+
+ // Mmap area layout.
+ //
+ // Readers should not index directly into |records| as this is not valid when
+ // dynamic record sizes are used; use record_mmap_reader() instead.
+ struct Mmap {
+ Header header;
+ RecordStorage records[];
+ };
+
+ static_assert(std::is_standard_layout<Mmap>::value,
+ "Mmap must be standard layout");
+ static_assert(sizeof(std::atomic<uint32_t>) == sizeof(uint32_t),
+ "Lockless atomics contain extra state");
+ static_assert(sizeof(std::atomic<StorageType>) == sizeof(StorageType),
+ "Lockless atomics contain extra state");
+
+ explicit BroadcastRing(void* mmap) {
+ CHECK_EQ(0U, reinterpret_cast<uintptr_t>(mmap) % alignof(Mmap));
+ data_.mmap = reinterpret_cast<Mmap*>(mmap);
+ }
+
+ // Initializes the mmap area header for a new ring.
+ void InitializeHeader(uint32_t record_size, uint32_t record_count) {
+ constexpr uint32_t kInitialSequence = -256; // Force an early wrap.
+ std::atomic_store_explicit(&header_mmap()->record_size, record_size,
+ std::memory_order_relaxed);
+ std::atomic_store_explicit(&header_mmap()->record_count, record_count,
+ std::memory_order_relaxed);
+ std::atomic_store_explicit(&header_mmap()->head, kInitialSequence,
+ std::memory_order_relaxed);
+ std::atomic_store_explicit(&header_mmap()->tail, kInitialSequence,
+ std::memory_order_relaxed);
+ }
+
+ // Validates ring geometry.
+ //
+ // Ring geometry is validated carefully on import and then cached. This allows
+ // us to avoid out-of-range accesses even if the parameters in the header are
+ // later changed.
+ bool ValidateGeometry(size_t mmap_size, uint32_t header_record_size,
+ uint32_t header_record_count) {
+ set_record_size(header_record_size);
+ set_record_count(header_record_count);
+
+ if (record_size() != header_record_size) return false;
+ if (record_count() != header_record_count) return false;
+ if (record_count() < Traits::kMinRecordCount) return false;
+ if (record_size() < sizeof(Record)) return false;
+ if (record_size() % kRecordAlignment != 0) return false;
+ if (!IsPowerOfTwo(record_count())) return false;
+
+ size_t memory_size = record_count() * record_size();
+ if (memory_size / record_size() != record_count()) return false;
+ if (memory_size + sizeof(Header) < memory_size) return false;
+ if (memory_size + sizeof(Header) > mmap_size) return false;
+
+ return true;
+ }
+
+ // Copies a record into the ring.
+ //
+ // This is done with relaxed atomics because otherwise it is racy according to
+ // the C++ memory model. This is very low overhead once optimized.
+ static inline void PutRecordInternal(const Record* in, RecordStorage* out) {
+ StorageType data[sizeof(Record) / sizeof(StorageType)];
+ memcpy(data, in, sizeof(*in));
+ for (size_t i = 0; i < std::extent<decltype(data)>(); ++i) {
+ std::atomic_store_explicit(&out->data[i], data[i],
+ std::memory_order_relaxed);
+ }
+ }
+
+ // Copies a record out of the ring.
+ //
+ // This is done with relaxed atomics because otherwise it is racy according to
+ // the C++ memory model. This is very low overhead once optimized.
+ static inline void GetRecordInternal(RecordStorage* in, Record* out) {
+ StorageType data[sizeof(Record) / sizeof(StorageType)];
+ for (size_t i = 0; i < std::extent<decltype(data)>(); ++i) {
+ data[i] =
+ std::atomic_load_explicit(&in->data[i], std::memory_order_relaxed);
+ }
+ memcpy(out, &data, sizeof(*out));
+ }
+
+ // Converts a record's sequence number into a storage index.
+ static uint32_t SequenceToIndex(uint32_t sequence, uint32_t record_count) {
+ return sequence & (record_count - 1);
+ }
+
+ // Computes readable & writable ranges from ring parameters.
+ static Geometry CalculateGeometry(uint32_t record_count, uint32_t record_size,
+ uint32_t head, uint32_t tail) {
+ Geometry geometry;
+ geometry.record_count = record_count;
+ geometry.record_size = record_size;
+ DCHECK_EQ(0U, geometry.record_size % kRecordAlignment);
+ geometry.head = head;
+ geometry.tail = tail;
+ geometry.head_index = SequenceToIndex(head, record_count);
+ geometry.tail_index = SequenceToIndex(tail, record_count);
+ geometry.count = geometry.tail - geometry.head;
+ DCHECK_LE(geometry.count, record_count);
+ geometry.space = geometry.record_count - geometry.count;
+ return geometry;
+ }
+
+ // Gets the current ring readable & writable regions.
+ //
+ // This this is always safe from the writing thread since it is the only
+ // thread allowed to update the header.
+ Geometry GetGeometry() const {
+ return CalculateGeometry(
+ record_count(), record_size(),
+ std::atomic_load_explicit(&header_mmap()->head,
+ std::memory_order_relaxed),
+ std::atomic_load_explicit(&header_mmap()->tail,
+ std::memory_order_relaxed));
+ }
+
+ // Makes space for at least |reserve_count| records.
+ //
+ // There is nothing to prevent overwriting records that have concurrent
+ // readers. We do however ensure that this situation can be detected: the
+ // fence ensures the |head| update will be the first update seen by readers,
+ // and readers check this value after reading and discard data that may have
+ // been concurrently modified.
+ void Reserve(uint32_t reserve_count) {
+ Geometry geometry = GetGeometry();
+ DCHECK_LE(reserve_count, Traits::kMaxReservedRecords);
+ uint32_t needed =
+ (geometry.space >= reserve_count ? 0 : reserve_count - geometry.space);
+
+ std::atomic_store_explicit(&header_mmap()->head, geometry.head + needed,
+ std::memory_order_relaxed);
+
+ // NB: It is not sufficient to change this to a store-release of |head|.
+ std::atomic_thread_fence(std::memory_order_release);
+ }
+
+ // Makes |publish_count| records visible to readers.
+ //
+ // Space must have been reserved by a previous call to Reserve().
+ void Publish(uint32_t publish_count) {
+ Geometry geometry = GetGeometry();
+ DCHECK_LE(publish_count, geometry.space);
+ std::atomic_store_explicit(&header_mmap()->tail,
+ geometry.tail + publish_count,
+ std::memory_order_release);
+ }
+
+ // Helpers to compute addresses in mmap area.
+ Mmap* mmap() const { return data_.mmap; }
+ Header* header_mmap() const { return &data_.mmap->header; }
+ RecordStorage* record_mmap_writer(uint32_t index) const {
+ DCHECK_EQ(sizeof(Record), record_size());
+ return &data_.mmap->records[index];
+ }
+ RecordStorage* record_mmap_reader(uint32_t index) const {
+ if (Traits::kUseStaticRecordSize) {
+ return &data_.mmap->records[index];
+ } else {
+ // Calculate the location of a record in the ring without assuming that
+ // sizeof(Record) == record_size.
+ return reinterpret_cast<RecordStorage*>(
+ reinterpret_cast<char*>(data_.mmap->records) + index * record_size());
+ }
+ }
+
+ // The following horrifying template gunk enables us to store just the mmap
+ // base pointer for compile-time statically sized rings. Dynamically sized
+ // rings also store the validated copy of the record size & count.
+ //
+ // This boils down to: use a compile time constant if available, and otherwise
+ // load the value that was validated on import from a member variable.
+ template <typename T = Traits>
+ typename std::enable_if<T::kUseStaticRecordSize, uint32_t>::type
+ record_size_internal() const {
+ return sizeof(Record);
+ }
+
+ template <typename T = Traits>
+ typename std::enable_if<!T::kUseStaticRecordSize, uint32_t>::type
+ record_size_internal() const {
+ return data_.record_size;
+ }
+
+ template <typename T = Traits>
+ typename std::enable_if<T::kUseStaticRecordSize, void>::type set_record_size(
+ uint32_t /*record_size*/) {}
+
+ template <typename T = Traits>
+ typename std::enable_if<!T::kUseStaticRecordSize, void>::type set_record_size(
+ uint32_t record_size) {
+ data_.record_size = record_size;
+ }
+
+ template <typename T = Traits>
+ typename std::enable_if<T::kUseStaticRecordCount, uint32_t>::type
+ record_count_internal() const {
+ return Traits::kStaticRecordCount;
+ }
+
+ template <typename T = Traits>
+ typename std::enable_if<!T::kUseStaticRecordCount, uint32_t>::type
+ record_count_internal() const {
+ return data_.record_count;
+ }
+
+ template <typename T = Traits>
+ typename std::enable_if<T::kUseStaticRecordCount, void>::type
+ set_record_count(uint32_t /*record_count*/) const {}
+
+ template <typename T = Traits>
+ typename std::enable_if<!T::kUseStaticRecordCount, void>::type
+ set_record_count(uint32_t record_count) {
+ data_.record_count = record_count;
+ }
+
+ // Data we need to store for statically sized rings.
+ struct DataStaticSize {
+ Mmap* mmap = nullptr;
+ };
+
+ // Data we need to store for dynamically sized rings.
+ struct DataDynamicSize {
+ Mmap* mmap = nullptr;
+
+ // These are cached to make sure misbehaving writers cannot cause
+ // out-of-bounds memory accesses by updating the values in the mmap header.
+ uint32_t record_size = 0;
+ uint32_t record_count = 0;
+ };
+
+ using DataStaticOrDynamic =
+ typename std::conditional<Traits::kIsStaticSize, DataStaticSize,
+ DataDynamicSize>::type;
+
+ DataStaticOrDynamic data_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_BROADCAST_RING_H_
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 2749fd1..a1f952e 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -20,6 +20,7 @@
namespace {
+// TODO(hendrikw): These flags can not be hard coded.
constexpr int kUncachedBlobUsageFlags = GRALLOC_USAGE_SW_READ_RARELY |
GRALLOC_USAGE_SW_WRITE_RARELY |
GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -110,6 +111,7 @@
int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
int width = static_cast<int>(size);
int height = 1;
+ // TODO(hendrikw): These flags can not be hard coded.
constexpr int usage = GRALLOC_USAGE_SW_READ_RARELY |
GRALLOC_USAGE_SW_WRITE_RARELY |
GRALLOC_USAGE_PRIVATE_UNCACHED;
@@ -196,18 +198,27 @@
InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
}
-BufferProducer::BufferProducer(int width, int height, int format, int usage,
+BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t metadata_size,
+ size_t slice_count)
+ : BufferProducer(width, height, format, usage, usage, metadata_size,
+ slice_count) {}
+
+BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t metadata_size, size_t slice_count)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
ALOGD_IF(TRACE,
- "BufferProducer::BufferProducer: fd=%d width=%d height=%d format=%d "
- "usage=%d, metadata_size=%zu, slice_count=%zu",
- event_fd(), width, height, format, usage, metadata_size,
- slice_count);
+ "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+ " metadata_size=%zu slice_count=%zu",
+ event_fd(), width, height, format, producer_usage, consumer_usage,
+ metadata_size, slice_count);
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, metadata_size, slice_count);
+ width, height, format, producer_usage, consumer_usage, metadata_size,
+ slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create producer buffer: %s",
@@ -226,21 +237,29 @@
}
BufferProducer::BufferProducer(const std::string& name, int user_id,
- int group_id, int width, int height, int format,
- int usage, size_t meta_size_bytes,
+ int group_id, uint32_t width, uint32_t height,
+ uint32_t format, uint32_t usage,
+ size_t meta_size_bytes, size_t slice_count)
+ : BufferProducer(name, user_id, group_id, width, height, format, usage,
+ usage, meta_size_bytes, slice_count) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+ int group_id, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes,
size_t slice_count)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
ALOGD_IF(TRACE,
"BufferProducer::BufferProducer: fd=%d name=%s user_id=%d "
- "group_id=%d width=%d height=%d format=%d usage=%d, "
- "meta_size_bytes=%zu, slice_count=%zu",
+ "group_id=%d width=%u height=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64 " meta_size_bytes=%zu slice_count=%zu",
event_fd(), name.c_str(), user_id, group_id, width, height, format,
- usage, meta_size_bytes, slice_count);
+ producer_usage, consumer_usage, meta_size_bytes, slice_count);
auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
- name, user_id, group_id, width, height, format, usage, meta_size_bytes,
- slice_count);
+ name, user_id, group_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes, slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create/get persistent "
@@ -260,18 +279,25 @@
}
}
-BufferProducer::BufferProducer(int usage, size_t size)
+BufferProducer::BufferProducer(uint32_t usage, size_t size)
+ : BufferProducer(usage, usage, size) {}
+
+BufferProducer::BufferProducer(uint64_t producer_usage, uint64_t consumer_usage,
+ size_t size)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
- ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%d size=%zu", usage,
- size);
+ ALOGD_IF(TRACE,
+ "BufferProducer::BufferProducer: producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64 " size=%zu",
+ producer_usage, consumer_usage, size);
const int width = static_cast<int>(size);
const int height = 1;
const int format = HAL_PIXEL_FORMAT_BLOB;
const size_t meta_size_bytes = 0;
const size_t slice_count = 1;
auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, meta_size_bytes, slice_count);
+ width, height, format, producer_usage, consumer_usage, meta_size_bytes,
+ slice_count);
if (!status) {
ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
status.GetErrorMessage().c_str());
@@ -289,21 +315,27 @@
}
BufferProducer::BufferProducer(const std::string& name, int user_id,
- int group_id, int usage, size_t size)
+ int group_id, uint32_t usage, size_t size)
+ : BufferProducer(name, user_id, group_id, usage, usage, size) {}
+
+BufferProducer::BufferProducer(const std::string& name, int user_id,
+ int group_id, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t size)
: BASE(BufferHubRPC::kClientPath) {
ATRACE_NAME("BufferProducer::BufferProducer");
ALOGD_IF(TRACE,
"BufferProducer::BufferProducer: name=%s user_id=%d group=%d "
- "usage=%d size=%zu",
- name.c_str(), user_id, group_id, usage, size);
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64 " size=%zu",
+ name.c_str(), user_id, group_id, producer_usage, consumer_usage,
+ size);
const int width = static_cast<int>(size);
const int height = 1;
const int format = HAL_PIXEL_FORMAT_BLOB;
const size_t meta_size_bytes = 0;
const size_t slice_count = 1;
auto status = InvokeRemoteMethod<BufferHubRPC::CreatePersistentBuffer>(
- name, user_id, group_id, width, height, format, usage, meta_size_bytes,
- slice_count);
+ name, user_id, group_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes, slice_count);
if (!status) {
ALOGE(
"BufferProducer::BufferProducer: Failed to create persistent "
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index dfeed50..c772ed3 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -107,11 +107,14 @@
// The following methods return settings of the first buffer. Currently,
// it is only possible to create multi-buffer BufferHubBuffers with the same
// settings.
- int width() const { return slices_[0].width(); }
- int height() const { return slices_[0].height(); }
- int stride() const { return slices_[0].stride(); }
- int format() const { return slices_[0].format(); }
- int usage() const { return slices_[0].usage(); }
+ uint32_t width() const { return slices_[0].width(); }
+ uint32_t height() const { return slices_[0].height(); }
+ uint32_t stride() const { return slices_[0].stride(); }
+ uint32_t format() const { return slices_[0].format(); }
+ uint32_t usage() const { return slices_[0].usage(); }
+ uint32_t layer_count() const { return slices_[0].layer_count(); }
+ uint64_t producer_usage() const { return slices_[0].producer_usage(); }
+ uint64_t consumer_usage() const { return slices_[0].consumer_usage(); }
protected:
explicit BufferHubBuffer(LocalChannelHandle channel);
@@ -218,8 +221,12 @@
// arguments as the constructors.
// Constructs a buffer with the given geometry and parameters.
- BufferProducer(int width, int height, int format, int usage,
- size_t metadata_size = 0, size_t slice_count = 1);
+ BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t metadata_size = 0,
+ size_t slice_count = 1);
+ BufferProducer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t metadata_size, size_t slice_count);
// Constructs a persistent buffer with the given geometry and parameters and
// binds it to |name| in one shot. If a persistent buffer with the same name
@@ -233,16 +240,24 @@
// created and cannot be changed. A user or group id of -1 disables checks for
// that respective id. A user or group id of 0 is substituted with the
// effective user or group id of the calling process.
- BufferProducer(const std::string& name, int user_id, int group_id, int width,
- int height, int format, int usage, size_t metadata_size = 0,
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t metadata_size = 0,
size_t slice_count = 1);
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t metadata_size, size_t slice_count);
// Constructs a blob (flat) buffer with the given usage flags.
- BufferProducer(int usage, size_t size);
+ BufferProducer(uint32_t usage, size_t size);
+ BufferProducer(uint64_t producer_usage, uint64_t consumer_usage, size_t size);
// Constructs a persistent blob (flat) buffer and binds it to |name|.
- BufferProducer(const std::string& name, int user_id, int group_id, int usage,
- size_t size);
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint32_t usage, size_t size);
+ BufferProducer(const std::string& name, int user_id, int group_id,
+ uint64_t producer_usage, uint64_t consumer_usage, size_t size);
// Constructs a channel to persistent buffer by name only. The buffer must
// have been previously created or made persistent.
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index 7ed024f..b6302f1 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -24,7 +24,8 @@
width_(buffer.width()),
height_(buffer.height()),
format_(buffer.format()),
- usage_(buffer.usage()) {
+ producer_usage_(buffer.producer_usage()),
+ consumer_usage_(buffer.consumer_usage()) {
// Populate the fd and int vectors: native_handle->data[] is an array of fds
// followed by an array of opaque ints.
const int fd_count = buffer.handle()->numFds;
@@ -37,6 +38,7 @@
}
}
NativeBufferHandle(NativeBufferHandle&& other) = default;
+ NativeBufferHandle& operator=(NativeBufferHandle&& other) = default;
// Imports the native handle into the given IonBuffer instance.
int Import(IonBuffer* buffer) {
@@ -46,9 +48,10 @@
for (const auto& fd : fds_)
fd_ints.push_back(fd.Get());
- const int ret = buffer->Import(fd_ints.data(), fd_ints.size(),
- opaque_ints_.data(), opaque_ints_.size(),
- width_, height_, stride_, format_, usage_);
+ const int ret =
+ buffer->Import(fd_ints.data(), fd_ints.size(), opaque_ints_.data(),
+ opaque_ints_.size(), width_, height_, stride_, format_,
+ producer_usage_, consumer_usage_);
if (ret < 0)
return ret;
@@ -68,24 +71,32 @@
private:
int id_;
- int stride_;
- int width_;
- int height_;
- int format_;
- int usage_;
+ uint32_t stride_;
+ uint32_t width_;
+ uint32_t height_;
+ uint32_t format_;
+ uint64_t producer_usage_;
+ uint64_t consumer_usage_;
std::vector<int> opaque_ints_;
std::vector<FileHandleType> fds_;
- void Clear() { id_ = stride_ = width_ = height_ = format_ = usage_ = -1; }
+ void Clear() {
+ id_ = -1;
+ stride_ = width_ = height_ = format_ = producer_usage_ = consumer_usage_ =
+ 0;
+ }
PDX_SERIALIZABLE_MEMBERS(NativeBufferHandle<FileHandleType>, id_, stride_,
- width_, height_, format_, usage_, opaque_ints_,
- fds_);
+ width_, height_, format_, producer_usage_,
+ consumer_usage_, opaque_ints_, fds_);
NativeBufferHandle(const NativeBufferHandle&) = delete;
void operator=(const NativeBufferHandle&) = delete;
};
+using BorrowedNativeBufferHandle = NativeBufferHandle<pdx::BorrowedHandle>;
+using LocalNativeBufferHandle = NativeBufferHandle<pdx::LocalHandle>;
+
template <typename FileHandleType>
class FenceHandle {
public:
@@ -127,6 +138,23 @@
PDX_SERIALIZABLE_MEMBERS(QueueInfo, meta_size_bytes, id);
};
+struct UsagePolicy {
+ uint64_t producer_set_mask;
+ uint64_t producer_clear_mask;
+ uint64_t producer_deny_set_mask;
+ uint64_t producer_deny_clear_mask;
+ uint64_t consumer_set_mask;
+ uint64_t consumer_clear_mask;
+ uint64_t consumer_deny_set_mask;
+ uint64_t consumer_deny_clear_mask;
+
+ private:
+ PDX_SERIALIZABLE_MEMBERS(UsagePolicy, producer_set_mask, producer_clear_mask,
+ producer_deny_set_mask, producer_deny_clear_mask,
+ consumer_set_mask, consumer_clear_mask,
+ consumer_deny_set_mask, consumer_deny_clear_mask);
+};
+
// BufferHub Service RPC interface. Defines the endpoints, op codes, and method
// type signatures supported by bufferhubd.
struct BufferHubRPC {
@@ -173,44 +201,46 @@
// Methods.
PDX_REMOTE_METHOD(CreateBuffer, kOpCreateBuffer,
- int(int width, int height, int format, int usage,
- size_t meta_size_bytes, size_t slice_count));
+ void(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count));
PDX_REMOTE_METHOD(CreatePersistentBuffer, kOpCreatePersistentBuffer,
- int(const std::string& name, int user_id, int group_id,
- int width, int height, int format, int usage,
- size_t meta_size_bytes, size_t slice_count));
+ void(const std::string& name, int user_id, int group_id,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count));
PDX_REMOTE_METHOD(GetPersistentBuffer, kOpGetPersistentBuffer,
- int(const std::string& name));
+ void(const std::string& name));
PDX_REMOTE_METHOD(GetBuffer, kOpGetBuffer,
NativeBufferHandle<LocalHandle>(unsigned index));
PDX_REMOTE_METHOD(GetBuffers, kOpGetBuffers,
std::vector<NativeBufferHandle<LocalHandle>>(Void));
PDX_REMOTE_METHOD(NewConsumer, kOpNewConsumer, LocalChannelHandle(Void));
PDX_REMOTE_METHOD(ProducerMakePersistent, kOpProducerMakePersistent,
- int(const std::string& name, int user_id, int group_id));
+ void(const std::string& name, int user_id, int group_id));
PDX_REMOTE_METHOD(ProducerRemovePersistence, kOpProducerRemovePersistence,
- int(Void));
+ void(Void));
PDX_REMOTE_METHOD(ProducerPost, kOpProducerPost,
- int(LocalFence acquire_fence, MetaData));
+ void(LocalFence acquire_fence, MetaData));
PDX_REMOTE_METHOD(ProducerGain, kOpProducerGain, LocalFence(Void));
PDX_REMOTE_METHOD(ConsumerAcquire, kOpConsumerAcquire,
std::pair<LocalFence, MetaData>(std::size_t metadata_size));
PDX_REMOTE_METHOD(ConsumerRelease, kOpConsumerRelease,
- int(LocalFence release_fence));
- PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, int(bool ignore));
+ void(LocalFence release_fence));
+ PDX_REMOTE_METHOD(ConsumerSetIgnore, kOpConsumerSetIgnore, void(bool ignore));
// Buffer Queue Methods.
PDX_REMOTE_METHOD(CreateProducerQueue, kOpCreateProducerQueue,
- QueueInfo(size_t meta_size_bytes, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask));
+ QueueInfo(size_t meta_size_bytes,
+ const UsagePolicy& usage_policy));
PDX_REMOTE_METHOD(CreateConsumerQueue, kOpCreateConsumerQueue,
LocalChannelHandle(Void));
PDX_REMOTE_METHOD(GetQueueInfo, kOpGetQueueInfo, QueueInfo(Void));
PDX_REMOTE_METHOD(ProducerQueueAllocateBuffers,
kOpProducerQueueAllocateBuffers,
std::vector<std::pair<LocalChannelHandle, size_t>>(
- int width, int height, int format, int usage,
+ uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t slice_count, size_t buffer_count));
PDX_REMOTE_METHOD(ProducerQueueDetachBuffer, kOpProducerQueueDetachBuffer,
void(size_t slot));
diff --git a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
index ffc42d6..e167a17 100644
--- a/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/ion_buffer.h
@@ -12,11 +12,20 @@
class IonBuffer {
public:
IonBuffer();
- IonBuffer(int width, int height, int format, int usage);
- IonBuffer(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage);
- IonBuffer(buffer_handle_t handle, int width, int height, int layer_count,
- int stride, int layer_stride, int format, int usage);
+ IonBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+ IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+ uint32_t format, uint32_t usage);
+ IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride, uint32_t layer_stride,
+ uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
~IonBuffer();
IonBuffer(IonBuffer&& other);
@@ -30,25 +39,36 @@
// previous native handle if necessary. Returns 0 on success or a negative
// errno code otherwise. If allocation fails the previous native handle is
// left intact.
- int Alloc(int width, int height, int format, int usage);
+ int Alloc(uint32_t width, uint32_t height, uint32_t format, uint32_t usage);
+ int Alloc(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage);
// Resets the underlying native handle and parameters, freeing the previous
// native handle if necessary.
- void Reset(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage);
+ void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage);
+ void Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage);
// Like Reset but also registers the native handle, which is necessary for
// native handles received over IPC. Returns 0 on success or a negative errno
// code otherwise. If import fails the previous native handle is left intact.
- int Import(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage);
+ int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage);
+ int Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage);
// Like Reset but imports a native handle from raw fd and int arrays. Returns
// 0 on success or a negative errno code otherwise. If import fails the
// previous native handle is left intact.
int Import(const int* fd_array, int fd_count, const int* int_array,
- int int_count, int width, int height, int stride, int format,
- int usage);
+ int int_count, uint32_t width, uint32_t height, uint32_t stride,
+ uint32_t format, uint32_t usage);
+ int Import(const int* fd_array, int fd_count, const int* int_array,
+ int int_count, uint32_t width, uint32_t height, uint32_t stride,
+ uint32_t format, uint64_t producer_usage, uint64_t consumer_usage);
// Duplicates the native handle underlying |other| and then imports it. This
// is useful for creating multiple, independent views of the same Ion/Gralloc
@@ -56,8 +76,8 @@
// duplication or import fail the previous native handle is left intact.
int Duplicate(const IonBuffer* other);
- int Lock(int usage, int x, int y, int width, int height, void** address);
- int LockYUV(int usage, int x, int y, int width, int height,
+ int Lock(uint32_t usage, int x, int y, int width, int height, void** address);
+ int LockYUV(uint32_t usage, int x, int y, int width, int height,
struct android_ycbcr* yuv);
int Unlock();
@@ -65,19 +85,29 @@
buffer_handle_t handle() const {
return buffer_.get() ? buffer_->handle : nullptr;
}
- int width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
- int height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
- int layer_count() const {
+ uint32_t width() const { return buffer_.get() ? buffer_->getWidth() : 0; }
+ uint32_t height() const { return buffer_.get() ? buffer_->getHeight() : 0; }
+ uint32_t layer_count() const {
return buffer_.get() ? buffer_->getLayerCount() : 0;
}
- int stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
- int layer_stride() const { return 0; }
- int format() const { return buffer_.get() ? buffer_->getPixelFormat() : 0; }
- int usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
+ uint32_t stride() const { return buffer_.get() ? buffer_->getStride() : 0; }
+ uint32_t layer_stride() const { return 0; }
+ uint32_t format() const {
+ return buffer_.get() ? buffer_->getPixelFormat() : 0;
+ }
+ uint64_t producer_usage() const { return producer_usage_; }
+ uint64_t consumer_usage() const { return consumer_usage_; }
+ uint32_t usage() const { return buffer_.get() ? buffer_->getUsage() : 0; }
private:
sp<GraphicBuffer> buffer_;
+ // GraphicBuffer doesn't expose these separately. Keep these values cached for
+ // BufferHub to check policy against. Clients that import these buffers won't
+ // get the full picture, which is okay.
+ uint64_t producer_usage_;
+ uint64_t consumer_usage_;
+
IonBuffer(const IonBuffer&) = delete;
void operator=(const IonBuffer&) = delete;
};
diff --git a/libs/vr/libbufferhub/ion_buffer.cpp b/libs/vr/libbufferhub/ion_buffer.cpp
index e5a56c1..df9ae81 100644
--- a/libs/vr/libbufferhub/ion_buffer.cpp
+++ b/libs/vr/libbufferhub/ion_buffer.cpp
@@ -6,40 +6,59 @@
#include <mutex>
+namespace {
+
+constexpr uint32_t kDefaultGraphicBufferLayerCount = 1;
+
+} // anonymous namespace
+
namespace android {
namespace dvr {
IonBuffer::IonBuffer() : IonBuffer(nullptr, 0, 0, 0, 0, 0, 0, 0) {}
-IonBuffer::IonBuffer(int width, int height, int format, int usage)
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage)
+ : IonBuffer(width, height, format, usage, usage) {}
+
+IonBuffer::IonBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage)
: IonBuffer() {
- Alloc(width, height, format, usage);
+ Alloc(width, height, format, producer_usage, consumer_usage);
}
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage)
: IonBuffer(handle, width, height, 1, stride, 0, format, usage) {}
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride,
+ uint32_t layer_stride, uint32_t format, uint32_t usage)
+ : IonBuffer(handle, width, height, layer_count, stride, layer_stride,
+ format, usage, usage) {}
-IonBuffer::IonBuffer(buffer_handle_t handle, int width, int height,
- int layer_count, int stride, int layer_stride, int format,
- int usage)
+IonBuffer::IonBuffer(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t layer_count, uint32_t stride,
+ uint32_t layer_stride, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage)
: buffer_(nullptr) {
ALOGD_IF(TRACE,
- "IonBuffer::IonBuffer: handle=%p width=%d height=%d layer_count=%d "
- "stride=%d layer stride=%d format=%d usage=%d",
- handle, width, height, layer_count, stride, layer_stride,
- format, usage);
+ "IonBuffer::IonBuffer: handle=%p width=%u height=%u layer_count=%u "
+ "stride=%u layer stride=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64,
+ handle, width, height, layer_count, stride, layer_stride, format,
+ producer_usage, consumer_usage);
if (handle != 0) {
- Import(handle, width, height, stride, format, usage);
+ Import(handle, width, height, stride, format, producer_usage,
+ consumer_usage);
}
}
IonBuffer::~IonBuffer() {
ALOGD_IF(TRACE,
- "IonBuffer::~IonBuffer: handle=%p width=%d height=%d stride=%d "
- "format=%d usage=%d",
- handle() , width(), height(), stride(), format(), usage());
+ "IonBuffer::~IonBuffer: handle=%p width=%u height=%u stride=%u "
+ "format=%u usage=%x",
+ handle(), width(), height(), stride(), format(), usage());
FreeHandle();
}
@@ -62,55 +81,101 @@
if (buffer_.get()) {
// GraphicBuffer unregisters and cleans up the handle if needed
buffer_ = nullptr;
+ producer_usage_ = 0;
+ consumer_usage_ = 0;
}
}
-int IonBuffer::Alloc(int width, int height, int format, int usage) {
- ALOGD_IF(TRACE, "IonBuffer::Alloc: width=%d height=%d format=%d usage=%d",
- width, height, format, usage);
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage) {
+ return Alloc(width, height, format, usage, usage);
+}
- buffer_ = new GraphicBuffer(width, height, format, usage);
- if (buffer_->initCheck() != OK) {
+int IonBuffer::Alloc(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage) {
+ ALOGD_IF(
+ TRACE,
+ "IonBuffer::Alloc: width=%u height=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64,
+ width, height, format, producer_usage, consumer_usage);
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(width, height, format, kDefaultGraphicBufferLayerCount,
+ producer_usage, consumer_usage);
+ if (buffer->initCheck() != OK) {
ALOGE("IonBuffer::Aloc: Failed to allocate buffer");
+ return -EINVAL;
+ } else {
+ buffer_ = buffer;
+ producer_usage_ = producer_usage;
+ consumer_usage_ = consumer_usage;
+ return 0;
}
- return 0;
}
-void IonBuffer::Reset(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage) {
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage) {
+ Reset(handle, width, height, stride, format, usage, usage);
+}
+
+void IonBuffer::Reset(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage) {
ALOGD_IF(TRACE,
- "IonBuffer::Reset: handle=%p width=%d height=%d stride=%d format=%d "
- "usage=%d",
- handle, width, height, stride, format, usage);
- Import(handle, width, height, stride, format, usage);
+ "IonBuffer::Reset: handle=%p width=%u height=%u stride=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+ handle, width, height, stride, format, producer_usage,
+ consumer_usage);
+ Import(handle, width, height, stride, format, producer_usage, consumer_usage);
}
-int IonBuffer::Import(buffer_handle_t handle, int width, int height, int stride,
- int format, int usage) {
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage) {
+ return Import(handle, width, height, stride, format, usage, usage);
+}
+
+int IonBuffer::Import(buffer_handle_t handle, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage) {
ATRACE_NAME("IonBuffer::Import1");
ALOGD_IF(
TRACE,
- "IonBuffer::Import: handle=%p width=%d height=%d stride=%d format=%d "
- "usage=%d",
- handle, width, height, stride, format, usage);
+ "IonBuffer::Import: handle=%p width=%u height=%u stride=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64,
+ handle, width, height, stride, format, producer_usage, consumer_usage);
FreeHandle();
- buffer_ = new GraphicBuffer(handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE,
- width, height, format, 1, usage, stride);
- if (buffer_->initCheck() != OK) {
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ handle, GraphicBuffer::TAKE_UNREGISTERED_HANDLE, width, height, format,
+ kDefaultGraphicBufferLayerCount, producer_usage, consumer_usage, stride);
+ if (buffer->initCheck() != OK) {
ALOGE("IonBuffer::Import: Failed to import buffer");
return -EINVAL;
+ } else {
+ buffer_ = buffer;
+ producer_usage_ = producer_usage;
+ consumer_usage_ = consumer_usage;
+ return 0;
}
- return 0;
}
int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
- int int_count, int width, int height, int stride,
- int format, int usage) {
+ int int_count, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint32_t usage) {
+ return Import(fd_array, fd_count, int_array, int_count, width, height, stride,
+ format, usage, usage);
+}
+
+int IonBuffer::Import(const int* fd_array, int fd_count, const int* int_array,
+ int int_count, uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage) {
ATRACE_NAME("IonBuffer::Import2");
ALOGD_IF(TRACE,
- "IonBuffer::Import: fd_count=%d int_count=%d width=%d height=%d "
- "stride=%d format=%d usage=%d",
- fd_count, int_count, width, height, stride, format, usage);
+ "IonBuffer::Import: fd_count=%d int_count=%d width=%u height=%u "
+ "stride=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64,
+ fd_count, int_count, width, height, stride, format, producer_usage,
+ consumer_usage);
if (fd_count < 0 || int_count < 0) {
ALOGE("IonBuffer::Import: invalid arguments.");
@@ -128,7 +193,8 @@
memcpy(handle->data, fd_array, sizeof(int) * fd_count);
memcpy(handle->data + fd_count, int_array, sizeof(int) * int_count);
- int ret = Import(handle, width, height, stride, format, usage);
+ const int ret = Import(handle, width, height, stride, format, producer_usage,
+ consumer_usage);
if (ret < 0) {
ALOGE("IonBuffer::Import: failed to import raw native handle: %s",
strerror(-ret));
@@ -163,8 +229,9 @@
memcpy(handle->data + fd_count, other->handle()->data + fd_count,
sizeof(int) * int_count);
- const int ret = Import(handle, other->width(), other->height(),
- other->stride(), other->format(), other->usage());
+ const int ret =
+ Import(handle, other->width(), other->height(), other->stride(),
+ other->format(), other->producer_usage(), other->consumer_usage());
if (ret < 0) {
ALOGE("IonBuffer::Duplicate: Failed to import duplicate native handle: %s",
strerror(-ret));
@@ -175,7 +242,7 @@
return ret;
}
-int IonBuffer::Lock(int usage, int x, int y, int width, int height,
+int IonBuffer::Lock(uint32_t usage, int x, int y, int width, int height,
void** address) {
ATRACE_NAME("IonBuffer::Lock");
ALOGD_IF(TRACE,
@@ -183,23 +250,23 @@
"address=%p",
handle(), usage, x, y, width, height, address);
- status_t err = buffer_->lock(usage, Rect(x, y, x + width, y + height),
- address);
+ status_t err =
+ buffer_->lock(usage, Rect(x, y, x + width, y + height), address);
if (err != NO_ERROR)
return -EINVAL;
else
return 0;
}
-int IonBuffer::LockYUV(int usage, int x, int y, int width, int height,
+int IonBuffer::LockYUV(uint32_t usage, int x, int y, int width, int height,
struct android_ycbcr* yuv) {
ATRACE_NAME("IonBuffer::LockYUV");
ALOGD_IF(TRACE,
"IonBuffer::Lock: handle=%p usage=%d x=%d y=%d width=%d height=%d",
handle(), usage, x, y, width, height);
- status_t err = buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height),
- yuv);
+ status_t err =
+ buffer_->lockYCbCr(usage, Rect(x, y, x + width, y + height), yuv);
if (err != NO_ERROR)
return -EINVAL;
else
@@ -216,5 +283,5 @@
else
return 0;
}
-} // namespace dvr
-} // namespace android
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index e491abc..b431d2f 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -317,7 +317,7 @@
}
ProducerQueue::ProducerQueue(size_t meta_size)
- : ProducerQueue(meta_size, 0, 0, 0, 0) {}
+ : ProducerQueue(meta_size, 0, 0, 0, 0, 0, 0, 0, 0) {}
ProducerQueue::ProducerQueue(LocalChannelHandle handle)
: BASE(std::move(handle)) {
@@ -329,13 +329,22 @@
}
}
-ProducerQueue::ProducerQueue(size_t meta_size, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask)
+ProducerQueue::ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+ uint64_t producer_usage_clear_mask,
+ uint64_t producer_usage_deny_set_mask,
+ uint64_t producer_usage_deny_clear_mask,
+ uint64_t consumer_usage_set_mask,
+ uint64_t consumer_usage_clear_mask,
+ uint64_t consumer_usage_deny_set_mask,
+ uint64_t consumer_usage_deny_clear_mask)
: BASE(BufferHubRPC::kClientPath) {
auto status = InvokeRemoteMethod<BufferHubRPC::CreateProducerQueue>(
- meta_size, usage_set_mask, usage_clear_mask, usage_deny_set_mask,
- usage_deny_clear_mask);
+ meta_size,
+ UsagePolicy{producer_usage_set_mask, producer_usage_clear_mask,
+ producer_usage_deny_set_mask, producer_usage_deny_clear_mask,
+ consumer_usage_set_mask, consumer_usage_clear_mask,
+ consumer_usage_deny_set_mask,
+ consumer_usage_deny_clear_mask});
if (!status) {
ALOGE("ProducerQueue::ProducerQueue: Failed to create producer queue: %s",
status.GetErrorMessage().c_str());
@@ -346,8 +355,17 @@
SetupQueue(status.get().meta_size_bytes, status.get().id);
}
-int ProducerQueue::AllocateBuffer(int width, int height, int format, int usage,
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t format, uint32_t usage,
size_t slice_count, size_t* out_slot) {
+ return AllocateBuffer(width, height, format, usage, usage, slice_count,
+ out_slot);
+}
+
+int ProducerQueue::AllocateBuffer(uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t slice_count,
+ size_t* out_slot) {
if (out_slot == nullptr) {
ALOGE("ProducerQueue::AllocateBuffer: Parameter out_slot cannot be null.");
return -EINVAL;
@@ -363,7 +381,8 @@
Status<std::vector<std::pair<LocalChannelHandle, size_t>>> status =
InvokeRemoteMethod<BufferHubRPC::ProducerQueueAllocateBuffers>(
- width, height, format, usage, slice_count, kBufferCount);
+ width, height, format, producer_usage, consumer_usage, slice_count,
+ kBufferCount);
if (!status) {
ALOGE(
"ProducerQueue::AllocateBuffer failed to create producer buffer "
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
index 3fe7642..ebd7da0 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_producer.cpp
@@ -38,22 +38,8 @@
}
const auto& buffer_producer = core_->buffers_[slot].mBufferProducer;
+ sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
- // Create new GraphicBuffer based on the newly created |buffer_producer|. Here
- // we have to cast |buffer_handle_t| to |native_handle_t|, it's OK because
- // internally, GraphicBuffer is still an |ANativeWindowBuffer| and |handle|
- // is still type of |buffer_handle_t| and bears const property.
- sp<GraphicBuffer> graphic_buffer(new GraphicBuffer(
- buffer_producer->width(), buffer_producer->height(),
- buffer_producer->format(),
- 1, /* layer count */
- buffer_producer->usage(),
- buffer_producer->stride(),
- const_cast<native_handle_t*>(buffer_producer->buffer()->handle()),
- false));
-
- LOG_ALWAYS_FATAL_IF(NO_ERROR != graphic_buffer->initCheck(),
- "Failed to init GraphicBuffer.");
core_->buffers_[slot].mGraphicBuffer = graphic_buffer;
core_->buffers_[slot].mRequestBufferCalled = true;
@@ -155,9 +141,9 @@
if (!buffer_producer)
return NO_MEMORY;
- if (static_cast<int>(width) == buffer_producer->width() &&
- static_cast<int>(height) == buffer_producer->height() &&
- static_cast<int>(format) == buffer_producer->format()) {
+ if (width == buffer_producer->width() &&
+ height == buffer_producer->height() &&
+ static_cast<uint32_t>(format) == buffer_producer->format()) {
// The producer queue returns a buffer producer matches the request.
break;
}
@@ -165,8 +151,8 @@
// Needs reallocation.
// TODO(jwcai) Consider use VLOG instead if we find this log is not useful.
ALOGI(
- "dequeueBuffer: requested buffer (w=%u, h=%u, format=%d) is different "
- "from the buffer returned at slot: %zu (w=%d, h=%d, format=%d). Need "
+ "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
+ "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
"re-allocattion.",
width, height, format, slot, buffer_producer->width(),
buffer_producer->height(), buffer_producer->format());
@@ -322,7 +308,7 @@
output->width = buffer_producer->width();
output->height = buffer_producer->height();
- output->transformHint = 0; // default value, we don't use it yet.
+ output->transformHint = 0; // default value, we don't use it yet.
// |numPendingBuffers| counts of the number of buffers that has been enqueued
// by the producer but not yet acquired by the consumer. Due to the nature
@@ -456,7 +442,7 @@
return NO_ERROR;
}
-status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode mode) {
+status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) {
// Consumer interaction are actually handled by buffer hub, and we need
// to maintain consumer operations here. We only need to perform basic input
// parameter checks here.
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 2b70c5b..255793f 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -274,12 +274,27 @@
// |usage_deny_clear_mask| shall not conflict with each other. Such
// configuration will be treated as invalid input on creation.
template <typename Meta>
- static std::unique_ptr<ProducerQueue> Create(int usage_set_mask,
- int usage_clear_mask,
- int usage_deny_set_mask,
- int usage_deny_clear_mask) {
+ static std::unique_ptr<ProducerQueue> Create(uint32_t usage_set_mask,
+ uint32_t usage_clear_mask,
+ uint32_t usage_deny_set_mask,
+ uint32_t usage_deny_clear_mask) {
return BASE::Create(sizeof(Meta), usage_set_mask, usage_clear_mask,
- usage_deny_set_mask, usage_deny_clear_mask);
+ usage_deny_set_mask, usage_deny_clear_mask,
+ usage_set_mask, usage_clear_mask, usage_deny_set_mask,
+ usage_deny_clear_mask);
+ }
+ template <typename Meta>
+ static std::unique_ptr<ProducerQueue> Create(
+ uint64_t producer_usage_set_mask, uint64_t producer_usage_clear_mask,
+ uint64_t producer_usage_deny_set_mask,
+ uint64_t producer_usage_deny_clear_mask, uint64_t consumer_usage_set_mask,
+ uint64_t consumer_usage_clear_mask, uint64_t consumer_usage_deny_set_mask,
+ uint64_t consumer_usage_deny_clear_mask) {
+ return BASE::Create(sizeof(Meta), producer_usage_set_mask,
+ producer_usage_clear_mask, producer_usage_deny_set_mask,
+ producer_usage_deny_clear_mask, consumer_usage_set_mask,
+ consumer_usage_clear_mask, consumer_usage_deny_set_mask,
+ consumer_usage_deny_clear_mask);
}
// Import a |ProducerQueue| from a channel handle.
@@ -301,7 +316,10 @@
// use (i.e. in |Gain|'ed mode).
// Returns Zero on success and negative error code when buffer allocation
// fails.
- int AllocateBuffer(int width, int height, int format, int usage,
+ int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint32_t usage, size_t slice_count, size_t* out_slot);
+ int AllocateBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t slice_count, size_t* out_slot);
// Add a producer buffer to populate the queue. Once added, a producer buffer
@@ -327,8 +345,14 @@
// arguments as the constructors.
explicit ProducerQueue(size_t meta_size);
ProducerQueue(LocalChannelHandle handle);
- ProducerQueue(size_t meta_size, int usage_set_mask, int usage_clear_mask,
- int usage_deny_set_mask, int usage_deny_clear_mask);
+ ProducerQueue(size_t meta_size, uint64_t producer_usage_set_mask,
+ uint64_t producer_usage_clear_mask,
+ uint64_t producer_usage_deny_set_mask,
+ uint64_t producer_usage_deny_clear_mask,
+ uint64_t consumer_usage_set_mask,
+ uint64_t consumer_usage_clear_mask,
+ uint64_t consumer_usage_deny_set_mask,
+ uint64_t consumer_usage_deny_clear_mask);
int OnBufferReady(std::shared_ptr<BufferHubBuffer> buf,
LocalHandle* release_fence) override;
diff --git a/libs/vr/libdisplay/display_client.cpp b/libs/vr/libdisplay/display_client.cpp
index 6d39cdb..ef50a0f 100644
--- a/libs/vr/libdisplay/display_client.cpp
+++ b/libs/vr/libdisplay/display_client.cpp
@@ -216,7 +216,8 @@
return 0;
}
-pdx::Status<void> DisplayClient::SetViewerParams(const ViewerParams& viewer_params) {
+pdx::Status<void> DisplayClient::SetViewerParams(
+ const ViewerParams& viewer_params) {
auto status = InvokeRemoteMethod<DisplayRPC::SetViewerParams>(viewer_params);
if (!status) {
ALOGE("DisplayClient::SetViewerParams: Failed to set viewer params: %s",
@@ -252,16 +253,20 @@
return DisplaySurfaceClient::Create(width, height, format, usage, flags);
}
-std::unique_ptr<BufferConsumer> DisplayClient::GetPoseBuffer() {
- auto status = InvokeRemoteMethod<DisplayRPC::GetPoseBuffer>();
+std::unique_ptr<IonBuffer> DisplayClient::GetNamedBuffer(
+ const std::string& name) {
+ auto status = InvokeRemoteMethod<DisplayRPC::GetNamedBuffer>(name);
if (!status) {
ALOGE(
- "DisplayClient::GetPoseBuffer: Failed to get pose buffer %s",
- status.GetErrorMessage().c_str());
+ "DisplayClient::GetNamedBuffer: Failed to get pose buffer. name=%s, "
+ "error=%s",
+ name.c_str(), status.GetErrorMessage().c_str());
return nullptr;
}
- return BufferConsumer::Import(std::move(status));
+ auto ion_buffer = std::make_unique<IonBuffer>();
+ status.take().Import(ion_buffer.get());
+ return ion_buffer;
}
bool DisplayClient::IsVrAppRunning() {
diff --git a/libs/vr/libdisplay/display_manager_client_impl.cpp b/libs/vr/libdisplay/display_manager_client_impl.cpp
index 7993fce..44b3c4b 100644
--- a/libs/vr/libdisplay/display_manager_client_impl.cpp
+++ b/libs/vr/libdisplay/display_manager_client_impl.cpp
@@ -31,19 +31,22 @@
return 0;
}
-std::unique_ptr<BufferProducer> DisplayManagerClient::SetupPoseBuffer(
- size_t extended_region_size, int usage) {
- auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
- extended_region_size, usage);
+std::unique_ptr<IonBuffer> DisplayManagerClient::SetupNamedBuffer(
+ const std::string& name, size_t size, uint64_t producer_usage,
+ uint64_t consumer_usage) {
+ auto status = InvokeRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+ name, size, producer_usage, consumer_usage);
if (!status) {
ALOGE(
- "DisplayManagerClient::SetupPoseBuffer: Failed to create the pose "
- "buffer %s",
- status.GetErrorMessage().c_str());
+ "DisplayManagerClient::SetupNamedBuffer: Failed to create the named "
+ "buffer: name=%s, error=%s",
+ name.c_str(), status.GetErrorMessage().c_str());
return {};
}
- return BufferProducer::Import(std::move(status));
+ auto ion_buffer = std::make_unique<IonBuffer>();
+ status.take().Import(ion_buffer.get());
+ return ion_buffer;
}
} // namespace dvr
diff --git a/libs/vr/libdisplay/include/private/dvr/display_client.h b/libs/vr/libdisplay/include/private/dvr/display_client.h
index 378f67c..fec2ea5 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_client.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_client.h
@@ -108,7 +108,7 @@
std::unique_ptr<DisplaySurfaceClient> CreateDisplaySurface(
int width, int height, int format, int usage, int flags);
- std::unique_ptr<BufferConsumer> GetPoseBuffer();
+ std::unique_ptr<IonBuffer> GetNamedBuffer(const std::string& name);
// Temporary query for current VR status. Will be removed later.
bool IsVrAppRunning();
diff --git a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
index 144cd3b..b0a7d13 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_manager_client_impl.h
@@ -17,8 +17,10 @@
int GetSurfaceList(std::vector<DisplaySurfaceInfo>* surface_list);
- std::unique_ptr<BufferProducer> SetupPoseBuffer(size_t extended_region_size,
- int usage);
+ std::unique_ptr<IonBuffer> SetupNamedBuffer(const std::string& name,
+ size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage);
using Client::event_fd;
using Client::GetChannel;
diff --git a/libs/vr/libdisplay/include/private/dvr/display_rpc.h b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
index ac08650..c12b090 100644
--- a/libs/vr/libdisplay/include/private/dvr/display_rpc.h
+++ b/libs/vr/libdisplay/include/private/dvr/display_rpc.h
@@ -9,6 +9,7 @@
#include <pdx/rpc/remote_method.h>
#include <pdx/rpc/serializable.h>
#include <pdx/rpc/variant.h>
+#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/display_types.h>
namespace android {
@@ -218,7 +219,7 @@
kOpCreateVideoMeshSurface,
kOpVideoMeshSurfaceCreateProducerQueue,
kOpSetViewerParams,
- kOpGetPoseBuffer,
+ kOpGetNamedBuffer,
kOpIsVrAppRunning,
};
@@ -247,8 +248,8 @@
LocalChannelHandle(Void));
PDX_REMOTE_METHOD(SetViewerParams, kOpSetViewerParams,
void(const ViewerParams& viewer_params));
- PDX_REMOTE_METHOD(GetPoseBuffer, kOpGetPoseBuffer,
- LocalChannelHandle(Void));
+ PDX_REMOTE_METHOD(GetNamedBuffer, kOpGetNamedBuffer,
+ LocalNativeBufferHandle(const std::string& name));
PDX_REMOTE_METHOD(IsVrAppRunning, kOpIsVrAppRunning, int(Void));
};
@@ -260,7 +261,7 @@
enum {
kOpGetSurfaceList = 0,
kOpUpdateSurfaces,
- kOpSetupPoseBuffer,
+ kOpSetupNamedBuffer,
};
// Aliases.
@@ -273,8 +274,11 @@
PDX_REMOTE_METHOD(
UpdateSurfaces, kOpUpdateSurfaces,
int(const std::map<int, DisplaySurfaceAttributes>& updates));
- PDX_REMOTE_METHOD(SetupPoseBuffer, kOpSetupPoseBuffer,
- LocalChannelHandle(size_t extended_region_size, int usage));
+ PDX_REMOTE_METHOD(SetupNamedBuffer, kOpSetupNamedBuffer,
+ LocalNativeBufferHandle(const std::string& name,
+ size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage));
};
struct ScreenshotData {
diff --git a/libs/vr/libdvr/display_manager_client.cpp b/libs/vr/libdvr/display_manager_client.cpp
index 7cbfc21..8d84f7b 100644
--- a/libs/vr/libdvr/display_manager_client.cpp
+++ b/libs/vr/libdvr/display_manager_client.cpp
@@ -42,14 +42,16 @@
delete client;
}
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
- DvrDisplayManagerClient* client, size_t extended_region_size,
- uint64_t usage0, uint64_t usage1) {
- // TODO(hendrikw): When we move to gralloc1, pass both usage0 and usage1 down.
- auto buffer_producer = client->client->SetupPoseBuffer(
- extended_region_size, static_cast<int>(usage0));
- if (buffer_producer) {
- return CreateDvrWriteBufferFromBufferProducer(std::move(buffer_producer));
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+ const char* name, size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage) {
+ // TODO(hendrikw): When we move to gralloc1, pass both producer_usage and
+ // consumer_usage down.
+ auto ion_buffer = client->client->SetupNamedBuffer(name, size, producer_usage,
+ consumer_usage);
+ if (ion_buffer) {
+ return CreateDvrBufferFromIonBuffer(std::move(ion_buffer));
}
return nullptr;
}
@@ -109,8 +111,8 @@
}
int dvrDisplayManagerClientGetSurfaceBuffers(
- DvrDisplayManagerClient* client, int surface_id,
- DvrDisplayManagerClientSurfaceBuffers** surface_buffers) {
+ DvrDisplayManagerClient* /* client */, int /* surface_id */,
+ DvrDisplayManagerClientSurfaceBuffers** /* surface_buffers */) {
// TODO(jwcai, hendrikw) Remove this after we replacing
// dvrDisplayManagerClientGetSurfaceBuffers is dvr_api.
return -1;
diff --git a/libs/vr/libdvr/dvr_api.cpp b/libs/vr/libdvr/dvr_api.cpp
index 49702fd..5dc4a1b 100644
--- a/libs/vr/libdvr/dvr_api.cpp
+++ b/libs/vr/libdvr/dvr_api.cpp
@@ -31,8 +31,8 @@
dvrDisplayManagerClientGetSurfaceList;
dvr_api->display_manager_client_surface_list_destroy =
dvrDisplayManagerClientSurfaceListDestroy;
- dvr_api->display_manager_setup_pose_buffer =
- dvrDisplayManagerSetupPoseBuffer;
+ dvr_api->display_manager_setup_named_buffer =
+ dvrDisplayManagerSetupNamedBuffer;
dvr_api->display_manager_client_surface_list_get_size =
dvrDisplayManagerClientSurfaceListGetSize;
dvr_api->display_manager_client_surface_list_get_surface_id =
@@ -48,7 +48,6 @@
// dvr_buffer.h
dvr_api->write_buffer_destroy = dvrWriteBufferDestroy;
- dvr_api->write_buffer_get_blob_fds = dvrWriteBufferGetBlobFds;
dvr_api->write_buffer_get_ahardwarebuffer =
dvrWriteBufferGetAHardwareBuffer;
dvr_api->write_buffer_post = dvrWriteBufferPost;
@@ -56,11 +55,12 @@
dvr_api->write_buffer_gain_async = dvrWriteBufferGainAsync;
dvr_api->read_buffer_destroy = dvrReadBufferDestroy;
- dvr_api->read_buffer_get_blob_fds = dvrReadBufferGetBlobFds;
dvr_api->read_buffer_get_ahardwarebuffer = dvrReadBufferGetAHardwareBuffer;
dvr_api->read_buffer_acquire = dvrReadBufferAcquire;
dvr_api->read_buffer_release = dvrReadBufferRelease;
dvr_api->read_buffer_release_async = dvrReadBufferReleaseAsync;
+ dvr_api->buffer_destroy = dvrBufferDestroy;
+ dvr_api->buffer_get_ahardwarebuffer = dvrBufferGetAHardwareBuffer;
// dvr_buffer_queue.h
dvr_api->write_buffer_queue_destroy = dvrWriteBufferQueueDestroy;
@@ -77,7 +77,7 @@
dvr_api->read_buffer_queue_dequeue = dvrReadBufferQueueDequeue;
// dvr_surface.h
- dvr_api->get_pose_buffer = dvrGetPoseBuffer;
+ dvr_api->get_named_buffer = dvrGetNamedBuffer;
dvr_api->surface_create = dvrSurfaceCreate;
dvr_api->surface_get_write_buffer_queue = dvrSurfaceGetWriteBufferQueue;
@@ -109,6 +109,11 @@
dvr_api->hwc_frame_get_display_width = dvrHwcFrameGetDisplayWidth;
dvr_api->hwc_frame_get_display_height = dvrHwcFrameGetDisplayHeight;
dvr_api->hwc_frame_get_display_removed = dvrHwcFrameGetDisplayRemoved;
+ dvr_api->hwc_frame_get_active_config = dvrHwcFrameGetActiveConfig;
+ dvr_api->hwc_frame_get_color_mode = dvrHwcFrameGetColorMode;
+ dvr_api->hwc_frame_get_color_transform = dvrHwcFrameGetColorTransform;
+ dvr_api->hwc_frame_get_power_mode = dvrHwcFrameGetPowerMode;
+ dvr_api->hwc_frame_get_vsync_enabled = dvrHwcFrameGetVsyncEnabled;
dvr_api->hwc_frame_get_layer_count = dvrHwcFrameGetLayerCount;
dvr_api->hwc_frame_get_layer_id = dvrHwcFrameGetLayerId;
dvr_api->hwc_frame_get_layer_buffer = dvrHwcFrameGetLayerBuffer;
@@ -121,6 +126,19 @@
dvr_api->hwc_frame_get_layer_type = dvrHwcFrameGetLayerType;
dvr_api->hwc_frame_get_layer_application_id =
dvrHwcFrameGetLayerApplicationId;
+ dvr_api->hwc_frame_get_layer_z_order = dvrHwcFrameGetLayerZOrder;
+ dvr_api->hwc_frame_get_layer_cursor = dvrHwcFrameGetLayerCursor;
+ dvr_api->hwc_frame_get_layer_transform = dvrHwcFrameGetLayerTransform;
+ dvr_api->hwc_frame_get_layer_dataspace = dvrHwcFrameGetLayerDataspace;
+ dvr_api->hwc_frame_get_layer_color = dvrHwcFrameGetLayerColor;
+ dvr_api->hwc_frame_get_layer_num_visible_regions =
+ dvrHwcFrameGetLayerNumVisibleRegions;
+ dvr_api->hwc_frame_get_layer_visible_region =
+ dvrHwcFrameGetLayerVisibleRegion;
+ dvr_api->hwc_frame_get_layer_num_damaged_regions =
+ dvrHwcFrameGetLayerNumDamagedRegions;
+ dvr_api->hwc_frame_get_layer_damaged_region =
+ dvrHwcFrameGetLayerDamagedRegion;
return 0;
}
diff --git a/libs/vr/libdvr/dvr_buffer.cpp b/libs/vr/libdvr/dvr_buffer.cpp
index 25128a6..0942b3d 100644
--- a/libs/vr/libdvr/dvr_buffer.cpp
+++ b/libs/vr/libdvr/dvr_buffer.cpp
@@ -6,13 +6,15 @@
using namespace android;
struct DvrWriteBuffer {
- std::shared_ptr<dvr::BufferProducer> write_buffer_;
- sp<GraphicBuffer> graphic_buffer_;
+ std::shared_ptr<dvr::BufferProducer> write_buffer;
};
struct DvrReadBuffer {
- std::shared_ptr<dvr::BufferConsumer> read_buffer_;
- sp<GraphicBuffer> graphic_buffer_;
+ std::shared_ptr<dvr::BufferConsumer> read_buffer;
+};
+
+struct DvrBuffer {
+ std::shared_ptr<dvr::IonBuffer> buffer;
};
namespace android {
@@ -20,16 +22,23 @@
DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
const std::shared_ptr<dvr::BufferProducer>& buffer_producer) {
- DvrWriteBuffer* write_buffer = new DvrWriteBuffer;
- write_buffer->write_buffer_ = std::move(buffer_producer);
- return write_buffer;
+ if (!buffer_producer)
+ return nullptr;
+ return new DvrWriteBuffer{std::move(buffer_producer)};
}
DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
const std::shared_ptr<dvr::BufferConsumer>& buffer_consumer) {
- DvrReadBuffer* read_buffer = new DvrReadBuffer;
- read_buffer->read_buffer_ = std::move(buffer_consumer);
- return read_buffer;
+ if (!buffer_consumer)
+ return nullptr;
+ return new DvrReadBuffer{std::move(buffer_consumer)};
+}
+
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+ const std::shared_ptr<IonBuffer>& ion_buffer) {
+ if (!ion_buffer)
+ return nullptr;
+ return new DvrBuffer{std::move(ion_buffer)};
}
} // namespace dvr
@@ -49,79 +58,82 @@
extern "C" {
-void dvrWriteBufferDestroy(DvrWriteBuffer* client) { delete client; }
-
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
- size_t* fds_count, size_t max_fds_count) {
- client->write_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
+ delete write_buffer;
}
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer) {
+ return write_buffer->write_buffer->id();
+}
+
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
AHardwareBuffer** hardware_buffer) {
- if (!client->graphic_buffer_.get()) {
- InitializeGraphicBuffer(client->write_buffer_.get(),
- &client->graphic_buffer_);
- }
- *hardware_buffer =
- reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+ *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+ write_buffer->write_buffer->buffer()->buffer().get());
return 0;
}
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
const void* meta, size_t meta_size_bytes) {
pdx::LocalHandle fence(ready_fence_fd);
- int result = client->write_buffer_->Post(fence, meta, meta_size_bytes);
- fence.Release();
+ int result = write_buffer->write_buffer->Post(fence, meta, meta_size_bytes);
return result;
}
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd) {
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd) {
pdx::LocalHandle release_fence;
- int result = client->write_buffer_->Gain(&release_fence);
+ int result = write_buffer->write_buffer->Gain(&release_fence);
*release_fence_fd = release_fence.Release();
return result;
}
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client) {
- return client->write_buffer_->GainAsync();
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer) {
+ return write_buffer->write_buffer->GainAsync();
}
-void dvrReadBufferDestroy(DvrReadBuffer* client) { delete client; }
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
- size_t max_fds_count) {
- client->read_buffer_->GetBlobFds(fds, fds_count, max_fds_count);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer) {
+ return read_buffer->read_buffer->id();
}
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
AHardwareBuffer** hardware_buffer) {
- if (!client->graphic_buffer_.get()) {
- InitializeGraphicBuffer(client->read_buffer_.get(),
- &client->graphic_buffer_);
- }
- *hardware_buffer =
- reinterpret_cast<AHardwareBuffer*>(client->graphic_buffer_.get());
+ *hardware_buffer = reinterpret_cast<AHardwareBuffer*>(
+ read_buffer->read_buffer->buffer()->buffer().get());
return 0;
}
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
- size_t meta_size_bytes) {
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+ void* meta, size_t meta_size_bytes) {
pdx::LocalHandle ready_fence;
int result =
- client->read_buffer_->Acquire(&ready_fence, meta, meta_size_bytes);
+ read_buffer->read_buffer->Acquire(&ready_fence, meta, meta_size_bytes);
*ready_fence_fd = ready_fence.Release();
return result;
}
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd) {
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd) {
pdx::LocalHandle fence(release_fence_fd);
- int result = client->read_buffer_->Release(fence);
- fence.Release();
+ int result = read_buffer->read_buffer->Release(fence);
return result;
}
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client) {
- return client->read_buffer_->ReleaseAsync();
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer) {
+ return read_buffer->read_buffer->ReleaseAsync();
+}
+
+void dvrBufferDestroy(DvrBuffer* buffer) { delete buffer; }
+
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+ AHardwareBuffer** hardware_buffer) {
+ if (!hardware_buffer) {
+ return -EINVAL;
+ }
+
+ *hardware_buffer =
+ reinterpret_cast<AHardwareBuffer*>(buffer->buffer->buffer().get());
+ return 0;
}
} // extern "C"
diff --git a/libs/vr/libdvr/dvr_hardware_composer_client.cpp b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
index e5665e1..d3ae299 100644
--- a/libs/vr/libdvr/dvr_hardware_composer_client.cpp
+++ b/libs/vr/libdvr/dvr_hardware_composer_client.cpp
@@ -84,7 +84,7 @@
delete frame;
}
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame) {
return frame->frame.display_id;
}
@@ -104,7 +104,30 @@
return frame->frame.layers.size();
}
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
+uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame) {
+ return static_cast<uint32_t>(frame->frame.active_config);
+}
+
+uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame) {
+ return static_cast<uint32_t>(frame->frame.color_mode);
+}
+
+void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
+ int32_t* out_hint) {
+ *out_hint = frame->frame.color_transform_hint;
+ memcpy(out_matrix, frame->frame.color_transform,
+ sizeof(frame->frame.color_transform));
+}
+
+uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame) {
+ return static_cast<uint32_t>(frame->frame.power_mode);
+}
+
+uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame) {
+ return static_cast<uint32_t>(frame->frame.vsync_enabled);
+}
+
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index) {
return frame->frame.layers[layer_index].id;
}
@@ -120,8 +143,9 @@
return frame->frame.layers[layer_index].fence->dup();
}
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index) {
- return Recti{
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+ size_t layer_index) {
+ return DvrHwcRecti{
frame->frame.layers[layer_index].display_frame.left,
frame->frame.layers[layer_index].display_frame.top,
frame->frame.layers[layer_index].display_frame.right,
@@ -129,8 +153,8 @@
};
}
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
- return Rectf{
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index) {
+ return DvrHwcRectf{
frame->frame.layers[layer_index].crop.left,
frame->frame.layers[layer_index].crop.top,
frame->frame.layers[layer_index].crop.right,
@@ -138,8 +162,10 @@
};
}
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index) {
- return static_cast<BlendMode>(frame->frame.layers[layer_index].blend_mode);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+ size_t layer_index) {
+ return static_cast<DvrHwcBlendMode>(
+ frame->frame.layers[layer_index].blend_mode);
}
float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index) {
@@ -154,3 +180,58 @@
size_t layer_index) {
return frame->frame.layers[layer_index].app_id;
}
+
+uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index) {
+ return frame->frame.layers[layer_index].z_order;
+}
+
+void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
+ int32_t* out_x, int32_t* out_y) {
+ *out_x = frame->frame.layers[layer_index].cursor_x;
+ *out_y = frame->frame.layers[layer_index].cursor_y;
+}
+
+uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index) {
+ return frame->frame.layers[layer_index].transform;
+}
+
+uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index) {
+ return frame->frame.layers[layer_index].dataspace;
+}
+
+uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index) {
+ const auto& color = frame->frame.layers[layer_index].color;
+ return color.r | (static_cast<uint32_t>(color.g) << 8) |
+ (static_cast<uint32_t>(color.b) << 16) |
+ (static_cast<uint32_t>(color.a) << 24);
+}
+
+uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
+ size_t layer_index) {
+ return frame->frame.layers[layer_index].visible_regions.size();
+}
+
+DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
+ size_t layer_index, size_t index) {
+ return DvrHwcRecti{
+ frame->frame.layers[layer_index].visible_regions[index].left,
+ frame->frame.layers[layer_index].visible_regions[index].top,
+ frame->frame.layers[layer_index].visible_regions[index].right,
+ frame->frame.layers[layer_index].visible_regions[index].bottom,
+ };
+}
+
+uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
+ size_t layer_index) {
+ return frame->frame.layers[layer_index].damaged_regions.size();
+}
+
+DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
+ size_t layer_index, size_t index) {
+ return DvrHwcRecti{
+ frame->frame.layers[layer_index].damaged_regions[index].left,
+ frame->frame.layers[layer_index].damaged_regions[index].top,
+ frame->frame.layers[layer_index].damaged_regions[index].right,
+ frame->frame.layers[layer_index].damaged_regions[index].bottom,
+ };
+}
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3cbba5..a04ed50 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -58,14 +58,25 @@
return 0;
}
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer) {
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer) {
auto client = android::dvr::DisplayClient::Create();
if (!client) {
- ALOGE("Failed to create display client!");
+ ALOGE("dvrGetNamedBuffer: Failed to create display client!");
return -ECOMM;
}
- *pose_buffer = CreateDvrReadBufferFromBufferConsumer(client->GetPoseBuffer());
+ if (out_buffer == nullptr || name == nullptr) {
+ ALOGE("dvrGetNamedBuffer: Invalid inputs: name=%p, out_buffer=%p.", name,
+ out_buffer);
+ return -EINVAL;
+ }
+
+ auto named_buffer = client->GetNamedBuffer(name);
+ if (!named_buffer) {
+ ALOGE("dvrGetNamedBuffer: Failed to find named buffer: %s.", name);
+ return -EINVAL;
+ }
+ *out_buffer = CreateDvrBufferFromIonBuffer(std::move(named_buffer));
return 0;
}
diff --git a/libs/vr/libdvr/include/dvr/display_manager_client.h b/libs/vr/libdvr/include/dvr/display_manager_client.h
index 0928d43..4e1f227 100644
--- a/libs/vr/libdvr/include/dvr/display_manager_client.h
+++ b/libs/vr/libdvr/include/dvr/display_manager_client.h
@@ -14,15 +14,16 @@
DvrDisplayManagerClientSurfaceList;
typedef struct DvrDisplayManagerClientSurfaceBuffers
DvrDisplayManagerClientSurfaceBuffers;
-typedef struct DvrWriteBuffer DvrWriteBuffer;
+typedef struct DvrBuffer DvrBuffer;
DvrDisplayManagerClient* dvrDisplayManagerClientCreate();
void dvrDisplayManagerClientDestroy(DvrDisplayManagerClient* client);
-DvrWriteBuffer* dvrDisplayManagerSetupPoseBuffer(
- DvrDisplayManagerClient* client, size_t extended_region_size,
- uint64_t usage0, uint64_t usage1);
+DvrBuffer* dvrDisplayManagerSetupNamedBuffer(DvrDisplayManagerClient* client,
+ const char* name, size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage);
// Return an event fd for checking if there was an event on the server
// Note that the only event which will be flagged is POLLIN. You must use
diff --git a/libs/vr/libdvr/include/dvr/dvr_api.h b/libs/vr/libdvr/include/dvr/dvr_api.h
index a4fef19..a69433d 100644
--- a/libs/vr/libdvr/include/dvr/dvr_api.h
+++ b/libs/vr/libdvr/include/dvr/dvr_api.h
@@ -30,6 +30,7 @@
typedef struct DvrWriteBuffer DvrWriteBuffer;
typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
typedef struct AHardwareBuffer AHardwareBuffer;
typedef struct DvrWriteBufferQueue DvrWriteBufferQueue;
@@ -43,9 +44,9 @@
DvrDisplayManagerClientSurfaceList** surface_list);
typedef void (*DvrDisplayManagerClientSurfaceListDestroyPtr)(
DvrDisplayManagerClientSurfaceList* surface_list);
-typedef DvrWriteBuffer* (*DvrDisplayManagerSetupPoseBufferPtr)(
- DvrDisplayManagerClient* client, size_t extended_region_size,
- uint64_t usage0, uint64_t usage1);
+typedef DvrBuffer* (*DvrDisplayManagerSetupNamedBufferPtr)(
+ DvrDisplayManagerClient* client, const char* name, size_t size,
+ uint64_t producer_usage, uint64_t consumer_usage);
typedef size_t (*DvrDisplayManagerClientSurfaceListGetSizePtr)(
DvrDisplayManagerClientSurfaceList* surface_list);
typedef int (*DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr)(
@@ -62,9 +63,6 @@
// dvr_buffer.h
typedef void (*DvrWriteBufferDestroyPtr)(DvrWriteBuffer* client);
-typedef void (*DvrWriteBufferGetBlobFdsPtr)(DvrWriteBuffer* client, int* fds,
- size_t* fds_count,
- size_t max_fds_count);
typedef int (*DvrWriteBufferGetAHardwareBufferPtr)(
DvrWriteBuffer* client, AHardwareBuffer** hardware_buffer);
typedef int (*DvrWriteBufferPostPtr)(DvrWriteBuffer* client, int ready_fence_fd,
@@ -74,9 +72,6 @@
typedef int (*DvrWriteBufferGainAsyncPtr)(DvrWriteBuffer* client);
typedef void (*DvrReadBufferDestroyPtr)(DvrReadBuffer* client);
-typedef void (*DvrReadBufferGetBlobFdsPtr)(DvrReadBuffer* client, int* fds,
- size_t* fds_count,
- size_t max_fds_count);
typedef int (*DvrReadBufferGetAHardwareBufferPtr)(
DvrReadBuffer* client, AHardwareBuffer** hardware_buffer);
typedef int (*DvrReadBufferAcquirePtr)(DvrReadBuffer* client,
@@ -85,6 +80,9 @@
typedef int (*DvrReadBufferReleasePtr)(DvrReadBuffer* client,
int release_fence_fd);
typedef int (*DvrReadBufferReleaseAsyncPtr)(DvrReadBuffer* client);
+typedef void (*DvrBufferDestroy)(DvrBuffer* buffer);
+typedef int (*DvrBufferGetAHardwareBuffer)(DvrBuffer* buffer,
+ AHardwareBuffer** hardware_buffer);
// dvr_buffer_queue.h
typedef void (*DvrWriteBufferQueueDestroyPtr)(DvrWriteBufferQueue* write_queue);
@@ -110,7 +108,7 @@
size_t meta_size_bytes);
// dvr_surface.h
-typedef int (*DvrGetPoseBufferPtr)(DvrReadBuffer** pose_buffer);
+typedef int (*DvrGetNamedBufferPtr)(const char* name, DvrBuffer** out_buffer);
typedef int (*DvrSurfaceCreatePtr)(int width, int height, int format,
uint64_t usage0, uint64_t usage1, int flags,
DvrSurface** out_surface);
@@ -149,33 +147,68 @@
// dvr_hardware_composer_client.h
typedef struct DvrHwcClient DvrHwcClient;
typedef struct DvrHwcFrame DvrHwcFrame;
-typedef int(*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
+typedef int (*DvrHwcOnFrameCallback)(void* client_state, DvrHwcFrame* frame);
typedef DvrHwcClient* (*DvrHwcClientCreatePtr)(DvrHwcOnFrameCallback callback,
void* client_state);
typedef void (*DvrHwcClientDestroyPtr)(DvrHwcClient* client);
typedef void (*DvrHwcFrameDestroyPtr)(DvrHwcFrame* frame);
-typedef Display (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
+typedef DvrHwcDisplay (*DvrHwcFrameGetDisplayIdPtr)(DvrHwcFrame* frame);
typedef int32_t (*DvrHwcFrameGetDisplayWidthPtr)(DvrHwcFrame* frame);
typedef int32_t (*DvrHwcFrameGetDisplayHeightPtr)(DvrHwcFrame* frame);
typedef bool (*DvrHwcFrameGetDisplayRemovedPtr)(DvrHwcFrame* frame);
typedef size_t (*DvrHwcFrameGetLayerCountPtr)(DvrHwcFrame* frame);
-typedef Layer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame, size_t layer_index);
+typedef DvrHwcLayer (*DvrHwcFrameGetLayerIdPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+typedef uint32_t (*DvrHwcFrameGetActiveConfigPtr)(DvrHwcFrame* frame);
+typedef uint32_t (*DvrHwcFrameGetColorModePtr)(DvrHwcFrame* frame);
+typedef void (*DvrHwcFrameGetColorTransformPtr)(DvrHwcFrame* frame,
+ float* out_matrix,
+ int32_t* out_hint);
+typedef uint32_t (*DvrHwcFrameGetPowerModePtr)(DvrHwcFrame* frame);
+typedef uint32_t (*DvrHwcFrameGetVsyncEnabledPtr)(DvrHwcFrame* frame);
typedef AHardwareBuffer* (*DvrHwcFrameGetLayerBufferPtr)(DvrHwcFrame* frame,
size_t layer_index);
typedef int (*DvrHwcFrameGetLayerFencePtr)(DvrHwcFrame* frame,
size_t layer_index);
-typedef Recti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
- size_t layer_index);
-typedef Rectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
- size_t layer_index);
-typedef BlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
- size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerDisplayFramePtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+typedef DvrHwcRectf (*DvrHwcFrameGetLayerCropPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+typedef DvrHwcBlendMode (*DvrHwcFrameGetLayerBlendModePtr)(DvrHwcFrame* frame,
+ size_t layer_index);
typedef float (*DvrHwcFrameGetLayerAlphaPtr)(DvrHwcFrame* frame,
size_t layer_index);
typedef uint32_t (*DvrHwcFrameGetLayerTypePtr)(DvrHwcFrame* frame,
size_t layer_index);
typedef uint32_t (*DvrHwcFrameGetLayerApplicationIdPtr)(DvrHwcFrame* frame,
size_t layer_index);
+typedef uint32_t (*DvrHwcFrameGetLayerZOrderPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+
+typedef void (*DvrHwcFrameGetLayerCursorPtr)(DvrHwcFrame* frame,
+ size_t layer_index, int32_t* out_x,
+ int32_t* out_y);
+
+typedef uint32_t (*DvrHwcFrameGetLayerTransformPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerDataspacePtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerColorPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerNumVisibleRegionsPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerVisibleRegionPtr)(DvrHwcFrame* frame,
+ size_t layer_index,
+ size_t index);
+
+typedef uint32_t (*DvrHwcFrameGetLayerNumDamagedRegionsPtr)(DvrHwcFrame* frame,
+ size_t layer_index);
+typedef DvrHwcRecti (*DvrHwcFrameGetLayerDamagedRegionPtr)(DvrHwcFrame* frame,
+ size_t layer_index,
+ size_t index);
struct DvrApi_v1 {
// Display manager client
@@ -185,7 +218,7 @@
display_manager_client_get_surface_list;
DvrDisplayManagerClientSurfaceListDestroyPtr
display_manager_client_surface_list_destroy;
- DvrDisplayManagerSetupPoseBufferPtr display_manager_setup_pose_buffer;
+ DvrDisplayManagerSetupNamedBufferPtr display_manager_setup_named_buffer;
DvrDisplayManagerClientSurfaceListGetSizePtr
display_manager_client_surface_list_get_size;
DvrDisplayManagerClientSurfaceListGetSurfaceIdPtr
@@ -201,7 +234,6 @@
// Write buffer
DvrWriteBufferDestroyPtr write_buffer_destroy;
- DvrWriteBufferGetBlobFdsPtr write_buffer_get_blob_fds;
DvrWriteBufferGetAHardwareBufferPtr write_buffer_get_ahardwarebuffer;
DvrWriteBufferPostPtr write_buffer_post;
DvrWriteBufferGainPtr write_buffer_gain;
@@ -209,11 +241,12 @@
// Read buffer
DvrReadBufferDestroyPtr read_buffer_destroy;
- DvrReadBufferGetBlobFdsPtr read_buffer_get_blob_fds;
DvrReadBufferGetAHardwareBufferPtr read_buffer_get_ahardwarebuffer;
DvrReadBufferAcquirePtr read_buffer_acquire;
DvrReadBufferReleasePtr read_buffer_release;
DvrReadBufferReleaseAsyncPtr read_buffer_release_async;
+ DvrBufferDestroy buffer_destroy;
+ DvrBufferGetAHardwareBuffer buffer_get_ahardwarebuffer;
// Write buffer queue
DvrWriteBufferQueueDestroyPtr write_buffer_queue_destroy;
@@ -235,7 +268,7 @@
DvrVSyncClientGetSchedInfoPtr vsync_client_get_sched_info;
// Display surface
- DvrGetPoseBufferPtr get_pose_buffer;
+ DvrGetNamedBufferPtr get_named_buffer;
DvrSurfaceCreatePtr surface_create;
DvrSurfaceGetWriteBufferQueuePtr surface_get_write_buffer_queue;
@@ -262,6 +295,11 @@
DvrHwcFrameGetDisplayWidthPtr hwc_frame_get_display_width;
DvrHwcFrameGetDisplayHeightPtr hwc_frame_get_display_height;
DvrHwcFrameGetDisplayRemovedPtr hwc_frame_get_display_removed;
+ DvrHwcFrameGetActiveConfigPtr hwc_frame_get_active_config;
+ DvrHwcFrameGetColorModePtr hwc_frame_get_color_mode;
+ DvrHwcFrameGetColorTransformPtr hwc_frame_get_color_transform;
+ DvrHwcFrameGetPowerModePtr hwc_frame_get_power_mode;
+ DvrHwcFrameGetVsyncEnabledPtr hwc_frame_get_vsync_enabled;
DvrHwcFrameGetLayerCountPtr hwc_frame_get_layer_count;
DvrHwcFrameGetLayerIdPtr hwc_frame_get_layer_id;
DvrHwcFrameGetLayerBufferPtr hwc_frame_get_layer_buffer;
@@ -272,6 +310,17 @@
DvrHwcFrameGetLayerAlphaPtr hwc_frame_get_layer_alpha;
DvrHwcFrameGetLayerTypePtr hwc_frame_get_layer_type;
DvrHwcFrameGetLayerApplicationIdPtr hwc_frame_get_layer_application_id;
+ DvrHwcFrameGetLayerZOrderPtr hwc_frame_get_layer_z_order;
+ DvrHwcFrameGetLayerCursorPtr hwc_frame_get_layer_cursor;
+ DvrHwcFrameGetLayerTransformPtr hwc_frame_get_layer_transform;
+ DvrHwcFrameGetLayerDataspacePtr hwc_frame_get_layer_dataspace;
+ DvrHwcFrameGetLayerColorPtr hwc_frame_get_layer_color;
+ DvrHwcFrameGetLayerNumVisibleRegionsPtr
+ hwc_frame_get_layer_num_visible_regions;
+ DvrHwcFrameGetLayerVisibleRegionPtr hwc_frame_get_layer_visible_region;
+ DvrHwcFrameGetLayerNumDamagedRegionsPtr
+ hwc_frame_get_layer_num_damaged_regions;
+ DvrHwcFrameGetLayerDamagedRegionPtr hwc_frame_get_layer_damaged_region;
};
int dvrGetApi(void* api, size_t struct_size, int version);
diff --git a/libs/vr/libdvr/include/dvr/dvr_buffer.h b/libs/vr/libdvr/include/dvr/dvr_buffer.h
index bbfbb00..6c9c4d3 100644
--- a/libs/vr/libdvr/include/dvr/dvr_buffer.h
+++ b/libs/vr/libdvr/include/dvr/dvr_buffer.h
@@ -1,9 +1,9 @@
#ifndef ANDROID_DVR_BUFFER_H_
#define ANDROID_DVR_BUFFER_H_
-#include <memory>
#include <stdbool.h>
#include <stdint.h>
+#include <memory>
#ifdef __cplusplus
extern "C" {
@@ -11,29 +11,33 @@
typedef struct DvrWriteBuffer DvrWriteBuffer;
typedef struct DvrReadBuffer DvrReadBuffer;
+typedef struct DvrBuffer DvrBuffer;
typedef struct AHardwareBuffer AHardwareBuffer;
// Write buffer
-void dvrWriteBufferDestroy(DvrWriteBuffer* client);
-void dvrWriteBufferGetBlobFds(DvrWriteBuffer* client, int* fds,
- size_t* fds_count, size_t max_fds_count);
-int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* client,
+void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetId(DvrWriteBuffer* write_buffer);
+int dvrWriteBufferGetAHardwareBuffer(DvrWriteBuffer* write_buffer,
AHardwareBuffer** hardware_buffer);
-int dvrWriteBufferPost(DvrWriteBuffer* client, int ready_fence_fd,
+int dvrWriteBufferPost(DvrWriteBuffer* write_buffer, int ready_fence_fd,
const void* meta, size_t meta_size_bytes);
-int dvrWriteBufferGain(DvrWriteBuffer* client, int* release_fence_fd);
-int dvrWriteBufferGainAsync(DvrWriteBuffer* client);
+int dvrWriteBufferGain(DvrWriteBuffer* write_buffer, int* release_fence_fd);
+int dvrWriteBufferGainAsync(DvrWriteBuffer* write_buffer);
// Read buffer
-void dvrReadBufferDestroy(DvrReadBuffer* client);
-void dvrReadBufferGetBlobFds(DvrReadBuffer* client, int* fds, size_t* fds_count,
- size_t max_fds_count);
-int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* client,
+void dvrReadBufferDestroy(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetId(DvrReadBuffer* read_buffer);
+int dvrReadBufferGetAHardwareBuffer(DvrReadBuffer* read_buffer,
AHardwareBuffer** hardware_buffer);
-int dvrReadBufferAcquire(DvrReadBuffer* client, int* ready_fence_fd, void* meta,
- size_t meta_size_bytes);
-int dvrReadBufferRelease(DvrReadBuffer* client, int release_fence_fd);
-int dvrReadBufferReleaseAsync(DvrReadBuffer* client);
+int dvrReadBufferAcquire(DvrReadBuffer* read_buffer, int* ready_fence_fd,
+ void* meta, size_t meta_size_bytes);
+int dvrReadBufferRelease(DvrReadBuffer* read_buffer, int release_fence_fd);
+int dvrReadBufferReleaseAsync(DvrReadBuffer* read_buffer);
+
+// Buffer
+void dvrBufferDestroy(DvrBuffer* buffer);
+int dvrBufferGetAHardwareBuffer(DvrBuffer* buffer,
+ AHardwareBuffer** hardware_buffer);
#ifdef __cplusplus
} // extern "C"
@@ -44,11 +48,14 @@
class BufferProducer;
class BufferConsumer;
+class IonBuffer;
DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
const std::shared_ptr<BufferProducer>& buffer_producer);
DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
const std::shared_ptr<BufferConsumer>& buffer_consumer);
+DvrBuffer* CreateDvrBufferFromIonBuffer(
+ const std::shared_ptr<IonBuffer>& ion_buffer);
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
index 692864d..7ee7f9e 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_client.h
@@ -29,7 +29,7 @@
// Called to free the frame information.
void dvrHwcFrameDestroy(DvrHwcFrame* frame);
-Display dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
+DvrHwcDisplay dvrHwcFrameGetDisplayId(DvrHwcFrame* frame);
int32_t dvrHwcFrameGetDisplayWidth(DvrHwcFrame* frame);
@@ -43,7 +43,14 @@
// @return Number of layers in the frame.
size_t dvrHwcFrameGetLayerCount(DvrHwcFrame* frame);
-Layer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
+uint32_t dvrHwcFrameGetActiveConfig(DvrHwcFrame* frame);
+uint32_t dvrHwcFrameGetColorMode(DvrHwcFrame* frame);
+void dvrHwcFrameGetColorTransform(DvrHwcFrame* frame, float* out_matrix,
+ int32_t* out_hint);
+uint32_t dvrHwcFrameGetPowerMode(DvrHwcFrame* frame);
+uint32_t dvrHwcFrameGetVsyncEnabled(DvrHwcFrame* frame);
+
+DvrHwcLayer dvrHwcFrameGetLayerId(DvrHwcFrame* frame, size_t layer_index);
// Return the graphic buffer associated with the layer at |layer_index| in
// |frame|.
@@ -58,11 +65,13 @@
// @return Fence FD. Caller owns the FD and is responsible for closing it.
int dvrHwcFrameGetLayerFence(DvrHwcFrame* frame, size_t layer_index);
-Recti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerDisplayFrame(DvrHwcFrame* frame,
+ size_t layer_index);
-Rectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcRectf dvrHwcFrameGetLayerCrop(DvrHwcFrame* frame, size_t layer_index);
-BlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame, size_t layer_index);
+DvrHwcBlendMode dvrHwcFrameGetLayerBlendMode(DvrHwcFrame* frame,
+ size_t layer_index);
float dvrHwcFrameGetLayerAlpha(DvrHwcFrame* frame, size_t layer_index);
@@ -71,6 +80,26 @@
uint32_t dvrHwcFrameGetLayerApplicationId(DvrHwcFrame* frame,
size_t layer_index);
+uint32_t dvrHwcFrameGetLayerZOrder(DvrHwcFrame* frame, size_t layer_index);
+
+void dvrHwcFrameGetLayerCursor(DvrHwcFrame* frame, size_t layer_index,
+ int32_t* out_x, int32_t* out_y);
+
+uint32_t dvrHwcFrameGetLayerTransform(DvrHwcFrame* frame, size_t layer_index);
+
+uint32_t dvrHwcFrameGetLayerDataspace(DvrHwcFrame* frame, size_t layer_index);
+
+uint32_t dvrHwcFrameGetLayerColor(DvrHwcFrame* frame, size_t layer_index);
+
+uint32_t dvrHwcFrameGetLayerNumVisibleRegions(DvrHwcFrame* frame,
+ size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerVisibleRegion(DvrHwcFrame* frame,
+ size_t layer_index, size_t index);
+
+uint32_t dvrHwcFrameGetLayerNumDamagedRegions(DvrHwcFrame* frame,
+ size_t layer_index);
+DvrHwcRecti dvrHwcFrameGetLayerDamagedRegion(DvrHwcFrame* frame,
+ size_t layer_index, size_t index);
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
index 546ed7b..36c30f9 100644
--- a/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
+++ b/libs/vr/libdvr/include/dvr/dvr_hardware_composer_defs.h
@@ -10,33 +10,33 @@
// NOTE: These definitions must match the ones in
// //hardware/libhardware/include/hardware/hwcomposer2.h. They are used by the
// client side which does not have access to hwc2 headers.
-enum BlendMode {
- BLEND_MODE_INVALID = 0,
- BLEND_MODE_NONE = 1,
- BLEND_MODE_PREMULTIPLIED = 2,
- BLEND_MODE_COVERAGE = 3,
+enum DvrHwcBlendMode {
+ DVR_HWC_BLEND_MODE_INVALID = 0,
+ DVR_HWC_BLEND_MODE_NONE = 1,
+ DVR_HWC_BLEND_MODE_PREMULTIPLIED = 2,
+ DVR_HWC_BLEND_MODE_COVERAGE = 3,
};
-enum Composition {
- COMPOSITION_INVALID = 0,
- COMPOSITION_CLIENT = 1,
- COMPOSITION_DEVICE = 2,
- COMPOSITION_SOLID_COLOR = 3,
- COMPOSITION_CURSOR = 4,
- COMPOSITION_SIDEBAND = 5,
+enum DvrHwcComposition {
+ DVR_HWC_COMPOSITION_INVALID = 0,
+ DVR_HWC_COMPOSITION_CLIENT = 1,
+ DVR_HWC_COMPOSITION_DEVICE = 2,
+ DVR_HWC_COMPOSITION_SOLID_COLOR = 3,
+ DVR_HWC_COMPOSITION_CURSOR = 4,
+ DVR_HWC_COMPOSITION_SIDEBAND = 5,
};
-typedef uint64_t Display;
-typedef uint64_t Layer;
+typedef uint64_t DvrHwcDisplay;
+typedef uint64_t DvrHwcLayer;
-struct Recti {
+struct DvrHwcRecti {
int32_t left;
int32_t top;
int32_t right;
int32_t bottom;
};
-struct Rectf {
+struct DvrHwcRectf {
float left;
float top;
float right;
diff --git a/libs/vr/libdvr/include/dvr/dvr_surface.h b/libs/vr/libdvr/include/dvr/dvr_surface.h
index 2712f24..e5228d6 100644
--- a/libs/vr/libdvr/include/dvr/dvr_surface.h
+++ b/libs/vr/libdvr/include/dvr/dvr_surface.h
@@ -12,7 +12,7 @@
typedef struct DvrSurfaceParameter DvrSurfaceParameter;
// Get a pointer to the global pose buffer.
-int dvrGetPoseBuffer(DvrReadBuffer** pose_buffer);
+int dvrGetNamedBuffer(const char* name, DvrBuffer** out_buffer);
int dvrSurfaceCreate(int width, int height, int format, uint64_t usage0,
uint64_t usage1, int flags, DvrSurface** out_surface);
diff --git a/libs/vr/libdvr/tests/Android.mk b/libs/vr/libdvr/tests/Android.mk
index 75e2a7d..29cdc13 100644
--- a/libs/vr/libdvr/tests/Android.mk
+++ b/libs/vr/libdvr/tests/Android.mk
@@ -17,14 +17,18 @@
libbufferhub \
libchrome \
libdvrcommon \
+ libdisplay \
libpdx_default_transport \
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dvr_buffer_queue-test.cpp
+LOCAL_SRC_FILES := \
+ dvr_buffer_queue-test.cpp \
+ dvr_named_buffer-test.cpp \
+
LOCAL_STATIC_LIBRARIES := $(static_libraries)
LOCAL_SHARED_LIBRARIES := $(shared_libraries)
LOCAL_EXPORT_C_INCLUDE_DIRS := ${LOCAL_C_INCLUDES}
-LOCAL_CFLAGS := -DLOG_TAG=\"dvr_buffer_queue-test\" -DTRACE=0 -O0 -g
-LOCAL_MODULE := dvr_buffer_queue-test
+LOCAL_CFLAGS := -DLOG_TAG=\"dvr_api-test\" -DTRACE=0 -O0 -g
+LOCAL_MODULE := dvr_api-test
LOCAL_MODULE_TAGS := optional
include $(BUILD_NATIVE_TEST)
diff --git a/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
new file mode 100644
index 0000000..cd3285f
--- /dev/null
+++ b/libs/vr/libdvr/tests/dvr_named_buffer-test.cpp
@@ -0,0 +1,122 @@
+#include <android/hardware_buffer.h>
+#include <dvr/display_manager_client.h>
+#include <dvr/dvr_buffer.h>
+#include <dvr/dvr_surface.h>
+#include <system/graphics.h>
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace dvr {
+
+namespace {
+
+class DvrNamedBufferTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ client_ = dvrDisplayManagerClientCreate();
+ ASSERT_NE(nullptr, client_);
+ }
+
+ void TearDown() override {
+ if (client_ != nullptr) {
+ dvrDisplayManagerClientDestroy(client_);
+ client_ = nullptr;
+ }
+ }
+
+ DvrDisplayManagerClient* client_ = nullptr;
+};
+
+TEST_F(DvrNamedBufferTest, TestNamedBuffersSameName) {
+ const char* buffer_name = "same_name";
+ DvrBuffer* buffer1 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+ ASSERT_NE(nullptr, buffer1);
+
+ DvrBuffer* buffer2 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name, 10, 0, 0);
+ ASSERT_NE(nullptr, buffer2);
+
+ AHardwareBuffer* hardware_buffer1 = nullptr;
+ int e1 = dvrBufferGetAHardwareBuffer(buffer1, &hardware_buffer1);
+ ASSERT_EQ(0, e1);
+
+ AHardwareBuffer* hardware_buffer2 = nullptr;
+ int e2 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer2);
+ ASSERT_EQ(0, e2);
+ ASSERT_NE(nullptr, hardware_buffer1);
+
+ AHardwareBuffer_Desc desc1 = {};
+ AHardwareBuffer_describe(hardware_buffer1, &desc1);
+ AHardwareBuffer_Desc desc2 = {};
+ AHardwareBuffer_describe(hardware_buffer2, &desc2);
+ ASSERT_EQ(desc1.width, 10u);
+ ASSERT_EQ(desc1.height, 1u);
+ ASSERT_EQ(desc1.layers, 1u);
+ ASSERT_EQ(desc1.format, HAL_PIXEL_FORMAT_BLOB);
+ ASSERT_EQ(desc1.usage0, 0u);
+ ASSERT_EQ(desc1.usage1, 0u);
+ ASSERT_EQ(desc2.width, 10u);
+ ASSERT_EQ(desc2.height, 1u);
+ ASSERT_EQ(desc2.layers, 1u);
+ ASSERT_EQ(desc2.format, HAL_PIXEL_FORMAT_BLOB);
+ ASSERT_EQ(desc2.usage0, 0u);
+ ASSERT_EQ(desc2.usage1, 0u);
+
+ dvrBufferDestroy(buffer1);
+ dvrBufferDestroy(buffer2);
+
+ DvrBuffer* buffer3 = nullptr;
+ int e3 = dvrGetNamedBuffer(buffer_name, &buffer3);
+ ASSERT_NE(nullptr, buffer3);
+ ASSERT_EQ(0, e3);
+
+ AHardwareBuffer* hardware_buffer3 = nullptr;
+ int e4 = dvrBufferGetAHardwareBuffer(buffer2, &hardware_buffer3);
+ ASSERT_EQ(0, e4);
+ ASSERT_NE(nullptr, hardware_buffer3);
+
+ AHardwareBuffer_Desc desc3 = {};
+ AHardwareBuffer_describe(hardware_buffer3, &desc3);
+ ASSERT_EQ(desc3.width, 10u);
+ ASSERT_EQ(desc3.height, 1u);
+ ASSERT_EQ(desc3.layers, 1u);
+ ASSERT_EQ(desc3.format, HAL_PIXEL_FORMAT_BLOB);
+ ASSERT_EQ(desc3.usage0, 0u);
+ ASSERT_EQ(desc3.usage1, 0u);
+
+ dvrBufferDestroy(buffer3);
+}
+
+TEST_F(DvrNamedBufferTest, TestMultipleNamedBuffers) {
+ const char* buffer_name1 = "test1";
+ const char* buffer_name2 = "test2";
+ DvrBuffer* setup_buffer1 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name1, 10, 0, 0);
+ ASSERT_NE(nullptr, setup_buffer1);
+ dvrBufferDestroy(setup_buffer1);
+
+ DvrBuffer* setup_buffer2 =
+ dvrDisplayManagerSetupNamedBuffer(client_, buffer_name2, 10, 0, 0);
+ ASSERT_NE(nullptr, setup_buffer2);
+ dvrBufferDestroy(setup_buffer2);
+
+ DvrBuffer* buffer1 = nullptr;
+ int e1 = dvrGetNamedBuffer(buffer_name1, &buffer1);
+ ASSERT_NE(nullptr, buffer1);
+ ASSERT_EQ(0, e1);
+ dvrBufferDestroy(buffer1);
+
+ DvrBuffer* buffer2 = nullptr;
+ int e2 = dvrGetNamedBuffer(buffer_name2, &buffer2);
+ ASSERT_NE(nullptr, buffer2);
+ ASSERT_EQ(0, e2);
+ dvrBufferDestroy(buffer2);
+}
+
+} // namespace
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libeds/Android.bp b/libs/vr/libeds/Android.bp
index 187cbbf..85e43cc 100644
--- a/libs/vr/libeds/Android.bp
+++ b/libs/vr/libeds/Android.bp
@@ -16,11 +16,9 @@
"eds.cpp",
"eds_mesh.cpp",
"composite_hmd.cpp",
- "cpu_thread_pose_updater.cpp",
"display_metrics.cpp",
"distortion_renderer.cpp",
- "lucid_metrics.cpp",
- "lucid_pose_tracker.cpp",
+ "device_metrics.cpp",
"lookup_radial_distortion.cpp",
"polynomial_radial_distortion.cpp",
]
diff --git a/libs/vr/libeds/cpu_thread_pose_updater.cpp b/libs/vr/libeds/cpu_thread_pose_updater.cpp
deleted file mode 100644
index 5b8a734..0000000
--- a/libs/vr/libeds/cpu_thread_pose_updater.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "include/private/dvr/cpu_thread_pose_updater.h"
-
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#define ATRACE_TAG ATRACE_TAG_INPUT
-#include <utils/Trace.h>
-
-#include <private/dvr/clock_ns.h>
-#include <private/dvr/debug.h>
-
-namespace android {
-namespace dvr {
-
-CpuThreadPoseUpdater::CpuThreadPoseUpdater()
- : stop_request_(false), update_period_us_(0), count_(0) {}
-
-CpuThreadPoseUpdater::~CpuThreadPoseUpdater() { StopAndJoin(); }
-
-void CpuThreadPoseUpdater::Start(volatile RawPosePair* mapped_pose_buffer,
- int period_us) {
- mapped_pose_buffer_ = mapped_pose_buffer;
- update_period_us_ = period_us;
- stop_request_ = false;
-
- // First buffer is odd (starts at 1), second is even (starts at 2).
- count_ = 0;
- mapped_pose_buffer_->pose1.Reset(++count_);
- mapped_pose_buffer_->pose2.Reset(++count_);
-
- update_thread_ = std::thread(&CpuThreadPoseUpdater::UpdateThread, this);
-}
-
-void CpuThreadPoseUpdater::StopAndJoin() {
- stop_request_ = true;
- if (update_thread_.joinable()) {
- update_thread_.join();
- }
-}
-
-void CpuThreadPoseUpdater::UpdateThread() {
- prctl(PR_SET_NAME, reinterpret_cast<intptr_t>("CpuPoseUpdater"),
- 0, 0, 0);
-
- ATRACE_NAME(__PRETTY_FUNCTION__);
- for (;;) {
- if (stop_request_) {
- break;
- }
-
- ++count_;
-
- // Choose the writable pose based on whether count is odd or even.
- volatile RawPose* out_pose = nullptr;
- if (count_ & 1) {
- out_pose = &mapped_pose_buffer_->pose1;
- } else {
- out_pose = &mapped_pose_buffer_->pose2;
- }
-
- {
- ATRACE_NAME("GetPose");
- Posef pose = pose_tracker_.GetPose(GetSystemClockNs());
- out_pose->qx = pose.GetRotation().x();
- out_pose->qy = pose.GetRotation().y();
- out_pose->qz = pose.GetRotation().z();
- out_pose->qw = pose.GetRotation().w();
- out_pose->px = pose.GetPosition()[0];
- out_pose->py = pose.GetPosition()[1];
- out_pose->pz = pose.GetPosition()[2];
- // Atomically store the count so that it hits memory last:
- out_pose->count.store(count_, std::memory_order_release);
- }
-
- // Sleep to simulate the IMU update process.
- usleep(update_period_us_);
- // TODO(jbates) sleep_for returns immediately, we need to fix our toolchain!
- // int64_t c1 = GetSystemClockNs();
- // std::this_thread::sleep_for(std::chrono::milliseconds(10));
- // int64_t c2 = GetSystemClockNs();
- // fprintf(stderr, "%lld us\n", (long long)(c2 - c1) / 1000);
- }
-}
-
-} // namesapce dvr
-} // namesapce android
diff --git a/libs/vr/libeds/device_metrics.cpp b/libs/vr/libeds/device_metrics.cpp
new file mode 100644
index 0000000..50c3e54
--- /dev/null
+++ b/libs/vr/libeds/device_metrics.cpp
@@ -0,0 +1,182 @@
+#include <private/dvr/device_metrics.h>
+
+#include <cutils/properties.h>
+#include <private/dvr/head_mount_metrics.h>
+#include <private/dvr/identity_distortion.h>
+#include <private/dvr/lookup_radial_distortion.h>
+#include <private/dvr/polynomial_radial_distortion.h>
+#include <private/dvr/types.h>
+#include "include/private/dvr/display_metrics.h"
+
+namespace {
+
+static constexpr char kRGBPolynomialOffset[] = "persist.dvr.rgb_poly_offset";
+static constexpr char kRPolynomial[] = "persist.dvr.r_poly";
+static constexpr char kGPolynomial[] = "persist.dvr.g_poly";
+static constexpr char kBPolynomial[] = "persist.dvr.b_poly";
+static constexpr char kLensDistance[] = "persist.dvr.lens_distance";
+static constexpr char kDisplayGap[] = "persist.dvr.display_gap";
+static constexpr char kVEyeToDisplay[] = "persist.dvr.v_eye_to_display";
+static constexpr char kFovIOBT[] = "persist.dvr.fov_iobt";
+static constexpr char kScreenSize[] = "persist.dvr.screen_size";
+
+bool StringToFloat(const char* str, float* result) {
+ char* endptr = nullptr;
+ *result = std::strtof(str, &endptr);
+ return !(str == endptr || !endptr);
+}
+
+std::vector<std::string> SplitString(const std::string& string_to_split,
+ char deliminator) {
+ std::vector<std::string> result;
+ std::string sub_string;
+ std::stringstream ss(string_to_split);
+ while (std::getline(ss, sub_string, deliminator))
+ result.push_back(sub_string);
+ return result;
+}
+
+std::vector<float> GetProperty(const char* name,
+ const std::vector<float>& default_values) {
+ char prop[PROPERTY_VALUE_MAX + 1] = {};
+ property_get(name, prop, "");
+ std::vector<std::string> values = SplitString(prop, ',');
+ std::vector<float> results;
+ for (const auto& value : values) {
+ float result = 0.0f;
+ if (StringToFloat(value.c_str(), &result)) {
+ results.push_back(static_cast<float>(result));
+ }
+ }
+ if (results.empty()) {
+ return default_values;
+ }
+ return results;
+}
+
+float GetProperty(const char* name, float default_value) {
+ char prop[PROPERTY_VALUE_MAX + 1] = {};
+ property_get(name, prop, "");
+ float result = 0.0f;
+ if (StringToFloat(prop, &result)) {
+ return static_cast<float>(result);
+ }
+ return default_value;
+}
+
+float GetInterLensDistance() { return GetProperty(kLensDistance, 0.064f); }
+
+float GetDisplayGap() { return GetProperty(kDisplayGap, 0.0f); }
+
+float GetVEyeToDisplay() { return GetProperty(kVEyeToDisplay, 0.035f); }
+
+android::dvr::vec2 GetDisplaySize() {
+ static const std::vector<float> default_size = {0.0742177f, 0.131943f};
+ std::vector<float> sizes = GetProperty(kScreenSize, default_size);
+ if (sizes.size() != 0)
+ sizes = default_size;
+ return android::dvr::vec2(sizes[0], sizes[1]);
+}
+
+std::vector<float> GetMaxFOVs() {
+ static const std::vector<float> defaults = {43.7f, 47.8f, 54.2f, 54.2f};
+ std::vector<float> fovs = GetProperty(kFovIOBT, defaults);
+ if (fovs.size() != 4)
+ fovs = defaults;
+ for (auto& value : fovs) {
+ value = value * M_PI / 180.0f;
+ }
+ return fovs;
+}
+
+static const android::dvr::HeadMountMetrics::VerticalAlignment
+ kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter;
+
+// Default border size in meters.
+static const float kScreenBorderSize = 0.004f;
+
+// Refresh rate.
+static const float kScreenRefreshRate = 60.0f;
+
+// Default display orientation is portrait.
+static const android::dvr::DisplayOrientation kDisplayOrientation =
+ android::dvr::DisplayOrientation::kPortrait;
+
+} // anonymous namespace
+
+namespace android {
+namespace dvr {
+
+HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
+ const FieldOfView& r_fov) {
+ static const std::vector<float> default_r = {
+ -4.08519004f, 34.70282075f, -67.37781249f, 56.97304235f,
+ -23.35768685f, 4.7199597f, 0.63198082f};
+ static const std::vector<float> default_g = {
+ 4.43078318f, 3.47806617f, -20.58017398f, 20.85880414f,
+ -8.4046504f, 1.61284685f, 0.8881761f};
+ static const std::vector<float> default_b = {
+ 12.04141265f, -21.98112491f, 14.06758389f, -3.15245629f,
+ 0.36549102f, 0.05252705f, 0.99844279f};
+ static const std::vector<float> default_offsets = {
+ 0.20971645238f, 0.15189450000f, 1.00096958278f};
+
+ std::vector<float> poly_offsets =
+ GetProperty(kRGBPolynomialOffset, default_offsets);
+ std::vector<float> poly_r = GetProperty(kRPolynomial, default_r);
+ std::vector<float> poly_g = GetProperty(kGPolynomial, default_g);
+ std::vector<float> poly_b = GetProperty(kBPolynomial, default_b);
+ if (poly_offsets.size() != 3)
+ poly_offsets = default_offsets;
+
+ std::shared_ptr<ColorChannelDistortion> distortion_r(
+ new PolynomialRadialDistortion(poly_offsets[0], poly_r));
+ std::shared_ptr<ColorChannelDistortion> distortion_g(
+ new PolynomialRadialDistortion(poly_offsets[1], poly_g));
+ std::shared_ptr<ColorChannelDistortion> distortion_b(
+ new PolynomialRadialDistortion(poly_offsets[2], poly_b));
+
+ return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
+ GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
+ r_fov, distortion_r, distortion_g, distortion_b,
+ HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+ HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+ (GetInterLensDistance() - GetDisplayGap()) / 2.0f);
+}
+
+HeadMountMetrics CreateHeadMountMetrics() {
+ std::vector<float> fovs = GetMaxFOVs();
+ FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
+ FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
+ return CreateHeadMountMetrics(l_fov, r_fov);
+}
+
+DisplayMetrics CreateDisplayMetrics(vec2i screen_size) {
+ android::dvr::vec2 size_in_meters = GetDisplaySize();
+ vec2 meters_per_pixel(size_in_meters[0] / static_cast<float>(screen_size[0]),
+ size_in_meters[1] / static_cast<float>(screen_size[1]));
+ return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize,
+ 1000.0f / kScreenRefreshRate, kDisplayOrientation);
+}
+
+HeadMountMetrics CreateUndistortedHeadMountMetrics() {
+ std::vector<float> fovs = GetMaxFOVs();
+ FieldOfView l_fov(fovs[1], fovs[0], fovs[2], fovs[3]);
+ FieldOfView r_fov(fovs[0], fovs[1], fovs[2], fovs[3]);
+ return CreateUndistortedHeadMountMetrics(l_fov, r_fov);
+}
+
+HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov,
+ const FieldOfView& r_fov) {
+ auto distortion_all = std::make_shared<IdentityDistortion>();
+
+ return HeadMountMetrics(GetInterLensDistance(), GetVEyeToDisplay(),
+ GetVEyeToDisplay(), kDefaultVerticalAlignment, l_fov,
+ r_fov, distortion_all, distortion_all, distortion_all,
+ HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+ HeadMountMetrics::EyeOrientation::kCCW0Degrees,
+ (GetInterLensDistance() - GetDisplayGap()) / 2.0f);
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libeds/include/private/dvr/cpu_thread_pose_updater.h b/libs/vr/libeds/include/private/dvr/cpu_thread_pose_updater.h
deleted file mode 100644
index 6a2c8a6..0000000
--- a/libs/vr/libeds/include/private/dvr/cpu_thread_pose_updater.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef ANDROID_DVR_CPU_THREAD_POSE_UPDATER_H_
-#define ANDROID_DVR_CPU_THREAD_POSE_UPDATER_H_
-
-#include <atomic>
-#include <thread>
-
-#include <private/dvr/lucid_pose_tracker.h>
-#include <private/dvr/raw_pose.h>
-
-namespace android {
-namespace dvr {
-
-// Temporary version of pose updater that uses a CPU thread to update
-// the pose buffer. Note that this thread starts and runs indefinitely
-class CpuThreadPoseUpdater {
- public:
- CpuThreadPoseUpdater();
- ~CpuThreadPoseUpdater();
-
- // Start the thread to update the given buffer with the given number of
- // microseconds between updates.
- void Start(volatile RawPosePair* mapped_pose_buffer, int period_us);
-
- void StopAndJoin();
-
- private:
- void UpdateThread();
-
- volatile RawPosePair* mapped_pose_buffer_;
-
- // Pose update thread.
- std::thread update_thread_;
-
- volatile bool stop_request_;
-
- // Update period in microseconds.
- int update_period_us_;
-
- // Current pose count, used to avoid writing to the same buffer that is being
- // read by the GPU.
- uint32_t count_;
- LucidPoseTracker pose_tracker_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_CPU_THREAD_POSE_UPDATER_H_
diff --git a/libs/vr/libeds/include/private/dvr/lucid_metrics.h b/libs/vr/libeds/include/private/dvr/device_metrics.h
similarity index 84%
rename from libs/vr/libeds/include/private/dvr/lucid_metrics.h
rename to libs/vr/libeds/include/private/dvr/device_metrics.h
index 0e4ada4..7985f28 100644
--- a/libs/vr/libeds/include/private/dvr/lucid_metrics.h
+++ b/libs/vr/libeds/include/private/dvr/device_metrics.h
@@ -1,5 +1,5 @@
-#ifndef ANDROID_DVR_LUCID_METRICS_H_
-#define ANDROID_DVR_LUCID_METRICS_H_
+#ifndef ANDROID_DVR_DEVICE_METRICS_H_
+#define ANDROID_DVR_DEVICE_METRICS_H_
#include <private/dvr/display_metrics.h>
#include <private/dvr/head_mount_metrics.h>
@@ -19,4 +19,4 @@
} // namespace dvr
} // namespace android
-#endif // ANDROID_DVR_LUCID_METRICS_H_
+#endif // ANDROID_DVR_DEVICE_METRICS_H_
diff --git a/libs/vr/libeds/include/private/dvr/distortion_renderer.h b/libs/vr/libeds/include/private/dvr/distortion_renderer.h
index e1c8114..28fd48a 100644
--- a/libs/vr/libeds/include/private/dvr/distortion_renderer.h
+++ b/libs/vr/libeds/include/private/dvr/distortion_renderer.h
@@ -9,7 +9,6 @@
#include <private/dvr/eds_mesh.h>
#include <private/dvr/graphics/shader_program.h>
#include <private/dvr/late_latch.h>
-#include <private/dvr/lucid_pose_tracker.h>
#include <private/dvr/render_texture_params.h>
#include <private/dvr/types.h>
diff --git a/libs/vr/libeds/include/private/dvr/lucid_pose_tracker.h b/libs/vr/libeds/include/private/dvr/lucid_pose_tracker.h
deleted file mode 100644
index 4ceda5a..0000000
--- a/libs/vr/libeds/include/private/dvr/lucid_pose_tracker.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef ANDROID_DVR_LUCID_POSE_TRACKER_H_
-#define ANDROID_DVR_LUCID_POSE_TRACKER_H_
-
-#include <memory>
-
-#include <dvr/pose_client.h>
-
-#include <private/dvr/types.h>
-
-namespace android {
-namespace dvr {
-
-// Provides pose tracking via the system pose service.
-class LucidPoseTracker {
- public:
- // When set, the pose service is ignored and the given pose is always returned
- // by GetPose. As long as this is called before any LucidPoseTracker is
- // used, the pose service will not be created.
- // Threading: this is not thread safe.
- static void SetPoseOverride(const Posef& pose);
-
- // Reset prior override pose.
- static void ClearPoseOverride();
-
- LucidPoseTracker();
- ~LucidPoseTracker();
-
- // Currently GetPose() will ignore timestamp_ns and always return the most
- // recent orientation.
- // TODO(stefanus): support prediction.
- Posef GetPose(uint64_t timestamp_ns);
-
- private:
- static bool is_override_pose_;
- static Posef override_pose_;
-
- DvrPose* pose_client_;
-
- // The most recent pose.
- Posef latest_pose_;
-
- // The time stamp corresponding to when latest_pose_ was last updated.
- uint64_t latest_timestamp_ns_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_LUCID_POSE_TRACKER_H_
diff --git a/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h b/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
index 8f080aa..c1f1ce9 100644
--- a/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
+++ b/libs/vr/libeds/include/private/dvr/polynomial_radial_distortion.h
@@ -28,7 +28,8 @@
// in the distortion equation: coefficients[0] is K1, coefficients[1] is K2,
// etc. Thus the polynomial used for distortion has degree
// (2 * coefficients.size()).
- explicit PolynomialRadialDistortion(const std::vector<float>& coefficients);
+ explicit PolynomialRadialDistortion(float polynomial_offset,
+ const std::vector<float>& coefficients);
// Given a radius (measuring distance from the optical axis of the lens),
// returns the distortion factor for that radius.
@@ -51,6 +52,10 @@
const std::vector<float>& GetCoefficients() const;
private:
+ // This is makes the polynomial work nicer with a specific lens that doesn't
+ // fit nicely to a lower order polynomial. It's basically piecewise
+ // line->poly.
+ float polynomial_offset_;
std::vector<float> coefficients_;
};
diff --git a/libs/vr/libeds/lucid_metrics.cpp b/libs/vr/libeds/lucid_metrics.cpp
deleted file mode 100644
index 690c326..0000000
--- a/libs/vr/libeds/lucid_metrics.cpp
+++ /dev/null
@@ -1,327 +0,0 @@
-#include "include/private/dvr/display_metrics.h"
-#include <private/dvr/head_mount_metrics.h>
-#include <private/dvr/identity_distortion.h>
-#include <private/dvr/lookup_radial_distortion.h>
-#include <private/dvr/lucid_metrics.h>
-#include <private/dvr/types.h>
-
-namespace {
-
-// These numbers are specific to the OnePlus One and therefore
-// temporary until we advance to the next Lucid development platform.
-
-// Head mount metrics for Lucid A00
-static const float kDefaultInterLensDistance = 0.064f; // 64mm
-static const float kDefaultTrayToLensDistance = 0.035f;
-static const float kDefaultVirtualEyeToScreenDistance = 0.042f;
-static const android::dvr::HeadMountMetrics::VerticalAlignment
- kDefaultVerticalAlignment = android::dvr::HeadMountMetrics::kCenter;
-static const float kDefaultFovHalfAngleInsideH = 43.7f * M_PI / 180.0f;
-static const float kDefaultFovHalfAngleOutsideH = 47.8f * M_PI / 180.0f;
-static const float kDefaultFovHalfAngleV = 54.2f * M_PI / 180.0f;
-
-// Screen size in meters for Lucid (Nexus 6 display in portrait mode).
-static const android::dvr::vec2 kScreenSizeInMeters(0.0742177f, 0.131943f);
-
-// Border size in meters for the OnePlus One.
-static const float kScreenBorderSize = 0.004f;
-
-// Refresh rate.
-static const float kScreenRefreshRate = 60.0f;
-
-// Lucid display orientation is portrait.
-static const android::dvr::DisplayOrientation kDisplayOrientation =
- android::dvr::DisplayOrientation::kPortrait;
-
-} // anonymous namespace
-
-namespace android {
-namespace dvr {
-
-// The distortion lookup tables were generated via a raytraced lens simulation.
-// Please see for full calculations:
-// https://docs.google.com/a/google.com/spreadsheets/d/
-// 15cfHmCw5mHVOQ1rAJxMhta4q0e8zzcUDka1nRkfl7pY/edit?usp=sharing
-LookupRadialDistortion* GetBlueDistortionLookup() {
- // clang-format off
- vec2 kBlueDistortionLookup[] = {
- {0.00000000000f, 1.00000000000f},
- {0.01888626190f, 1.00096958278f},
- {0.03777223810f, 1.00133301793f},
- {0.05665761905f, 1.00193985168f},
- {0.07554214286f, 1.00279048731f},
- {0.09442542857f, 1.00388751781f},
- {0.11330704762f, 1.00523363045f},
- {0.13218657143f, 1.00683149424f},
- {0.15106340476f, 1.00868516849f},
- {0.16993695238f, 1.01079861126f},
- {0.18880640476f, 1.01317712726f},
- {0.20767092857f, 1.01582607321f},
- {0.22652945238f, 1.01875203063f},
- {0.24538078571f, 1.02196207850f},
- {0.26422352381f, 1.02546421601f},
- {0.28305602381f, 1.02926737969f},
- {0.30187640476f, 1.03338139216f},
- {0.32068252381f, 1.03781702504f},
- {0.33947190476f, 1.04258620905f},
- {0.35824171429f, 1.04770206653f},
- {0.37698869048f, 1.05317909331f},
- {0.39570916667f, 1.05903306635f},
- {0.41439900000f, 1.06528124790f},
- {0.43305350000f, 1.07194257391f},
- {0.45166738095f, 1.07903777957f},
- {0.47023471429f, 1.08658953759f},
- {0.48874897619f, 1.09462239798f},
- {0.50720285714f, 1.10316330018f},
- {0.52558835714f, 1.11224144183f},
- {0.54389669048f, 1.12188861421f},
- {0.56211826190f, 1.13213939967f},
- {0.58024261905f, 1.14303145047f},
- {0.59825847619f, 1.15460566091f},
- {0.61615335714f, 1.16690711338f},
- {0.63391345238f, 1.17998560444f},
- {0.65152300000f, 1.19389708987f},
- {0.66896328571f, 1.20870580446f},
- {0.68621100000f, 1.22448751087f},
- {0.70323578571f, 1.24133415620f},
- {0.71999716667f, 1.25935962776f},
- {0.73643969048f, 1.27870875648f},
- {0.75250778571f, 1.29953256670f},
- {0.76817614286f, 1.32193822000f},
- {0.78342009524f, 1.34604270338f},
- {0.79828314286f, 1.37185833833f},
- {0.81267376190f, 1.39964322604f},
- {0.82656559524f, 1.42955958262f},
- {0.83983054762f, 1.46196539657f},
- {0.85234333333f, 1.49724142650f},
- {0.86394971429f, 1.53585530271f},
- {0.87422461905f, 1.57881139444f},
- {0.88382583095f, 1.62091537826f},
- {0.89571361286f, 1.67610209261f},
- {0.90490389167f, 1.72118819668f},
- {0.91526452143f, 1.77496904481f},
- {0.92651365452f, 1.83722833673f},
- {0.93437489976f, 1.88337590145f},
- {0.94654105500f, 1.95937892848f},
- {0.95476685095f, 2.01469745492f},
- {0.96720383310f, 2.10451495481f},
- {0.97546726405f, 2.16904926656f},
- {0.98774046786f, 2.27302748020f},
- {0.99579206762f, 2.34720582421f},
- {1.00763328857f, 2.46603526105f},
- {1.01533118405f, 2.55049232288f},
- {1.02287120929f, 2.63936582235f}
- };
- // clang-format on
- return new LookupRadialDistortion(
- kBlueDistortionLookup, sizeof(kBlueDistortionLookup) / sizeof(vec2));
-}
-
-LookupRadialDistortion* GetGreenDistortionLookup() {
- // clang-format off
- vec2 kGreenDistortionLookup[] = {
- {0.00000000000f, 1.00000000000f},
- {0.01898883333f, 1.00000000000f},
- {0.03797750000f, 1.00000000000f},
- {0.05696585714f, 1.00000000000f},
- {0.07595369048f, 1.00000000000f},
- {0.09494078571f, 1.00000000000f},
- {0.11392685714f, 1.00000000000f},
- {0.13291157143f, 1.00000000000f},
- {0.15189450000f, 1.00176560670f},
- {0.17087511905f, 1.00384553961f},
- {0.18985280952f, 1.00618614484f},
- {0.20882680952f, 1.00879302066f},
- {0.22779623810f, 1.01167234096f},
- {0.24675997619f, 1.01483135203f},
- {0.26571680952f, 1.01827767641f},
- {0.28466519048f, 1.02202026825f},
- {0.30360342857f, 1.02606859705f},
- {0.32252950000f, 1.03043334057f},
- {0.34144104762f, 1.03512630376f},
- {0.36033538095f, 1.04016038545f},
- {0.37920942857f, 1.04554970984f},
- {0.39805966667f, 1.05130981266f},
- {0.41688209524f, 1.05745768999f},
- {0.43567214286f, 1.06401204155f},
- {0.45442473810f, 1.07099310305f},
- {0.47313411905f, 1.07842314596f},
- {0.49179388095f, 1.08632639514f},
- {0.51039692857f, 1.09472920992f},
- {0.52893538095f, 1.10366038032f},
- {0.54740061905f, 1.11315113705f},
- {0.56578326190f, 1.12323535769f},
- {0.58407300000f, 1.13395008040f},
- {0.60225871429f, 1.14533547370f},
- {0.62032809524f, 1.15743581542f},
- {0.63826750000f, 1.17030000749f},
- {0.65606135714f, 1.18398295206f},
- {0.67369107143f, 1.19854780583f},
- {0.69113350000f, 1.21406895255f},
- {0.70835842857f, 1.23063670464f},
- {0.72532545238f, 1.24836302903f},
- {0.74197478571f, 1.26739777609f},
- {0.75822164286f, 1.28793886907f},
- {0.77407361905f, 1.31003521318f},
- {0.78948523810f, 1.33383710115f},
- {0.80448471429f, 1.35938255065f},
- {0.81901733333f, 1.38686361242f},
- {0.83305214286f, 1.41644808409f},
- {0.84646438095f, 1.44848277406f},
- {0.85912733333f, 1.48334485259f},
- {0.87088369048f, 1.52149970074f},
- {0.88131250000f, 1.56392750036f},
- {0.89105132929f, 1.60552684742f},
- {0.90312479476f, 1.66002695068f},
- {0.91244067452f, 1.70458805205f},
- {0.92297971714f, 1.75767475825f},
- {0.93440940905f, 1.81916050294f},
- {0.94237194976f, 1.86478635937f},
- {0.95471202405f, 1.93989738862f},
- {0.96305355738f, 1.99457325750f},
- {0.97567372071f, 2.08333293385f},
- {0.98407229071f, 2.14708073108f},
- {0.99653762071f, 2.24981649552f},
- {1.00471276167f, 2.32311751786f},
- {1.01672394000f, 2.44057411530f},
- {1.02452363381f, 2.52407947994f},
- {1.03216732667f, 2.61194301580f}
- };
- // clang-format on
- return new LookupRadialDistortion(
- kGreenDistortionLookup, sizeof(kGreenDistortionLookup) / sizeof(vec2));
-}
-
-LookupRadialDistortion* GetRedDistortionLookup() {
- // clang-format off
- vec2 kRedDistortionLookup[] = {
- {0.00000000000f, 1.00000000000f},
- {0.01906776190f, 1.00000000000f},
- {0.03813547619f, 1.00000000000f},
- {0.05720304762f, 1.00000000000f},
- {0.07627040476f, 1.00000000000f},
- {0.09533740476f, 1.00000000000f},
- {0.11440385714f, 1.00000000000f},
- {0.13346952381f, 1.00000000000f},
- {0.15253409524f, 1.00000000000f},
- {0.17159714286f, 1.00000000000f},
- {0.19065814286f, 1.00053530030f},
- {0.20971645238f, 1.00310924426f},
- {0.22877123810f, 1.00595236192f},
- {0.24782154762f, 1.00907150786f},
- {0.26686623810f, 1.01247435420f},
- {0.28590388095f, 1.01616968529f},
- {0.30493288095f, 1.02016688932f},
- {0.32395133333f, 1.02447646681f},
- {0.34295697619f, 1.02911011406f},
- {0.36194726190f, 1.03408046560f},
- {0.38091921429f, 1.03940151599f},
- {0.39986942857f, 1.04508858434f},
- {0.41879402381f, 1.05115843585f},
- {0.43768857143f, 1.05762946333f},
- {0.45654809524f, 1.06452169646f},
- {0.47536695238f, 1.07185711363f},
- {0.49413888095f, 1.07965956927f},
- {0.51285690476f, 1.08795508025f},
- {0.53151326190f, 1.09677206014f},
- {0.55009952381f, 1.10614118417f},
- {0.56860633333f, 1.11609607621f},
- {0.58702361905f, 1.12667304464f},
- {0.60534028571f, 1.13791190276f},
- {0.62354421429f, 1.14985618930f},
- {0.64162188095f, 1.16255413653f},
- {0.65955780952f, 1.17605992962f},
- {0.67733352381f, 1.19043584317f},
- {0.69492602381f, 1.20575517508f},
- {0.71230514286f, 1.22210708787f},
- {0.72943057143f, 1.23960199799f},
- {0.74623921429f, 1.25839340501f},
- {0.76262400000f, 1.27871385661f},
- {0.77861754762f, 1.30056919119f},
- {0.79415866667f, 1.32413401001f},
- {0.80926385714f, 1.34946540639f},
- {0.82390640476f, 1.37670655635f},
- {0.83805190476f, 1.40602920817f},
- {0.85157807143f, 1.43777181543f},
- {0.86435700000f, 1.47230885729f},
- {0.87622914286f, 1.51010361811f},
- {0.88677650000f, 1.55211817236f},
- {0.89663317738f, 1.59330127207f},
- {0.90883197952f, 1.64729627820f},
- {0.91827594357f, 1.69138814689f},
- {0.92892199405f, 1.74398939784f},
- {0.94047261548f, 1.80490554711f},
- {0.94852659262f, 1.85009630648f},
- {0.96099790167f, 1.92451421938f},
- {0.96945317500f, 1.97863645920f},
- {0.98221554286f, 2.06656418112f},
- {0.99069599476f, 2.12974390154f},
- {1.00331392976f, 2.23149730290f},
- {1.01157138762f, 2.30414058939f},
- {1.02372409452f, 2.42049694265f},
- {1.03162992905f, 2.50318810924f},
- {1.03934762000f, 2.59027212626f}
- };
- // clang-format on
- return new LookupRadialDistortion(
- kRedDistortionLookup, sizeof(kRedDistortionLookup) / sizeof(vec2));
-}
-
-HeadMountMetrics CreateHeadMountMetrics(const FieldOfView& l_fov,
- const FieldOfView& r_fov) {
- std::shared_ptr<ColorChannelDistortion> default_distortion_r(
- GetRedDistortionLookup());
- std::shared_ptr<ColorChannelDistortion> default_distortion_g(
- GetGreenDistortionLookup());
- std::shared_ptr<ColorChannelDistortion> default_distortion_b(
- GetBlueDistortionLookup());
-
- return HeadMountMetrics(
- kDefaultInterLensDistance, kDefaultTrayToLensDistance,
- kDefaultVirtualEyeToScreenDistance, kDefaultVerticalAlignment, l_fov,
- r_fov, default_distortion_r, default_distortion_g, default_distortion_b,
- HeadMountMetrics::EyeOrientation::kCCW0Degrees,
- HeadMountMetrics::EyeOrientation::kCCW0Degrees,
- kDefaultInterLensDistance / 2.0f);
-}
-
-HeadMountMetrics CreateHeadMountMetrics() {
- FieldOfView l_fov(kDefaultFovHalfAngleOutsideH, kDefaultFovHalfAngleInsideH,
- kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
- FieldOfView r_fov(kDefaultFovHalfAngleInsideH, kDefaultFovHalfAngleOutsideH,
- kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
-
- return CreateHeadMountMetrics(l_fov, r_fov);
-}
-
-DisplayMetrics CreateDisplayMetrics(vec2i screen_size) {
- vec2 meters_per_pixel(
- kScreenSizeInMeters[0] / static_cast<float>(screen_size[0]),
- kScreenSizeInMeters[1] / static_cast<float>(screen_size[1]));
- return DisplayMetrics(screen_size, meters_per_pixel, kScreenBorderSize,
- 1000.0f / kScreenRefreshRate, kDisplayOrientation);
-}
-
-HeadMountMetrics CreateUndistortedHeadMountMetrics() {
- FieldOfView l_fov(kDefaultFovHalfAngleOutsideH, kDefaultFovHalfAngleInsideH,
- kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
- FieldOfView r_fov(kDefaultFovHalfAngleInsideH, kDefaultFovHalfAngleOutsideH,
- kDefaultFovHalfAngleV, kDefaultFovHalfAngleV);
- return CreateUndistortedHeadMountMetrics(l_fov, r_fov);
-}
-
-HeadMountMetrics CreateUndistortedHeadMountMetrics(const FieldOfView& l_fov,
- const FieldOfView& r_fov) {
- auto distortion_all = std::make_shared<IdentityDistortion>();
-
- return HeadMountMetrics(kDefaultInterLensDistance, kDefaultTrayToLensDistance,
- kDefaultVirtualEyeToScreenDistance,
- kDefaultVerticalAlignment, l_fov, r_fov,
- distortion_all, distortion_all, distortion_all,
- HeadMountMetrics::EyeOrientation::kCCW0Degrees,
- HeadMountMetrics::EyeOrientation::kCCW0Degrees,
- kDefaultInterLensDistance / 2.0f);
-}
-
-} // namespace dvr
-} // namespace dvr
diff --git a/libs/vr/libeds/lucid_pose_tracker.cpp b/libs/vr/libeds/lucid_pose_tracker.cpp
deleted file mode 100644
index 5247020..0000000
--- a/libs/vr/libeds/lucid_pose_tracker.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "include/private/dvr/lucid_pose_tracker.h"
-
-#define LOG_TAG "LucidPoseTracker"
-#include <log/log.h>
-
-#include <private/dvr/clock_ns.h>
-
-namespace android {
-namespace dvr {
-
-bool LucidPoseTracker::is_override_pose_ = false;
-Posef LucidPoseTracker::override_pose_ = Posef();
-
-void LucidPoseTracker::SetPoseOverride(const Posef& pose) {
- is_override_pose_ = true;
- override_pose_ = pose;
-}
-
-void LucidPoseTracker::ClearPoseOverride() {
- is_override_pose_ = false;
- override_pose_ = Posef();
-}
-
-LucidPoseTracker::LucidPoseTracker() : pose_client_(NULL) {}
-
-LucidPoseTracker::~LucidPoseTracker() {
- if (pose_client_) {
- dvrPoseDestroy(pose_client_);
- }
-}
-
-Posef LucidPoseTracker::GetPose(uint64_t timestamp_ns) {
- if (is_override_pose_) {
- return override_pose_;
- }
-
- if (!pose_client_) {
- pose_client_ = dvrPoseCreate();
-
- if (!pose_client_) {
- ALOGE("No pose service, returning identity pose");
- return Posef();
- }
- }
-
- DvrPoseState state;
- dvrPosePoll(pose_client_, &state);
-
- const vec4 head_rotation_in_start_quat(
- state.head_from_start_rotation.x, state.head_from_start_rotation.y,
- state.head_from_start_rotation.z, state.head_from_start_rotation.w);
-
- // When the pose service hasn't computed a pose yet, it returns a zero
- // quaternion; just use the identity rotation in that case.
- // TODO(stefanus): Find a better way to signal and check this.
- if (head_rotation_in_start_quat.squaredNorm() < 0.5f) {
- latest_pose_.SetRotation(quat::Identity());
- } else {
- latest_pose_.SetRotation(
- quat(head_rotation_in_start_quat.w(), head_rotation_in_start_quat.x(),
- head_rotation_in_start_quat.y(), head_rotation_in_start_quat.z())
- .normalized());
- }
-
- const vec3 head_position_in_start(state.head_from_start_translation.x,
- state.head_from_start_translation.y,
- state.head_from_start_translation.z);
- latest_pose_.SetPosition(head_position_in_start);
-
- latest_timestamp_ns_ = GetSystemClockNs();
-
- // PoseState pose_state;
- // pose_state.timestamp_ns = latest_timestamp_ns_;
- // pose_state.sensor_from_start_rotation =
- // ion::math::Rotationd::FromQuaternion(ion::math::Vector4d(
- // state.head_from_start_rotation.x, state.head_from_start_rotation.y,
- // state.head_from_start_rotation.z,
- // state.head_from_start_rotation.w));
- //// TODO(stefanus): Determine the first derivative of the rotation and set it
- //// here.
- // pose_state.sensor_from_start_rotation_velocity =
- // ion::math::Vector3d::Zero();
-
- // TODO(stefanus): perform prediction.
-
- return latest_pose_;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/libs/vr/libeds/polynomial_radial_distortion.cpp b/libs/vr/libeds/polynomial_radial_distortion.cpp
index fa01bb4..a0c6ea3 100644
--- a/libs/vr/libeds/polynomial_radial_distortion.cpp
+++ b/libs/vr/libeds/polynomial_radial_distortion.cpp
@@ -4,10 +4,13 @@
namespace dvr {
PolynomialRadialDistortion::PolynomialRadialDistortion(
- const std::vector<float>& coefficients)
- : coefficients_(coefficients) {}
+ float polynomial_offset, const std::vector<float>& coefficients)
+ : polynomial_offset_(polynomial_offset), coefficients_(coefficients) {}
float PolynomialRadialDistortion::DistortionFactor(float r_squared) const {
+ if (r_squared < polynomial_offset_)
+ return 1.0f;
+
float r_factor = 1.0f;
float distortion_factor = 1.0f;
diff --git a/libs/vr/libpdx_uds/client_channel_factory.cpp b/libs/vr/libpdx_uds/client_channel_factory.cpp
index 323236d..9202cd5 100644
--- a/libs/vr/libpdx_uds/client_channel_factory.cpp
+++ b/libs/vr/libpdx_uds/client_channel_factory.cpp
@@ -65,6 +65,7 @@
auto time_end = now + std::chrono::milliseconds{timeout_ms};
bool connected = false;
+ int max_eaccess = 5; // Max number of times to retry when EACCES returned.
while (!connected) {
int64_t timeout = -1;
if (use_timeout) {
@@ -84,10 +85,14 @@
if (ret == -1) {
ALOGD("ClientChannelFactory: Connect error %d: %s", errno,
strerror(errno));
- if (errno == ECONNREFUSED) {
- // Connection refused can be the result of connecting too early (the
- // service socket is created but not being listened to yet).
- ALOGD("ClientChannelFactory: Connection refused, waiting...");
+ // if |max_eaccess| below reaches zero when errno is EACCES, the control
+ // flows into the next "else if" statement and a permanent error is
+ // returned from this function.
+ if (errno == ECONNREFUSED || (errno == EACCES && max_eaccess-- > 0)) {
+ // Connection refused/Permission denied can be the result of connecting
+ // too early (the service socket is created but its access rights are
+ // not set or not being listened to yet).
+ ALOGD("ClientChannelFactory: %s, waiting...", strerror(errno));
using namespace std::literals::chrono_literals;
std::this_thread::sleep_for(100ms);
} else if (errno != ENOENT && errno != ENOTDIR) {
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index 0daab64..632978b 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -47,6 +47,7 @@
]
sharedLibraries = [
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.composer@2.1",
"libbinder",
@@ -75,7 +76,7 @@
cflags: [
"-DLOG_TAG=\"vr_flinger\"",
"-DTRACE=0",
- "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+ "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
"-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
],
diff --git a/libs/vr/libvrflinger/compositor.cpp b/libs/vr/libvrflinger/compositor.cpp
index 5a111d4..aa01f22 100644
--- a/libs/vr/libvrflinger/compositor.cpp
+++ b/libs/vr/libvrflinger/compositor.cpp
@@ -13,12 +13,12 @@
#include <private/dvr/buffer_hub_client.h>
#include <private/dvr/clock_ns.h>
#include <private/dvr/debug.h>
+#include <private/dvr/device_metrics.h>
#include <private/dvr/display_types.h>
#include <private/dvr/dummy_native_window.h>
#include <private/dvr/gl_fenced_flush.h>
#include <private/dvr/graphics/blur.h>
#include <private/dvr/graphics/gpu_profiler.h>
-#include <private/dvr/lucid_metrics.h>
#include <private/dvr/native_buffer.h>
#include <private/dvr/platform_defines.h>
#include <utils/Log.h>
diff --git a/libs/vr/libvrflinger/display_manager_service.cpp b/libs/vr/libvrflinger/display_manager_service.cpp
index 49b6f09..99f93bf 100644
--- a/libs/vr/libvrflinger/display_manager_service.cpp
+++ b/libs/vr/libvrflinger/display_manager_service.cpp
@@ -2,7 +2,9 @@
#include <pdx/channel_handle.h>
#include <pdx/default_transport/service_endpoint.h>
+#include <private/android_filesystem_config.h>
#include <private/dvr/display_rpc.h>
+#include <private/dvr/trusted_uids.h>
#include <sys/poll.h>
#include <array>
@@ -82,9 +84,9 @@
*this, &DisplayManagerService::OnUpdateSurfaces, message);
return {};
- case DisplayManagerRPC::SetupPoseBuffer::Opcode:
- DispatchRemoteMethod<DisplayManagerRPC::SetupPoseBuffer>(
- *this, &DisplayManagerService::OnSetupPoseBuffer, message);
+ case DisplayManagerRPC::SetupNamedBuffer::Opcode:
+ DispatchRemoteMethod<DisplayManagerRPC::SetupNamedBuffer>(
+ *this, &DisplayManagerService::OnSetupNamedBuffer, message);
return {};
default:
@@ -188,9 +190,20 @@
return 0;
}
-pdx::BorrowedChannelHandle DisplayManagerService::OnSetupPoseBuffer(
- pdx::Message& /*message*/, size_t extended_region_size, int usage) {
- return display_service_->SetupPoseBuffer(extended_region_size, usage);
+pdx::Status<BorrowedNativeBufferHandle>
+DisplayManagerService::OnSetupNamedBuffer(pdx::Message& message,
+ const std::string& name, size_t size,
+ uint64_t producer_usage,
+ uint64_t consumer_usage) {
+ if (message.GetEffectiveUserId() != AID_ROOT &&
+ !IsTrustedUid(message.GetEffectiveUserId())) {
+ // Only trusted users can setup named buffers.
+ ALOGE("DisplayService::SetupNamedBuffer: Called by untrusted user: uid=%d.",
+ message.GetEffectiveUserId());
+ return {};
+ }
+ return display_service_->SetupNamedBuffer(name, size, producer_usage,
+ consumer_usage);
}
void DisplayManagerService::OnDisplaySurfaceChange() {
diff --git a/libs/vr/libvrflinger/display_manager_service.h b/libs/vr/libvrflinger/display_manager_service.h
index 80324fd..7b037de 100644
--- a/libs/vr/libvrflinger/display_manager_service.h
+++ b/libs/vr/libvrflinger/display_manager_service.h
@@ -54,9 +54,9 @@
int OnUpdateSurfaces(pdx::Message& message,
const std::map<int, DisplaySurfaceAttributes>& updates);
- pdx::BorrowedChannelHandle OnSetupPoseBuffer(pdx::Message& message,
- size_t extended_region_size,
- int usage);
+ pdx::Status<BorrowedNativeBufferHandle> OnSetupNamedBuffer(
+ pdx::Message& message, const std::string& name, size_t size,
+ uint64_t producer_usage, uint64_t consumer_usage);
// Called by the display service to indicate changes to display surfaces that
// the display manager should evaluate.
diff --git a/libs/vr/libvrflinger/display_service.cpp b/libs/vr/libvrflinger/display_service.cpp
index bb8613c..5cdb3bb 100644
--- a/libs/vr/libvrflinger/display_service.cpp
+++ b/libs/vr/libvrflinger/display_service.cpp
@@ -1,13 +1,14 @@
#include "display_service.h"
+#include <unistd.h>
#include <vector>
#include <pdx/default_transport/service_endpoint.h>
#include <pdx/rpc/remote_method.h>
#include <private/dvr/composite_hmd.h>
+#include <private/dvr/device_metrics.h>
#include <private/dvr/display_rpc.h>
#include <private/dvr/display_types.h>
-#include <private/dvr/lucid_metrics.h>
#include <private/dvr/numeric.h>
#include <private/dvr/polynomial_radial_distortion.h>
#include <private/dvr/types.h>
@@ -18,20 +19,10 @@
using android::pdx::rpc::DispatchRemoteMethod;
using android::pdx::rpc::WrapBuffer;
-namespace {
-
-constexpr char kPersistentPoseBufferName[] = "DvrPersistentPoseBuffer";
-const int kPersistentPoseBufferUserId = 0;
-const int kPersistentPoseBufferGroupId = 0;
-const size_t kTimingDataSizeOffset = 128;
-
-} // anonymous namespace
-
namespace android {
namespace dvr {
-DisplayService::DisplayService()
- : DisplayService(nullptr) {}
+DisplayService::DisplayService() : DisplayService(nullptr) {}
DisplayService::DisplayService(Hwc2::Composer* hidl)
: BASE("DisplayService", Endpoint::Create(DisplayRPC::kClientPath)),
@@ -89,9 +80,9 @@
*this, &DisplayService::OnSetViewerParams, message);
return {};
- case DisplayRPC::GetPoseBuffer::Opcode:
- DispatchRemoteMethod<DisplayRPC::GetPoseBuffer>(
- *this, &DisplayService::OnGetPoseBuffer, message);
+ case DisplayRPC::GetNamedBuffer::Opcode:
+ DispatchRemoteMethod<DisplayRPC::GetNamedBuffer>(
+ *this, &DisplayService::OnGetNamedBuffer, message);
return {};
case DisplayRPC::IsVrAppRunning::Opcode:
@@ -217,16 +208,16 @@
// We should always have a red distortion.
LOG_FATAL_IF(view_params.distortion_coefficients_r.empty());
- red_distortion = std::make_shared<PolynomialRadialDistortion>(
+ red_distortion = std::make_shared<PolynomialRadialDistortion>(0.0f,
view_params.distortion_coefficients_r);
if (!view_params.distortion_coefficients_g.empty()) {
- green_distortion = std::make_shared<PolynomialRadialDistortion>(
+ green_distortion = std::make_shared<PolynomialRadialDistortion>(0.0f,
view_params.distortion_coefficients_g);
}
if (!view_params.distortion_coefficients_b.empty()) {
- blue_distortion = std::make_shared<PolynomialRadialDistortion>(
+ blue_distortion = std::make_shared<PolynomialRadialDistortion>(0.0f,
view_params.distortion_coefficients_b);
}
@@ -254,13 +245,14 @@
compositor->UpdateHeadMountMetrics(head_mount_metrics);
}
-pdx::LocalChannelHandle DisplayService::OnGetPoseBuffer(pdx::Message& message) {
- if (pose_buffer_) {
- return pose_buffer_->CreateConsumer().take();
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::OnGetNamedBuffer(
+ pdx::Message& /* message */, const std::string& name) {
+ auto named_buffer = named_buffers_.find(name);
+ if (named_buffer != named_buffers_.end()) {
+ return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
}
- pdx::rpc::RemoteMethodError(message, EAGAIN);
- return {};
+ return pdx::ErrorStatus(EINVAL);
}
// Calls the message handler for the DisplaySurface associated with this
@@ -334,16 +326,22 @@
hardware_composer_.SetDisplaySurfaces(std::move(visible_surfaces));
}
-pdx::BorrowedChannelHandle DisplayService::SetupPoseBuffer(
- size_t extended_region_size, int usage) {
- if (!pose_buffer_) {
- pose_buffer_ = BufferProducer::Create(
- kPersistentPoseBufferName, kPersistentPoseBufferUserId,
- kPersistentPoseBufferGroupId, usage,
- extended_region_size + kTimingDataSizeOffset);
+pdx::Status<BorrowedNativeBufferHandle> DisplayService::SetupNamedBuffer(
+ const std::string& name, size_t size, int producer_usage,
+ int consumer_usage) {
+ auto named_buffer = named_buffers_.find(name);
+ if (named_buffer == named_buffers_.end()) {
+ // TODO(hendrikw): Update BufferProducer to take producer_usage and
+ // consumer_usage flags.
+ auto ion_buffer = std::make_unique<IonBuffer>(
+ static_cast<int>(size), 1, HAL_PIXEL_FORMAT_BLOB,
+ producer_usage | consumer_usage);
+ named_buffer =
+ named_buffers_.insert(std::make_pair(name, std::move(ion_buffer)))
+ .first;
}
- return pose_buffer_->GetChannelHandle().Borrow();
+ return {BorrowedNativeBufferHandle(*named_buffer->second, 0)};
}
void DisplayService::OnHardwareComposerRefresh() {
@@ -362,10 +360,11 @@
int DisplayService::IsVrAppRunning(pdx::Message& message) {
bool visible = false;
- ForEachDisplaySurface([&visible](const std::shared_ptr<DisplaySurface>& surface) {
- if (surface->client_z_order() == 0 && surface->IsVisible())
- visible = true;
- });
+ ForEachDisplaySurface(
+ [&visible](const std::shared_ptr<DisplaySurface>& surface) {
+ if (surface->client_z_order() == 0 && surface->IsVisible())
+ visible = true;
+ });
REPLY_SUCCESS_RETURN(message, visible, 0);
}
diff --git a/libs/vr/libvrflinger/display_service.h b/libs/vr/libvrflinger/display_service.h
index da80a84..db89064 100644
--- a/libs/vr/libvrflinger/display_service.h
+++ b/libs/vr/libvrflinger/display_service.h
@@ -3,6 +3,7 @@
#include <pdx/service.h>
#include <private/dvr/buffer_hub_client.h>
+#include <private/dvr/bufferhub_rpc.h>
#include <private/dvr/display_rpc.h>
#include <private/dvr/late_latch.h>
@@ -38,8 +39,9 @@
// any change to client/manager attributes that affect visibility or z order.
void UpdateActiveDisplaySurfaces();
- pdx::BorrowedChannelHandle SetupPoseBuffer(size_t extended_region_size,
- int usage);
+ pdx::Status<BorrowedNativeBufferHandle> SetupNamedBuffer(
+ const std::string& name, size_t size, int producer_usage,
+ int consumer_usage);
template <class A>
void ForEachDisplaySurface(A action) const {
@@ -85,7 +87,8 @@
void OnSetViewerParams(pdx::Message& message,
const ViewerParams& view_params);
- pdx::LocalChannelHandle OnGetPoseBuffer(pdx::Message& message);
+ pdx::Status<BorrowedNativeBufferHandle> OnGetNamedBuffer(
+ pdx::Message& message, const std::string& name);
// Temporary query for current VR status. Will be removed later.
int IsVrAppRunning(pdx::Message& message);
@@ -102,7 +105,7 @@
HardwareComposer hardware_composer_;
DisplayConfigurationUpdateNotifier update_notifier_;
- std::unique_ptr<BufferProducer> pose_buffer_;
+ std::unordered_map<std::string, std::unique_ptr<IonBuffer>> named_buffers_;
};
} // namespace dvr
diff --git a/libs/vr/libvrflinger/hardware_composer.cpp b/libs/vr/libvrflinger/hardware_composer.cpp
index 542bbd9..6602d78 100644
--- a/libs/vr/libvrflinger/hardware_composer.cpp
+++ b/libs/vr/libvrflinger/hardware_composer.cpp
@@ -1416,7 +1416,7 @@
void Layer::Prepare() {
int right, bottom;
- buffer_handle_t handle;
+ sp<GraphicBuffer> handle;
if (surface_) {
// Only update the acquired buffer when one is either available or this is
@@ -1465,14 +1465,14 @@
}
right = acquired_buffer_.buffer()->width();
bottom = acquired_buffer_.buffer()->height();
- handle = acquired_buffer_.buffer()->native_handle();
+ handle = acquired_buffer_.buffer()->buffer()->buffer();
acquire_fence_fd_.Reset(acquired_buffer_.ClaimAcquireFence().Release());
} else {
// TODO(jwcai) Note: this is the GPU compositor's layer, and we need the
// mechanism to accept distorted layers from VrCore.
right = direct_buffer_->width();
bottom = direct_buffer_->height();
- handle = direct_buffer_->handle();
+ handle = direct_buffer_->buffer();
acquire_fence_fd_.Close();
}
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index bf831a7..d0996f0 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -627,19 +627,21 @@
#ifndef EGL_ANDROID_get_frame_timestamps
#define EGL_ANDROID_get_frame_timestamps 1
-#define EGL_TIMESTAMPS_ANDROID 0x314D
-#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
-#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
-#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
-#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
-#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
-#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
-#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
-#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
-#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
-#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
-#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
-#define EGL_READS_DONE_TIME_ANDROID 0x3159
+#define EGL_TIMESTAMPS_ANDROID 0x3430
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+#define EGL_READS_DONE_TIME_ANDROID 0x343C
+#define EGL_TIMESTAMP_PENDING_ANDROID EGL_CAST(EGLnsecsANDROID, -2)
+#define EGL_TIMESTAMP_INVALID_ANDROID EGL_CAST(EGLnsecsANDROID, -1)
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLBoolean eglGetNextFrameIdANDROID(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *frameId);
EGLAPI EGLBoolean eglGetCompositorTimingANDROID(EGLDisplay dpy, EGLSurface surface, EGLint numTimestamps, const EGLint *names, EGLnsecsANDROID *values);
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 6a62e8d..a895e63 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -23,28 +23,28 @@
// The headers modules are in frameworks/native/opengl/Android.bp.
ndk_library {
- name: "libEGL.ndk",
+ name: "libEGL",
symbol_file: "libEGL.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv1_CM.ndk",
+ name: "libGLESv1_CM",
symbol_file: "libGLESv1_CM.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv2.ndk",
+ name: "libGLESv2",
symbol_file: "libGLESv2.map.txt",
first_version: "9",
unversioned_until: "current",
}
ndk_library {
- name: "libGLESv3.ndk",
+ name: "libGLESv3",
symbol_file: "libGLESv3.map.txt",
first_version: "18",
unversioned_until: "current",
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index b00d401..0807d1f 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -2166,10 +2166,15 @@
case EGL_FIRST_COMPOSITION_START_TIME_ANDROID:
case EGL_LAST_COMPOSITION_START_TIME_ANDROID:
case EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID:
- case EGL_DISPLAY_PRESENT_TIME_ANDROID:
case EGL_DEQUEUE_READY_TIME_ANDROID:
case EGL_READS_DONE_TIME_ANDROID:
return EGL_TRUE;
+ case EGL_DISPLAY_PRESENT_TIME_ANDROID: {
+ int value = 0;
+ window->query(window,
+ NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT, &value);
+ return value == 0 ? EGL_FALSE : EGL_TRUE;
+ }
default:
return EGL_FALSE;
}
diff --git a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
index 61b9b66..b8a9add 100644
--- a/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
+++ b/opengl/specs/EGL_ANDROID_get_frame_timestamps.txt
@@ -28,7 +28,7 @@
Version
- Version 1, January 13, 2017
+ Version 8, April 11, 2017
Number
@@ -81,19 +81,21 @@
New Tokens
- EGL_TIMESTAMPS_ANDROID 0x314D
- EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
- EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
- EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
- EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
- EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
- EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
- EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
- EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
- EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
- EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
- EGL_DEQUEUE_READY_TIME_ANDROID 0x3158
- EGL_READS_DONE_TIME_ANDROID 0x3159
+ EGL_TIMESTAMPS_ANDROID 0x3430
+ EGL_COMPOSITE_DEADLINE_ANDROID 0x3431
+ EGL_COMPOSITE_INTERVAL_ANDROID 0x3432
+ EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3433
+ EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3434
+ EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3435
+ EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3436
+ EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3437
+ EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3438
+ EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3439
+ EGL_DISPLAY_PRESENT_TIME_ANDROID 0x343A
+ EGL_DEQUEUE_READY_TIME_ANDROID 0x343B
+ EGL_READS_DONE_TIME_ANDROID 0x343C
+ EGL_TIMESTAMP_PENDING_ANDROID -2
+ EGL_TIMESTAMP_INVALID_ANDROID -1
Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
"Surface Attributes", page 43:
@@ -155,10 +157,12 @@
limited history of timestamp data. If a query is made for a frame whose
timestamp history no longer exists then EGL_BAD_ACCESS is generated. If
timestamp collection has not been enabled for the surface then
- EGL_BAD_SURFACE is generated. Timestamps for events that will not occur or
- have not yet occurred will be zero. Timestamp queries that are not
- supported will generate an EGL_BAD_PARAMETER error. If any error is
- generated the function will return EGL_FALSE.
+ EGL_BAD_SURFACE is generated. Timestamps for events that might still occur
+ will have the value EGL_TIMESTAMP_PENDING_ANDROID. Timestamps for events
+ that did not occur will have the value EGL_TIMESTAMP_INVALID_ANDROID.
+ Otherwise, the timestamp will be valid and indicate the event has occured.
+ Timestamp queries that are not supported will generate an EGL_BAD_PARAMETER
+ error. If any error is generated the function will return EGL_FALSE.
The application can poll for the timestamp of particular events by calling
eglGetFrameTimestamps over and over without needing to call any other EGL
@@ -222,6 +226,12 @@
Revision History
+#8 (Brian Anderson, April 11, 2017)
+ - Use reserved enumerant values.
+
+#7 (Brian Anderson, March 21, 2017)
+ - Differentiate between pending events and events that did not occur.
+
#6 (Brian Anderson, March 16, 2017)
- Remove DISPLAY_RETIRE_TIME_ANDROID.
diff --git a/opengl/specs/README b/opengl/specs/README
index e922740..cba4453 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -4,8 +4,14 @@
The table below tracks usage of EGL enumerant values that have been reserved
for use by Android extensions.
+See https://github.com/KhronosGroup/EGL-Registry/blob/master/api/egl.xml
+for a list of all enumarant values currently reserved and registered with
+Khronos.
+
Value Extension
----------------- ----------------------------------
+================ ==================================
+0x3140 - 0x314F Reserved block
+================ ==================================
0x3140 EGL_NATIVE_BUFFER_ANDROID (EGL_ANDROID_image_native_buffer)
0x3141 EGL_PLATFORM_ANDROID_KHR (KHR_platform_android)
0x3142 EGL_RECORDABLE_ANDROID (EGL_ANDROID_recordable)
@@ -18,17 +24,23 @@
0x314A EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
0x314B EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
0x314C EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
-0x314D EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314E EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x314F EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3150 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3151 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3152 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3153 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3154 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3155 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3156 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3157 EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3158 EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x3159 EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
-0x315A - 0x315F (unused)
+0x314D - 0x314F (unused)
+
+ Value Extension
+================ ==================================
+0x3430 - 0x343F Reserved block
+================ ==================================
+0x3430 EGL_TIMESTAMPS_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3431 EGL_COMPOSITE_DEADLINE_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3432 EGL_COMPOSITE_INTERVAL_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3433 EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3434 EGL_REQUESTED_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3435 EGL_RENDERING_COMPLETE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3436 EGL_COMPOSITION_LATCH_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3437 EGL_FIRST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3438 EGL_LAST_COMPOSITION_START_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x3439 EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343A EGL_DISPLAY_PRESENT_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343B EGL_DEQUEUE_READY_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343C EGL_READS_DONE_TIME_ANDROID (EGL_ANDROID_get_frame_timestamps)
+0x343D - 0x343F (unused)
diff --git a/services/schedulerservice/SchedulingPolicyService.cpp b/services/schedulerservice/SchedulingPolicyService.cpp
index 522a8c0..1f6ed57 100644
--- a/services/schedulerservice/SchedulingPolicyService.cpp
+++ b/services/schedulerservice/SchedulingPolicyService.cpp
@@ -17,8 +17,6 @@
#include "SchedulingPolicyService.h"
-#include <private/android_filesystem_config.h> // for AID_CAMERASERVER
-
#include <log/log.h>
#include <hwbinder/IPCThreadState.h>
#include <mediautils/SchedulingPolicyService.h>
@@ -29,23 +27,36 @@
namespace V1_0 {
namespace implementation {
-Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
- using ::android::hardware::IPCThreadState;
+bool SchedulingPolicyService::isAllowed() {
+ // TODO(b/37291237)
+ return true;
+}
+Return<bool> SchedulingPolicyService::requestPriority(int32_t pid, int32_t tid, int32_t priority) {
if (priority < static_cast<int32_t>(Priority::MIN) ||
priority > static_cast<int32_t>(Priority::MAX)) {
return false;
}
- if (IPCThreadState::self()->getCallingUid() != AID_CAMERASERVER) {
+ if (!isAllowed()) {
return false;
}
+ // TODO(b/37226359): decouple from and remove AIDL service
// this should always be allowed since we are in system_server.
int value = ::android::requestPriority(pid, tid, priority, false /* isForApp */);
return value == 0 /* success */;
}
+Return<int32_t> SchedulingPolicyService::getMaxAllowedPriority() {
+ if (!isAllowed()) {
+ return 0;
+ }
+
+ // TODO(b/37226359): decouple from and remove AIDL service
+ return 3;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace schedulerservice
diff --git a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
index eb5a4ae..7d1c478 100644
--- a/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
+++ b/services/schedulerservice/include/schedulerservice/SchedulingPolicyService.h
@@ -38,6 +38,9 @@
struct SchedulingPolicyService : public ISchedulingPolicyService {
Return<bool> requestPriority(int32_t pid, int32_t tid, int32_t priority) override;
+ Return<int32_t> getMaxAllowedPriority() override;
+private:
+ bool isAllowed();
};
} // namespace implementation
diff --git a/services/sensorservice/hidl/DirectReportChannel.cpp b/services/sensorservice/hidl/DirectReportChannel.cpp
index 773ce8c..adc4675 100644
--- a/services/sensorservice/hidl/DirectReportChannel.cpp
+++ b/services/sensorservice/hidl/DirectReportChannel.cpp
@@ -31,10 +31,13 @@
}
// Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
-Return<Result> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate) {
+Return<void> DirectReportChannel::configure(int32_t sensorHandle, RateLevel rate,
+ configure_cb _hidl_cb) {
int token = mManager.configureDirectChannel(mId,
static_cast<int>(sensorHandle), static_cast<int>(rate));
- return token <= 0 ? convertResult(token) : Result::OK;
+ _hidl_cb(token <= 0 ? 0 : token,
+ token <= 0 ? convertResult(token) : Result::OK);
+ return Void();
}
diff --git a/services/sensorservice/hidl/DirectReportChannel.h b/services/sensorservice/hidl/DirectReportChannel.h
index 9134944..dd67827 100644
--- a/services/sensorservice/hidl/DirectReportChannel.h
+++ b/services/sensorservice/hidl/DirectReportChannel.h
@@ -47,7 +47,8 @@
~DirectReportChannel();
// Methods from ::android::frameworks::sensorservice::V1_0::IDirectReportChannel follow.
- Return<Result> configure(int32_t sensorHandle, RateLevel rate) override;
+ Return<void> configure(int32_t sensorHandle, RateLevel rate,
+ configure_cb _hidl_cb) override;
private:
::android::SensorManager& mManager;
diff --git a/services/sensorservice/hidl/EventQueue.cpp b/services/sensorservice/hidl/EventQueue.cpp
index 86d365c..c0365e5 100644
--- a/services/sensorservice/hidl/EventQueue.cpp
+++ b/services/sensorservice/hidl/EventQueue.cpp
@@ -39,7 +39,8 @@
while ((actual = internalQueue->read(&event, 1 /* count */)) > 0) {
internalQueue->sendAck(&event, actual);
- mCallback->onEvent(convertEvent(event));
+ Return<void> ret = mCallback->onEvent(convertEvent(event));
+ (void)ret.isOk(); // ignored
}
return 1; // continue to receive callbacks
diff --git a/services/sensorservice/hidl/SensorManager.cpp b/services/sensorservice/hidl/SensorManager.cpp
index 0743fc3..06ff95c 100644
--- a/services/sensorservice/hidl/SensorManager.cpp
+++ b/services/sensorservice/hidl/SensorManager.cpp
@@ -22,12 +22,14 @@
#include "SensorManager.h"
+#include <sched.h>
+
+#include <thread>
+
#include "EventQueue.h"
#include "DirectReportChannel.h"
#include "utils.h"
-#include <thread>
-
namespace android {
namespace frameworks {
namespace sensorservice {
@@ -131,6 +133,14 @@
std::condition_variable looperSet;
std::thread{[&mutex = mLooperMutex, &looper = mLooper, &looperSet] {
+
+ struct sched_param p = {0};
+ p.sched_priority = 10;
+ if (sched_setscheduler(0 /* current thread*/, SCHED_FIFO, &p) != 0) {
+ LOG(WARNING) << "Could not use SCHED_FIFO for looper thread: "
+ << strerror(errno);
+ }
+
std::unique_lock<std::mutex> lock(mutex);
looper = Looper::prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS /* opts */);
lock.unlock();
diff --git a/services/sensorservice/hidl/utils.cpp b/services/sensorservice/hidl/utils.cpp
index b540525..2f9e922 100644
--- a/services/sensorservice/hidl/utils.cpp
+++ b/services/sensorservice/hidl/utils.cpp
@@ -63,6 +63,8 @@
return Result::NO_MEMORY;
case NO_INIT:
return Result::NO_INIT;
+ case PERMISSION_DENIED:
+ return Result::PERMISSION_DENIED;
case BAD_VALUE:
return Result::BAD_VALUE;
case INVALID_OPERATION:
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 76baa01..7bb20ba 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -133,10 +133,15 @@
main_surfaceflinger.cpp
LOCAL_SHARED_LIBRARIES := \
+ android.hardware.configstore@1.0 \
+ android.hardware.configstore-utils \
+ android.hardware.graphics.allocator@2.0 \
libsurfaceflinger \
libcutils \
liblog \
libbinder \
+ libhidlbase \
+ libhidltransport \
libutils \
libui \
libgui \
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 33aa759..262ab62 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -17,7 +17,6 @@
#undef LOG_TAG
#define LOG_TAG "HwcComposer"
-#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <inttypes.h>
#include <log/log.h>
#include <gui/BufferQueue.h>
@@ -26,7 +25,6 @@
namespace android {
-using frameworks::vr::composer::V1_0::IVrComposerClient;
using hardware::Return;
using hardware::hidl_vec;
using hardware::hidl_handle;
@@ -124,6 +122,41 @@
endCommand();
}
+void Composer::CommandWriter::setClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata)
+{
+ constexpr uint16_t kSetClientTargetMetadataLength = 7;
+ beginCommand(
+ static_cast<IComposerClient::Command>(
+ IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA),
+ kSetClientTargetMetadataLength);
+ writeBufferMetadata(metadata);
+ endCommand();
+}
+
+void Composer::CommandWriter::setLayerBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata)
+{
+ constexpr uint16_t kSetLayerBufferMetadataLength = 7;
+ beginCommand(
+ static_cast<IComposerClient::Command>(
+ IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA),
+ kSetLayerBufferMetadataLength);
+ writeBufferMetadata(metadata);
+ endCommand();
+}
+
+void Composer::CommandWriter::writeBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata)
+{
+ write(metadata.width);
+ write(metadata.height);
+ write(metadata.stride);
+ write(metadata.layerCount);
+ writeSigned(static_cast<int32_t>(metadata.format));
+ write64(metadata.usage);
+}
+
Composer::Composer(bool useVrComposer)
: mWriter(kWriterInitialSize),
mIsUsingVrComposer(useVrComposer)
@@ -426,12 +459,29 @@
}
Error Composer::setClientTarget(Display display, uint32_t slot,
- const native_handle_t* target,
+ const sp<GraphicBuffer>& target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage)
{
mWriter.selectDisplay(display);
- mWriter.setClientTarget(slot, target, acquireFence, dataspace, damage);
+ if (mIsUsingVrComposer && target.get()) {
+ IVrComposerClient::BufferMetadata metadata = {
+ .width = target->getWidth(),
+ .height = target->getHeight(),
+ .stride = target->getStride(),
+ .layerCount = target->getLayerCount(),
+ .format = static_cast<PixelFormat>(target->getPixelFormat()),
+ .usage = target->getUsage(),
+ };
+ mWriter.setClientTargetMetadata(metadata);
+ }
+
+ const native_handle_t* handle = nullptr;
+ if (target.get()) {
+ handle = target->getNativeBuffer()->handle;
+ }
+
+ mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
return Error::NONE;
}
@@ -502,11 +552,28 @@
}
Error Composer::setLayerBuffer(Display display, Layer layer,
- uint32_t slot, const native_handle_t* buffer, int acquireFence)
+ uint32_t slot, const sp<GraphicBuffer>& buffer, int acquireFence)
{
mWriter.selectDisplay(display);
mWriter.selectLayer(layer);
- mWriter.setLayerBuffer(slot, buffer, acquireFence);
+ if (mIsUsingVrComposer && buffer.get()) {
+ IVrComposerClient::BufferMetadata metadata = {
+ .width = buffer->getWidth(),
+ .height = buffer->getHeight(),
+ .stride = buffer->getStride(),
+ .layerCount = buffer->getLayerCount(),
+ .format = static_cast<PixelFormat>(buffer->getPixelFormat()),
+ .usage = buffer->getUsage(),
+ };
+ mWriter.setLayerBufferMetadata(metadata);
+ }
+
+ const native_handle_t* handle = nullptr;
+ if (buffer.get()) {
+ handle = buffer->getNativeBuffer()->handle;
+ }
+
+ mWriter.setLayerBuffer(slot, handle, acquireFence);
return Error::NONE;
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 18af9dd..37b7766 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -23,6 +23,7 @@
#include <utility>
#include <vector>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <android/hardware/graphics/composer/2.1/IComposer.h>
#include <utils/StrongPointer.h>
#include <IComposerCommandBuffer.h>
@@ -31,6 +32,8 @@
namespace Hwc2 {
+using android::frameworks::vr::composer::V1_0::IVrComposerClient;
+
using android::hardware::graphics::common::V1_0::ColorMode;
using android::hardware::graphics::common::V1_0::ColorTransform;
using android::hardware::graphics::common::V1_0::Dataspace;
@@ -179,7 +182,7 @@
* When target is not nullptr, the cache is updated with the new target.
*/
Error setClientTarget(Display display, uint32_t slot,
- const native_handle_t* target,
+ const sp<GraphicBuffer>& target,
int acquireFence, Dataspace dataspace,
const std::vector<IComposerClient::Rect>& damage);
Error setColorMode(Display display, ColorMode mode);
@@ -199,7 +202,7 @@
int32_t x, int32_t y);
/* see setClientTarget for the purpose of slot */
Error setLayerBuffer(Display display, Layer layer, uint32_t slot,
- const native_handle_t* buffer, int acquireFence);
+ const sp<GraphicBuffer>& buffer, int acquireFence);
Error setLayerSurfaceDamage(Display display, Layer layer,
const std::vector<IComposerClient::Rect>& damage);
Error setLayerBlendMode(Display display, Layer layer,
@@ -232,6 +235,14 @@
~CommandWriter() override;
void setLayerInfo(uint32_t type, uint32_t appId);
+ void setClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
+ void setLayerBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
+
+ private:
+ void writeBufferMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
};
// Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 1b598f8..5b869e1 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -32,7 +32,6 @@
#include <hardware/hardware.h>
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
-#include <gui/GraphicBufferAlloc.h>
#include <gui/Surface.h>
#include <ui/GraphicBuffer.h>
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index e49e734..8270c39 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -244,7 +244,7 @@
ALOGE("Failed to get display by id");
return Error::BadDisplay;
}
- (*outDisplay)->setVirtual();
+ (*outDisplay)->setConnected(true);
return Error::None;
}
@@ -531,15 +531,28 @@
: mDevice(device),
mId(id),
mIsConnected(false),
- mIsVirtual(false)
+ mType(DisplayType::Invalid)
{
ALOGV("Created display %" PRIu64, id);
+
+#ifdef BYPASS_IHWC
+ int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
+ reinterpret_cast<int32_t *>(&mType));
+#else
+ auto intError = mDevice.mComposer->getDisplayType(mId,
+ reinterpret_cast<Hwc2::IComposerClient::DisplayType *>(&mType));
+#endif
+ auto error = static_cast<Error>(intError);
+ if (error != Error::None) {
+ ALOGE("getDisplayType(%" PRIu64 ") failed: %s (%d)",
+ id, to_string(error).c_str(), intError);
+ }
}
Display::~Display()
{
ALOGV("Destroyed display %" PRIu64, mId);
- if (mIsVirtual) {
+ if (mType == DisplayType::Virtual) {
mDevice.destroyVirtualDisplay(mId);
}
}
@@ -802,21 +815,7 @@
Error Display::getType(DisplayType* outType) const
{
-#ifdef BYPASS_IHWC
- int32_t intType = 0;
- int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
- &intType);
-#else
- Hwc2::IComposerClient::DisplayType intType =
- Hwc2::IComposerClient::DisplayType::INVALID;
- auto intError = mDevice.mComposer->getDisplayType(mId, &intType);
-#endif
- auto error = static_cast<Error>(intError);
- if (error != Error::None) {
- return error;
- }
-
- *outType = static_cast<DisplayType>(intType);
+ *outType = mType;
return Error::None;
}
@@ -961,14 +960,19 @@
return static_cast<Error>(intError);
}
-Error Display::setClientTarget(uint32_t slot, buffer_handle_t target,
+Error Display::setClientTarget(uint32_t slot, const sp<GraphicBuffer>& target,
const sp<Fence>& acquireFence, android_dataspace_t dataspace)
{
// TODO: Properly encode client target surface damage
int32_t fenceFd = acquireFence->dup();
#ifdef BYPASS_IHWC
(void) slot;
- int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
+ buffer_handle_t handle = nullptr;
+ if (target.get() && target->getNativeBuffer()) {
+ handle = target->getNativeBuffer()->handle;
+ }
+
+ int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, handle,
fenceFd, static_cast<int32_t>(dataspace), {0, nullptr});
#else
auto intError = mDevice.mComposer->setClientTarget(mId, slot, target,
@@ -1195,14 +1199,19 @@
return static_cast<Error>(intError);
}
-Error Layer::setBuffer(uint32_t slot, buffer_handle_t buffer,
+Error Layer::setBuffer(uint32_t slot, const sp<GraphicBuffer>& buffer,
const sp<Fence>& acquireFence)
{
int32_t fenceFd = acquireFence->dup();
#ifdef BYPASS_IHWC
(void) slot;
+ buffer_handle_t handle = nullptr;
+ if (buffer.get() && buffer->getNativeBuffer()) {
+ handle = buffer->getNativeBuffer()->handle;
+ }
+
int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
- mId, buffer, fenceFd);
+ mId, handle, fenceFd);
#else
auto intError = mDevice.mComposer->setLayerBuffer(mDisplayId,
mId, slot, buffer, fenceFd);
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 4419dc1..643b1e0 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -329,7 +329,7 @@
[[clang::warn_unused_result]] Error setActiveConfig(
const std::shared_ptr<const Config>& config);
[[clang::warn_unused_result]] Error setClientTarget(
- uint32_t slot, buffer_handle_t target,
+ uint32_t slot, const android::sp<android::GraphicBuffer>& target,
const android::sp<android::Fence>& acquireFence,
android_dataspace_t dataspace);
[[clang::warn_unused_result]] Error setColorMode(android_color_mode_t mode);
@@ -352,12 +352,6 @@
private:
// For use by Device
- // Virtual displays are always connected
- void setVirtual() {
- mIsVirtual = true;
- mIsConnected = true;
- }
-
void setConnected(bool connected) { mIsConnected = connected; }
int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
void loadConfig(hwc2_config_t configId);
@@ -375,7 +369,7 @@
Device& mDevice;
hwc2_display_t mId;
bool mIsConnected;
- bool mIsVirtual;
+ DisplayType mType;
std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
};
@@ -392,7 +386,7 @@
[[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
[[clang::warn_unused_result]] Error setBuffer(uint32_t slot,
- buffer_handle_t buffer,
+ const android::sp<android::GraphicBuffer>& buffer,
const android::sp<android::Fence>& acquireFence);
[[clang::warn_unused_result]] Error setSurfaceDamage(
const android::Region& damage);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 09434f6..7314127 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -465,12 +465,7 @@
ALOGV("setClientTarget for display %d", displayId);
auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
- buffer_handle_t handle = nullptr;
- if ((target != nullptr) && target->getNativeBuffer()) {
- handle = target->getNativeBuffer()->handle;
- }
- auto error = hwcDisplay->setClientTarget(slot, handle,
- acquireFence, dataspace);
+ auto error = hwcDisplay->setClientTarget(slot, target, acquireFence, dataspace);
if (error != HWC2::Error::None) {
ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
to_string(error).c_str(), static_cast<int32_t>(error));
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index c211c7b..5e5efb7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -167,7 +167,7 @@
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer, nullptr, true);
+ BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName, this);
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0));
@@ -852,18 +852,12 @@
}
uint32_t hwcSlot = 0;
- buffer_handle_t hwcHandle = nullptr;
- {
- sp<GraphicBuffer> hwcBuffer;
- hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
- &hwcSlot, &hwcBuffer);
- if (hwcBuffer != nullptr) {
- hwcHandle = hwcBuffer->handle;
- }
- }
+ sp<GraphicBuffer> hwcBuffer;
+ hwcInfo.bufferCache.getHwcBuffer(mActiveBufferSlot, mActiveBuffer,
+ &hwcSlot, &hwcBuffer);
auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
- error = hwcLayer->setBuffer(hwcSlot, hwcHandle, acquireFence);
+ error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence);
if (error != HWC2::Error::None) {
ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
mActiveBuffer->handle, to_string(error).c_str(),
@@ -1719,10 +1713,55 @@
mCurrentState.sequence++;
mCurrentState.z = z;
mCurrentState.modified = true;
+
+ // Discard all relative layering.
+ if (mCurrentState.zOrderRelativeOf != nullptr) {
+ sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote();
+ if (strongRelative != nullptr) {
+ strongRelative->removeZOrderRelative(this);
+ }
+ mCurrentState.zOrderRelativeOf = nullptr;
+ }
setTransactionFlags(eTransactionNeeded);
return true;
}
+void Layer::removeZOrderRelative(const wp<Layer>& relative) {
+ mCurrentState.zOrderRelatives.remove(relative);
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+}
+
+void Layer::addZOrderRelative(const wp<Layer>& relative) {
+ mCurrentState.zOrderRelatives.add(relative);
+ mCurrentState.modified = true;
+ mCurrentState.sequence++;
+ setTransactionFlags(eTransactionNeeded);
+}
+
+bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) {
+ sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get());
+ if (handle == nullptr) {
+ return false;
+ }
+ sp<Layer> relative = handle->owner.promote();
+ if (relative == nullptr) {
+ return false;
+ }
+
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ mCurrentState.z = z;
+
+ mCurrentState.zOrderRelativeOf = relative;
+ relative->addZOrderRelative(this);
+
+ setTransactionFlags(eTransactionNeeded);
+
+ return true;
+}
+
bool Layer::setSize(uint32_t w, uint32_t h) {
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
return false;
@@ -2506,40 +2545,70 @@
return mDrawingState.z;
}
+LayerVector Layer::makeTraversalList() {
+ if (mDrawingState.zOrderRelatives.size() == 0) {
+ return mDrawingChildren;
+ }
+ LayerVector traverse;
+
+ for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) {
+ sp<Layer> strongRelative = weakRelative.promote();
+ if (strongRelative != nullptr) {
+ traverse.add(strongRelative);
+ } else {
+ // We need to erase from current state instead of drawing
+ // state so we don't overwrite when copying
+ // the current state to the drawing state.
+ mCurrentState.zOrderRelatives.remove(weakRelative);
+ }
+ }
+
+ for (const sp<Layer>& child : mDrawingChildren) {
+ traverse.add(child);
+ }
+
+ return traverse;
+}
+
/**
- * Negatively signed children are before 'this' in Z-order.
+ * Negatively signed relatives are before 'this' in Z-order.
*/
void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) {
+ LayerVector list = makeTraversalList();
+
size_t i = 0;
- for (; i < mDrawingChildren.size(); i++) {
- const auto& child = mDrawingChildren[i];
- if (child->getZ() >= 0)
+ for (; i < list.size(); i++) {
+ const auto& relative = list[i];
+ if (relative->getZ() >= 0) {
break;
- child->traverseInZOrder(exec);
+ }
+ relative->traverseInZOrder(exec);
}
exec(this);
- for (; i < mDrawingChildren.size(); i++) {
- const auto& child = mDrawingChildren[i];
- child->traverseInZOrder(exec);
+ for (; i < list.size(); i++) {
+ const auto& relative = list[i];
+ relative->traverseInZOrder(exec);
}
}
/**
- * Positively signed children are before 'this' in reverse Z-order.
+ * Positively signed relatives are before 'this' in reverse Z-order.
*/
void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) {
+ LayerVector list = makeTraversalList();
+
int32_t i = 0;
- for (i = mDrawingChildren.size()-1; i>=0; i--) {
- const auto& child = mDrawingChildren[i];
- if (child->getZ() < 0) {
+ for (i = list.size()-1; i>=0; i--) {
+ const auto& relative = list[i];
+ if (relative->getZ() < 0) {
break;
}
- child->traverseInReverseZOrder(exec);
+ relative->traverseInReverseZOrder(exec);
}
exec(this);
for (; i>=0; i--) {
- const auto& child = mDrawingChildren[i];
- child->traverseInReverseZOrder(exec);
+ const auto& relative = list[i];
+ relative->traverseInReverseZOrder(exec);
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e21be8b..a5224ec 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -151,6 +151,12 @@
uint32_t appId;
uint32_t type;
+
+ // If non-null, a Surface this Surface's Z-order is interpreted relative to.
+ wp<Layer> zOrderRelativeOf;
+
+ // A list of surfaces whose Z-order is interpreted relative to ours.
+ SortedVector<wp<Layer>> zOrderRelatives;
};
// -----------------------------------------------------------------------
@@ -173,6 +179,8 @@
bool setFinalCrop(const Rect& crop, bool immediate);
bool setLayer(int32_t z);
+ bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
+
bool setSize(uint32_t w, uint32_t h);
#ifdef USE_HWC2
bool setAlpha(float alpha);
@@ -549,6 +557,10 @@
void setParent(const sp<Layer>& layer);
+ LayerVector makeTraversalList();
+ void addZOrderRelative(const wp<Layer>& relative);
+ void removeZOrderRelative(const wp<Layer>& relative);
+
// -----------------------------------------------------------------------
class SyncPoint
diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp
index 7ba6ad3..90e6395 100644
--- a/services/surfaceflinger/LayerVector.cpp
+++ b/services/surfaceflinger/LayerVector.cpp
@@ -42,13 +42,21 @@
void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const {
for (size_t i = 0; i < size(); i++) {
- (*this)[i]->traverseInZOrder(consume);
+ const auto& layer = (*this)[i];
+ if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+ continue;
+ }
+ layer->traverseInZOrder(consume);
}
}
void LayerVector::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const {
for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) {
- (*this)[i]->traverseInReverseZOrder(consume);
+ const auto& layer = (*this)[i];
+ if (layer->getDrawingState().zOrderRelativeOf != nullptr) {
+ continue;
+ }
+ layer->traverseInReverseZOrder(consume);
}
}
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 26baaae..a5f1d60 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -45,7 +45,6 @@
#include <gui/GuiConfig.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/Surface.h>
-#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/PixelFormat.h>
@@ -340,12 +339,6 @@
return mBuiltinDisplays[id];
}
-sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
-{
- sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
- return gba;
-}
-
void SurfaceFlinger::bootFinished()
{
if (mStartBootAnimThread->join() != NO_ERROR) {
@@ -578,6 +571,14 @@
Mutex::Autolock _l(mStateLock);
+ // Inform native graphics APIs whether the present timestamp is supported:
+ if (getHwComposer().hasCapability(
+ HWC2::Capability::PresentFenceIsNotReliable)) {
+ property_set(kTimestampProperty, "0");
+ } else {
+ property_set(kTimestampProperty, "1");
+ }
+
if (useVrFlinger) {
auto vrFlingerRequestDisplayCallback = [this] (bool requestDisplay) {
mVrFlingerRequestsDisplay = requestDisplay;
@@ -651,6 +652,25 @@
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const {
+ *outSupported = {
+ FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE,
+ };
+ if (!getHwComposer().hasCapability(
+ HWC2::Capability::PresentFenceIsNotReliable)) {
+ outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
+ }
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) {
if ((configs == NULL) || (display.get() == NULL)) {
@@ -1144,8 +1164,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer,
- new GraphicBufferAlloc());
+ BufferQueue::createBufferQueue(&producer, &consumer);
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
DisplayDevice::DISPLAY_PRIMARY, consumer);
@@ -1223,6 +1242,13 @@
// mCurrentState and mDrawingState and re-apply all changes when we make the
// transition.
mDrawingState.displays.clear();
+ // Release virtual display hwcId during vr mode transition.
+ for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+ const sp<DisplayDevice>& displayDevice = mDisplays[displayId];
+ if (displayDevice->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL) {
+ displayDevice->disconnect(getHwComposer());
+ }
+ }
mDisplays.clear();
initializeDisplays();
}
@@ -1967,8 +1993,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferProducer> bqProducer;
sp<IGraphicBufferConsumer> bqConsumer;
- BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
- new GraphicBufferAlloc());
+ BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
int32_t hwcId = -1;
if (state.isVirtualDisplay()) {
@@ -2820,6 +2845,11 @@
}
}
}
+ if (what & layer_state_t::eRelativeLayerChanged) {
+ if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) {
+ flags |= eTransactionNeeded|eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eSizeChanged) {
if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 46121cf..b17a5f2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -76,7 +76,6 @@
class Client;
class DisplayEventConnection;
class EventThread;
-class IGraphicBufferAlloc;
class Layer;
class LayerDim;
class Surface;
@@ -227,6 +226,7 @@
enum { LOG_FRAME_STATS_PERIOD = 30*60*60 };
static const size_t MAX_LAYERS = 4096;
+ static constexpr const char* kTimestampProperty = "service.sf.present_timestamp";
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -256,7 +256,6 @@
*/
virtual sp<ISurfaceComposerClient> createConnection();
virtual sp<ISurfaceComposerClient> createScopedConnection(const sp<IGraphicBufferProducer>& gbp);
- virtual sp<IGraphicBufferAlloc> createGraphicBufferAlloc();
virtual sp<IBinder> createDisplay(const String8& displayName, bool secure);
virtual void destroyDisplay(const sp<IBinder>& display);
virtual sp<IBinder> getBuiltInDisplay(int32_t id);
@@ -265,6 +264,8 @@
virtual void bootFinished();
virtual bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const;
+ virtual status_t getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection();
virtual status_t captureScreen(const sp<IBinder>& display,
const sp<IGraphicBufferProducer>& producer,
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 1d2b485..9babeef 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -139,7 +139,9 @@
}
sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const {
- return mConsumer->getSidebandStream();
+ sp<NativeHandle> stream;
+ mConsumer->getSidebandStream(&stream);
+ return stream;
}
// We need to determine the time when a buffer acquired now will be
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index e640ef7..59c8b76 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -42,7 +42,6 @@
#include <gui/GuiConfig.h>
#include <gui/IDisplayEventConnection.h>
#include <gui/Surface.h>
-#include <gui/GraphicBufferAlloc.h>
#include <ui/GraphicBufferAllocator.h>
#include <ui/HdrCapabilities.h>
@@ -319,12 +318,6 @@
return mBuiltinDisplays[id];
}
-sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
-{
- sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
- return gba;
-}
-
void SurfaceFlinger::bootFinished()
{
if (mStartBootAnimThread->join() != NO_ERROR) {
@@ -549,6 +542,9 @@
LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
"couldn't create EGLContext");
+ // Inform native graphics APIs that the present timestamp is NOT supported:
+ property_set(kTimestampProperty, "0");
+
// initialize our non-virtual displays
for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
@@ -561,8 +557,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
- BufferQueue::createBufferQueue(&producer, &consumer,
- new GraphicBufferAlloc());
+ BufferQueue::createBufferQueue(&producer, &consumer);
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
consumer);
@@ -647,6 +642,21 @@
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
}
+status_t SurfaceFlinger::getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) const {
+ *outSupported = {
+ FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE,
+ };
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs) {
if ((configs == NULL) || (display.get() == NULL)) {
@@ -1687,8 +1697,7 @@
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferProducer> bqProducer;
sp<IGraphicBufferConsumer> bqConsumer;
- BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
- new GraphicBufferAlloc());
+ BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);
int32_t hwcDisplayId = -1;
if (state.isVirtualDisplay()) {
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index f151087..d15376e 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -18,17 +18,44 @@
#include <sched.h>
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
#include <cutils/sched_policy.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
+#include <hidl/LegacySupport.h>
+#include <configstore/Utils.h>
#include "GpuService.h"
#include "SurfaceFlinger.h"
using namespace android;
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+using android::hardware::configstore::getBool;
+using android::hardware::configstore::getBool;
+
+static status_t startGraphicsAllocatorService() {
+ hardware::configureRpcThreadpool( 1 /* maxThreads */,
+ false /* callerWillJoin */);
+ status_t result =
+ hardware::registerPassthroughServiceImplementation<IAllocator>();
+ if (result != OK) {
+ ALOGE("could not start graphics allocator service");
+ return result;
+ }
+
+ return OK;
+}
+
int main(int, char**) {
+ if (getBool<ISurfaceFlingerConfigs,
+ &ISurfaceFlingerConfigs::startGraphicsAllocatorService>(false)) {
+ startGraphicsAllocatorService();
+ }
+
signal(SIGPIPE, SIG_IGN);
// When SF is launched in its own process, limit the number of
// binder threads to 4.
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index a46ba48..441fc7e 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -662,6 +662,49 @@
}
}
+TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) {
+ sp<ScreenCapture> sc;
+ {
+ SCOPED_TRACE("before adding relative surface");
+ ScreenCapture::captureScreen(&sc);
+ sc->expectBGColor(24, 24);
+ sc->expectFGColor(75, 75);
+ sc->expectBGColor(145, 145);
+ }
+
+ auto relativeSurfaceControl = mComposerClient->createSurface(
+ String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0);
+ fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177);
+ waitForPostedBuffers();
+
+ // Now we stack the surface above the foreground surface and make sure it is visible.
+ SurfaceComposerClient::openGlobalTransaction();
+ relativeSurfaceControl->setPosition(64, 64);
+ relativeSurfaceControl->show();
+ relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1);
+ SurfaceComposerClient::closeGlobalTransaction(true);
+
+
+ {
+ SCOPED_TRACE("after adding relative surface");
+ ScreenCapture::captureScreen(&sc);
+ // our relative surface should be visible now.
+ sc->checkPixel(75, 75, 255, 177, 177);
+ }
+
+ // A call to setLayer will override a call to setRelativeLayer
+ SurfaceComposerClient::openGlobalTransaction();
+ relativeSurfaceControl->setLayer(0);
+ SurfaceComposerClient::closeGlobalTransaction();
+
+ {
+ SCOPED_TRACE("after set layer");
+ ScreenCapture::captureScreen(&sc);
+ // now the FG surface should be visible again.
+ sc->expectFGColor(75, 75);
+ }
+}
+
class ChildLayerTest : public LayerUpdateTest {
protected:
void SetUp() override {
diff --git a/services/vr/bufferhubd/buffer_hub.cpp b/services/vr/bufferhubd/buffer_hub.cpp
index 2ce60e5..4b1a522 100644
--- a/services/vr/bufferhubd/buffer_hub.cpp
+++ b/services/vr/bufferhubd/buffer_hub.cpp
@@ -1,5 +1,6 @@
#include "buffer_hub.h"
+#include <inttypes.h>
#include <log/log.h>
#include <poll.h>
#include <utils/Trace.h>
@@ -52,7 +53,7 @@
stream << " ";
stream << std::setw(6) << "Format";
stream << " ";
- stream << std::setw(10) << "Usage";
+ stream << std::setw(21) << "Usage";
stream << " ";
stream << "Name";
stream << std::endl;
@@ -79,7 +80,9 @@
stream << std::setw(6) << info.format;
stream << " ";
stream << "0x" << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage;
+ stream << std::setw(8) << info.producer_usage;
+ stream << "0x";
+ stream << std::setw(8) << info.consumer_usage;
stream << std::dec << std::setfill(' ');
stream << " ";
stream << info.name;
@@ -137,6 +140,10 @@
stream << " UsageClearMask";
stream << " UsageDenySetMask";
stream << " UsageDenyClearMask";
+ stream << " UsageSetMask";
+ stream << " UsageClearMask";
+ stream << " UsageDenySetMask";
+ stream << " UsageDenyClearMask";
stream << " ";
stream << std::endl;
@@ -150,16 +157,30 @@
stream << std::right << std::setw(12) << info.consumer_count;
stream << std::setw(5) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_set_mask;
+ stream << std::setw(8) << info.usage_policy.producer_set_mask;
stream << std::setw(7) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_clear_mask;
+ stream << std::setw(8) << info.usage_policy.producer_clear_mask;
stream << std::setw(9) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_deny_set_mask;
+ stream << std::setw(8) << info.usage_policy.producer_deny_set_mask;
stream << std::setw(11) << std::setfill(' ') << "0x";
stream << std::hex << std::setfill('0');
- stream << std::setw(8) << info.usage_deny_clear_mask;
+ stream << std::setw(8) << info.usage_policy.producer_deny_clear_mask;
+ stream << std::setw(5) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_set_mask;
+ stream << std::setw(7) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_clear_mask;
+ stream << std::setw(9) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_deny_set_mask;
+ stream << std::setw(11) << std::setfill(' ') << "0x";
+ stream << std::hex << std::setfill('0');
+ stream << std::setw(8) << info.usage_policy.consumer_deny_clear_mask;
+ stream << std::hex << std::setfill('0');
+ stream << std::endl;
}
}
@@ -177,6 +198,7 @@
stream << std::right << std::setw(6) << info.id;
stream << std::right << std::setw(12) << info.capacity;
+ stream << std::endl;
}
}
@@ -235,48 +257,53 @@
buffer->Detach();
}
-int BufferHubService::OnCreateBuffer(Message& message, int width, int height,
- int format, int usage,
- size_t meta_size_bytes,
- size_t slice_count) {
+Status<void> BufferHubService::OnCreateBuffer(Message& message, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage,
+ uint64_t consumer_usage,
+ size_t meta_size_bytes,
+ size_t slice_count) {
// Use the producer channel id as the global buffer id.
const int buffer_id = message.GetChannelId();
ALOGD_IF(TRACE,
- "BufferHubService::OnCreateBuffer: buffer_id=%d width=%d height=%d "
- "format=%d usage=%d meta_size_bytes=%zu slice_count=%zu",
- buffer_id, width, height, format, usage, meta_size_bytes,
- slice_count);
+ "BufferHubService::OnCreateBuffer: buffer_id=%d width=%u height=%u "
+ "format=%u producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+ " meta_size_bytes=%zu slice_count=%zu",
+ buffer_id, width, height, format, producer_usage, consumer_usage,
+ meta_size_bytes, slice_count);
// See if this channel is already attached to a buffer.
if (const auto channel = message.GetChannel<BufferHubChannel>()) {
ALOGE("BufferHubService::OnCreateBuffer: Buffer already created: buffer=%d",
buffer_id);
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
- int error;
- if (const auto producer_channel =
- ProducerChannel::Create(this, buffer_id, width, height, format, usage,
- meta_size_bytes, slice_count, &error)) {
- message.SetChannel(producer_channel);
- return 0;
+ auto status = ProducerChannel::Create(this, buffer_id, width, height, format,
+ producer_usage, consumer_usage,
+ meta_size_bytes, slice_count);
+ if (status) {
+ message.SetChannel(status.take());
+ return {};
} else {
- ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
- return error;
+ ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer: %s",
+ status.GetErrorMessage().c_str());
+ return status.error_status();
}
}
-int BufferHubService::OnCreatePersistentBuffer(
+Status<void> BufferHubService::OnCreatePersistentBuffer(
Message& message, const std::string& name, int user_id, int group_id,
- int width, int height, int format, int usage, size_t meta_size_bytes,
- size_t slice_count) {
+ uint32_t width, uint32_t height, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count) {
const int channel_id = message.GetChannelId();
ALOGD_IF(TRACE,
"BufferHubService::OnCreatePersistentBuffer: channel_id=%d name=%s "
- "user_id=%d group_id=%d width=%d height=%d format=%d usage=%d "
- "meta_size_bytes=%zu slice_count=%zu",
+ "user_id=%d group_id=%d width=%u height=%u format=%u "
+ "producer_usage=%" PRIx64 " consumer_usage=%" PRIx64
+ " meta_size_bytes=%zu slice_count=%zu",
channel_id, name.c_str(), user_id, group_id, width, height, format,
- usage, meta_size_bytes, slice_count);
+ producer_usage, consumer_usage, meta_size_bytes, slice_count);
// See if this channel is already attached to a buffer.
if (const auto channel = message.GetChannel<BufferHubChannel>()) {
@@ -284,12 +311,11 @@
"BufferHubService::OnCreatePersistentBuffer: Channel already attached "
"to buffer: channel_id=%d buffer_id=%d",
channel_id, channel->buffer_id());
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
const int euid = message.GetEffectiveUserId();
const int egid = message.GetEffectiveGroupId();
- int error;
if (auto buffer = GetNamedBuffer(name)) {
if (!buffer->CheckAccess(euid, egid)) {
@@ -297,41 +323,45 @@
"BufferHubService::OnCreatePersistentBuffer: Requesting process does "
"not have permission to access named buffer: name=%s euid=%d egid=%d",
name.c_str(), euid, euid);
- return -EPERM;
- } else if (!buffer->CheckParameters(width, height, format, usage,
- meta_size_bytes, slice_count)) {
+ return ErrorStatus(EPERM);
+ } else if (!buffer->CheckParameters(width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes,
+ slice_count)) {
ALOGE(
"BufferHubService::OnCreatePersistentBuffer: Requested an existing "
"buffer with different parameters: name=%s",
name.c_str());
- return -EINVAL;
+ return ErrorStatus(EINVAL);
} else if (!buffer->IsDetached()) {
ALOGE(
"BufferHubService::OnCreatePersistentBuffer: Requesting a persistent "
"buffer that is already attached to a channel: name=%s",
name.c_str());
- return -EINVAL;
+ return ErrorStatus(EINVAL);
} else {
buffer->Attach(channel_id);
message.SetChannel(buffer);
- return 0;
+ return {};
}
- } else if (auto buffer = ProducerChannel::Create(
- this, channel_id, width, height, format, usage,
- meta_size_bytes, slice_count, &error)) {
- const int ret =
- buffer->OnProducerMakePersistent(message, name, user_id, group_id);
- if (!ret)
- message.SetChannel(buffer);
- return ret;
} else {
- ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
- return error;
+ auto status = ProducerChannel::Create(
+ this, channel_id, width, height, format, producer_usage, consumer_usage,
+ meta_size_bytes, slice_count);
+ if (!status) {
+ ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
+ return status.error_status();
+ }
+ auto persistent_buffer = status.take();
+ auto make_persistent_status = persistent_buffer->OnProducerMakePersistent(
+ message, name, user_id, group_id);
+ if (make_persistent_status)
+ message.SetChannel(persistent_buffer);
+ return make_persistent_status;
}
}
-int BufferHubService::OnGetPersistentBuffer(Message& message,
- const std::string& name) {
+Status<void> BufferHubService::OnGetPersistentBuffer(Message& message,
+ const std::string& name) {
const int channel_id = message.GetChannelId();
ALOGD_IF(TRACE,
"BufferHubService::OnGetPersistentBuffer: channel_id=%d name=%s",
@@ -343,7 +373,7 @@
"BufferHubService::OnGetPersistentBuffer: Channel already attached to "
"buffer: channel_id=%d buffer_id=%d",
channel_id, channel->buffer_id());
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
const int euid = message.GetEffectiveUserId();
@@ -355,28 +385,28 @@
"BufferHubService::OnGetPersistentBuffer: Requesting process does "
"not have permission to access named buffer: name=%s euid=%d egid=%d",
name.c_str(), euid, egid);
- return -EPERM;
+ return ErrorStatus(EPERM);
} else if (!buffer->IsDetached()) {
ALOGE(
"BufferHubService::OnGetPersistentBuffer: Requesting a persistent "
"buffer that is already attached to a channel: name=%s",
name.c_str());
- return -EINVAL;
+ return ErrorStatus(EINVAL);
} else {
buffer->Attach(channel_id);
message.SetChannel(buffer);
- return 0;
+ return {};
}
} else {
ALOGE("BufferHubService::OnGetPersistentBuffer: Buffer \"%s\" not found!",
name.c_str());
- return -ENOENT;
+ return ErrorStatus(ENOENT);
}
}
Status<QueueInfo> BufferHubService::OnCreateProducerQueue(
- pdx::Message& message, size_t meta_size_bytes, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask, int usage_deny_clear_mask) {
+ pdx::Message& message, size_t meta_size_bytes,
+ const UsagePolicy& usage_policy) {
// Use the producer channel id as the global queue id.
const int queue_id = message.GetChannelId();
ALOGD_IF(TRACE, "BufferHubService::OnCreateProducerQueue: queue_id=%d",
@@ -389,15 +419,14 @@
return ErrorStatus(EALREADY);
}
- int error;
- if (const auto producer_channel = ProducerQueueChannel::Create(
- this, queue_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
- usage_deny_set_mask, usage_deny_clear_mask, &error)) {
- message.SetChannel(producer_channel);
+ auto status = ProducerQueueChannel::Create(this, queue_id, meta_size_bytes,
+ usage_policy);
+ if (status) {
+ message.SetChannel(status.take());
return {{meta_size_bytes, queue_id}};
} else {
ALOGE("BufferHubService::OnCreateBuffer: Failed to create producer!!");
- return ErrorStatus(-error);
+ return status.error_status();
}
}
diff --git a/services/vr/bufferhubd/buffer_hub.h b/services/vr/bufferhubd/buffer_hub.h
index 150e399..4cb1eb9 100644
--- a/services/vr/bufferhubd/buffer_hub.h
+++ b/services/vr/bufferhubd/buffer_hub.h
@@ -48,43 +48,40 @@
size_t consumer_count = 0;
// Data field for buffer producer.
- int width = 0;
- int height = 0;
- int format = 0;
- int usage = 0;
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint32_t format = 0;
+ uint64_t producer_usage = 0;
+ uint64_t consumer_usage = 0;
size_t slice_count = 0;
std::string name;
// Data filed for producer queue.
size_t capacity = 0;
- int usage_set_mask = 0;
- int usage_clear_mask = 0;
- int usage_deny_set_mask = 0;
- int usage_deny_clear_mask = 0;
+ UsagePolicy usage_policy{0, 0, 0, 0, 0, 0, 0, 0};
- BufferInfo(int id, size_t consumer_count, int width, int height, int format,
- int usage, size_t slice_count, const std::string& name)
+ BufferInfo(int id, size_t consumer_count, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t slice_count,
+ const std::string& name)
: id(id),
type(kProducerType),
consumer_count(consumer_count),
width(width),
height(height),
format(format),
- usage(usage),
+ producer_usage(producer_usage),
+ consumer_usage(consumer_usage),
slice_count(slice_count),
name(name) {}
BufferInfo(int id, size_t consumer_count, size_t capacity,
- int usage_set_mask, int usage_clear_mask,
- int usage_deny_set_mask, int usage_deny_clear_mask)
+ const UsagePolicy& usage_policy)
: id(id),
type(kProducerQueueType),
consumer_count(consumer_count),
capacity(capacity),
- usage_set_mask(usage_set_mask),
- usage_clear_mask(usage_clear_mask),
- usage_deny_set_mask(usage_deny_set_mask),
- usage_deny_clear_mask(usage_deny_clear_mask) {}
+ usage_policy(usage_policy) {}
BufferInfo() {}
};
@@ -162,16 +159,19 @@
std::unordered_map<std::string, std::shared_ptr<ProducerChannel>>
named_buffers_;
- int OnCreateBuffer(pdx::Message& message, int width, int height, int format,
- int usage, size_t meta_size_bytes, size_t slice_count);
- int OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
- int user_id, int group_id, int width, int height,
- int format, int usage, size_t meta_size_bytes,
- size_t slice_count);
- int OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
- pdx::Status<QueueInfo> OnCreateProducerQueue(
- pdx::Message& message, size_t meta_size_bytes, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask, int usage_deny_clear_mask);
+ pdx::Status<void> OnCreateBuffer(pdx::Message& message, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes,
+ size_t slice_count);
+ pdx::Status<void> OnCreatePersistentBuffer(pdx::Message& message, const std::string& name,
+ int user_id, int group_id, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count);
+ pdx::Status<void> OnGetPersistentBuffer(pdx::Message& message, const std::string& name);
+ pdx::Status<QueueInfo> OnCreateProducerQueue(pdx::Message& message,
+ size_t meta_size_bytes,
+ const UsagePolicy& usage_policy);
BufferHubService(const BufferHubService&) = delete;
void operator=(const BufferHubService&) = delete;
diff --git a/services/vr/bufferhubd/consumer_channel.cpp b/services/vr/bufferhubd/consumer_channel.cpp
index 2264cef..311f5c6 100644
--- a/services/vr/bufferhubd/consumer_channel.cpp
+++ b/services/vr/bufferhubd/consumer_channel.cpp
@@ -8,9 +8,11 @@
#include <private/dvr/bufferhub_rpc.h>
#include "producer_channel.h"
+using android::pdx::ErrorStatus;
using android::pdx::BorrowedHandle;
using android::pdx::Channel;
using android::pdx::Message;
+using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
namespace android {
@@ -103,53 +105,53 @@
}
}
-std::pair<BorrowedFence, ConsumerChannel::MetaData>
+Status<std::pair<BorrowedFence, ConsumerChannel::MetaData>>
ConsumerChannel::OnConsumerAcquire(Message& message,
std::size_t metadata_size) {
ATRACE_NAME("ConsumerChannel::OnConsumerAcquire");
auto producer = GetProducer();
if (!producer)
- REPLY_ERROR_RETURN(message, EPIPE, {});
+ return ErrorStatus(EPIPE);
if (ignored_ || handled_) {
ALOGE(
"ConsumerChannel::OnConsumerAcquire: Acquire when not posted: "
"ignored=%d handled=%d channel_id=%d buffer_id=%d",
ignored_, handled_, message.GetChannelId(), producer->buffer_id());
- REPLY_ERROR_RETURN(message, EBUSY, {});
+ return ErrorStatus(EBUSY);
} else {
ClearAvailable();
return producer->OnConsumerAcquire(message, metadata_size);
}
}
-int ConsumerChannel::OnConsumerRelease(Message& message,
- LocalFence release_fence) {
+Status<void> ConsumerChannel::OnConsumerRelease(Message& message,
+ LocalFence release_fence) {
ATRACE_NAME("ConsumerChannel::OnConsumerRelease");
auto producer = GetProducer();
if (!producer)
- return -EPIPE;
+ return ErrorStatus(EPIPE);
if (ignored_ || handled_) {
ALOGE(
"ConsumerChannel::OnConsumerRelease: Release when not acquired: "
"ignored=%d handled=%d channel_id=%d buffer_id=%d",
ignored_, handled_, message.GetChannelId(), producer->buffer_id());
- return -EBUSY;
+ return ErrorStatus(EBUSY);
} else {
ClearAvailable();
- const int ret =
+ auto status =
producer->OnConsumerRelease(message, std::move(release_fence));
- handled_ = ret == 0;
- return ret;
+ handled_ = !!status;
+ return status;
}
}
-int ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
+Status<void> ConsumerChannel::OnConsumerSetIgnore(Message&, bool ignored) {
ATRACE_NAME("ConsumerChannel::OnConsumerSetIgnore");
auto producer = GetProducer();
if (!producer)
- return -EPIPE;
+ return ErrorStatus(EPIPE);
ignored_ = ignored;
if (ignored_ && !handled_) {
@@ -160,7 +162,7 @@
handled_ = false;
}
- return 0;
+ return {};
}
bool ConsumerChannel::OnProducerPosted() {
diff --git a/services/vr/bufferhubd/consumer_channel.h b/services/vr/bufferhubd/consumer_channel.h
index d2a078f..d84055c 100644
--- a/services/vr/bufferhubd/consumer_channel.h
+++ b/services/vr/bufferhubd/consumer_channel.h
@@ -32,10 +32,11 @@
std::shared_ptr<ProducerChannel> GetProducer() const;
- std::pair<BorrowedFence, MetaData> OnConsumerAcquire(
+ pdx::Status<std::pair<BorrowedFence, MetaData>> OnConsumerAcquire(
Message& message, std::size_t metadata_size);
- int OnConsumerRelease(Message& message, LocalFence release_fence);
- int OnConsumerSetIgnore(Message& message, bool ignore);
+ pdx::Status<void> OnConsumerRelease(Message& message,
+ LocalFence release_fence);
+ pdx::Status<void> OnConsumerSetIgnore(Message& message, bool ignore);
bool handled_; // True if we have processed RELEASE.
bool ignored_; // True if we are ignoring events.
diff --git a/services/vr/bufferhubd/consumer_queue_channel.cpp b/services/vr/bufferhubd/consumer_queue_channel.cpp
index cc16f1f..7422751 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.cpp
+++ b/services/vr/bufferhubd/consumer_queue_channel.cpp
@@ -4,7 +4,9 @@
#include "producer_channel.h"
+using android::pdx::ErrorStatus;
using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
using android::pdx::rpc::DispatchRemoteMethod;
namespace android {
@@ -83,7 +85,7 @@
SignalAvailable();
}
-std::vector<std::pair<RemoteChannelHandle, size_t>>
+Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
ConsumerQueueChannel::OnConsumerQueueImportBuffers(Message& message) {
std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
ATRACE_NAME("ConsumerQueueChannel::OnConsumerQueueImportBuffers");
@@ -106,31 +108,30 @@
continue;
}
- RemoteChannelHandle consumer_handle(
- producer_channel->CreateConsumer(message));
+ auto status = producer_channel->CreateConsumer(message);
// If no buffers are imported successfully, clear available and return an
// error. Otherwise, return all consumer handles already imported
// successfully, but keep available bits on, so that the client can retry
// importing remaining consumer buffers.
- if (!consumer_handle.valid()) {
+ if (!status) {
ALOGE(
- "ConsumerQueueChannel::OnConsumerQueueImportBuffers: imported "
- "consumer handle is invalid.");
+ "ConsumerQueueChannel::OnConsumerQueueImportBuffers: Failed create "
+ "consumer: %s",
+ status.GetErrorMessage().c_str());
if (buffer_handles.empty()) {
ClearAvailable();
- REPLY_ERROR_RETURN(message, EIO, {});
+ return status.error_status();
} else {
- return buffer_handles;
+ return {std::move(buffer_handles)};
}
}
- // Move consumer_handle into buffer_handles.
- buffer_handles.emplace_back(std::move(consumer_handle), producer_slot);
+ buffer_handles.emplace_back(status.take(), producer_slot);
}
ClearAvailable();
- return buffer_handles;
+ return {std::move(buffer_handles)};
}
} // namespace dvr
diff --git a/services/vr/bufferhubd/consumer_queue_channel.h b/services/vr/bufferhubd/consumer_queue_channel.h
index b345595..e1005e4 100644
--- a/services/vr/bufferhubd/consumer_queue_channel.h
+++ b/services/vr/bufferhubd/consumer_queue_channel.h
@@ -36,7 +36,7 @@
// allocated. Clients uses kOpConsumerQueueImportBuffers to import new
// consumer buffers and this handler returns a vector of fd representing
// BufferConsumers that clients can import.
- std::vector<std::pair<RemoteChannelHandle, size_t>>
+ pdx::Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
OnConsumerQueueImportBuffers(Message& message);
private:
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 903d174..c946a8d 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -13,8 +13,10 @@
#include "consumer_channel.h"
using android::pdx::BorrowedHandle;
+using android::pdx::ErrorStatus;
using android::pdx::Message;
using android::pdx::RemoteChannelHandle;
+using android::pdx::Status;
using android::pdx::rpc::BufferWrapper;
using android::pdx::rpc::DispatchRemoteMethod;
using android::pdx::rpc::WrapBuffer;
@@ -23,7 +25,9 @@
namespace dvr {
ProducerChannel::ProducerChannel(BufferHubService* service, int channel_id,
- int width, int height, int format, int usage,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage,
size_t meta_size_bytes, size_t slice_count,
int* error)
: BufferHubChannel(service, channel_id, channel_id, kProducerType),
@@ -33,7 +37,8 @@
meta_size_bytes_(meta_size_bytes),
meta_(meta_size_bytes ? new uint8_t[meta_size_bytes] : nullptr) {
for (auto& ion_buffer : slices_) {
- const int ret = ion_buffer.Alloc(width, height, format, usage);
+ const int ret =
+ ion_buffer.Alloc(width, height, format, producer_usage, consumer_usage);
if (ret < 0) {
ALOGE("ProducerChannel::ProducerChannel: Failed to allocate buffer: %s",
strerror(-ret));
@@ -46,17 +51,18 @@
*error = 0;
}
-std::shared_ptr<ProducerChannel> ProducerChannel::Create(
- BufferHubService* service, int channel_id, int width, int height,
- int format, int usage, size_t meta_size_bytes, size_t slice_count,
- int* error) {
- std::shared_ptr<ProducerChannel> producer(
- new ProducerChannel(service, channel_id, width, height, format, usage,
- meta_size_bytes, slice_count, error));
- if (*error < 0)
- return nullptr;
+Status<std::shared_ptr<ProducerChannel>> ProducerChannel::Create(
+ BufferHubService* service, int channel_id, uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage, uint64_t consumer_usage,
+ size_t meta_size_bytes, size_t slice_count) {
+ int error;
+ std::shared_ptr<ProducerChannel> producer(new ProducerChannel(
+ service, channel_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes, slice_count, &error));
+ if (error < 0)
+ return ErrorStatus(-error);
else
- return producer;
+ return {std::move(producer)};
}
ProducerChannel::~ProducerChannel() {
@@ -70,7 +76,8 @@
BufferHubChannel::BufferInfo ProducerChannel::GetBufferInfo() const {
return BufferInfo(buffer_id(), consumer_channels_.size(), slices_[0].width(),
slices_[0].height(), slices_[0].format(),
- slices_[0].usage(), slices_.size(), name_);
+ slices_[0].producer_usage(), slices_[0].consumer_usage(),
+ slices_.size(), name_);
}
void ProducerChannel::HandleImpulse(Message& message) {
@@ -125,28 +132,28 @@
}
}
-NativeBufferHandle<BorrowedHandle> ProducerChannel::OnGetBuffer(
+Status<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffer(
Message& message, unsigned index) {
ATRACE_NAME("ProducerChannel::OnGetBuffer");
ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffer: buffer=%d", buffer_id());
if (index < slices_.size()) {
- return NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id());
+ return {NativeBufferHandle<BorrowedHandle>(slices_[index], buffer_id())};
} else {
- REPLY_ERROR_RETURN(message, EINVAL, NativeBufferHandle<BorrowedHandle>());
+ return ErrorStatus(EINVAL);
}
}
-std::vector<NativeBufferHandle<BorrowedHandle>> ProducerChannel::OnGetBuffers(
- Message&) {
+Status<std::vector<NativeBufferHandle<BorrowedHandle>>>
+ProducerChannel::OnGetBuffers(Message&) {
ATRACE_NAME("ProducerChannel::OnGetBuffers");
ALOGD_IF(TRACE, "ProducerChannel::OnGetBuffers: buffer_id=%d", buffer_id());
std::vector<NativeBufferHandle<BorrowedHandle>> buffer_handles;
for (const auto& buffer : slices_)
buffer_handles.emplace_back(buffer, buffer_id());
- return buffer_handles;
+ return {std::move(buffer_handles)};
}
-RemoteChannelHandle ProducerChannel::CreateConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::CreateConsumer(Message& message) {
ATRACE_NAME("ProducerChannel::CreateConsumer");
ALOGD_IF(TRACE, "ProducerChannel::CreateConsumer: buffer_id=%d", buffer_id());
@@ -154,9 +161,9 @@
auto status = message.PushChannel(0, nullptr, &channel_id);
if (!status) {
ALOGE(
- "ProducerChannel::CreateConsumer: failed to push consumer channel: %s",
+ "ProducerChannel::CreateConsumer: Failed to push consumer channel: %s",
status.GetErrorMessage().c_str());
- return RemoteChannelHandle();
+ return ErrorStatus(ENOMEM);
}
auto consumer = std::make_shared<ConsumerChannel>(
@@ -167,7 +174,7 @@
"ProducerChannel::CreateConsumer: failed to set new consumer channel: "
"%s",
channel_status.GetErrorMessage().c_str());
- return RemoteChannelHandle();
+ return ErrorStatus(ENOMEM);
}
if (!producer_owns_) {
@@ -176,33 +183,27 @@
pending_consumers_++;
}
- return status.take();
+ return {status.take()};
}
-RemoteChannelHandle ProducerChannel::OnNewConsumer(Message& message) {
+Status<RemoteChannelHandle> ProducerChannel::OnNewConsumer(Message& message) {
ATRACE_NAME("ProducerChannel::OnNewConsumer");
ALOGD_IF(TRACE, "ProducerChannel::OnNewConsumer: buffer_id=%d", buffer_id());
-
- RemoteChannelHandle consumer_handle(CreateConsumer(message));
-
- if (consumer_handle.valid())
- return consumer_handle;
- else
- REPLY_ERROR_RETURN(message, ENOMEM, RemoteChannelHandle());
+ return CreateConsumer(message);
}
-int ProducerChannel::OnProducerPost(
+Status<void> ProducerChannel::OnProducerPost(
Message&, LocalFence acquire_fence,
BufferWrapper<std::vector<std::uint8_t>> metadata) {
ATRACE_NAME("ProducerChannel::OnProducerPost");
ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: buffer_id=%d", buffer_id());
if (!producer_owns_) {
ALOGE("ProducerChannel::OnProducerPost: Not in gained state!");
- return -EBUSY;
+ return ErrorStatus(EBUSY);
}
if (meta_size_bytes_ != metadata.size())
- return -EINVAL;
+ return ErrorStatus(EINVAL);
std::copy(metadata.begin(), metadata.end(), meta_.get());
post_fence_ = std::move(acquire_fence);
@@ -220,29 +221,29 @@
ALOGD_IF(TRACE, "ProducerChannel::OnProducerPost: %d pending consumers",
pending_consumers_);
- return 0;
+ return {};
}
-LocalFence ProducerChannel::OnProducerGain(Message& message) {
+Status<LocalFence> ProducerChannel::OnProducerGain(Message& message) {
ATRACE_NAME("ProducerChannel::OnGain");
ALOGD_IF(TRACE, "ProducerChannel::OnGain: buffer_id=%d", buffer_id());
if (producer_owns_) {
ALOGE("ProducerChanneL::OnGain: Already in gained state: channel=%d",
channel_id());
- REPLY_ERROR_RETURN(message, EALREADY, {});
+ return ErrorStatus(EALREADY);
}
// There are still pending consumers, return busy.
if (pending_consumers_ > 0)
- REPLY_ERROR_RETURN(message, EBUSY, {});
+ return ErrorStatus(EBUSY);
ClearAvailable();
producer_owns_ = true;
post_fence_.close();
- return std::move(returned_fence_);
+ return {std::move(returned_fence_)};
}
-std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>
+Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
ProducerChannel::OnConsumerAcquire(Message& message,
std::size_t metadata_size) {
ATRACE_NAME("ProducerChannel::OnConsumerAcquire");
@@ -250,26 +251,27 @@
buffer_id());
if (producer_owns_) {
ALOGE("ProducerChannel::OnConsumerAcquire: Not in posted state!");
- REPLY_ERROR_RETURN(message, EBUSY, {});
+ return ErrorStatus(EBUSY);
}
// Return a borrowed fd to avoid unnecessary duplication of the underlying fd.
// Serialization just needs to read the handle.
if (metadata_size == 0)
- return std::make_pair(post_fence_.borrow(),
- WrapBuffer<std::uint8_t>(nullptr, 0));
+ return {std::make_pair(post_fence_.borrow(),
+ WrapBuffer<std::uint8_t>(nullptr, 0))};
else
- return std::make_pair(post_fence_.borrow(),
- WrapBuffer(meta_.get(), meta_size_bytes_));
+ return {std::make_pair(post_fence_.borrow(),
+ WrapBuffer(meta_.get(), meta_size_bytes_))};
}
-int ProducerChannel::OnConsumerRelease(Message&, LocalFence release_fence) {
+Status<void> ProducerChannel::OnConsumerRelease(Message&,
+ LocalFence release_fence) {
ATRACE_NAME("ProducerChannel::OnConsumerRelease");
ALOGD_IF(TRACE, "ProducerChannel::OnConsumerRelease: buffer_id=%d",
buffer_id());
if (producer_owns_) {
ALOGE("ProducerChannel::OnConsumerRelease: Not in acquired state!");
- return -EBUSY;
+ return ErrorStatus(EBUSY);
}
// Attempt to merge the fences if necessary.
@@ -282,7 +284,7 @@
if (!merged_fence) {
ALOGE("ProducerChannel::OnConsumerRelease: Failed to merge fences: %s",
strerror(error));
- return -error;
+ return ErrorStatus(error);
}
returned_fence_ = std::move(merged_fence);
} else {
@@ -291,7 +293,7 @@
}
OnConsumerIgnored();
- return 0;
+ return {};
}
void ProducerChannel::OnConsumerIgnored() {
@@ -302,9 +304,10 @@
buffer_id(), pending_consumers_);
}
-int ProducerChannel::OnProducerMakePersistent(Message& message,
- const std::string& name,
- int user_id, int group_id) {
+Status<void> ProducerChannel::OnProducerMakePersistent(Message& message,
+ const std::string& name,
+ int user_id,
+ int group_id) {
ATRACE_NAME("ProducerChannel::OnProducerMakePersistent");
ALOGD_IF(TRACE,
"ProducerChannel::OnProducerMakePersistent: buffer_id=%d name=%s "
@@ -313,7 +316,7 @@
if (name.empty() || (user_id < 0 && user_id != kNoCheckId) ||
(group_id < 0 && group_id != kNoCheckId)) {
- return -EINVAL;
+ return ErrorStatus(EINVAL);
}
// Try to add this buffer with the requested name.
@@ -331,18 +334,18 @@
owner_user_id_ = user_id;
owner_group_id_ = group_id;
name_ = name;
- return 0;
+ return {};
} else {
// Otherwise a buffer with that name already exists.
- return -EALREADY;
+ return ErrorStatus(EALREADY);
}
}
-int ProducerChannel::OnRemovePersistence(Message&) {
+Status<void> ProducerChannel::OnRemovePersistence(Message&) {
if (service()->RemoveNamedBuffer(*this))
- return 0;
+ return {};
else
- return -ENOENT;
+ return ErrorStatus(ENOENT);
}
void ProducerChannel::AddConsumer(ConsumerChannel* channel) {
@@ -365,12 +368,16 @@
}
// Returns true if the given parameters match the underlying buffer parameters.
-bool ProducerChannel::CheckParameters(int width, int height, int format,
- int usage, size_t meta_size_bytes,
+bool ProducerChannel::CheckParameters(uint32_t width, uint32_t height,
+ uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage,
+ size_t meta_size_bytes,
size_t slice_count) {
return slices_.size() == slice_count && meta_size_bytes == meta_size_bytes_ &&
slices_[0].width() == width && slices_[0].height() == height &&
- slices_[0].format() == format && slices_[0].usage() == usage;
+ slices_[0].format() == format &&
+ slices_[0].producer_usage() == producer_usage &&
+ slices_[0].consumer_usage() == consumer_usage;
}
} // namespace dvr
diff --git a/services/vr/bufferhubd/producer_channel.h b/services/vr/bufferhubd/producer_channel.h
index e7ca459..f04c8a5 100644
--- a/services/vr/bufferhubd/producer_channel.h
+++ b/services/vr/bufferhubd/producer_channel.h
@@ -30,10 +30,10 @@
template <typename T>
using BufferWrapper = pdx::rpc::BufferWrapper<T>;
- static std::shared_ptr<ProducerChannel> Create(
- BufferHubService* service, int channel_id, int width, int height,
- int format, int usage, size_t meta_size_bytes, size_t slice_count,
- int* error);
+ static pdx::Status<std::shared_ptr<ProducerChannel>> Create(
+ BufferHubService* service, int channel_id, uint32_t width,
+ uint32_t height, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes, size_t slice_count);
~ProducerChannel() override;
@@ -42,17 +42,18 @@
BufferInfo GetBufferInfo() const override;
- NativeBufferHandle<BorrowedHandle> OnGetBuffer(Message& message,
- unsigned index);
- std::vector<NativeBufferHandle<BorrowedHandle>> OnGetBuffers(
+ pdx::Status<NativeBufferHandle<BorrowedHandle>> OnGetBuffer(Message& message,
+ unsigned index);
+ pdx::Status<std::vector<NativeBufferHandle<BorrowedHandle>>> OnGetBuffers(
Message& message);
- RemoteChannelHandle CreateConsumer(Message& message);
- RemoteChannelHandle OnNewConsumer(Message& message);
+ pdx::Status<RemoteChannelHandle> CreateConsumer(Message& message);
+ pdx::Status<RemoteChannelHandle> OnNewConsumer(Message& message);
- std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>> OnConsumerAcquire(
- Message& message, std::size_t metadata_size);
- int OnConsumerRelease(Message& message, LocalFence release_fence);
+ pdx::Status<std::pair<BorrowedFence, BufferWrapper<std::uint8_t*>>>
+ OnConsumerAcquire(Message& message, std::size_t metadata_size);
+ pdx::Status<void> OnConsumerRelease(Message& message,
+ LocalFence release_fence);
void OnConsumerIgnored();
@@ -60,12 +61,14 @@
void RemoveConsumer(ConsumerChannel* channel);
bool CheckAccess(int euid, int egid);
- bool CheckParameters(int width, int height, int format, int usage,
+ bool CheckParameters(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage,
size_t meta_size_bytes, size_t slice_count);
- int OnProducerMakePersistent(Message& message, const std::string& name,
- int user_id, int group_id);
- int OnRemovePersistence(Message& message);
+ pdx::Status<void> OnProducerMakePersistent(Message& message,
+ const std::string& name,
+ int user_id, int group_id);
+ pdx::Status<void> OnRemovePersistence(Message& message);
private:
std::vector<ConsumerChannel*> consumer_channels_;
@@ -91,13 +94,15 @@
std::string name_;
- ProducerChannel(BufferHubService* service, int channel, int width, int height,
- int format, int usage, size_t meta_size_bytes,
+ ProducerChannel(BufferHubService* service, int channel, uint32_t width,
+ uint32_t height, uint32_t format, uint64_t producer_usage,
+ uint64_t consumer_usage, size_t meta_size_bytes,
size_t slice_count, int* error);
- int OnProducerPost(Message& message, LocalFence acquire_fence,
- BufferWrapper<std::vector<std::uint8_t>> metadata);
- LocalFence OnProducerGain(Message& message);
+ pdx::Status<void> OnProducerPost(
+ Message& message, LocalFence acquire_fence,
+ BufferWrapper<std::vector<std::uint8_t>> metadata);
+ pdx::Status<LocalFence> OnProducerGain(Message& message);
ProducerChannel(const ProducerChannel&) = delete;
void operator=(const ProducerChannel&) = delete;
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 7741058..dc2a47e 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -1,5 +1,7 @@
#include "producer_queue_channel.h"
+#include <inttypes.h>
+
#include "consumer_queue_channel.h"
#include "producer_channel.h"
@@ -12,16 +14,14 @@
namespace android {
namespace dvr {
-ProducerQueueChannel::ProducerQueueChannel(
- BufferHubService* service, int channel_id, size_t meta_size_bytes,
- int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error)
+ProducerQueueChannel::ProducerQueueChannel(BufferHubService* service,
+ int channel_id,
+ size_t meta_size_bytes,
+ const UsagePolicy& usage_policy,
+ int* error)
: BufferHubChannel(service, channel_id, channel_id, kProducerQueueType),
meta_size_bytes_(meta_size_bytes),
- usage_set_mask_(usage_set_mask),
- usage_clear_mask_(usage_clear_mask),
- usage_deny_set_mask_(usage_deny_set_mask),
- usage_deny_clear_mask_(usage_deny_clear_mask),
+ usage_policy_(usage_policy),
capacity_(0) {
*error = 0;
}
@@ -29,28 +29,34 @@
ProducerQueueChannel::~ProducerQueueChannel() {}
/* static */
-std::shared_ptr<ProducerQueueChannel> ProducerQueueChannel::Create(
+Status<std::shared_ptr<ProducerQueueChannel>> ProducerQueueChannel::Create(
BufferHubService* service, int channel_id, size_t meta_size_bytes,
- int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error) {
+ const UsagePolicy& usage_policy) {
// Configuration between |usage_deny_set_mask| and |usage_deny_clear_mask|
// should be mutually exclusive.
- if (usage_deny_set_mask & usage_deny_clear_mask) {
+ if ((usage_policy.producer_deny_set_mask &
+ usage_policy.producer_deny_clear_mask) ||
+ (usage_policy.consumer_deny_set_mask &
+ usage_policy.consumer_deny_clear_mask)) {
ALOGE(
"BufferHubService::OnCreateProducerQueue: illegal usage mask "
- "configuration: usage_deny_set_mask=%d, usage_deny_clear_mask=%d",
- usage_deny_set_mask, usage_deny_clear_mask);
- *error = -EINVAL;
- return nullptr;
+ "configuration: producer_deny_set_mask=%" PRIx64
+ " producer_deny_clear_mask=%" PRIx64 " consumer_deny_set_mask=%" PRIx64
+ " consumer_deny_clear_mask=%" PRIx64,
+ usage_policy.producer_deny_set_mask,
+ usage_policy.producer_deny_clear_mask,
+ usage_policy.consumer_deny_set_mask,
+ usage_policy.consumer_deny_clear_mask);
+ return ErrorStatus(EINVAL);
}
+ int error = 0;
std::shared_ptr<ProducerQueueChannel> producer(new ProducerQueueChannel(
- service, channel_id, meta_size_bytes, usage_set_mask, usage_clear_mask,
- usage_deny_set_mask, usage_deny_clear_mask, error));
- if (*error < 0)
- return nullptr;
+ service, channel_id, meta_size_bytes, usage_policy, &error));
+ if (error < 0)
+ return ErrorStatus(-error);
else
- return producer;
+ return {std::move(producer)};
}
bool ProducerQueueChannel::HandleMessage(Message& message) {
@@ -88,8 +94,7 @@
BufferHubChannel::BufferInfo ProducerQueueChannel::GetBufferInfo() const {
return BufferInfo(channel_id(), consumer_channels_.size(), capacity_,
- usage_set_mask_, usage_clear_mask_, usage_deny_set_mask_,
- usage_deny_clear_mask_);
+ usage_policy_);
}
Status<RemoteChannelHandle> ProducerQueueChannel::OnCreateConsumerQueue(
@@ -127,11 +132,10 @@
}
Status<std::vector<std::pair<RemoteChannelHandle, size_t>>>
-ProducerQueueChannel::OnProducerQueueAllocateBuffers(Message& message,
- int width, int height,
- int format, int usage,
- size_t slice_count,
- size_t buffer_count) {
+ProducerQueueChannel::OnProducerQueueAllocateBuffers(
+ Message& message, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count,
+ size_t buffer_count) {
ATRACE_NAME("ProducerQueueChannel::OnProducerQueueAllocateBuffers");
ALOGD_IF(TRACE,
"ProducerQueueChannel::OnProducerQueueAllocateBuffers: "
@@ -141,31 +145,58 @@
std::vector<std::pair<RemoteChannelHandle, size_t>> buffer_handles;
// Deny buffer allocation violating preset rules.
- if (usage & usage_deny_set_mask_) {
+ if (producer_usage & usage_policy_.producer_deny_set_mask) {
ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
- "not permitted. Violating usage_deny_set_mask, the following bits "
- "shall not be set: %d.",
- usage, usage_deny_set_mask_);
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating producer_deny_set_mask, the following "
+ "bits shall not be set: %" PRIx64 ".",
+ producer_usage, usage_policy_.producer_deny_set_mask);
return ErrorStatus(EINVAL);
}
- if (~usage & usage_deny_clear_mask_) {
+ if (consumer_usage & usage_policy_.consumer_deny_set_mask) {
ALOGE(
- "ProducerQueueChannel::OnProducerQueueAllocateBuffers: usage: %d is "
- "not permitted. Violating usage_deny_clear_mask, the following bits "
- "must be set: %d.",
- usage, usage_deny_clear_mask_);
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating consumer_deny_set_mask, the following "
+ "bits shall not be set: %" PRIx64 ".",
+ consumer_usage, usage_policy_.consumer_deny_set_mask);
return ErrorStatus(EINVAL);
}
- // Force set mask and clear mask. Note that |usage_set_mask_| takes precedence
- // and will overwrite |usage_clear_mask_|.
- int effective_usage = (usage & ~usage_clear_mask_) | usage_set_mask_;
+ if (~producer_usage & usage_policy_.producer_deny_clear_mask) {
+ ALOGE(
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: producer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating producer_deny_clear_mask, the following "
+ "bits must be set: %" PRIx64 ".",
+ producer_usage, usage_policy_.producer_deny_clear_mask);
+ return ErrorStatus(EINVAL);
+ }
+
+ if (~consumer_usage & usage_policy_.consumer_deny_clear_mask) {
+ ALOGE(
+ "ProducerQueueChannel::OnProducerQueueAllocateBuffers: consumer_usage: "
+ "%" PRIx64
+ " is not permitted. Violating consumer_deny_clear_mask, the following "
+ "bits must be set: %" PRIx64 ".",
+ consumer_usage, usage_policy_.consumer_deny_clear_mask);
+ return ErrorStatus(EINVAL);
+ }
+ // Force set mask and clear mask. Note that |usage_policy_.X_set_mask_| takes
+ // precedence and will overwrite |usage_policy_.X_clear_mask|.
+ uint64_t effective_producer_usage =
+ (producer_usage & ~usage_policy_.producer_clear_mask) |
+ usage_policy_.producer_set_mask;
+ uint64_t effective_consumer_usage =
+ (consumer_usage & ~usage_policy_.consumer_clear_mask) |
+ usage_policy_.consumer_set_mask;
for (size_t i = 0; i < buffer_count; i++) {
- auto status = AllocateBuffer(message, width, height, format,
- effective_usage, slice_count);
+ auto status =
+ AllocateBuffer(message, width, height, format, effective_producer_usage,
+ effective_consumer_usage, slice_count);
if (!status) {
ALOGE(
"ProducerQueueChannel::OnProducerQueueAllocateBuffers: Failed to "
@@ -179,8 +210,10 @@
}
Status<std::pair<RemoteChannelHandle, size_t>>
-ProducerQueueChannel::AllocateBuffer(Message& message, int width, int height,
- int format, int usage,
+ProducerQueueChannel::AllocateBuffer(Message& message, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage,
+ uint64_t consumer_usage,
size_t slice_count) {
ATRACE_NAME("ProducerQueueChannel::AllocateBuffer");
ALOGD_IF(TRACE,
@@ -205,21 +238,24 @@
}
ALOGD_IF(TRACE,
- "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%d "
- "height=%d format=%d usage=%d slice_count=%zu",
- buffer_id, width, height, format, usage, slice_count);
+ "ProducerQueueChannel::AllocateBuffer: buffer_id=%d width=%u "
+ "height=%u format=%u producer_usage=%" PRIx64
+ " consumer_usage=%" PRIx64 " slice_count=%zu",
+ buffer_id, width, height, format, producer_usage, consumer_usage,
+ slice_count);
auto buffer_handle = status.take();
- int error;
- const auto producer_channel =
- ProducerChannel::Create(service(), buffer_id, width, height, format,
- usage, meta_size_bytes_, slice_count, &error);
- if (!producer_channel) {
+ auto producer_channel_status = ProducerChannel::Create(
+ service(), buffer_id, width, height, format, producer_usage,
+ consumer_usage, meta_size_bytes_, slice_count);
+ if (!producer_channel_status) {
ALOGE(
- "ProducerQueueChannel::AllocateBuffer: Failed to create "
- "BufferHubBuffer producer!!");
+ "ProducerQueueChannel::AllocateBuffer: Failed to create producer "
+ "buffer: %s",
+ producer_channel_status.GetErrorMessage().c_str());
return ErrorStatus(ENOMEM);
}
+ auto producer_channel = producer_channel_status.take();
ALOGD_IF(
TRACE,
diff --git a/services/vr/bufferhubd/producer_queue_channel.h b/services/vr/bufferhubd/producer_queue_channel.h
index a12a37d..09b0243 100644
--- a/services/vr/bufferhubd/producer_queue_channel.h
+++ b/services/vr/bufferhubd/producer_queue_channel.h
@@ -11,10 +11,9 @@
class ProducerQueueChannel : public BufferHubChannel {
public:
- static std::shared_ptr<ProducerQueueChannel> Create(
+ static pdx::Status<std::shared_ptr<ProducerQueueChannel>> Create(
BufferHubService* service, int channel_id, size_t meta_size_bytes,
- int usage_set_mask, int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error);
+ const UsagePolicy& usage_policy);
~ProducerQueueChannel() override;
bool HandleMessage(pdx::Message& message) override;
@@ -34,8 +33,10 @@
// Allocate a new BufferHubProducer according to the input spec. Client may
// handle this as if a new producer is created through kOpCreateBuffer.
pdx::Status<std::vector<std::pair<pdx::RemoteChannelHandle, size_t>>>
- OnProducerQueueAllocateBuffers(pdx::Message& message, int width, int height,
- int format, int usage, size_t slice_count,
+ OnProducerQueueAllocateBuffers(pdx::Message& message, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint64_t producer_usage,
+ uint64_t consumer_usage, size_t slice_count,
size_t buffer_count);
// Detach a BufferHubProducer indicated by |slot|. Note that the buffer must
@@ -48,18 +49,17 @@
private:
ProducerQueueChannel(BufferHubService* service, int channel_id,
- size_t meta_size_bytes, int usage_set_mask,
- int usage_clear_mask, int usage_deny_set_mask,
- int usage_deny_clear_mask, int* error);
+ size_t meta_size_bytes, const UsagePolicy& usage_policy,
+ int* error);
// Allocate one single producer buffer by |OnProducerQueueAllocateBuffers|.
// Note that the newly created buffer's file handle will be pushed to client
// and our return type is a RemoteChannelHandle.
- // Returns the remote channdel handle and the slot number for the newly
+ // Returns the remote channel handle and the slot number for the newly
// allocated buffer.
pdx::Status<std::pair<pdx::RemoteChannelHandle, size_t>> AllocateBuffer(
- pdx::Message& message, int width, int height, int format, int usage,
- size_t slice_count);
+ pdx::Message& message, uint32_t width, uint32_t height, uint32_t format,
+ uint64_t producer_usage, uint64_t consumer_usage, size_t slice_count);
// Size of the meta data associated with all the buffers allocated from the
// queue. Now we assume the metadata size is immutable once the queue is
@@ -68,10 +68,7 @@
// A set of variables to control what |usage| bits can this ProducerQueue
// allocate.
- int usage_set_mask_;
- int usage_clear_mask_;
- int usage_deny_set_mask_;
- int usage_deny_clear_mask_;
+ UsagePolicy usage_policy_;
// Provides access to the |channel_id| of all consumer channels associated
// with this producer.
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
index 45eabca..db7d5dc 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_frame.cpp
@@ -28,6 +28,26 @@
ret = parcel->writeBool(frame_.removed);
if (ret != OK) return ret;
+ ret = parcel->writeUint32(static_cast<uint32_t>(frame_.active_config));
+ if (ret != OK) return ret;
+
+ ret = parcel->writeUint32(static_cast<uint32_t>(frame_.color_mode));
+ if (ret != OK) return ret;
+
+ ret = parcel->writeUint32(static_cast<uint32_t>(frame_.power_mode));
+ if (ret != OK) return ret;
+
+ ret = parcel->writeUint32(static_cast<uint32_t>(frame_.vsync_enabled));
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(frame_.color_transform_hint);
+ if (ret != OK) return ret;
+
+ for(size_t i = 0; i < 16; i++) {
+ ret = parcel->writeFloat(frame_.color_transform[i]);
+ if (ret != OK) return ret;
+ }
+
std::vector<ParcelableComposerLayer> layers;
for (size_t i = 0; i < frame_.layers.size(); ++i)
layers.push_back(ParcelableComposerLayer(frame_.layers[i]));
@@ -50,6 +70,31 @@
ret = parcel->readBool(&frame_.removed);
if (ret != OK) return ret;
+ uint32_t value;
+ ret = parcel->readUint32(&value);
+ if (ret != OK) return ret;
+ frame_.active_config = static_cast<Config>(value);
+
+ ret = parcel->readUint32(&value);
+ if (ret != OK) return ret;
+ frame_.color_mode = static_cast<ColorMode>(value);
+
+ ret = parcel->readUint32(&value);
+ if (ret != OK) return ret;
+ frame_.power_mode = static_cast<IComposerClient::PowerMode>(value);
+
+ ret = parcel->readUint32(&value);
+ if (ret != OK) return ret;
+ frame_.vsync_enabled = static_cast<IComposerClient::Vsync>(value);
+
+ ret = parcel->readInt32(&frame_.color_transform_hint);
+ if (ret != OK) return ret;
+
+ for(size_t i = 0; i < 16; i++) {
+ ret = parcel->readFloat(&frame_.color_transform[i]);
+ if (ret != OK) return ret;
+ }
+
std::vector<ParcelableComposerLayer> layers;
ret = parcel->readParcelableVector(&layers);
if (ret != OK) return ret;
diff --git a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
index 999d71e..c3621eb 100644
--- a/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
+++ b/services/vr/hardware_composer/aidl/android/dvr/parcelable_composer_layer.cpp
@@ -7,41 +7,6 @@
namespace android {
namespace dvr {
-namespace {
-
-sp<GraphicBuffer> GetBufferFromHandle(native_handle_t* handle) {
- uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
- uint64_t producer_usage = 0, consumer_usage = 0;
- int32_t format = 0;
-
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
- // Need to register |handle| otherwise we can't read its properties.
- if (mapper.registerBuffer(handle) != OK) {
- ALOGE("Failed to register buffer");
- return nullptr;
- }
-
- if (mapper.getDimensions(handle, &width, &height) ||
- mapper.getStride(handle, &stride) ||
- mapper.getFormat(handle, &format) ||
- mapper.getProducerUsage(handle, &producer_usage) ||
- mapper.getConsumerUsage(handle, &consumer_usage)) {
- ALOGE("Failed to read handle properties");
- return nullptr;
- }
-
- // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
- // capability. Otherwise assume a count of 1.
- mapper.getLayerCount(handle, &layer_count);
-
- sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
- GraphicBuffer::TAKE_HANDLE, width, height, format, layer_count,
- producer_usage, consumer_usage, stride);
-
- return buffer;
-}
-
-} // namespace
ParcelableComposerLayer::ParcelableComposerLayer() {}
@@ -54,7 +19,7 @@
status_t ret = parcel->writeUint64(layer_.id);
if (ret != OK) return ret;
- ret = parcel->writeNativeHandle(layer_.buffer->getNativeBuffer()->handle);
+ ret = parcel->write(*layer_.buffer);
if (ret != OK) return ret;
ret = parcel->writeBool(layer_.fence->isValid());
@@ -101,6 +66,50 @@
ret = parcel->writeUint32(layer_.app_id);
if (ret != OK) return ret;
+ ret = parcel->writeUint32(layer_.z_order);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(layer_.cursor_x);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(layer_.cursor_y);
+ if (ret != OK) return ret;
+
+ uint32_t color = layer_.color.r |
+ (static_cast<uint32_t>(layer_.color.g) << 8) |
+ (static_cast<uint32_t>(layer_.color.b) << 16) |
+ (static_cast<uint32_t>(layer_.color.a) << 24);
+ ret = parcel->writeUint32(color);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(layer_.dataspace);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeInt32(layer_.transform);
+ if (ret != OK) return ret;
+
+ ret = parcel->writeUint32(static_cast<uint32_t>(layer_.visible_regions.size()));
+ if (ret != OK) return ret;
+
+ for (auto& rect: layer_.visible_regions) {
+ ret = parcel->writeInt32(rect.left);
+ ret = parcel->writeInt32(rect.top);
+ ret = parcel->writeInt32(rect.right);
+ ret = parcel->writeInt32(rect.bottom);
+ if (ret != OK) return ret;
+ }
+
+ ret = parcel->writeUint32(static_cast<uint32_t>(layer_.damaged_regions.size()));
+ if (ret != OK) return ret;
+
+ for (auto& rect: layer_.damaged_regions) {
+ ret = parcel->writeInt32(rect.left);
+ ret = parcel->writeInt32(rect.top);
+ ret = parcel->writeInt32(rect.right);
+ ret = parcel->writeInt32(rect.bottom);
+ if (ret != OK) return ret;
+ }
+
return OK;
}
@@ -108,11 +117,12 @@
status_t ret = parcel->readUint64(&layer_.id);
if (ret != OK) return ret;
- native_handle* handle = parcel->readNativeHandle();
- if (!handle) return BAD_VALUE;
-
- layer_.buffer = GetBufferFromHandle(handle);
- if (!layer_.buffer.get()) return BAD_VALUE;
+ layer_.buffer = new GraphicBuffer();
+ ret = parcel->read(*layer_.buffer);
+ if (ret != OK) {
+ layer_.buffer.clear();
+ return ret;
+ }
bool has_fence = 0;
ret = parcel->readBool(&has_fence);
@@ -159,6 +169,70 @@
ret = parcel->readUint32(&layer_.app_id);
if (ret != OK) return ret;
+ ret = parcel->readUint32(&layer_.z_order);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&layer_.cursor_x);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&layer_.cursor_y);
+ if (ret != OK) return ret;
+
+ uint32_t color;
+ ret = parcel->readUint32(&color);
+ if (ret != OK) return ret;
+ layer_.color.r = color & 0xFF;
+ layer_.color.g = (color >> 8) & 0xFF;
+ layer_.color.b = (color >> 16) & 0xFF;
+ layer_.color.a = (color >> 24) & 0xFF;
+
+ ret = parcel->readInt32(&layer_.dataspace);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&layer_.transform);
+ if (ret != OK) return ret;
+
+ uint32_t size;
+ ret = parcel->readUint32(&size);
+ if (ret != OK) return ret;
+
+ for(size_t i = 0; i < size; i++) {
+ hwc_rect_t rect;
+ ret = parcel->readInt32(&rect.left);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&rect.top);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&rect.right);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&rect.bottom);
+ if (ret != OK) return ret;
+
+ layer_.visible_regions.push_back(rect);
+ }
+
+ ret = parcel->readUint32(&size);
+ if (ret != OK) return ret;
+
+ for(size_t i = 0; i < size; i++) {
+ hwc_rect_t rect;
+ ret = parcel->readInt32(&rect.left);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&rect.top);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&rect.right);
+ if (ret != OK) return ret;
+
+ ret = parcel->readInt32(&rect.bottom);
+ if (ret != OK) return ret;
+
+ layer_.damaged_regions.push_back(rect);
+ }
+
return OK;
}
diff --git a/services/vr/vr_window_manager/composer/Android.bp b/services/vr/vr_window_manager/composer/Android.bp
index 007251f..1998749 100644
--- a/services/vr/vr_window_manager/composer/Android.bp
+++ b/services/vr/vr_window_manager/composer/Android.bp
@@ -10,9 +10,9 @@
static_libs: [
"libhwcomposer-client",
"libdisplay",
- "libpdx_default_transport",
- "libbufferhub",
"libbufferhubqueue",
+ "libbufferhub",
+ "libpdx_default_transport",
],
shared_libs: [
@@ -35,6 +35,7 @@
],
export_shared_lib_headers: [
+ "android.frameworks.vr.composer@1.0",
"android.hardware.graphics.composer@2.1",
],
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
index acf0dac..e0bdf1c 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.cpp
@@ -50,6 +50,10 @@
switch (vrCommand) {
case IVrComposerClient::VrCommand::SET_LAYER_INFO:
return parseSetLayerInfo(length);
+ case IVrComposerClient::VrCommand::SET_CLIENT_TARGET_METADATA:
+ return parseSetClientTargetMetadata(length);
+ case IVrComposerClient::VrCommand::SET_LAYER_BUFFER_METADATA:
+ return parseSetLayerBufferMetadata(length);
default:
return CommandReader::parseCommand(command, length);
}
@@ -68,5 +72,43 @@
return true;
}
+bool VrComposerClient::VrCommandReader::parseSetClientTargetMetadata(
+ uint16_t length) {
+ if (length != 7)
+ return false;
+
+ auto err = mVrHal.setClientTargetMetadata(mDisplay, readBufferMetadata());
+ if (err != Error::NONE)
+ mWriter.setError(getCommandLoc(), err);
+
+ return true;
+}
+
+bool VrComposerClient::VrCommandReader::parseSetLayerBufferMetadata(
+ uint16_t length) {
+ if (length != 7)
+ return false;
+
+ auto err = mVrHal.setLayerBufferMetadata(mDisplay, mLayer,
+ readBufferMetadata());
+ if (err != Error::NONE)
+ mWriter.setError(getCommandLoc(), err);
+
+ return true;
+}
+
+IVrComposerClient::BufferMetadata
+VrComposerClient::VrCommandReader::readBufferMetadata() {
+ IVrComposerClient::BufferMetadata metadata = {
+ .width = read(),
+ .height = read(),
+ .stride = read(),
+ .layerCount = read(),
+ .format = static_cast<PixelFormat>(readSigned()),
+ .usage = read64(),
+ };
+ return metadata;
+}
+
} // namespace dvr
} // namespace android
diff --git a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
index 8f0c562..8d601ab 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_composer_client.h
@@ -17,6 +17,7 @@
#ifndef VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
#define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_COMPOSER_CLIENT_H_
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <ComposerClient.h>
#include <IComposerCommandBuffer.h>
@@ -44,6 +45,10 @@
private:
bool parseSetLayerInfo(uint16_t length);
+ bool parseSetClientTargetMetadata(uint16_t length);
+ bool parseSetLayerBufferMetadata(uint16_t length);
+
+ IVrComposerClient::BufferMetadata readBufferMetadata();
VrComposerClient& mVrClient;
android::dvr::VrHwc& mVrHal;
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
index 9ba01f9..f5d88f2 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.cpp
@@ -16,8 +16,6 @@
#include "vr_hwc.h"
#include <ui/Fence.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicBufferMapper.h>
#include <mutex>
@@ -43,35 +41,19 @@
const Display kDefaultDisplayId = 1;
const Config kDefaultConfigId = 1;
-sp<GraphicBuffer> GetBufferFromHandle(const native_handle_t* handle) {
- uint32_t width = 0, height = 0, stride = 0, layer_count = 1;
- uint64_t producer_usage = 0, consumer_usage = 0;
- int32_t format = 0;
+sp<GraphicBuffer> CreateGraphicBuffer(
+ const native_handle_t* handle,
+ const IVrComposerClient::BufferMetadata& metadata) {
+ sp<GraphicBuffer> buffer = new GraphicBuffer(
+ handle, GraphicBuffer::CLONE_HANDLE, metadata.width, metadata.height,
+ static_cast<int32_t>(metadata.format), metadata.layerCount,
+ metadata.usage, metadata.usage, metadata.stride);
+ if (buffer->initCheck() != OK) {
+ ALOGE("Failed to create graphic buffer");
+ return nullptr;
+ }
- GraphicBufferMapper& mapper = GraphicBufferMapper::get();
- if (mapper.getDimensions(handle, &width, &height) ||
- mapper.getStride(handle, &stride) ||
- mapper.getFormat(handle, &format) ||
- mapper.getProducerUsage(handle, &producer_usage) ||
- mapper.getConsumerUsage(handle, &consumer_usage)) {
- ALOGE("Failed to read handle properties");
- return nullptr;
- }
-
- // This will only succeed if gralloc has GRALLOC1_CAPABILITY_LAYERED_BUFFERS
- // capability. Otherwise assume a count of 1.
- mapper.getLayerCount(handle, &layer_count);
-
- // NOTE: Can't re-use |handle| since we don't own it.
- sp<GraphicBuffer> buffer = new GraphicBuffer(handle,
- GraphicBuffer::CLONE_HANDLE, width, height, format, layer_count,
- producer_usage, consumer_usage, stride);
- if (buffer->initCheck() != OK) {
- ALOGE("Failed to register cloned buffer");
- return nullptr;
- }
-
- return buffer;
+ return buffer;
}
void GetPrimaryDisplaySize(int32_t* width, int32_t* height) {
@@ -109,12 +91,17 @@
bool HwcDisplay::SetClientTarget(const native_handle_t* handle,
base::unique_fd fence) {
if (handle)
- buffer_ = GetBufferFromHandle(handle);
+ buffer_ = CreateGraphicBuffer(handle, buffer_metadata_);
fence_ = new Fence(fence.release());
return true;
}
+void HwcDisplay::SetClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata) {
+ buffer_metadata_ = metadata;
+}
+
HwcLayer* HwcDisplay::CreateLayer() {
uint64_t layer_id = layer_ids_++;
layers_.push_back(HwcLayer(layer_id));
@@ -145,7 +132,7 @@
std::vector<IComposerClient::Composition>* types) {
std::sort(layers_.begin(), layers_.end(),
[](const auto& lhs, const auto& rhs) {
- return lhs.z_order < rhs.z_order;
+ return lhs.info.z_order < rhs.info.z_order;
});
int first_client_layer = -1, last_client_layer = -1;
@@ -233,6 +220,12 @@
return last_frame_layers;
}
+void HwcDisplay::SetColorTransform(const float* matrix, int32_t hint) {
+ color_transform_hint_ = hint;
+ if (matrix)
+ memcpy(color_transform_, matrix, sizeof(color_transform_));
+}
+
////////////////////////////////////////////////////////////////////////////////
// VrHwcClient
@@ -410,40 +403,54 @@
Error VrHwc::setActiveConfig(Display display, Config config) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
if (config != kDefaultConfigId)
return Error::BAD_CONFIG;
+ display_ptr->set_active_config(config);
return Error::NONE;
}
Error VrHwc::setColorMode(Display display, ColorMode mode) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ display_ptr->set_color_mode(mode);
return Error::NONE;
}
Error VrHwc::setPowerMode(Display display, IComposerClient::PowerMode mode) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ display_ptr->set_power_mode(mode);
return Error::NONE;
}
Error VrHwc::setVsyncEnabled(Display display, IComposerClient::Vsync enabled) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ display_ptr->set_vsync_enabled(enabled);
return Error::NONE;
}
Error VrHwc::setColorTransform(Display display, const float* matrix,
int32_t hint) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ display_ptr->SetColorTransform(matrix, hint);
return Error::NONE;
}
@@ -513,6 +520,13 @@
frame.display_id = display;
frame.display_width = display_ptr->width();
frame.display_height = display_ptr->height();
+ frame.active_config = display_ptr->active_config();
+ frame.power_mode = display_ptr->power_mode();
+ frame.vsync_enabled = display_ptr->vsync_enabled();
+ frame.color_transform_hint = display_ptr->color_transform_hint();
+ frame.color_mode = display_ptr->color_mode();
+ memcpy(frame.color_transform, display_ptr->color_transform(),
+ sizeof(frame.color_transform));
if (status != Error::NONE)
return status;
@@ -536,8 +550,16 @@
Error VrHwc::setLayerCursorPosition(Display display, Layer layer, int32_t x,
int32_t y) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->info.cursor_x = x;
+ hwc_layer->info.cursor_y = y;
return Error::NONE;
}
@@ -553,7 +575,8 @@
if (!hwc_layer)
return Error::BAD_LAYER;
- hwc_layer->info.buffer = GetBufferFromHandle(buffer);
+ hwc_layer->info.buffer = CreateGraphicBuffer(
+ buffer, hwc_layer->buffer_metadata);
hwc_layer->info.fence = new Fence(fence.release());
return Error::NONE;
@@ -562,8 +585,15 @@
Error VrHwc::setLayerSurfaceDamage(Display display, Layer layer,
const std::vector<hwc_rect_t>& damage) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->info.damaged_regions = damage;
return Error::NONE;
}
@@ -586,8 +616,15 @@
Error VrHwc::setLayerColor(Display display, Layer layer,
IComposerClient::Color color) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->info.color = color;
return Error::NONE;
}
@@ -610,8 +647,15 @@
Error VrHwc::setLayerDataspace(Display display, Layer layer,
int32_t dataspace) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->info.dataspace = dataspace;
return Error::NONE;
}
@@ -674,16 +718,30 @@
Error VrHwc::setLayerTransform(Display display, Layer layer,
int32_t transform) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->info.transform = transform;
return Error::NONE;
}
Error VrHwc::setLayerVisibleRegion(Display display, Layer layer,
const std::vector<hwc_rect_t>& visible) {
std::lock_guard<std::mutex> guard(mutex_);
- if (!FindDisplay(display))
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->info.visible_regions = visible;
return Error::NONE;
}
@@ -697,7 +755,7 @@
if (!hwc_layer)
return Error::BAD_LAYER;
- hwc_layer->z_order = z;
+ hwc_layer->info.z_order = z;
return Error::NONE;
}
@@ -719,6 +777,35 @@
return Error::NONE;
}
+Error VrHwc::setClientTargetMetadata(
+ Display display, const IVrComposerClient::BufferMetadata& metadata) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
+ return Error::BAD_DISPLAY;
+
+ display_ptr->SetClientTargetMetadata(metadata);
+
+ return Error::NONE;
+}
+
+Error VrHwc::setLayerBufferMetadata(
+ Display display, Layer layer,
+ const IVrComposerClient::BufferMetadata& metadata) {
+ std::lock_guard<std::mutex> guard(mutex_);
+ auto display_ptr = FindDisplay(display);
+ if (!display_ptr)
+ return Error::BAD_DISPLAY;
+
+ HwcLayer* hwc_layer = display_ptr->GetLayer(layer);
+ if (!hwc_layer)
+ return Error::BAD_LAYER;
+
+ hwc_layer->buffer_metadata = metadata;
+
+ return Error::NONE;
+}
+
Return<void> VrHwc::getCapabilities(getCapabilities_cb hidl_cb) {
hidl_cb(hidl_vec<Capability>());
return Void();
diff --git a/services/vr/vr_window_manager/composer/impl/vr_hwc.h b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
index bfca9a6..609d925 100644
--- a/services/vr/vr_window_manager/composer/impl/vr_hwc.h
+++ b/services/vr/vr_window_manager/composer/impl/vr_hwc.h
@@ -17,6 +17,7 @@
#define VR_WINDOW_MANAGER_COMPOSER_IMPL_VR_HWC_H_
#include <android-base/unique_fd.h>
+#include <android/frameworks/vr/composer/1.0/IVrComposerClient.h>
#include <android/hardware/graphics/composer/2.1/IComposer.h>
#include <ComposerBase.h>
#include <ui/Fence.h>
@@ -26,6 +27,7 @@
#include <mutex>
#include <unordered_map>
+using namespace android::frameworks::vr::composer::V1_0;
using namespace android::hardware::graphics::common::V1_0;
using namespace android::hardware::graphics::composer::V2_1;
@@ -38,7 +40,6 @@
namespace android {
class Fence;
-class GraphicBuffer;
namespace dvr {
@@ -55,8 +56,6 @@
using BlendMode =
hardware::graphics::composer::V2_1::IComposerClient::BlendMode;
- // TODO(dnicoara): Add all layer properties. For now just the basics to get
- // it going.
Layer id;
sp<GraphicBuffer> buffer;
sp<Fence> fence;
@@ -66,6 +65,14 @@
float alpha;
uint32_t type;
uint32_t app_id;
+ uint32_t z_order;
+ int32_t cursor_x;
+ int32_t cursor_y;
+ IComposerClient::Color color;
+ int32_t dataspace;
+ int32_t transform;
+ std::vector<hwc_rect_t> visible_regions;
+ std::vector<hwc_rect_t> damaged_regions;
};
struct Frame {
@@ -76,6 +83,12 @@
bool removed = false;
int32_t display_width;
int32_t display_height;
+ Config active_config;
+ ColorMode color_mode;
+ IComposerClient::PowerMode power_mode;
+ IComposerClient::Vsync vsync_enabled;
+ float color_transform[16];
+ int32_t color_transform_hint;
std::vector<ComposerLayer> layers;
};
@@ -103,8 +116,8 @@
}
Composition composition_type;
- uint32_t z_order;
ComposerView::ComposerLayer info;
+ IVrComposerClient::BufferMetadata buffer_metadata;
};
class HwcDisplay {
@@ -120,6 +133,8 @@
HwcLayer* GetLayer(Layer id);
bool SetClientTarget(const native_handle_t* handle, base::unique_fd fence);
+ void SetClientTargetMetadata(
+ const IVrComposerClient::BufferMetadata& metadata);
void GetChangedCompositionTypes(
std::vector<Layer>* layer_ids,
@@ -129,10 +144,28 @@
std::vector<Layer> UpdateLastFrameAndGetLastFrameLayers();
+ Config active_config() const { return active_config_; }
+ void set_active_config(Config config) { active_config_ = config; }
+
+ ColorMode color_mode() const { return color_mode_; }
+ void set_color_mode(ColorMode mode) { color_mode_ = mode; }
+
+ IComposerClient::PowerMode power_mode() const { return power_mode_; }
+ void set_power_mode(IComposerClient::PowerMode mode) { power_mode_ = mode; }
+
+ IComposerClient::Vsync vsync_enabled() const { return vsync_enabled_; }
+ void set_vsync_enabled(IComposerClient::Vsync vsync) {
+ vsync_enabled_ = vsync;
+ }
+
+ const float* color_transform() const { return color_transform_; }
+ int32_t color_transform_hint() const { return color_transform_hint_; }
+ void SetColorTransform(const float* matrix, int32_t hint);
+
private:
// The client target buffer and the associated fence.
- // TODO(dnicoara): Replace this with a list of ComposerView::ComposerLayer.
sp<GraphicBuffer> buffer_;
+ IVrComposerClient::BufferMetadata buffer_metadata_;
sp<Fence> fence_;
// List of currently active layers.
@@ -146,6 +179,13 @@
int32_t width_;
int32_t height_;
+ Config active_config_;
+ ColorMode color_mode_;
+ IComposerClient::PowerMode power_mode_;
+ IComposerClient::Vsync vsync_enabled_;
+ float color_transform_[16];
+ int32_t color_transform_hint_;
+
HwcDisplay(const HwcDisplay&) = delete;
void operator=(const HwcDisplay&) = delete;
};
@@ -159,6 +199,11 @@
Error setLayerInfo(Display display, Layer layer, uint32_t type,
uint32_t appId);
+ Error setClientTargetMetadata(
+ Display display, const IVrComposerClient::BufferMetadata& metadata);
+ Error setLayerBufferMetadata(
+ Display display, Layer layer,
+ const IVrComposerClient::BufferMetadata& metadata);
// ComposerBase
void removeClient() override;
diff --git a/services/vr/vr_window_manager/hwc_callback.cpp b/services/vr/vr_window_manager/hwc_callback.cpp
index 43f5042..28e97ff 100644
--- a/services/vr/vr_window_manager/hwc_callback.cpp
+++ b/services/vr/vr_window_manager/hwc_callback.cpp
@@ -32,6 +32,15 @@
} // namespace
+void HwcCallback::HwcLayer::PrintLayer() {
+ ALOGI("appid=%d, type=%d, alpha=%.2f, cursor=%dx%d, color=%02X%02X%02X%02X, "
+ "crop=%.1f,%.1f,%.1f,%.1f, display=%d,%d,%d,%d, dataspace=%d, "
+ "transform=%d", appid, type, alpha, cursor_x, cursor_y, color.r, color.g,
+ color.b, color.a, crop.left, crop.top, crop.right, crop.bottom,
+ display_frame.left, display_frame.right, display_frame.top,
+ display_frame.bottom, dataspace, transform);
+}
+
HwcCallback::HwcCallback(Client* client) : client_(client) {
}
@@ -54,6 +63,11 @@
.appid = layer.app_id,
.type = static_cast<HwcLayer::LayerType>(layer.type),
.alpha = layer.alpha,
+ .cursor_x = layer.cursor_x,
+ .cursor_y = layer.cursor_y,
+ .color = layer.color,
+ .dataspace = layer.dataspace,
+ .transform = layer.transform,
};
}
diff --git a/services/vr/vr_window_manager/hwc_callback.h b/services/vr/vr_window_manager/hwc_callback.h
index f1f91a1..4269430 100644
--- a/services/vr/vr_window_manager/hwc_callback.h
+++ b/services/vr/vr_window_manager/hwc_callback.h
@@ -65,6 +65,8 @@
}
}
+ void PrintLayer();
+
sp<Fence> fence;
sp<GraphicBuffer> buffer;
Rectf crop;
@@ -73,6 +75,11 @@
uint32_t appid;
LayerType type;
float alpha;
+ int32_t cursor_x;
+ int32_t cursor_y;
+ IComposerClient::Color color;
+ int32_t dataspace;
+ int32_t transform;
};
enum class FrameStatus {
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 3fd8c51..91c270e 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -26,6 +26,7 @@
cc_library_headers {
name: "vulkan_headers",
export_include_dirs: ["include"],
+ vendor_available: true,
}
subdirs = [
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 9444da5..6149894 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -14,7 +14,7 @@
// Headers module is in frameworks/native/vulkan/Android.bp.
ndk_library {
- name: "libvulkan.ndk",
+ name: "libvulkan",
symbol_file: "libvulkan.map.txt",
first_version: "24",
unversioned_until: "current",
@@ -78,6 +78,7 @@
"libutils",
"libcutils",
"libz",
+ "libnativewindow",
],
static_libs: ["libgrallocusage"],
}
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 5fbf5f5..f2cd8e6 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -34,6 +34,11 @@
#include "driver.h"
#include "stubhal.h"
+// TODO(b/37049319) Get this from a header once one exists
+extern "C" {
+android_namespace_t* android_get_exported_namespace(const char*);
+}
+
// Set to true to enable exposing unratified extensions for development
static const bool kEnableUnratifiedExtensions = false;
@@ -150,14 +155,12 @@
"ro.board.platform",
}};
-int LoadUpdatedDriver(const hw_module_t** module) {
+int LoadDriver(android_namespace_t* library_namespace,
+ const hwvulkan_module_t** module) {
const android_dlextinfo dlextinfo = {
.flags = ANDROID_DLEXT_USE_NAMESPACE,
- .library_namespace = android::GraphicsEnv::getInstance().getDriverNamespace(),
+ .library_namespace = library_namespace,
};
- if (!dlextinfo.library_namespace)
- return -ENOENT;
-
void* so = nullptr;
char prop[PROPERTY_VALUE_MAX];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
@@ -171,7 +174,7 @@
if (!so)
return -ENOENT;
- hw_module_t* hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
+ auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
if (!hmi) {
ALOGE("couldn't find symbol '%s' in HAL library: %s", HAL_MODULE_INFO_SYM_AS_STR, dlerror());
dlclose(so);
@@ -183,11 +186,24 @@
return -EINVAL;
}
hmi->dso = so;
- *module = hmi;
- ALOGD("loaded updated driver");
+ *module = reinterpret_cast<const hwvulkan_module_t*>(hmi);
return 0;
}
+int LoadBuiltinDriver(const hwvulkan_module_t** module) {
+ auto ns = android_get_exported_namespace("sphal");
+ if (!ns)
+ return -ENOENT;
+ return LoadDriver(ns, module);
+}
+
+int LoadUpdatedDriver(const hwvulkan_module_t** module) {
+ auto ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+ if (!ns)
+ return -ENOENT;
+ return LoadDriver(ns, module);
+}
+
bool Hal::Open() {
ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
@@ -197,9 +213,21 @@
int result;
const hwvulkan_module_t* module = nullptr;
- result = LoadUpdatedDriver(reinterpret_cast<const hw_module_t**>(&module));
+ result = LoadUpdatedDriver(&module);
if (result == -ENOENT) {
- result = hw_get_module(HWVULKAN_HARDWARE_MODULE_ID, reinterpret_cast<const hw_module_t**>(&module));
+ result = LoadBuiltinDriver(&module);
+ if (result != 0) {
+ // -ENOENT means the sphal namespace doesn't exist, not that there
+ // is a problem with the driver.
+ ALOGW_IF(
+ result != -ENOENT,
+ "Failed to load Vulkan driver into sphal namespace. This "
+ "usually means the driver has forbidden library dependencies."
+ "Please fix, this will soon stop working.");
+ result =
+ hw_get_module(HWVULKAN_HARDWARE_MODULE_ID,
+ reinterpret_cast<const hw_module_t**>(&module));
+ }
}
if (result != 0) {
ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
@@ -789,9 +817,6 @@
loader_extensions.push_back({
VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME,
VK_KHR_INCREMENTAL_PRESENT_SPEC_VERSION});
- loader_extensions.push_back({
- VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
- VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
if (kEnableUnratifiedExtensions) {
// conditionally add shared_presentable_image if supportable
@@ -804,6 +829,16 @@
}
}
+ // conditionally add VK_GOOGLE_display_timing if present timestamps are
+ // supported by the driver:
+ char timestamp_property[PROPERTY_VALUE_MAX];
+ property_get("service.sf.present_timestamp", timestamp_property, "1");
+ if (strcmp(timestamp_property, "1") == 0) {
+ loader_extensions.push_back({
+ VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME,
+ VK_GOOGLE_DISPLAY_TIMING_SPEC_VERSION});
+ }
+
// enumerate our extensions first
if (!pLayerName && pProperties) {
uint32_t count = std::min(
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 3b785e6..caa2674 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -114,14 +114,34 @@
: vals_{qp->presentID, qp->desiredPresentTime, 0, 0, 0},
native_frame_id_(nativeFrameId) {}
bool ready() const {
- return (timestamp_desired_present_time_ &&
- timestamp_actual_present_time_ &&
- timestamp_render_complete_time_ &&
- timestamp_composition_latch_time_);
+ return (timestamp_desired_present_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_actual_present_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_render_complete_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING &&
+ timestamp_composition_latch_time_ !=
+ NATIVE_WINDOW_TIMESTAMP_PENDING);
}
- void calculate(uint64_t rdur) {
- vals_.actualPresentTime = timestamp_actual_present_time_;
- uint64_t margin = (timestamp_composition_latch_time_ -
+ void calculate(int64_t rdur) {
+ bool anyTimestampInvalid =
+ (timestamp_actual_present_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+ (timestamp_render_complete_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID) ||
+ (timestamp_composition_latch_time_ ==
+ NATIVE_WINDOW_TIMESTAMP_INVALID);
+ if (anyTimestampInvalid) {
+ ALOGE("Unexpectedly received invalid timestamp.");
+ vals_.actualPresentTime = 0;
+ vals_.earliestPresentTime = 0;
+ vals_.presentMargin = 0;
+ return;
+ }
+
+ vals_.actualPresentTime =
+ static_cast<uint64_t>(timestamp_actual_present_time_);
+ int64_t margin = (timestamp_composition_latch_time_ -
timestamp_render_complete_time_);
// Calculate vals_.earliestPresentTime, and potentially adjust
// vals_.presentMargin. The initial value of vals_.earliestPresentTime
@@ -132,14 +152,14 @@
// it did (per the extension specification). If for some reason, we
// can do this subtraction repeatedly, we do, since
// vals_.earliestPresentTime really is supposed to be the "earliest".
- uint64_t early_time = vals_.actualPresentTime;
+ int64_t early_time = timestamp_actual_present_time_;
while ((margin > rdur) &&
((early_time - rdur) > timestamp_composition_latch_time_)) {
early_time -= rdur;
margin -= rdur;
}
- vals_.earliestPresentTime = early_time;
- vals_.presentMargin = margin;
+ vals_.earliestPresentTime = static_cast<uint64_t>(early_time);
+ vals_.presentMargin = static_cast<uint64_t>(margin);
}
void get_values(VkPastPresentationTimingGOOGLE* values) const {
*values = vals_;
@@ -149,10 +169,11 @@
VkPastPresentationTimingGOOGLE vals_ { 0, 0, 0, 0, 0 };
uint64_t native_frame_id_ { 0 };
- uint64_t timestamp_desired_present_time_ { 0 };
- uint64_t timestamp_actual_present_time_ { 0 };
- uint64_t timestamp_render_complete_time_ { 0 };
- uint64_t timestamp_composition_latch_time_ { 0 };
+ int64_t timestamp_desired_present_time_{ NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_actual_present_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_render_complete_time_ { NATIVE_WINDOW_TIMESTAMP_PENDING };
+ int64_t timestamp_composition_latch_time_
+ { NATIVE_WINDOW_TIMESTAMP_PENDING };
};
// ----------------------------------------------------------------------------
@@ -187,18 +208,16 @@
shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
ANativeWindow* window = surface.window.get();
- int64_t rdur;
native_window_get_refresh_cycle_duration(
window,
- &rdur);
- refresh_duration = static_cast<uint64_t>(rdur);
+ &refresh_duration);
}
Surface& surface;
uint32_t num_images;
bool mailbox_mode;
bool frame_timestamps_enabled;
- uint64_t refresh_duration;
+ int64_t refresh_duration;
bool shared;
struct Image {
@@ -327,14 +346,10 @@
// Record the timestamp(s) we received, and then see if this TimingInfo
// is ready to be reported to the user:
- ti.timestamp_desired_present_time_ =
- static_cast<uint64_t>(desired_present_time);
- ti.timestamp_actual_present_time_ =
- static_cast<uint64_t>(actual_present_time);
- ti.timestamp_render_complete_time_ =
- static_cast<uint64_t>(render_complete_time);
- ti.timestamp_composition_latch_time_ =
- static_cast<uint64_t>(composition_latch_time);
+ ti.timestamp_desired_present_time_ = desired_present_time;
+ ti.timestamp_actual_present_time_ = actual_present_time;
+ ti.timestamp_render_complete_time_ = render_complete_time;
+ ti.timestamp_composition_latch_time_ = composition_latch_time;
if (ti.ready()) {
// The TimingInfo has received enough timestamps, and should now
@@ -1494,7 +1509,8 @@
Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
VkResult result = VK_SUCCESS;
- pDisplayTimingProperties->refreshDuration = swapchain.refresh_duration;
+ pDisplayTimingProperties->refreshDuration =
+ static_cast<uint64_t>(swapchain.refresh_duration);
return result;
}