Merge "C++17 is the default now."
diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h
index 8dd95cf..2b8cc57 100644
--- a/include/input/InputWindow.h
+++ b/include/input/InputWindow.h
@@ -225,6 +225,11 @@
virtual bool updateInfo() = 0;
/**
+ * Updates from another input window handle.
+ */
+ void updateFrom(const sp<InputWindowHandle> handle);
+
+ /**
* Releases the channel used by the associated information when it is
* no longer needed.
*/
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 80d435f..7d26151 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -636,6 +636,21 @@
*outComponentMask = static_cast<uint8_t>(value);
return error;
}
+
+ virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ uint8_t componentMask,
+ uint64_t maxFrames) const {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+ data.writeStrongBinder(display);
+ data.writeBool(enable);
+ data.writeByte(static_cast<int8_t>(componentMask));
+ data.writeUint64(maxFrames);
+ status_t result =
+ remote()->transact(BnSurfaceComposer::SET_DISPLAY_CONTENT_SAMPLING_ENABLED, data,
+ &reply);
+ return result;
+ }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -1004,6 +1019,42 @@
}
return result;
}
+ case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: {
+ CHECK_INTERFACE(ISurfaceComposer, data, reply);
+
+ sp<IBinder> display = nullptr;
+ bool enable = false;
+ int8_t componentMask = 0;
+ uint64_t maxFrames = 0;
+ status_t result = data.readStrongBinder(&display);
+ if (result != NO_ERROR) {
+ ALOGE("setDisplayContentSamplingEnabled failure in reading Display token: %d",
+ result);
+ return result;
+ }
+
+ result = data.readBool(&enable);
+ if (result != NO_ERROR) {
+ ALOGE("setDisplayContentSamplingEnabled failure in reading enable: %d", result);
+ return result;
+ }
+
+ result = data.readByte(static_cast<int8_t*>(&componentMask));
+ if (result != NO_ERROR) {
+ ALOGE("setDisplayContentSamplingEnabled failure in reading component mask: %d",
+ result);
+ return result;
+ }
+
+ result = data.readUint64(&maxFrames);
+ if (result != NO_ERROR) {
+ ALOGE("setDisplayContentSamplingEnabled failure in reading max frames: %d", result);
+ return result;
+ }
+
+ return setDisplayContentSamplingEnabled(display, enable,
+ static_cast<uint8_t>(componentMask), maxFrames);
+ }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9dfccc7..405d228 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1098,6 +1098,14 @@
outComponentMask);
}
+status_t SurfaceComposerClient::setDisplayContentSamplingEnabled(const sp<IBinder>& display,
+ bool enable, uint8_t componentMask,
+ uint64_t maxFrames) {
+ return ComposerService::getComposerService()->setDisplayContentSamplingEnabled(display, enable,
+ componentMask,
+ maxFrames);
+}
+
// ----------------------------------------------------------------------------
status_t ScreenshotClient::capture(const sp<IBinder>& display, const ui::Dataspace reqDataSpace,
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3b6c6e4..41369c8 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -300,6 +300,14 @@
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask) const = 0;
+
+ /* Turns on the color sampling engine on the display.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ uint8_t componentMask,
+ uint64_t maxFrames) const = 0;
};
// ----------------------------------------------------------------------------
@@ -340,6 +348,7 @@
GET_COMPOSITION_PREFERENCE,
GET_COLOR_MANAGEMENT,
GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
+ SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
};
virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 7d05512..ba943a0 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -386,6 +386,8 @@
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask);
+ static status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ uint8_t componentMask, uint64_t maxFrames);
private:
virtual void onFirstRef();
diff --git a/libs/gui/tests/DisplayedContentSampling_test.cpp b/libs/gui/tests/DisplayedContentSampling_test.cpp
index f2c0e0c..f9d5dd6 100644
--- a/libs/gui/tests/DisplayedContentSampling_test.cpp
+++ b/libs/gui/tests/DisplayedContentSampling_test.cpp
@@ -36,7 +36,12 @@
ASSERT_TRUE(mDisplayToken);
}
- bool shouldSkipTest(status_t status) {
+ bool shouldSkipTest() {
+ ui::PixelFormat format;
+ ui::Dataspace dataspace;
+ status_t status =
+ mComposerClient->getDisplayedContentSamplingAttributes(mDisplayToken, &format,
+ &dataspace, &componentMask);
if (status == PERMISSION_DENIED) {
SUCCEED() << "permissions denial, skipping test";
return true;
@@ -50,19 +55,53 @@
sp<SurfaceComposerClient> mComposerClient;
sp<IBinder> mDisplayToken;
+ uint8_t componentMask = 0;
};
TEST_F(DisplayedContentSamplingTest, GetDisplayedContentSamplingAttributesAreSane) {
+ // tradefed infrastructure does not support use of GTEST_SKIP
+ if (shouldSkipTest()) return;
+
ui::PixelFormat format;
ui::Dataspace dataspace;
- uint8_t componentMask = 0;
status_t status =
mComposerClient->getDisplayedContentSamplingAttributes(mDisplayToken, &format,
&dataspace, &componentMask);
- if (shouldSkipTest(status)) {
- return;
- }
EXPECT_EQ(OK, status);
EXPECT_LE(componentMask, INVALID_MASK);
}
+
+TEST_F(DisplayedContentSamplingTest, EnableWithInvalidMaskReturnsBadValue) {
+ if (shouldSkipTest()) return;
+
+ status_t status =
+ mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, true, INVALID_MASK, 0);
+ EXPECT_EQ(BAD_VALUE, status);
+}
+
+TEST_F(DisplayedContentSamplingTest, EnableAndDisableSucceed) {
+ if (shouldSkipTest()) return;
+
+ status_t status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, true,
+ componentMask, 10);
+ EXPECT_EQ(OK, status);
+
+ status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, false, componentMask,
+ 0);
+ EXPECT_EQ(OK, status);
+}
+
+TEST_F(DisplayedContentSamplingTest, SelectivelyDisableComponentOk) {
+ if (shouldSkipTest()) return;
+
+ status_t status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, true,
+ componentMask, 0);
+ EXPECT_EQ(OK, status);
+
+ // Clear the lowest bit.
+ componentMask &= (componentMask - 1);
+ status = mComposerClient->setDisplayContentSamplingEnabled(mDisplayToken, false, componentMask,
+ 0);
+ EXPECT_EQ(OK, status);
+}
} // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3950bb6..cb1756f 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -647,6 +647,11 @@
uint8_t* /*outComponentMask*/) const override {
return NO_ERROR;
}
+ status_t setDisplayContentSamplingEnabled(const sp<IBinder>& /*display*/, bool /*enable*/,
+ uint8_t /*componentMask*/,
+ uint64_t /*maxFrames*/) const override {
+ return NO_ERROR;
+ }
virtual status_t getColorManagement(bool* /*outGetColorManagement*/) const { return NO_ERROR; }
diff --git a/libs/input/InputWindow.cpp b/libs/input/InputWindow.cpp
index 556a005..aa1371f 100644
--- a/libs/input/InputWindow.cpp
+++ b/libs/input/InputWindow.cpp
@@ -162,4 +162,8 @@
return mInfo.token;
}
+void InputWindowHandle::updateFrom(sp<InputWindowHandle> handle) {
+ mInfo = handle->mInfo;
+}
+
} // namespace android
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 5943e68..997ae90 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -45,7 +45,7 @@
filegroup {
name: "librenderengine_gl_sources",
srcs: [
- "gl/GLES20RenderEngine.cpp",
+ "gl/GLESRenderEngine.cpp",
"gl/GLExtensions.cpp",
"gl/GLFramebuffer.cpp",
"gl/GLImage.cpp",
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index 8be1c3c..6dd7283 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -19,7 +19,7 @@
#include <cutils/properties.h>
#include <log/log.h>
#include <private/gui/SyncFeatures.h>
-#include "gl/GLES20RenderEngine.h"
+#include "gl/GLESRenderEngine.h"
namespace android {
namespace renderengine {
@@ -29,10 +29,10 @@
property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles");
if (strcmp(prop, "gles") == 0) {
ALOGD("RenderEngine GLES Backend");
- return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+ return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags);
}
ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop);
- return renderengine::gl::GLES20RenderEngine::create(hwcFormat, featureFlags);
+ return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags);
}
RenderEngine::~RenderEngine() = default;
diff --git a/libs/renderengine/gl/GLES20RenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
similarity index 86%
rename from libs/renderengine/gl/GLES20RenderEngine.cpp
rename to libs/renderengine/gl/GLESRenderEngine.cpp
index 7adda83..8a9e7bd 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -19,7 +19,7 @@
#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include "GLES20RenderEngine.h"
+#include "GLESRenderEngine.h"
#include <math.h>
#include <fstream>
@@ -221,8 +221,7 @@
return err;
}
-std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat,
- uint32_t featureFlags) {
+std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32_t featureFlags) {
// initialize EGL for the default display
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!eglInitialize(display, nullptr, nullptr)) {
@@ -263,7 +262,7 @@
GlesVersion version = parseGlesVersion(extensions.getVersion());
// initialize the renderer while GL is current
- std::unique_ptr<GLES20RenderEngine> engine;
+ std::unique_ptr<GLESRenderEngine> engine;
switch (version) {
case GLES_VERSION_1_0:
case GLES_VERSION_1_1:
@@ -271,8 +270,7 @@
break;
case GLES_VERSION_2_0:
case GLES_VERSION_3_0:
- engine = std::make_unique<GLES20RenderEngine>(featureFlags, display, config, ctxt,
- dummy);
+ engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy);
break;
}
@@ -287,17 +285,17 @@
return engine;
}
-EGLConfig GLES20RenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
+EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
status_t err;
EGLConfig config;
- // First try to get an ES2 config
- err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
+ // First try to get an ES3 config
+ err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config);
if (err != NO_ERROR) {
- // If ES2 fails, try ES1
- err = selectEGLConfig(display, format, EGL_OPENGL_ES_BIT, &config);
+ // If ES3 fails, try to get an ES2 config
+ err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
if (err != NO_ERROR) {
- // still didn't work, probably because we're on the emulator...
+ // If ES2 still doesn't work, probably because we're on the emulator.
// try a simplified query
ALOGW("no suitable EGLConfig found, trying a simpler query");
err = selectEGLConfig(display, format, 0, &config);
@@ -326,8 +324,8 @@
return config;
}
-GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
- EGLContext ctxt, EGLSurface dummy)
+GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
+ EGLContext ctxt, EGLSurface dummy)
: renderengine::impl::RenderEngine(featureFlags),
mEGLDisplay(display),
mEGLConfig(config),
@@ -382,28 +380,28 @@
}
}
-GLES20RenderEngine::~GLES20RenderEngine() {
+GLESRenderEngine::~GLESRenderEngine() {
eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglTerminate(mEGLDisplay);
}
-std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() {
+std::unique_ptr<Framebuffer> GLESRenderEngine::createFramebuffer() {
return std::make_unique<GLFramebuffer>(*this);
}
-std::unique_ptr<Image> GLES20RenderEngine::createImage() {
+std::unique_ptr<Image> GLESRenderEngine::createImage() {
return std::make_unique<GLImage>(*this);
}
-void GLES20RenderEngine::primeCache() const {
+void GLESRenderEngine::primeCache() const {
ProgramCache::getInstance().primeCache(mFeatureFlags & USE_COLOR_MANAGEMENT);
}
-bool GLES20RenderEngine::isCurrent() const {
+bool GLESRenderEngine::isCurrent() const {
return mEGLDisplay == eglGetCurrentDisplay() && mEGLContext == eglGetCurrentContext();
}
-base::unique_fd GLES20RenderEngine::flush() {
+base::unique_fd GLESRenderEngine::flush() {
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
}
@@ -427,7 +425,7 @@
return fenceFd;
}
-bool GLES20RenderEngine::finish() {
+bool GLESRenderEngine::finish() {
if (!GLExtensions::getInstance().hasFenceSync()) {
ALOGW("no synchronization support");
return false;
@@ -455,7 +453,7 @@
return true;
}
-bool GLES20RenderEngine::waitFence(base::unique_fd fenceFd) {
+bool GLESRenderEngine::waitFence(base::unique_fd fenceFd) {
if (!GLExtensions::getInstance().hasNativeFenceSync() ||
!GLExtensions::getInstance().hasWaitSync()) {
return false;
@@ -485,13 +483,13 @@
return true;
}
-void GLES20RenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+void GLESRenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
glClearColor(red, green, blue, alpha);
glClear(GL_COLOR_BUFFER_BIT);
}
-void GLES20RenderEngine::fillRegionWithColor(const Region& region, float red, float green,
- float blue, float alpha) {
+void GLESRenderEngine::fillRegionWithColor(const Region& region, float red, float green, float blue,
+ float alpha) {
size_t c;
Rect const* r = region.getArray(&c);
Mesh mesh(Mesh::TRIANGLES, c * 6, 2);
@@ -514,7 +512,7 @@
drawMesh(mesh);
}
-void GLES20RenderEngine::setScissor(const Rect& region) {
+void GLESRenderEngine::setScissor(const Rect& region) {
// Invert y-coordinate to map to GL-space.
int32_t canvasHeight = mFboHeight;
int32_t glBottom = canvasHeight - region.bottom;
@@ -523,19 +521,19 @@
glEnable(GL_SCISSOR_TEST);
}
-void GLES20RenderEngine::disableScissor() {
+void GLESRenderEngine::disableScissor() {
glDisable(GL_SCISSOR_TEST);
}
-void GLES20RenderEngine::genTextures(size_t count, uint32_t* names) {
+void GLESRenderEngine::genTextures(size_t count, uint32_t* names) {
glGenTextures(count, names);
}
-void GLES20RenderEngine::deleteTextures(size_t count, uint32_t const* names) {
+void GLESRenderEngine::deleteTextures(size_t count, uint32_t const* names) {
glDeleteTextures(count, names);
}
-void GLES20RenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
+void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
const GLImage& glImage = static_cast<const GLImage&>(image);
const GLenum target = GL_TEXTURE_EXTERNAL_OES;
@@ -545,7 +543,7 @@
}
}
-status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
+status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
EGLImageKHR eglImage = glFramebuffer->getEGLImage();
uint32_t textureName = glFramebuffer->getTextureName();
@@ -569,14 +567,14 @@
return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}
-void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
mFboHeight = 0;
// back to main framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-void GLES20RenderEngine::checkErrors() const {
+void GLESRenderEngine::checkErrors() const {
do {
// there could be more than one error flag
GLenum error = glGetError();
@@ -585,15 +583,15 @@
} while (true);
}
-status_t GLES20RenderEngine::drawLayers(const DisplaySettings& /*settings*/,
- const std::vector<LayerSettings>& /*layers*/,
- ANativeWindowBuffer* const /*buffer*/,
- base::unique_fd* /*displayFence*/) const {
+status_t GLESRenderEngine::drawLayers(const DisplaySettings& /*settings*/,
+ const std::vector<LayerSettings>& /*layers*/,
+ ANativeWindowBuffer* const /*buffer*/,
+ base::unique_fd* /*displayFence*/) const {
return NO_ERROR;
}
-void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
- ui::Transform::orientation_flags rotation) {
+void GLESRenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
+ ui::Transform::orientation_flags rotation) {
int32_t l = sourceCrop.left;
int32_t r = sourceCrop.right;
int32_t b = sourceCrop.bottom;
@@ -625,9 +623,8 @@
mVpHeight = vph;
}
-void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque,
- bool disableTexture, const half4& color,
- float cornerRadius) {
+void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
+ const half4& color, float cornerRadius) {
mState.isPremultipliedAlpha = premultipliedAlpha;
mState.isOpaque = opaque;
mState.color = color;
@@ -645,23 +642,23 @@
}
}
-void GLES20RenderEngine::setSourceY410BT2020(bool enable) {
+void GLESRenderEngine::setSourceY410BT2020(bool enable) {
mState.isY410BT2020 = enable;
}
-void GLES20RenderEngine::setSourceDataSpace(Dataspace source) {
+void GLESRenderEngine::setSourceDataSpace(Dataspace source) {
mDataSpace = source;
}
-void GLES20RenderEngine::setOutputDataSpace(Dataspace dataspace) {
+void GLESRenderEngine::setOutputDataSpace(Dataspace dataspace) {
mOutputDataSpace = dataspace;
}
-void GLES20RenderEngine::setDisplayMaxLuminance(const float maxLuminance) {
+void GLESRenderEngine::setDisplayMaxLuminance(const float maxLuminance) {
mState.displayMaxLuminance = maxLuminance;
}
-void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
+void GLESRenderEngine::setupLayerTexturing(const Texture& texture) {
GLuint target = texture.getTextureTarget();
glBindTexture(target, texture.getTextureName());
GLenum filter = GL_NEAREST;
@@ -677,7 +674,7 @@
mState.textureEnabled = true;
}
-void GLES20RenderEngine::setupLayerBlackedOut() {
+void GLESRenderEngine::setupLayerBlackedOut() {
glBindTexture(GL_TEXTURE_2D, mProtectedTexName);
Texture texture(Texture::TEXTURE_2D, mProtectedTexName);
texture.setDimensions(1, 1); // FIXME: we should get that from somewhere
@@ -685,19 +682,19 @@
mState.textureEnabled = true;
}
-void GLES20RenderEngine::setColorTransform(const mat4& colorTransform) {
+void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
mState.colorMatrix = colorTransform;
}
-void GLES20RenderEngine::disableTexturing() {
+void GLESRenderEngine::disableTexturing() {
mState.textureEnabled = false;
}
-void GLES20RenderEngine::disableBlending() {
+void GLESRenderEngine::disableBlending() {
glDisable(GL_BLEND);
}
-void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
+void GLESRenderEngine::setupFillWithColor(float r, float g, float b, float a) {
mState.isPremultipliedAlpha = true;
mState.isOpaque = false;
mState.color = half4(r, g, b, a);
@@ -705,11 +702,11 @@
glDisable(GL_BLEND);
}
-void GLES20RenderEngine::setupCornerRadiusCropSize(float width, float height) {
+void GLESRenderEngine::setupCornerRadiusCropSize(float width, float height) {
mState.cropSize = half2(width, height);
}
-void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
+void GLESRenderEngine::drawMesh(const Mesh& mesh) {
ATRACE_CALL();
if (mesh.getTexCoordsSize()) {
glEnableVertexAttribArray(Program::texCoords);
@@ -849,15 +846,15 @@
}
}
-size_t GLES20RenderEngine::getMaxTextureSize() const {
+size_t GLESRenderEngine::getMaxTextureSize() const {
return mMaxTextureSize;
}
-size_t GLES20RenderEngine::getMaxViewportDims() const {
+size_t GLESRenderEngine::getMaxViewportDims() const {
return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
}
-void GLES20RenderEngine::dump(String8& result) {
+void GLESRenderEngine::dump(String8& result) {
const GLExtensions& extensions = GLExtensions::getInstance();
result.appendFormat("EGL implementation : %s\n", extensions.getEGLVersion());
@@ -875,7 +872,7 @@
dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
}
-GLES20RenderEngine::GlesVersion GLES20RenderEngine::parseGlesVersion(const char* str) {
+GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str) {
int major, minor;
if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
@@ -893,16 +890,18 @@
return GLES_VERSION_1_0;
}
-EGLContext GLES20RenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
- EGLContext shareContext, bool useContextPriority) {
+EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
+ EGLContext shareContext, bool useContextPriority) {
EGLint renderableType = 0;
if (config == EGL_NO_CONFIG) {
- renderableType = EGL_OPENGL_ES2_BIT;
+ renderableType = EGL_OPENGL_ES3_BIT;
} else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
}
EGLint contextClientVersion = 0;
- if (renderableType & EGL_OPENGL_ES2_BIT) {
+ if (renderableType & EGL_OPENGL_ES3_BIT) {
+ contextClientVersion = 3;
+ } else if (renderableType & EGL_OPENGL_ES2_BIT) {
contextClientVersion = 2;
} else if (renderableType & EGL_OPENGL_ES_BIT) {
contextClientVersion = 1;
@@ -920,11 +919,25 @@
}
contextAttributes.push_back(EGL_NONE);
- return eglCreateContext(display, config, shareContext, contextAttributes.data());
+ EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
+
+ if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
+ // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
+ // EGL_NO_CONTEXT so that we can abort.
+ if (config != EGL_NO_CONFIG) {
+ return context;
+ }
+ // If |config| is EGL_NO_CONFIG, we speculatively try to create GLES 3 context, so we should
+ // try to fall back to GLES 2.
+ contextAttributes[1] = 2;
+ context = eglCreateContext(display, config, shareContext, contextAttributes.data());
+ }
+
+ return context;
}
-EGLSurface GLES20RenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
- int hwcFormat) {
+EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
+ int hwcFormat) {
EGLConfig dummyConfig = config;
if (dummyConfig == EGL_NO_CONFIG) {
dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
@@ -940,7 +953,7 @@
return eglCreatePbufferSurface(display, dummyConfig, attributes.data());
}
-bool GLES20RenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
+bool GLESRenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
const Dataspace standard = static_cast<Dataspace>(dataSpace & Dataspace::STANDARD_MASK);
const Dataspace transfer = static_cast<Dataspace>(dataSpace & Dataspace::TRANSFER_MASK);
return standard == Dataspace::STANDARD_BT2020 &&
@@ -957,7 +970,7 @@
// input data space or output data space is HDR data space, and the input transfer function
// doesn't match the output transfer function, we would enable an intermediate transfrom to
// XYZ color space.
-bool GLES20RenderEngine::needsXYZTransformMatrix() const {
+bool GLESRenderEngine::needsXYZTransformMatrix() const {
const bool isInputHdrDataSpace = isHdrDataSpace(mDataSpace);
const bool isOutputHdrDataSpace = isHdrDataSpace(mOutputDataSpace);
const Dataspace inputTransfer = static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK);
diff --git a/libs/renderengine/gl/GLES20RenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
similarity index 92%
rename from libs/renderengine/gl/GLES20RenderEngine.h
rename to libs/renderengine/gl/GLESRenderEngine.h
index a9f8cad..8876d66 100644
--- a/libs/renderengine/gl/GLES20RenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef SF_GLES20RENDERENGINE_H_
-#define SF_GLES20RENDERENGINE_H_
+#ifndef SF_GLESRENDERENGINE_H_
+#define SF_GLESRENDERENGINE_H_
#include <stdint.h>
#include <sys/types.h>
@@ -41,14 +41,14 @@
class GLImage;
-class GLES20RenderEngine : public impl::RenderEngine {
+class GLESRenderEngine : public impl::RenderEngine {
public:
- static std::unique_ptr<GLES20RenderEngine> create(int hwcFormat, uint32_t featureFlags);
+ static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags);
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
- GLES20RenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
- EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
- ~GLES20RenderEngine() override;
+ GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
+ EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy);
+ ~GLESRenderEngine() override;
std::unique_ptr<Framebuffer> createFramebuffer() override;
std::unique_ptr<Image> createImage() override;
@@ -165,4 +165,4 @@
} // namespace renderengine
} // namespace android
-#endif /* SF_GLES20RENDERENGINE_H_ */
+#endif /* SF_GLESRENDERENGINE_H_ */
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 2bd4e7f..f4de91a 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -21,13 +21,13 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <nativebase/nativebase.h>
-#include "GLES20RenderEngine.h"
+#include "GLESRenderEngine.h"
namespace android {
namespace renderengine {
namespace gl {
-GLFramebuffer::GLFramebuffer(const GLES20RenderEngine& engine)
+GLFramebuffer::GLFramebuffer(const GLESRenderEngine& engine)
: mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
glGenTextures(1, &mTextureName);
glGenFramebuffers(1, &mFramebufferName);
diff --git a/libs/renderengine/gl/GLFramebuffer.h b/libs/renderengine/gl/GLFramebuffer.h
index 90c6f4a..358ab47 100644
--- a/libs/renderengine/gl/GLFramebuffer.h
+++ b/libs/renderengine/gl/GLFramebuffer.h
@@ -28,11 +28,11 @@
namespace renderengine {
namespace gl {
-class GLES20RenderEngine;
+class GLESRenderEngine;
class GLFramebuffer : public renderengine::Framebuffer {
public:
- explicit GLFramebuffer(const GLES20RenderEngine& engine);
+ explicit GLFramebuffer(const GLESRenderEngine& engine);
~GLFramebuffer() override;
bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer) override;
diff --git a/libs/renderengine/gl/GLImage.cpp b/libs/renderengine/gl/GLImage.cpp
index 5a92093..a9529a7 100644
--- a/libs/renderengine/gl/GLImage.cpp
+++ b/libs/renderengine/gl/GLImage.cpp
@@ -19,7 +19,7 @@
#include <vector>
#include <log/log.h>
-#include "GLES20RenderEngine.h"
+#include "GLESRenderEngine.h"
#include "GLExtensions.h"
namespace android {
@@ -43,7 +43,7 @@
return attrs;
}
-GLImage::GLImage(const GLES20RenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
+GLImage::GLImage(const GLESRenderEngine& engine) : mEGLDisplay(engine.getEGLDisplay()) {}
GLImage::~GLImage() {
setNativeWindowBuffer(nullptr, false);
diff --git a/libs/renderengine/gl/GLImage.h b/libs/renderengine/gl/GLImage.h
index 0e451f8..c897d8e 100644
--- a/libs/renderengine/gl/GLImage.h
+++ b/libs/renderengine/gl/GLImage.h
@@ -29,11 +29,11 @@
namespace renderengine {
namespace gl {
-class GLES20RenderEngine;
+class GLESRenderEngine;
class GLImage : public renderengine::Image {
public:
- explicit GLImage(const GLES20RenderEngine& engine);
+ explicit GLImage(const GLESRenderEngine& engine);
~GLImage() override;
bool setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) override;
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index 5941cdf..aa4e319 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -29,32 +29,32 @@
struct DisplaySettings {
// Rectangle describing the physical display. We will project from the
// logical clip onto this rectangle.
- Rect physicalDisplay;
+ Rect physicalDisplay = Rect::INVALID_RECT;
// Rectangle bounded by the x,y- clipping planes in the logical display, so
// that the orthographic projection matrix can be computed. When
// constructing this matrix, z-coordinate bound are assumed to be at z=0 and
// z=1.
- Rect clip;
+ Rect clip = Rect::INVALID_RECT;
// Global transform to apply to all layers.
- mat4 globalTransform;
+ mat4 globalTransform = mat4();
// Maximum luminance pulled from the display's HDR capabilities.
- float maxLuminence;
+ float maxLuminence = 1.0f;
// Output dataspace that will be populated if wide color gamut is used, or
// DataSpace::UNKNOWN otherwise.
- ui::Dataspace outputDataspace;
+ ui::Dataspace outputDataspace = ui::Dataspace::UNKNOWN;
// Additional color transform to apply in linear space after transforming
// to the output dataspace.
- mat4 colorTransform;
+ mat4 colorTransform = mat4();
// Region that will be cleared to (0, 0, 0, 0) prior to rendering.
// clearRegion will first be transformed by globalTransform so that it will
// be in the same coordinate space as the rendered layers.
- Region clearRegion;
+ Region clearRegion = Region::INVALID_REGION;
};
} // namespace renderengine
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index facea21..38dee40 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -34,58 +34,58 @@
// Buffer containing the image that we will render.
// If buffer == nullptr, then the rest of the fields in this struct will be
// ignored.
- sp<GraphicBuffer> buffer;
+ sp<GraphicBuffer> buffer = nullptr;
// Texture identifier to bind the external texture to.
// TODO(alecmouri): This is GL-specific...make the type backend-agnostic.
- uint32_t textureName;
+ uint32_t textureName = 0;
// Whether to use filtering when rendering the texture.
- bool useTextureFiltering;
+ bool useTextureFiltering = false;
// Transform matrix to apply to texture coordinates.
- mat4 textureTransform;
+ mat4 textureTransform = mat4();
// Wheteher to use pre-multiplied alpha
- bool usePremultipliedAlpha;
+ bool usePremultipliedAlpha = true;
// HDR color-space setting for Y410.
- bool isY410BT2020;
+ bool isY410BT2020 = false;
};
// Metadata describing the layer geometry.
struct Geometry {
// Boundaries of the layer.
- FloatRect boundaries;
+ FloatRect boundaries = FloatRect();
// Transform matrix to apply to mesh coordinates.
- mat4 positionTransform;
+ mat4 positionTransform = mat4();
};
// Descriptor of the source pixels for this layer.
struct PixelSource {
// Source buffer
- Buffer buffer;
+ Buffer buffer = Buffer();
// The solid color with which to fill the layer.
// This should only be populated if we don't render from an application
// buffer.
- half3 solidColor;
+ half3 solidColor = half3(0.0f, 0.0f, 0.0f);
};
// The settings that RenderEngine requires for correctly rendering a Layer.
struct LayerSettings {
// Geometry information
- Geometry geometry;
+ Geometry geometry = Geometry();
// Source pixels for this layer.
- PixelSource source;
+ PixelSource source = PixelSource();
// Alpha option to apply to the source pixels
- half alpha;
+ half alpha = half(0.0);
// Color space describing how the source pixels should be interpreted.
- ui::Dataspace sourceDataspace;
+ ui::Dataspace sourceDataspace = ui::Dataspace::UNKNOWN;
};
} // namespace renderengine
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 6402fe8..956465c 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -54,6 +54,7 @@
srcs: [
"ColorSpace.cpp",
"BufferHubBuffer.cpp",
+ "BufferHubEventFd.cpp",
"BufferHubMetadata.cpp",
"DebugUtils.cpp",
"Fence.cpp",
@@ -111,6 +112,7 @@
cflags: ["-DLIBUI_IN_VNDK"],
exclude_srcs: [
"BufferHubBuffer.cpp",
+ "BufferHubEventFd.cpp",
"BufferHubMetadata.cpp",
],
exclude_header_libs: [
diff --git a/libs/ui/BufferHubEventFd.cpp b/libs/ui/BufferHubEventFd.cpp
new file mode 100644
index 0000000..978b352
--- /dev/null
+++ b/libs/ui/BufferHubEventFd.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/eventfd.h>
+
+#include <log/log.h>
+#include <ui/BufferHubEventFd.h>
+
+namespace android {
+
+BufferHubEventFd::BufferHubEventFd() : mFd(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK)) {}
+
+status_t BufferHubEventFd::signal() const {
+ if (!isValid()) {
+ ALOGE("%s: cannot signal an invalid eventfd.", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ eventfd_write(mFd.get(), 1);
+ return OK;
+}
+
+status_t BufferHubEventFd::clear() const {
+ if (!isValid()) {
+ ALOGE("%s: cannot clear an invalid eventfd.", __FUNCTION__);
+ return DEAD_OBJECT;
+ }
+
+ eventfd_t value;
+ eventfd_read(mFd.get(), &value);
+ return OK;
+}
+
+} // namespace android
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index d8702e5..13fed3a 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -72,6 +72,14 @@
return *this;
}
+Rect& Rect::inset(int32_t _left, int32_t _top, int32_t _right, int32_t _bottom) {
+ this->left += _left;
+ this->top += _top;
+ this->right -= _right;
+ this->bottom -= _bottom;
+ return *this;
+}
+
const Rect Rect::operator +(const Point& rhs) const {
const Rect result(left + rhs.x, top + rhs.y, right + rhs.x, bottom + rhs.y);
return result;
diff --git a/libs/ui/include/ui/BufferHubEventFd.h b/libs/ui/include/ui/BufferHubEventFd.h
new file mode 100644
index 0000000..0e856bd
--- /dev/null
+++ b/libs/ui/include/ui/BufferHubEventFd.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_BUFFER_HUB_EVENT_FD_H_
+#define ANDROID_BUFFER_HUB_EVENT_FD_H_
+
+#include <android-base/unique_fd.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class BufferHubEventFd {
+public:
+ /**
+ * Constructs a valid event fd.
+ */
+ BufferHubEventFd();
+
+ /**
+ * Returns whether this BufferHubEventFd holds a valid event_fd.
+ */
+ bool isValid() const { return get() >= 0; }
+
+ /**
+ * Returns the fd number of the BufferHubEventFd object. Note that there is no ownership
+ * transfer.
+ */
+ int get() const { return mFd.get(); }
+
+ /**
+ * Signals the eventfd.
+ */
+ status_t signal() const;
+
+ /**
+ * Clears the signal from this eventfd if it is signaled.
+ */
+ status_t clear() const;
+
+private:
+ base::unique_fd mFd;
+};
+
+} // namespace android
+
+#endif // ANDROID_BUFFER_HUB_EVENT_FD_H_
diff --git a/libs/ui/include/ui/Rect.h b/libs/ui/include/ui/Rect.h
index 0bec0b7..e9da087 100644
--- a/libs/ui/include/ui/Rect.h
+++ b/libs/ui/include/ui/Rect.h
@@ -120,7 +120,7 @@
right = rb.x;
bottom = rb.y;
}
-
+
// the following 4 functions return the 4 corners of the rect as Point
Point leftTop() const {
return Point(left, top);
@@ -175,6 +175,11 @@
Rect& offsetTo(int32_t x, int32_t y);
Rect& offsetBy(int32_t x, int32_t y);
+ /**
+ * Insets the rectangle on all sides specified by the insets.
+ */
+ Rect& inset(int32_t _left, int32_t _top, int32_t _right, int32_t _bottom);
+
bool intersect(const Rect& with, Rect* result) const;
// Create a new Rect by transforming this one using a graphics HAL
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index 00f30a6..fcc6d37 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -51,16 +51,23 @@
"libdvr_headers",
"libnativewindow_headers",
],
+ static_libs: [
+ "libgmock",
+ ],
shared_libs: [
"android.frameworks.bufferhub@1.0",
"libcutils",
"libhidlbase",
"libhwbinder",
+ "liblog",
"libpdx_default_transport",
"libui",
"libutils"
],
- srcs: ["BufferHubBuffer_test.cpp"],
+ srcs: [
+ "BufferHubBuffer_test.cpp",
+ "BufferHubEventFd_test.cpp",
+ ],
cflags: ["-Wall", "-Werror"],
}
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 7c85e66..6c7d06b 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -127,7 +127,7 @@
return;
}
-TEST_F(BufferHubBufferTest, AllocateBuffer) {
+TEST_F(BufferHubBufferTest, AllocateAndFreeBuffer) {
// TODO(b/116681016): directly test on BufferHubBuffer instead of the service.
sp<IBufferHub> bufferHub = IBufferHub::getService();
ASSERT_NE(nullptr, bufferHub.get());
@@ -138,11 +138,51 @@
HardwareBufferDescription desc;
memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
- IBufferHub::allocateBuffer_cb callback = [](const auto& client, const auto& status) {
- EXPECT_EQ(status, BufferHubStatus::NO_ERROR);
- EXPECT_NE(nullptr, client.get());
+ sp<IBufferClient> client;
+ BufferHubStatus ret;
+ IBufferHub::allocateBuffer_cb callback = [&](const auto& outClient, const auto& outStatus) {
+ client = outClient;
+ ret = outStatus;
};
EXPECT_TRUE(bufferHub->allocateBuffer(desc, kUserMetadataSize, callback).isOk());
+ EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
+ ASSERT_NE(nullptr, client.get());
+
+ EXPECT_EQ(BufferHubStatus::NO_ERROR, client->close());
+ EXPECT_EQ(BufferHubStatus::CLIENT_CLOSED, client->close());
+}
+
+TEST_F(BufferHubBufferTest, DuplicateFreedBuffer) {
+ // TODO(b/116681016): directly test on BufferHubBuffer instead of the service.
+ sp<IBufferHub> bufferHub = IBufferHub::getService();
+ ASSERT_NE(nullptr, bufferHub.get());
+
+ // Stride is an output, rfu0 and rfu1 are reserved data slot for future use.
+ AHardwareBuffer_Desc aDesc = {kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+ HardwareBufferDescription desc;
+ memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+ sp<IBufferClient> client;
+ BufferHubStatus ret;
+ IBufferHub::allocateBuffer_cb callback = [&](const auto& outClient, const auto& outStatus) {
+ client = outClient;
+ ret = outStatus;
+ };
+ EXPECT_TRUE(bufferHub->allocateBuffer(desc, kUserMetadataSize, callback).isOk());
+ EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
+ ASSERT_NE(nullptr, client.get());
+
+ EXPECT_EQ(BufferHubStatus::NO_ERROR, client->close());
+
+ hidl_handle token;
+ IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) {
+ token = outToken;
+ ret = status;
+ };
+ EXPECT_TRUE(client->duplicate(dup_cb).isOk());
+ EXPECT_EQ(ret, BufferHubStatus::CLIENT_CLOSED);
+ EXPECT_EQ(token.getNativeHandle(), nullptr);
}
TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) {
@@ -230,5 +270,50 @@
native_handle_delete(tokenHandle);
}
+TEST_F(BufferHubBufferTest, ImportFreedBuffer) {
+ // TODO(b/116681016): directly test on BufferHubBuffer instead of the service.
+ sp<IBufferHub> bufferhub = IBufferHub::getService();
+ ASSERT_NE(nullptr, bufferhub.get());
+
+ // Stride is an output, rfu0 and rfu1 are reserved data slot for future use.
+ AHardwareBuffer_Desc aDesc = {kWidth, kHeight, kLayerCount, kFormat,
+ kUsage, /*stride=*/0UL, /*rfu0=*/0UL, /*rfu1=*/0ULL};
+ HardwareBufferDescription desc;
+ memcpy(&desc, &aDesc, sizeof(HardwareBufferDescription));
+
+ sp<IBufferClient> client;
+ BufferHubStatus ret;
+ IBufferHub::allocateBuffer_cb alloc_cb = [&](const auto& outClient, const auto& status) {
+ client = outClient;
+ ret = status;
+ };
+ ASSERT_TRUE(bufferhub->allocateBuffer(desc, kUserMetadataSize, alloc_cb).isOk());
+ EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
+ ASSERT_NE(nullptr, client.get());
+
+ hidl_handle token;
+ IBufferClient::duplicate_cb dup_cb = [&](const auto& outToken, const auto& status) {
+ token = outToken;
+ ret = status;
+ };
+ ASSERT_TRUE(client->duplicate(dup_cb).isOk());
+ EXPECT_EQ(ret, BufferHubStatus::NO_ERROR);
+ ASSERT_NE(token.getNativeHandle(), nullptr);
+ EXPECT_EQ(token->numInts, 1);
+ EXPECT_EQ(token->numFds, 0);
+
+ // Close the client. Now the token should be invalid.
+ client->close();
+
+ sp<IBufferClient> client2;
+ IBufferHub::importBuffer_cb import_cb = [&](const auto& outClient, const auto& status) {
+ client2 = outClient;
+ ret = status;
+ };
+ EXPECT_TRUE(bufferhub->importBuffer(token, import_cb).isOk());
+ EXPECT_EQ(ret, BufferHubStatus::INVALID_TOKEN);
+ EXPECT_EQ(nullptr, client2.get());
+}
+
} // namespace
} // namespace android
diff --git a/libs/ui/tests/BufferHubEventFd_test.cpp b/libs/ui/tests/BufferHubEventFd_test.cpp
new file mode 100644
index 0000000..92fb33f
--- /dev/null
+++ b/libs/ui/tests/BufferHubEventFd_test.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BufferHubEventFdTest"
+
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+
+#include <array>
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <ui/BufferHubEventFd.h>
+
+namespace android {
+
+namespace {
+
+const int kTimeout = 100;
+const std::chrono::milliseconds kTimeoutMs(kTimeout);
+
+using ::testing::Contains;
+using BufferHubEventFdTest = ::testing::Test;
+
+} // namespace
+
+TEST_F(BufferHubEventFdTest, EventFd_testSingleEpollFd) {
+ BufferHubEventFd eventFd;
+ ASSERT_TRUE(eventFd.isValid());
+
+ base::unique_fd epollFd(epoll_create(64));
+ epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
+
+ ASSERT_GE(epollFd.get(), 0);
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
+
+ std::array<epoll_event, 1> events;
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+
+ eventFd.signal();
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
+
+ // The epoll fd is edge triggered, so it only responds to the eventFd once.
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+}
+
+TEST_F(BufferHubEventFdTest, EventFd_testClear) {
+ BufferHubEventFd eventFd;
+ ASSERT_TRUE(eventFd.isValid());
+
+ base::unique_fd epollFd(epoll_create(64));
+ epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
+
+ ASSERT_GE(epollFd.get(), 0);
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
+
+ eventFd.signal();
+ eventFd.clear();
+
+ std::array<epoll_event, 1> events;
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+}
+
+TEST_F(BufferHubEventFdTest, EventFd_testDupEventFd) {
+ BufferHubEventFd eventFd;
+ ASSERT_TRUE(eventFd.isValid());
+
+ base::unique_fd epollFd(epoll_create(64));
+ epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
+
+ ASSERT_GE(epollFd.get(), 0);
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
+
+ // Technically, the dupliated eventFd and the original eventFd are pointing
+ // to the same kernel object. This test signals the duplicated eventFd but epolls the origianl
+ // eventFd.
+ base::unique_fd dupedEventFd(dup(eventFd.get()));
+ ASSERT_GE(dupedEventFd.get(), 0);
+
+ std::array<epoll_event, 1> events;
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+
+ eventfd_write(dupedEventFd.get(), 1);
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
+
+ // The epoll fd is edge triggered, so it only responds to the eventFd once.
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+
+ eventfd_write(dupedEventFd.get(), 1);
+
+ eventfd_t value;
+ eventfd_read(dupedEventFd.get(), &value);
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+}
+
+TEST_F(BufferHubEventFdTest, EventFd_testTwoEpollFds) {
+ BufferHubEventFd eventFd;
+ ASSERT_TRUE(eventFd.isValid());
+
+ base::unique_fd epollFd1(epoll_create(64));
+ base::unique_fd epollFd2(epoll_create(64));
+ epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
+
+ ASSERT_GE(epollFd1.get(), 0);
+ ASSERT_GE(epollFd2.get(), 0);
+
+ // Register the same eventFd to two EpollFds.
+ ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
+ ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
+
+ std::array<epoll_event, 1> events;
+ EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
+ EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
+
+ eventFd.signal();
+ EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
+ EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 1);
+
+ // The epoll fd is edge triggered, so it only responds to the eventFd once.
+ EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
+ EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
+
+ eventFd.signal();
+ EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
+
+ eventFd.clear();
+ EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
+ EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
+}
+
+TEST_F(BufferHubEventFdTest, EventFd_testTwoEventFds) {
+ BufferHubEventFd eventFd1;
+ BufferHubEventFd eventFd2;
+
+ ASSERT_TRUE(eventFd1.isValid());
+ ASSERT_TRUE(eventFd2.isValid());
+
+ base::unique_fd epollFd(epoll_create(64));
+ epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
+ epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
+
+ ASSERT_GE(epollFd.get(), 0);
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
+
+ std::array<epoll_event, 2> events;
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+
+ // Signal one by one.
+ eventFd1.signal();
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
+ EXPECT_EQ(events[0].data.u32, e1.data.u32);
+
+ eventFd2.signal();
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
+ EXPECT_EQ(events[0].data.u32, e2.data.u32);
+
+ // Signal both.
+ eventFd1.signal();
+ eventFd2.signal();
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 2);
+
+ uint32_t u32s[] = {events[0].data.u32, events[1].data.u32};
+ EXPECT_THAT(u32s, Contains(e1.data.u32));
+ EXPECT_THAT(u32s, Contains(e2.data.u32));
+
+ // The epoll fd is edge triggered, so it only responds to the eventFd once.
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
+
+ eventFd1.signal();
+ eventFd2.signal();
+ eventFd2.clear();
+ EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
+}
+
+TEST_F(BufferHubEventFdTest, EventFd_testPollingThreadWithTwoEventFds) {
+ BufferHubEventFd eventFd1;
+ BufferHubEventFd eventFd2;
+
+ ASSERT_TRUE(eventFd1.isValid());
+ ASSERT_TRUE(eventFd2.isValid());
+
+ base::unique_fd epollFd(epoll_create(64));
+ epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
+ epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
+
+ ASSERT_GE(epollFd.get(), 0);
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
+ ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
+
+ int countEvent1 = 0;
+ int countEvent2 = 0;
+ std::atomic<bool> stop{false};
+ std::mutex mx;
+ std::condition_variable cv;
+
+ std::thread pollingThread([&] {
+ std::array<epoll_event, 2> events;
+ while (true) {
+ if (stop.load()) {
+ break;
+ }
+ int ret = epoll_wait(epollFd.get(), events.data(), events.size(), kTimeout);
+ ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
+
+ std::lock_guard<std::mutex> lock(mx);
+ for (int i = 0; i < ret; i++) {
+ if (events[i].data.u32 == e1.data.u32) {
+ countEvent1++;
+ cv.notify_one();
+ } else if (events[i].data.u32 == e2.data.u32) {
+ countEvent2++;
+ cv.notify_one();
+ }
+ }
+ }
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(mx);
+
+ eventFd1.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 1; }));
+
+ eventFd1.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 2; }));
+
+ eventFd2.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 1; }));
+
+ eventFd1.clear();
+ eventFd2.clear();
+ EXPECT_EQ(countEvent1, 2);
+ EXPECT_EQ(countEvent2, 1);
+
+ eventFd1.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 3; }));
+
+ eventFd2.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 2; }));
+ }
+
+ stop.store(true);
+ pollingThread.join();
+}
+
+TEST_F(BufferHubEventFdTest, EventFd_testTwoPollingThreads) {
+ BufferHubEventFd eventFd;
+ ASSERT_TRUE(eventFd.isValid());
+
+ base::unique_fd epollFd1(epoll_create(64));
+ base::unique_fd epollFd2(epoll_create(64));
+ epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
+
+ ASSERT_GE(epollFd1.get(), 0);
+ ASSERT_GE(epollFd2.get(), 0);
+
+ // Register the same eventFd to two EpollFds.
+ ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
+ ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
+
+ int countEpoll1 = 0;
+ int countEpoll2 = 0;
+ std::atomic<bool> stop{false};
+ std::mutex mx;
+ std::condition_variable cv;
+
+ std::thread pollingThread1([&] {
+ std::array<epoll_event, 1> events;
+ while (!stop.load()) {
+ int ret = epoll_wait(epollFd1.get(), events.data(), events.size(), kTimeout);
+ ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
+
+ if (ret > 0) {
+ std::lock_guard<std::mutex> lock(mx);
+ countEpoll1++;
+ cv.notify_one();
+ }
+ }
+ });
+
+ std::thread pollingThread2([&] {
+ std::array<epoll_event, 1> events;
+ while (!stop.load()) {
+ int ret = epoll_wait(epollFd2.get(), events.data(), events.size(), kTimeout);
+ ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
+
+ if (ret > 0) {
+ std::lock_guard<std::mutex> lock(mx);
+ countEpoll2++;
+ cv.notify_one();
+ }
+ }
+ });
+
+ {
+ std::unique_lock<std::mutex> lock(mx);
+
+ eventFd.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 1; }));
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 1; }));
+
+ eventFd.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 2; }));
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 2; }));
+
+ eventFd.clear();
+ EXPECT_EQ(countEpoll1, 2);
+ EXPECT_EQ(countEpoll2, 2);
+
+ eventFd.signal();
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 3; }));
+ EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 3; }));
+ }
+
+ stop.store(true);
+ pollingThread1.join();
+ pollingThread2.join();
+}
+
+} // namespace android
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 43ac79e..fa92830 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -22,14 +22,12 @@
"buffer_hub_base.cpp",
"buffer_hub_rpc.cpp",
"consumer_buffer.cpp",
- "buffer_client_impl.cpp",
"ion_buffer.cpp",
"producer_buffer.cpp",
]
sharedLibraries = [
"libbase",
- "libbinder",
"libcutils",
"libhardware",
"liblog",
diff --git a/libs/vr/libbufferhub/buffer_client_impl.cpp b/libs/vr/libbufferhub/buffer_client_impl.cpp
deleted file mode 100644
index efa9c28..0000000
--- a/libs/vr/libbufferhub/buffer_client_impl.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#include <log/log.h>
-#include <private/dvr/IBufferClient.h>
-
-namespace android {
-namespace dvr {
-
-class BpBufferClient : public BpInterface<IBufferClient> {
- public:
- explicit BpBufferClient(const sp<IBinder>& impl)
- : BpInterface<IBufferClient>(impl) {}
-
- bool isValid() override;
-
- status_t duplicate(uint64_t* outToken) override;
-};
-
-IMPLEMENT_META_INTERFACE(BufferClient, "android.dvr.IBufferClient");
-
-// Transaction code
-enum {
- IS_VALID = IBinder::FIRST_CALL_TRANSACTION,
- DUPLICATE,
-};
-
-bool BpBufferClient::isValid() {
- Parcel data, reply;
- status_t ret =
- data.writeInterfaceToken(IBufferClient::getInterfaceDescriptor());
- if (ret != OK) {
- ALOGE("BpBufferClient::isValid: failed to write into parcel; errno=%d",
- ret);
- return false;
- }
-
- ret = remote()->transact(IS_VALID, data, &reply);
- if (ret == OK) {
- return reply.readBool();
- } else {
- ALOGE("BpBufferClient::isValid: failed to transact; errno=%d", ret);
- return false;
- }
-}
-
-status_t BpBufferClient::duplicate(uint64_t* outToken) {
- Parcel data, reply;
- status_t ret =
- data.writeInterfaceToken(IBufferClient::getInterfaceDescriptor());
- if (ret != OK) {
- ALOGE("BpBufferClient::duplicate: failed to write into parcel; errno=%d",
- ret);
- return ret;
- }
-
- ret = remote()->transact(DUPLICATE, data, &reply);
- if (ret == OK) {
- *outToken = reply.readUint64();
- return OK;
- } else {
- ALOGE("BpBufferClient::duplicate: failed to transact; errno=%d", ret);
- return ret;
- }
-}
-
-status_t BnBufferClient::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags) {
- switch (code) {
- case IS_VALID: {
- CHECK_INTERFACE(IBufferClient, data, reply);
- return reply->writeBool(isValid());
- }
- case DUPLICATE: {
- CHECK_INTERFACE(IBufferClient, data, reply);
- uint64_t token = 0;
- status_t ret = duplicate(&token);
- if (ret != OK) {
- return ret;
- }
- return reply->writeUint64(token);
- }
- default:
- // Should not reach except binder defined transactions such as dumpsys
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file
diff --git a/libs/vr/libbufferhub/include/private/dvr/IBufferClient.h b/libs/vr/libbufferhub/include/private/dvr/IBufferClient.h
deleted file mode 100644
index 31bf79d..0000000
--- a/libs/vr/libbufferhub/include/private/dvr/IBufferClient.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef ANDROID_DVR_IBUFFERCLIENT_H
-#define ANDROID_DVR_IBUFFERCLIENT_H
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-
-namespace android {
-namespace dvr {
-
-// Interface for acessing BufferHubBuffer remotely.
-class IBufferClient : public IInterface {
- public:
- DECLARE_META_INTERFACE(BufferClient);
-
- // Checks if the buffer node is valid.
- virtual bool isValid() = 0;
-
- // Duplicates the client. Token_out will be set to a new token when succeed,
- // and not changed when failed.
- virtual status_t duplicate(uint64_t* outToken) = 0;
-};
-
-// BnInterface for IBufferClient. Should only be created in bufferhub service.
-class BnBufferClient : public BnInterface<IBufferClient> {
- public:
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_IBUFFERCLIENT_H
\ No newline at end of file
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index c177970..de03fad 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -171,7 +171,7 @@
if (BufferHubDefs::IsClientGained(current_buffer_state,
client_state_mask())) {
- ALOGI("%s: already gained id=%d.", __FUNCTION__, id());
+ ALOGV("%s: already gained id=%d.", __FUNCTION__, id());
return 0;
}
if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
diff --git a/services/bufferhub/Android.bp b/services/bufferhub/Android.bp
index b747dbc..f9aaa20 100644
--- a/services/bufferhub/Android.bp
+++ b/services/bufferhub/Android.bp
@@ -24,9 +24,9 @@
],
srcs: [
"BufferClient.cpp",
+ "BufferHubIdGenerator.cpp",
"BufferHubService.cpp",
"BufferNode.cpp",
- "UniqueIdGenerator.cpp",
],
header_libs: [
"libbufferhub_headers",
diff --git a/services/bufferhub/BufferClient.cpp b/services/bufferhub/BufferClient.cpp
index 37fd75f..7459517 100644
--- a/services/bufferhub/BufferClient.cpp
+++ b/services/bufferhub/BufferClient.cpp
@@ -39,7 +39,29 @@
return new BufferClient(service, node);
}
+BufferClient::~BufferClient() {
+ close();
+}
+
+Return<BufferHubStatus> BufferClient::close() {
+ std::lock_guard<std::mutex> lock(mClosedMutex);
+ if (mClosed) {
+ return BufferHubStatus::CLIENT_CLOSED;
+ }
+
+ getService()->onClientClosed(this);
+ mBufferNode.reset();
+ mClosed = true;
+ return BufferHubStatus::NO_ERROR;
+}
+
Return<void> BufferClient::duplicate(duplicate_cb _hidl_cb) {
+ std::lock_guard<std::mutex> lock(mClosedMutex);
+ if (mClosed) {
+ _hidl_cb(/*token=*/hidl_handle(), /*status=*/BufferHubStatus::CLIENT_CLOSED);
+ return Void();
+ }
+
if (!mBufferNode) {
// Should never happen
ALOGE("%s: node is missing.", __FUNCTION__);
@@ -47,15 +69,19 @@
return Void();
}
+ const hidl_handle token = getService()->registerToken(this);
+ _hidl_cb(/*token=*/token, /*status=*/BufferHubStatus::NO_ERROR);
+ return Void();
+}
+
+sp<BufferHubService> BufferClient::getService() {
sp<BufferHubService> service = mService.promote();
if (service == nullptr) {
// Should never happen. Kill the process.
LOG_FATAL("%s: service died.", __FUNCTION__);
}
- const hidl_handle token = service->registerToken(this);
- _hidl_cb(/*token=*/token, /*status=*/BufferHubStatus::NO_ERROR);
- return Void();
+ return service;
}
} // namespace implementation
diff --git a/services/bufferhub/UniqueIdGenerator.cpp b/services/bufferhub/BufferHubIdGenerator.cpp
similarity index 81%
rename from services/bufferhub/UniqueIdGenerator.cpp
rename to services/bufferhub/BufferHubIdGenerator.cpp
index 362a026..6444a03 100644
--- a/services/bufferhub/UniqueIdGenerator.cpp
+++ b/services/bufferhub/BufferHubIdGenerator.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <bufferhub/UniqueIdGenerator.h>
+#include <bufferhub/BufferHubIdGenerator.h>
namespace android {
namespace frameworks {
@@ -22,9 +22,15 @@
namespace V1_0 {
namespace implementation {
-constexpr uint32_t UniqueIdGenerator::kInvalidId;
+constexpr uint32_t BufferHubIdGenerator::kInvalidId;
-uint32_t UniqueIdGenerator::getId() {
+BufferHubIdGenerator& BufferHubIdGenerator::getInstance() {
+ static BufferHubIdGenerator generator;
+
+ return generator;
+}
+
+uint32_t BufferHubIdGenerator::getId() {
std::lock_guard<std::mutex> lock(mIdsInUseMutex);
do {
@@ -37,7 +43,7 @@
return mLastId;
}
-bool UniqueIdGenerator::freeId(uint32_t id) {
+bool BufferHubIdGenerator::freeId(uint32_t id) {
std::lock_guard<std::mutex> lock(mIdsInUseMutex);
auto iter = mIdsInUse.find(id);
if (iter != mIdsInUse.end()) {
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 6f97f0d..b0869fe 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -35,7 +35,8 @@
std::shared_ptr<BufferNode> node =
std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
- desc.usage, userMetadataSize, nodeIdGenerator.getId());
+ desc.usage, userMetadataSize,
+ BufferHubIdGenerator::getInstance().getId());
if (node == nullptr || !node->IsValid()) {
ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
_hidl_cb(/*bufferClient=*/nullptr, /*status=*/BufferHubStatus::ALLOCATION_FAILED);
@@ -44,8 +45,8 @@
sp<BufferClient> client = BufferClient::create(this, node);
// Add it to list for bookkeeping and dumpsys.
- std::lock_guard<std::mutex> lock(mClientListMutex);
- mClientList.push_back(client);
+ std::lock_guard<std::mutex> lock(mClientSetMutex);
+ mClientSet.emplace(client);
_hidl_cb(/*bufferClient=*/client, /*status=*/BufferHubStatus::NO_ERROR);
return Void();
@@ -86,8 +87,8 @@
sp<BufferClient> client = new BufferClient(*originClient);
- std::lock_guard<std::mutex> lock(mClientListMutex);
- mClientList.push_back(client);
+ std::lock_guard<std::mutex> lock(mClientSetMutex);
+ mClientSet.emplace(client);
_hidl_cb(/*bufferClient=*/client, /*status=*/BufferHubStatus::NO_ERROR);
return Void();
}
@@ -111,6 +112,30 @@
return returnToken;
}
+void BufferHubService::onClientClosed(const BufferClient* client) {
+ removeTokenByClient(client);
+
+ std::lock_guard<std::mutex> lock(mClientSetMutex);
+ auto iter = std::find(mClientSet.begin(), mClientSet.end(), client);
+ if (iter != mClientSet.end()) {
+ mClientSet.erase(iter);
+ }
+}
+
+void BufferHubService::removeTokenByClient(const BufferClient* client) {
+ std::lock_guard<std::mutex> lock(mTokenMapMutex);
+ auto iter = mTokenMap.begin();
+ while (iter != mTokenMap.end()) {
+ if (iter->second == client) {
+ auto oldIter = iter;
+ ++iter;
+ mTokenMap.erase(oldIter);
+ } else {
+ ++iter;
+ }
+ }
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace bufferhub
diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp
index 715d0a1..ec84849 100644
--- a/services/bufferhub/BufferNode.cpp
+++ b/services/bufferhub/BufferNode.cpp
@@ -66,8 +66,8 @@
}
// Free the id, if valid
- if (id() != UniqueIdGenerator::kInvalidId) {
- if (nodeIdGenerator.freeId(id())) {
+ if (id() != BufferHubIdGenerator::kInvalidId) {
+ if (BufferHubIdGenerator::getInstance().freeId(id())) {
ALOGI("%s: id #%u is freed.", __FUNCTION__, id());
} else {
ALOGE("%s: Cannot free nonexistent id #%u", __FUNCTION__, id());
diff --git a/services/bufferhub/include/bufferhub/BufferClient.h b/services/bufferhub/include/bufferhub/BufferClient.h
index 769ec86..7f5d3a6 100644
--- a/services/bufferhub/include/bufferhub/BufferClient.h
+++ b/services/bufferhub/include/bufferhub/BufferClient.h
@@ -44,14 +44,22 @@
// Creates a BufferClient from an existing BufferClient. Will share the same BufferNode.
explicit BufferClient(const BufferClient& other)
: mService(other.mService), mBufferNode(other.mBufferNode) {}
+ ~BufferClient();
+ Return<BufferHubStatus> close() override;
Return<void> duplicate(duplicate_cb _hidl_cb) override;
private:
BufferClient(wp<BufferHubService> service, const std::shared_ptr<BufferNode>& node)
: mService(service), mBufferNode(node) {}
+ sp<BufferHubService> getService();
+
wp<BufferHubService> mService;
+
+ std::mutex mClosedMutex;
+ bool mClosed GUARDED_BY(mClosedMutex) = false;
+
std::shared_ptr<BufferNode> mBufferNode;
};
diff --git a/services/bufferhub/include/bufferhub/UniqueIdGenerator.h b/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
similarity index 89%
rename from services/bufferhub/include/bufferhub/UniqueIdGenerator.h
rename to services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
index d2e702f..c5b2cde 100644
--- a/services/bufferhub/include/bufferhub/UniqueIdGenerator.h
+++ b/services/bufferhub/include/bufferhub/BufferHubIdGenerator.h
@@ -29,11 +29,14 @@
namespace implementation {
// A thread-safe incremental uint32_t id generator.
-class UniqueIdGenerator {
+class BufferHubIdGenerator {
public:
// 0 is considered invalid
static constexpr uint32_t kInvalidId = 0UL;
+ // Get the singleton instance of this class
+ static BufferHubIdGenerator& getInstance();
+
// Gets next available id. If next id is greater than std::numeric_limits<uint32_t>::max() (2 ^
// 32 - 1), it will try to get an id start from 1 again.
uint32_t getId();
@@ -42,6 +45,9 @@
bool freeId(uint32_t id);
private:
+ BufferHubIdGenerator() = default;
+ ~BufferHubIdGenerator() = default;
+
std::mutex mIdsInUseMutex;
// Start from kInvalidID to avoid generating it.
uint32_t mLastId = kInvalidId;
diff --git a/services/bufferhub/include/bufferhub/BufferHubService.h b/services/bufferhub/include/bufferhub/BufferHubService.h
index 6535659..f2c8ef8 100644
--- a/services/bufferhub/include/bufferhub/BufferHubService.h
+++ b/services/bufferhub/include/bufferhub/BufferHubService.h
@@ -22,7 +22,7 @@
#include <android/frameworks/bufferhub/1.0/IBufferHub.h>
#include <bufferhub/BufferClient.h>
-#include <bufferhub/UniqueIdGenerator.h>
+#include <bufferhub/BufferHubIdGenerator.h>
#include <utils/Mutex.h>
namespace android {
@@ -35,8 +35,6 @@
using hardware::Return;
using hardware::graphics::common::V1_2::HardwareBufferDescription;
-static UniqueIdGenerator nodeIdGenerator;
-
class BufferHubService : public IBufferHub {
public:
Return<void> allocateBuffer(const HardwareBufferDescription& description,
@@ -48,10 +46,15 @@
// Internal help function for IBufferClient::duplicate.
hidl_handle registerToken(const wp<BufferClient>& client);
+ void onClientClosed(const BufferClient* client);
+
private:
+ // Helper function to remove all the token belongs to a specific client.
+ void removeTokenByClient(const BufferClient* client);
+
// List of active BufferClient for bookkeeping.
- std::mutex mClientListMutex;
- std::vector<wp<BufferClient>> mClientList GUARDED_BY(mClientListMutex);
+ std::mutex mClientSetMutex;
+ std::set<wp<BufferClient>> mClientSet GUARDED_BY(mClientSetMutex);
// TODO(b/118180214): use a more secure implementation
std::mt19937 mTokenEngine;
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
index c490e7c..94ef505 100644
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ b/services/bufferhub/include/bufferhub/BufferNode.h
@@ -2,7 +2,7 @@
#define ANDROID_FRAMEWORKS_BUFFERHUB_V1_0_BUFFER_NODE_H_
#include <android/hardware_buffer.h>
-#include <bufferhub/UniqueIdGenerator.h>
+#include <bufferhub/BufferHubIdGenerator.h>
#include <ui/BufferHubMetadata.h>
namespace android {
@@ -16,7 +16,7 @@
// Allocates a new BufferNode.
BufferNode(uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
uint64_t usage, size_t user_metadata_size,
- uint32_t id = UniqueIdGenerator::kInvalidId);
+ uint32_t id = BufferHubIdGenerator::kInvalidId);
~BufferNode();
diff --git a/services/bufferhub/tests/Android.bp b/services/bufferhub/tests/Android.bp
index 8a30ef5..3967886 100644
--- a/services/bufferhub/tests/Android.bp
+++ b/services/bufferhub/tests/Android.bp
@@ -24,10 +24,10 @@
}
cc_test {
- name: "UniqueIdGenerator_test",
- srcs: ["UniqueIdGenerator_test.cpp"],
+ name: "BufferHubIdGenerator_test",
+ srcs: ["BufferHubIdGenerator_test.cpp"],
cflags: [
- "-DLOG_TAG=\"UniqueIdGenerator_test\"",
+ "-DLOG_TAG=\"BufferHubIdGenerator_test\"",
"-DTRACE=0",
"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
diff --git a/services/bufferhub/tests/BufferHubIdGenerator_test.cpp b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
new file mode 100644
index 0000000..4eddfe0
--- /dev/null
+++ b/services/bufferhub/tests/BufferHubIdGenerator_test.cpp
@@ -0,0 +1,45 @@
+#include <bufferhub/BufferHubIdGenerator.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace frameworks {
+namespace bufferhub {
+namespace V1_0 {
+namespace implementation {
+
+namespace {
+
+class BufferHubIdGeneratorTest : public testing::Test {
+protected:
+ BufferHubIdGenerator* mIdGenerator = &BufferHubIdGenerator::getInstance();
+};
+
+TEST_F(BufferHubIdGeneratorTest, TestGenerateAndFreeID) {
+ uint32_t id = mIdGenerator->getId();
+ EXPECT_NE(id, BufferHubIdGenerator::kInvalidId);
+
+ EXPECT_TRUE(mIdGenerator->freeId(id));
+ EXPECT_FALSE(mIdGenerator->freeId(id));
+}
+
+TEST_F(BufferHubIdGeneratorTest, TestGenerateUniqueIncrementalID) {
+ // 10 IDs should not overflow the UniqueIdGenerator to cause a roll back to start, so the
+ // resulting IDs should still keep incresing.
+ const size_t kTestSize = 10U;
+ uint32_t ids[kTestSize];
+ for (int i = 0; i < kTestSize; ++i) {
+ ids[i] = mIdGenerator->getId();
+ EXPECT_NE(ids[i], BufferHubIdGenerator::kInvalidId);
+ if (i >= 1) {
+ EXPECT_GT(ids[i], ids[i - 1]);
+ }
+ }
+}
+
+} // namespace
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace bufferhub
+} // namespace frameworks
+} // namespace android
\ No newline at end of file
diff --git a/services/bufferhub/tests/UniqueIdGenerator_test.cpp b/services/bufferhub/tests/UniqueIdGenerator_test.cpp
deleted file mode 100644
index c4d83e0..0000000
--- a/services/bufferhub/tests/UniqueIdGenerator_test.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include <bufferhub/UniqueIdGenerator.h>
-#include <gtest/gtest.h>
-
-namespace android {
-namespace frameworks {
-namespace bufferhub {
-namespace V1_0 {
-namespace implementation {
-
-namespace {
-
-class UniqueIdGeneratorTest : public testing::Test {
-protected:
- UniqueIdGenerator mIdGenerator;
-};
-
-TEST_F(UniqueIdGeneratorTest, TestGenerateAndFreeID) {
- uint32_t id = mIdGenerator.getId();
- EXPECT_NE(id, UniqueIdGenerator::kInvalidId);
-
- EXPECT_TRUE(mIdGenerator.freeId(id));
- EXPECT_FALSE(mIdGenerator.freeId(id));
-}
-
-TEST_F(UniqueIdGeneratorTest, TestGenerateUniqueIncrementalID) {
- // 10 IDs should not overflow the UniqueIdGenerator to cause a roll back to start, so the
- // resulting IDs should still keep incresing.
- const size_t kTestSize = 10U;
- uint32_t ids[kTestSize];
- for (int i = 0; i < kTestSize; ++i) {
- ids[i] = mIdGenerator.getId();
- EXPECT_NE(ids[i], UniqueIdGenerator::kInvalidId);
- if (i >= 1) {
- EXPECT_GT(ids[i], ids[i - 1]);
- }
- }
-}
-
-} // namespace
-
-} // namespace implementation
-} // namespace V1_0
-} // namespace bufferhub
-} // namespace frameworks
-} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 1dca1b6..885348e 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -3077,22 +3077,44 @@
// Remove all handles on a display if there are no windows left.
mWindowHandlesByDisplay.erase(displayId);
} else {
- size_t numWindows = inputWindowHandles.size();
+ // Since we compare the pointer of input window handles across window updates, we need
+ // to make sure the handle object for the same window stays unchanged across updates.
+ const Vector<sp<InputWindowHandle>>& oldHandles = mWindowHandlesByDisplay[displayId];
+ std::unordered_map<sp<IBinder>, sp<InputWindowHandle>, IBinderHash> oldHandlesByTokens;
+ for (size_t i = 0; i < oldHandles.size(); i++) {
+ const sp<InputWindowHandle>& handle = oldHandles.itemAt(i);
+ oldHandlesByTokens[handle->getToken()] = handle;
+ }
+
+ const size_t numWindows = inputWindowHandles.size();
+ Vector<sp<InputWindowHandle>> newHandles;
for (size_t i = 0; i < numWindows; i++) {
- const sp<InputWindowHandle>& windowHandle = inputWindowHandles.itemAt(i);
- if (!windowHandle->updateInfo() || getInputChannelLocked(windowHandle->getToken()) == nullptr) {
+ const sp<InputWindowHandle>& handle = inputWindowHandles.itemAt(i);
+ if (!handle->updateInfo() || getInputChannelLocked(handle->getToken()) == nullptr) {
ALOGE("Window handle %s has no registered input channel",
- windowHandle->getName().c_str());
+ handle->getName().c_str());
continue;
}
- if (windowHandle->getInfo()->displayId != displayId) {
+ if (handle->getInfo()->displayId != displayId) {
ALOGE("Window %s updated by wrong display %d, should belong to display %d",
- windowHandle->getName().c_str(), displayId,
- windowHandle->getInfo()->displayId);
+ handle->getName().c_str(), displayId,
+ handle->getInfo()->displayId);
continue;
}
+ if (oldHandlesByTokens.find(handle->getToken()) != oldHandlesByTokens.end()) {
+ const sp<InputWindowHandle> oldHandle =
+ oldHandlesByTokens.at(handle->getToken());
+ oldHandle->updateFrom(handle);
+ newHandles.push_back(oldHandle);
+ } else {
+ newHandles.push_back(handle);
+ }
+ }
+
+ for (size_t i = 0; i < newHandles.size(); i++) {
+ const sp<InputWindowHandle>& windowHandle = newHandles.itemAt(i);
if (windowHandle->getInfo()->hasFocus && windowHandle->getInfo()->visible) {
newFocusedWindowHandle = windowHandle;
}
@@ -3102,7 +3124,7 @@
}
// Insert or replace
- mWindowHandlesByDisplay[displayId] = inputWindowHandles;
+ mWindowHandlesByDisplay[displayId] = newHandles;
}
if (!foundHoveredWindow) {
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 5b641a2..3b7ed15 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -1067,6 +1067,18 @@
return error;
}
+Error Composer::setDisplayContentSamplingEnabled(Display display, bool enabled,
+ uint8_t componentMask, uint64_t maxFrames) {
+ if (!mClient_2_3) {
+ return Error::UNSUPPORTED;
+ }
+
+ auto enable = enabled ? V2_3::IComposerClient::DisplayedContentSampling::ENABLE
+ : V2_3::IComposerClient::DisplayedContentSampling::DISABLE;
+ return mClient_2_3->setDisplayedContentSamplingEnabled(display, enable, componentMask,
+ maxFrames);
+}
+
CommandReader::~CommandReader()
{
resetData();
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 61af348..0db12a1 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -192,6 +192,8 @@
virtual Error getDisplayedContentSamplingAttributes(Display display, PixelFormat* outFormat,
Dataspace* outDataspace,
uint8_t* outComponentMask) = 0;
+ virtual Error setDisplayContentSamplingEnabled(Display display, bool enabled,
+ uint8_t componentMask, uint64_t maxFrames) = 0;
virtual Error getDisplayCapabilities(Display display,
std::vector<DisplayCapability>* outCapabilities) = 0;
};
@@ -396,6 +398,8 @@
Error getDisplayedContentSamplingAttributes(Display display, PixelFormat* outFormat,
Dataspace* outDataspace,
uint8_t* outComponentMask) override;
+ Error setDisplayContentSamplingEnabled(Display display, bool enabled, uint8_t componentMask,
+ uint64_t maxFrames) override;
Error getDisplayCapabilities(Display display,
std::vector<DisplayCapability>* outCapabilities) override;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 2df2d3b..733a5da 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -555,6 +555,13 @@
return static_cast<Error>(intError);
}
+Error Display::setDisplayContentSamplingEnabled(bool enabled, uint8_t componentMask,
+ uint64_t maxFrames) const {
+ auto intError =
+ mComposer.setDisplayContentSamplingEnabled(mId, enabled, componentMask, maxFrames);
+ return static_cast<Error>(intError);
+}
+
Error Display::getReleaseFences(
std::unordered_map<Layer*, sp<Fence>>* outFences) const
{
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 8c0f50c..2d65051 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -240,6 +240,9 @@
[[clang::warn_unused_result]] Error getDisplayedContentSamplingAttributes(
android::ui::PixelFormat* outFormat, android::ui::Dataspace* outDataspace,
uint8_t* outComponentMask) const;
+ [[clang::warn_unused_result]] Error setDisplayContentSamplingEnabled(bool enabled,
+ uint8_t componentMask,
+ uint64_t maxFrames) const;
[[clang::warn_unused_result]] Error getReleaseFences(
std::unordered_map<Layer*,
android::sp<android::Fence>>* outFences) const;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index a752a7d..b27344d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -756,6 +756,20 @@
return NO_ERROR;
}
+status_t HWComposer::setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
+ uint8_t componentMask, uint64_t maxFrames) {
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error =
+ mDisplayData[displayId].hwcDisplay->setDisplayContentSamplingEnabled(enabled,
+ componentMask,
+ maxFrames);
+
+ if (error == HWC2::Error::Unsupported) RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ if (error == HWC2::Error::BadParameter) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
bool HWComposer::isUsingVrComposer() const {
return getComposer()->isUsingVrComposer();
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 0375f74..3f1328e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -131,6 +131,8 @@
status_t getDisplayedContentSamplingAttributes(DisplayId displayId, ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask);
+ status_t setDisplayContentSamplingEnabled(DisplayId displayId, bool enabled,
+ uint8_t componentMask, uint64_t maxFrames);
// Events handling ---------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 15e416a..f53ffae 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2121,10 +2121,6 @@
InputWindowInfo Layer::fillInputInfo(const Rect& screenBounds) {
InputWindowInfo info = mDrawingState.inputInfo;
- info.frameLeft = screenBounds.left + info.surfaceInset;
- info.frameTop = screenBounds.top + info.surfaceInset;
- info.frameRight = screenBounds.right - info.surfaceInset;
- info.frameBottom = screenBounds.bottom - info.surfaceInset;
ui::Transform t = getTransform();
const float xScale = t.sx();
@@ -2135,9 +2131,26 @@
info.touchableRegion.scaleSelf(xScale, yScale);
}
- info.touchableRegion = info.touchableRegion.translate(
- screenBounds.left,
- screenBounds.top);
+ // Transform layer size to screen space and inset it by surface insets.
+ Rect layerBounds = getCroppedBufferSize(getDrawingState());
+ layerBounds = t.transform(layerBounds);
+ layerBounds.inset(info.surfaceInset, info.surfaceInset, info.surfaceInset, info.surfaceInset);
+
+ // Intersect with screen bounds to shrink the frame by the surface insets. The surface insets
+ // are not set on the screen bounds directly since the surface inset region may already be
+ // cropped by a parent layer.
+ Rect frame;
+ screenBounds.intersect(layerBounds, &frame);
+
+ info.frameLeft = frame.left;
+ info.frameTop = frame.top;
+ info.frameRight = frame.right;
+ info.frameBottom = frame.bottom;
+
+ // Position the touchable region relative to frame screen location and restrict it to frame
+ // bounds.
+ info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop);
+ info.touchableRegion = info.touchableRegion.intersect(frame);
info.visible = isVisible();
return info;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a8de576..0bda020 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1123,8 +1123,7 @@
if (!outFormat || !outDataspace || !outComponentMask) {
return BAD_VALUE;
}
- Mutex::Autolock _l(mStateLock);
- const auto display = getDisplayDeviceLocked(displayToken);
+ const auto display = getDisplayDevice(displayToken);
if (!display || !display->getId()) {
ALOGE("getDisplayedContentSamplingAttributes: Bad display token: %p", display.get());
return BAD_VALUE;
@@ -1133,6 +1132,19 @@
outDataspace, outComponentMask);
}
+status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken,
+ bool enable, uint8_t componentMask,
+ uint64_t maxFrames) const {
+ const auto display = getDisplayDevice(displayToken);
+ if (!display || !display->getId()) {
+ ALOGE("setDisplayContentSamplingEnabled: Bad display token: %p", display.get());
+ return BAD_VALUE;
+ }
+
+ return getHwComposer().setDisplayContentSamplingEnabled(*display->getId(), enable,
+ componentMask, maxFrames);
+}
+
status_t SurfaceFlinger::enableVSyncInjections(bool enable) {
postMessageSync(new LambdaMessage([&] {
Mutex::Autolock _l(mStateLock);
@@ -4778,7 +4790,8 @@
case SET_ACTIVE_COLOR_MODE:
case INJECT_VSYNC:
case SET_POWER_MODE:
- case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: {
+ case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
+ case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: {
if (!callingThreadHasUnscopedSurfaceFlingerAccess()) {
IPCThreadState* ipc = IPCThreadState::self();
ALOGE("Permission Denial: can't access SurfaceFlinger pid=%d, uid=%d",
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9039a14..fe2f1c26 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -483,6 +483,9 @@
virtual status_t getDisplayedContentSamplingAttributes(
const sp<IBinder>& display, ui::PixelFormat* outFormat, ui::Dataspace* outDataspace,
uint8_t* outComponentMask) const override;
+ virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ uint8_t componentMask,
+ uint64_t maxFrames) const override;
/* ------------------------------------------------------------------------
* DeathRecipient interface
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index b0360a2..1a9249c 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1230,7 +1230,7 @@
sp<SurfaceControl> layer;
const uint8_t size = 64;
const uint8_t testArea = 4;
- const float cornerRadius = 16.0f;
+ const float cornerRadius = 20.0f;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size));
ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size));
@@ -1238,13 +1238,43 @@
.setCornerRadius(layer, cornerRadius)
.apply();
{
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
auto shot = screenshot();
// Transparent corners
shot->expectColor(Rect(0, 0, testArea, testArea), Color::BLACK);
- shot->expectColor(Rect(0, size - testArea, testArea, testArea), Color::BLACK);
- shot->expectColor(Rect(size - testArea, 0, testArea, testArea), Color::BLACK);
- shot->expectColor(Rect(size - testArea, size - testArea, testArea, testArea),
- Color::BLACK);
+ shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::BLACK);
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
+ shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::BLACK);
+ }
+}
+
+TEST_P(LayerTypeTransactionTest, SetCornerRadiusChildCrop) {
+ sp<SurfaceControl> parent;
+ sp<SurfaceControl> child;
+ const uint8_t size = 64;
+ const uint8_t testArea = 4;
+ const float cornerRadius = 20.0f;
+ ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", size, size));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, size, size));
+ ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2));
+
+ Transaction()
+ .setCornerRadius(parent, cornerRadius)
+ .reparent(child, parent->getHandle())
+ .setPosition(child, 0, size / 2)
+ .apply();
+ {
+ const uint8_t bottom = size - 1;
+ const uint8_t right = size - 1;
+ auto shot = screenshot();
+ // Top edge of child should not have rounded corners because it's translated in the parent
+ shot->expectColor(Rect(0, size / 2, right, static_cast<int>(bottom - cornerRadius)),
+ Color::GREEN);
+ // But bottom edges should have been clipped according to parent bounds
+ shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK);
+ shot->expectColor(Rect(right - testArea, bottom - testArea, right, bottom), Color::BLACK);
}
}
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 5a46c26..68fd8b4 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -115,6 +115,7 @@
MOCK_METHOD3(setLayerColorTransform, Error(Display, Layer, const float*));
MOCK_METHOD4(getDisplayedContentSamplingAttributes,
Error(Display, PixelFormat*, Dataspace*, uint8_t*));
+ MOCK_METHOD4(setDisplayContentSamplingEnabled, Error(Display, bool, uint8_t, uint64_t));
MOCK_METHOD2(getDisplayCapabilities, Error(Display, std::vector<DisplayCapability>*));
};
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 0a59f29..7a7e437 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -14,7 +14,6 @@
sharedLibraries = [
"libbase",
- "libbinder",
"libbufferhubservice",
"libcutils",
"libgtest_prod",
@@ -30,12 +29,9 @@
name: "libbufferhubd",
srcs: [
"buffer_channel.cpp",
- "buffer_client.cpp",
"buffer_hub.cpp",
- "buffer_hub_binder.cpp",
"consumer_channel.cpp",
"consumer_queue_channel.cpp",
- "IBufferHub.cpp",
"producer_channel.cpp",
"producer_queue_channel.cpp",
],
@@ -45,10 +41,7 @@
"-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
],
export_include_dirs: ["include"],
- header_libs: [
- "libdvr_headers",
- "libnativewindow_headers",
- ],
+ header_libs: ["libdvr_headers"],
shared_libs: sharedLibraries,
static_libs: [
"libbufferhub",
diff --git a/services/vr/bufferhubd/IBufferHub.cpp b/services/vr/bufferhubd/IBufferHub.cpp
deleted file mode 100644
index 5980873..0000000
--- a/services/vr/bufferhubd/IBufferHub.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <log/log.h>
-#include <private/dvr/IBufferHub.h>
-
-namespace android {
-namespace dvr {
-
-class BpBufferHub : public BpInterface<IBufferHub> {
- public:
- explicit BpBufferHub(const sp<IBinder>& impl)
- : BpInterface<IBufferHub>(impl) {}
-
- sp<IBufferClient> createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage,
- uint64_t user_metadata_size) override;
-
- status_t importBuffer(uint64_t token, sp<IBufferClient>* outClient) override;
-};
-
-IMPLEMENT_META_INTERFACE(BufferHub, "android.dvr.IBufferHub");
-
-// Transaction code
-enum {
- CREATE_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
- IMPORT_BUFFER,
-};
-
-sp<IBufferClient> BpBufferHub::createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count,
- uint32_t format, uint64_t usage,
- uint64_t user_metadata_size) {
- Parcel data, reply;
- status_t ret = OK;
- ret |= data.writeInterfaceToken(IBufferHub::getInterfaceDescriptor());
- ret |= data.writeUint32(width);
- ret |= data.writeUint32(height);
- ret |= data.writeUint32(layer_count);
- ret |= data.writeUint32(format);
- ret |= data.writeUint64(usage);
- ret |= data.writeUint64(user_metadata_size);
-
- if (ret != OK) {
- ALOGE("BpBufferHub::createBuffer: failed to write into parcel");
- return nullptr;
- }
-
- ret = remote()->transact(CREATE_BUFFER, data, &reply);
- if (ret == OK) {
- return interface_cast<IBufferClient>(reply.readStrongBinder());
- } else {
- ALOGE("BpBufferHub::createBuffer: failed to transact; errno=%d", ret);
- return nullptr;
- }
-}
-
-status_t BpBufferHub::importBuffer(uint64_t token,
- sp<IBufferClient>* outClient) {
- Parcel data, reply;
- status_t ret = OK;
- ret |= data.writeInterfaceToken(IBufferHub::getInterfaceDescriptor());
- ret |= data.writeUint64(token);
- if (ret != OK) {
- ALOGE("BpBufferHub::importBuffer: failed to write into parcel");
- return ret;
- }
-
- ret = remote()->transact(IMPORT_BUFFER, data, &reply);
- if (ret == OK) {
- *outClient = interface_cast<IBufferClient>(reply.readStrongBinder());
- return OK;
- } else {
- ALOGE("BpBufferHub::importBuffer: failed to transact; errno=%d", ret);
- return ret;
- }
-}
-
-status_t BnBufferHub::onTransact(uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags) {
- switch (code) {
- case CREATE_BUFFER: {
- CHECK_INTERFACE(IBufferHub, data, reply);
- uint32_t width = data.readUint32();
- uint32_t height = data.readUint32();
- uint32_t layer_count = data.readUint32();
- uint32_t format = data.readUint32();
- uint64_t usage = data.readUint64();
- uint64_t user_metadata_size = data.readUint64();
- sp<IBufferClient> ret = createBuffer(width, height, layer_count, format,
- usage, user_metadata_size);
- return reply->writeStrongBinder(IInterface::asBinder(ret));
- }
- case IMPORT_BUFFER: {
- CHECK_INTERFACE(IBufferHub, data, reply);
- uint64_t token = data.readUint64();
- sp<IBufferClient> client;
- status_t ret = importBuffer(token, &client);
- if (ret == OK) {
- return reply->writeStrongBinder(IInterface::asBinder(client));
- } else {
- return ret;
- }
- }
- default:
- // Should not reach except binder defined transactions such as dumpsys
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file
diff --git a/services/vr/bufferhubd/buffer_client.cpp b/services/vr/bufferhubd/buffer_client.cpp
deleted file mode 100644
index f14faf7..0000000
--- a/services/vr/bufferhubd/buffer_client.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <private/dvr/buffer_client.h>
-#include <private/dvr/buffer_hub_binder.h>
-
-namespace android {
-namespace dvr {
-
-status_t BufferClient::duplicate(uint64_t* outToken) {
- if (!buffer_node_) {
- // Should never happen
- ALOGE("BufferClient::duplicate: node is missing.");
- return UNEXPECTED_NULL;
- }
- return service_->registerToken(std::weak_ptr<BufferNode>(buffer_node_),
- outToken);
-}
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file
diff --git a/services/vr/bufferhubd/buffer_hub_binder.cpp b/services/vr/bufferhubd/buffer_hub_binder.cpp
deleted file mode 100644
index 580433e..0000000
--- a/services/vr/bufferhubd/buffer_hub_binder.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-#include <stdio.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <log/log.h>
-#include <private/dvr/buffer_hub_binder.h>
-#include <private/dvr/buffer_node.h>
-
-namespace android {
-namespace dvr {
-
-status_t BufferHubBinderService::start(
- const std::shared_ptr<BufferHubService>& pdx_service) {
- IPCThreadState::self()->disableBackgroundScheduling(true);
-
- sp<BufferHubBinderService> service = new BufferHubBinderService();
- service->pdx_service_ = pdx_service;
-
- // Not using BinderService::publish because need to get an instance of this
- // class (above). Following code is the same as
- // BinderService::publishAndJoinThreadPool
- sp<IServiceManager> sm = defaultServiceManager();
- status_t result = sm->addService(
- String16(getServiceName()), service,
- /*allowIsolated =*/false,
- /*dump flags =*/IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
- if (result != OK) {
- ALOGE("Publishing bufferhubd failed with error %d", result);
- return result;
- }
-
- sp<ProcessState> process_self(ProcessState::self());
- process_self->startThreadPool();
-
- return result;
-}
-
-status_t BufferHubBinderService::dump(int fd, const Vector<String16>& args) {
- FILE* out = fdopen(dup(fd), "w");
-
- // Currently not supporting args, so notify the user.
- if (!args.isEmpty()) {
- fprintf(out,
- "Note: dumpsys bufferhubd currently does not support args."
- "Input arguments are ignored.\n");
- }
-
- fprintf(out, "Binder service:\n");
- // Active buffers
- fprintf(out, "Active BufferClients: %zu\n", client_list_.size());
- // TODO(b/117790952): print buffer information after BufferNode has it
- // TODO(b/116526156): print more information once we have them
-
- if (pdx_service_) {
- fprintf(out, "\nPDX service:\n");
- // BufferHubService::Dumpstate(size_t) is not actually using the param
- // So just using 0 as the length
- fprintf(out, "%s", pdx_service_->DumpState(0).c_str());
- } else {
- fprintf(out, "PDX service not registered or died.\n");
- }
-
- fclose(out);
- return OK;
-}
-
-status_t BufferHubBinderService::registerToken(
- const std::weak_ptr<BufferNode> node, uint64_t* outToken) {
- do {
- *outToken = token_engine_();
- } while (token_map_.find(*outToken) != token_map_.end());
-
- token_map_.emplace(*outToken, node);
- return OK;
-}
-
-sp<IBufferClient> BufferHubBinderService::createBuffer(
- uint32_t width, uint32_t height, uint32_t layer_count, uint32_t format,
- uint64_t usage, uint64_t user_metadata_size) {
- std::shared_ptr<BufferNode> node = std::make_shared<BufferNode>(
- width, height, layer_count, format, usage, user_metadata_size);
-
- sp<BufferClient> client = new BufferClient(node, this);
- // Add it to list for bookkeeping and dumpsys.
- client_list_.push_back(client);
-
- return client;
-}
-
-status_t BufferHubBinderService::importBuffer(uint64_t token,
- sp<IBufferClient>* outClient) {
- auto iter = token_map_.find(token);
-
- if (iter == token_map_.end()) { // Not found
- ALOGE("BufferHubBinderService::importBuffer: token %" PRIu64
- "does not exist.",
- token);
- return PERMISSION_DENIED;
- }
-
- if (iter->second.expired()) { // Gone
- ALOGW(
- "BufferHubBinderService::importBuffer: the original node of token "
- "%" PRIu64 "has gone.",
- token);
- token_map_.erase(iter);
- return DEAD_OBJECT;
- }
-
- // Promote the weak_ptr
- std::shared_ptr<BufferNode> node(iter->second);
- if (!node) {
- ALOGE("BufferHubBinderService::importBuffer: promote weak_ptr failed.");
- token_map_.erase(iter);
- return DEAD_OBJECT;
- }
-
- sp<BufferClient> client = new BufferClient(node, this);
- *outClient = client;
-
- token_map_.erase(iter);
- client_list_.push_back(client);
-
- return OK;
-}
-
-} // namespace dvr
-} // namespace android
diff --git a/services/vr/bufferhubd/bufferhubd.cpp b/services/vr/bufferhubd/bufferhubd.cpp
index e44cc2a..50cb3b7 100644
--- a/services/vr/bufferhubd/bufferhubd.cpp
+++ b/services/vr/bufferhubd/bufferhubd.cpp
@@ -6,7 +6,6 @@
#include <log/log.h>
#include <pdx/service_dispatcher.h>
#include <private/dvr/buffer_hub.h>
-#include <private/dvr/buffer_hub_binder.h>
int main(int, char**) {
int ret = -1;
@@ -40,10 +39,6 @@
CHECK_ERROR(!pdx_service, error, "Failed to create bufferhub pdx service\n");
dispatcher->AddService(pdx_service);
- ret = android::dvr::BufferHubBinderService::start(pdx_service);
- CHECK_ERROR(ret != android::OK, error,
- "Failed to create bufferhub binder service\n");
-
ret = dvrSetSchedulerClass(0, "graphics");
CHECK_ERROR(ret < 0, error, "Failed to set thread priority");
diff --git a/services/vr/bufferhubd/include/private/dvr/IBufferHub.h b/services/vr/bufferhubd/include/private/dvr/IBufferHub.h
deleted file mode 100644
index 502c6d6..0000000
--- a/services/vr/bufferhubd/include/private/dvr/IBufferHub.h
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef ANDROID_DVR_IBUFFERHUB_H
-#define ANDROID_DVR_IBUFFERHUB_H
-
-#include <binder/IInterface.h>
-#include <binder/Parcel.h>
-#include <private/dvr/IBufferClient.h>
-
-namespace android {
-namespace dvr {
-
-class IBufferHub : public IInterface {
- public:
- DECLARE_META_INTERFACE(BufferHub);
-
- static const char* getServiceName() { return "bufferhubd"; }
- virtual sp<IBufferClient> createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage,
- uint64_t user_metadata_size) = 0;
-
- virtual status_t importBuffer(uint64_t token,
- sp<IBufferClient>* outClient) = 0;
-};
-
-class BnBufferHub : public BnInterface<IBufferHub> {
- public:
- virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags = 0);
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_IBUFFERHUB_H
\ No newline at end of file
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_client.h b/services/vr/bufferhubd/include/private/dvr/buffer_client.h
deleted file mode 100644
index d79ec0a..0000000
--- a/services/vr/bufferhubd/include/private/dvr/buffer_client.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef ANDROID_DVR_BUFFERCLIENT_H
-#define ANDROID_DVR_BUFFERCLIENT_H
-
-#include <private/dvr/IBufferClient.h>
-#include <private/dvr/buffer_node.h>
-
-namespace android {
-namespace dvr {
-
-// Forward declaration to avoid circular dependency
-class BufferHubBinderService;
-
-class BufferClient : public BnBufferClient {
- public:
- // Creates a server-side buffer client from an existing BufferNode. Note that
- // this funciton takes ownership of the shared_ptr.
- explicit BufferClient(std::shared_ptr<BufferNode> node,
- BufferHubBinderService* service)
- : service_(service), buffer_node_(std::move(node)){};
-
- // Binder IPC functions
- bool isValid() override {
- return buffer_node_ ? buffer_node_->IsValid() : false;
- };
-
- status_t duplicate(uint64_t* outToken) override;
-
- private:
- // Hold a pointer to the service to bypass binder interface, as BufferClient
- // and the service will be in the same process. Also, since service owns
- // Client, if service dead the clients will be destroyed, so this pointer is
- // guaranteed to be valid.
- BufferHubBinderService* service_;
-
- std::shared_ptr<BufferNode> buffer_node_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_IBUFFERCLIENT_H
\ No newline at end of file
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
deleted file mode 100644
index cf6124b..0000000
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub_binder.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef ANDROID_DVR_BUFFER_HUB_BINDER_H
-#define ANDROID_DVR_BUFFER_HUB_BINDER_H
-
-#include <random>
-#include <unordered_map>
-#include <vector>
-
-#include <binder/BinderService.h>
-#include <private/dvr/IBufferHub.h>
-#include <private/dvr/buffer_client.h>
-#include <private/dvr/buffer_hub.h>
-#include <private/dvr/buffer_node.h>
-
-namespace android {
-namespace dvr {
-
-class BufferHubBinderService : public BinderService<BufferHubBinderService>,
- public BnBufferHub {
- public:
- static status_t start(const std::shared_ptr<BufferHubService>& pdx_service);
- // Dumps bufferhub related information to given fd (usually stdout)
- // usage: adb shell dumpsys bufferhubd
- virtual status_t dump(int fd, const Vector<String16>& args) override;
-
- // Marks a BufferNode to be duplicated.
- // TODO(b/116681016): add importToken(int64_t)
- status_t registerToken(const std::weak_ptr<BufferNode> node,
- uint64_t* outToken);
-
- // Binder IPC functions
- sp<IBufferClient> createBuffer(uint32_t width, uint32_t height,
- uint32_t layer_count, uint32_t format,
- uint64_t usage,
- uint64_t user_metadata_size) override;
-
- status_t importBuffer(uint64_t token, sp<IBufferClient>* outClient) override;
-
- private:
- std::shared_ptr<BufferHubService> pdx_service_;
-
- std::vector<sp<BufferClient>> client_list_;
-
- // TODO(b/118180214): use a more secure implementation
- std::mt19937_64 token_engine_;
- // The mapping from token to a specific node. This is a many-to-one mapping.
- // One node could be refered by 0 to multiple tokens.
- std::unordered_map<uint64_t, std::weak_ptr<BufferNode>> token_map_;
-};
-
-} // namespace dvr
-} // namespace android
-
-#endif // ANDROID_DVR_BUFFER_HUB_BINDER_H
diff --git a/services/vr/bufferhubd/tests/Android.bp b/services/vr/bufferhubd/tests/Android.bp
deleted file mode 100644
index a611268..0000000
--- a/services/vr/bufferhubd/tests/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-cc_test {
- name: "buffer_hub_binder_service-test",
- srcs: ["buffer_hub_binder_service-test.cpp"],
- cflags: [
- "-DLOG_TAG=\"buffer_hub_binder_service-test\"",
- "-DTRACE=0",
- "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
- ],
- header_libs: ["libdvr_headers"],
- static_libs: [
- "libbufferhub",
- "libbufferhubd",
- "libgmock",
- ],
- shared_libs: [
- "libbase",
- "libbinder",
- "liblog",
- "libpdx_default_transport",
- "libui",
- "libutils",
- ],
-
- // TODO(b/117568153): Temporarily opt out using libcrt.
- no_libcrt: true,
-}
diff --git a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp b/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
deleted file mode 100644
index 94b422a..0000000
--- a/services/vr/bufferhubd/tests/buffer_hub_binder_service-test.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-#include <binder/IServiceManager.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <private/dvr/IBufferClient.h>
-#include <private/dvr/IBufferHub.h>
-#include <ui/PixelFormat.h>
-
-namespace android {
-namespace dvr {
-
-namespace {
-
-using testing::IsNull;
-using testing::NotNull;
-
-const int kWidth = 640;
-const int kHeight = 480;
-const int kLayerCount = 1;
-const int kFormat = HAL_PIXEL_FORMAT_RGBA_8888;
-const int kUsage = 0;
-const size_t kUserMetadataSize = 0;
-
-class BufferHubBinderServiceTest : public ::testing::Test {
- protected:
- void SetUp() override {
- status_t ret = getService<IBufferHub>(
- String16(IBufferHub::getServiceName()), &service);
- ASSERT_EQ(ret, OK);
- ASSERT_THAT(service, NotNull());
- }
-
- sp<IBufferHub> service;
-};
-
-TEST_F(BufferHubBinderServiceTest, TestCreateBuffer) {
- sp<IBufferClient> bufferClient = service->createBuffer(
- kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
- ASSERT_THAT(bufferClient, NotNull());
- EXPECT_TRUE(bufferClient->isValid());
-}
-
-TEST_F(BufferHubBinderServiceTest, TestDuplicateAndImportBuffer) {
- sp<IBufferClient> bufferClient = service->createBuffer(
- kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
- ASSERT_THAT(bufferClient, NotNull());
- EXPECT_TRUE(bufferClient->isValid());
-
- uint64_t token1 = 0ULL;
- status_t ret = bufferClient->duplicate(&token1);
- EXPECT_EQ(ret, OK);
-
- // Tokens should be unique even corresponding to the same buffer
- uint64_t token2 = 0ULL;
- ret = bufferClient->duplicate(&token2);
- EXPECT_EQ(ret, OK);
- EXPECT_NE(token2, token1);
-
- sp<IBufferClient> bufferClient1;
- ret = service->importBuffer(token1, &bufferClient1);
- EXPECT_EQ(ret, OK);
- ASSERT_THAT(bufferClient1, NotNull());
- EXPECT_TRUE(bufferClient1->isValid());
-
- // Consumes the token to keep the service clean
- sp<IBufferClient> bufferClient2;
- ret = service->importBuffer(token2, &bufferClient2);
- EXPECT_EQ(ret, OK);
- ASSERT_THAT(bufferClient2, NotNull());
- EXPECT_TRUE(bufferClient2->isValid());
-}
-
-TEST_F(BufferHubBinderServiceTest, TestImportUnexistingToken) {
- // There is very little chance that this test fails if there is a token = 0
- // in the service.
- uint64_t unexistingToken = 0ULL;
- sp<IBufferClient> bufferClient;
- status_t ret = service->importBuffer(unexistingToken, &bufferClient);
- EXPECT_EQ(ret, PERMISSION_DENIED);
- EXPECT_THAT(bufferClient, IsNull());
-}
-
-} // namespace
-
-} // namespace dvr
-} // namespace android
\ No newline at end of file