Merge "Process focus events first"
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9e135ac..f07f82a 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2836,8 +2836,6 @@
}
} else {
- desired = std::max(desired, (size_t)128);
-
// This is the first data. Easy!
uint8_t* data = (uint8_t*)malloc(desired);
if (!data) {
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 0442b8b..9aa7651 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -7,9 +7,6 @@
"name": "binderVendorDoubleLoadTest"
},
{
- "name": "binderAllocationLimits"
- },
- {
"name": "binderDriverInterfaceTest"
},
{
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 2680e84..c0da2cd 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -169,18 +169,3 @@
test_suites: ["device-tests"],
require_root: true,
}
-
-cc_test {
- name: "binderAllocationLimits",
- defaults: ["binder_test_defaults"],
- srcs: ["binderAllocationLimits.cpp"],
- shared_libs: [
- "libbinder",
- "liblog",
- "libutils",
- "libutilscallstack",
- "libbase",
- ],
- test_suites: ["device-tests"],
- require_root: true,
-}
diff --git a/libs/binder/tests/binderAllocationLimits.cpp b/libs/binder/tests/binderAllocationLimits.cpp
deleted file mode 100644
index e1f5ed5..0000000
--- a/libs/binder/tests/binderAllocationLimits.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <binder/Parcel.h>
-#include <binder/IServiceManager.h>
-#include <gtest/gtest.h>
-#include <utils/CallStack.h>
-
-#include <malloc.h>
-#include <functional>
-#include <vector>
-
-struct DestructionAction {
- DestructionAction(std::function<void()> f) : mF(std::move(f)) {}
- ~DestructionAction() { mF(); };
-private:
- std::function<void()> mF;
-};
-
-// Group of hooks
-struct MallocHooks {
- decltype(__malloc_hook) malloc_hook;
- decltype(__realloc_hook) realloc_hook;
-
- static MallocHooks save() {
- return {
- .malloc_hook = __malloc_hook,
- .realloc_hook = __realloc_hook,
- };
- }
-
- void overwrite() const {
- __malloc_hook = malloc_hook;
- __realloc_hook = realloc_hook;
- }
-};
-
-static const MallocHooks orig_malloc_hooks = MallocHooks::save();
-
-// When malloc is hit, executes lambda.
-namespace LambdaHooks {
- using AllocationHook = std::function<void(size_t)>;
- static std::vector<AllocationHook> lambdas = {};
-
- static void* lambda_realloc_hook(void* ptr, size_t bytes, const void* arg);
- static void* lambda_malloc_hook(size_t bytes, const void* arg);
-
- static const MallocHooks lambda_malloc_hooks = {
- .malloc_hook = lambda_malloc_hook,
- .realloc_hook = lambda_realloc_hook,
- };
-
- static void* lambda_malloc_hook(size_t bytes, const void* arg) {
- {
- orig_malloc_hooks.overwrite();
- lambdas.at(lambdas.size() - 1)(bytes);
- lambda_malloc_hooks.overwrite();
- }
- return orig_malloc_hooks.malloc_hook(bytes, arg);
- }
-
- static void* lambda_realloc_hook(void* ptr, size_t bytes, const void* arg) {
- {
- orig_malloc_hooks.overwrite();
- lambdas.at(lambdas.size() - 1)(bytes);
- lambda_malloc_hooks.overwrite();
- }
- return orig_malloc_hooks.realloc_hook(ptr, bytes, arg);
- }
-
-}
-
-// Action to execute when malloc is hit. Supports nesting. Malloc is not
-// restricted when the allocation hook is being processed.
-__attribute__((warn_unused_result))
-DestructionAction OnMalloc(LambdaHooks::AllocationHook f) {
- MallocHooks before = MallocHooks::save();
- LambdaHooks::lambdas.emplace_back(std::move(f));
- LambdaHooks::lambda_malloc_hooks.overwrite();
- return DestructionAction([before]() {
- before.overwrite();
- LambdaHooks::lambdas.pop_back();
- });
-}
-
-// exported symbol, to force compiler not to optimize away pointers we set here
-const void* imaginary_use;
-
-TEST(TestTheTest, OnMalloc) {
- size_t mallocs = 0;
- {
- const auto on_malloc = OnMalloc([&](size_t bytes) {
- mallocs++;
- EXPECT_EQ(bytes, 40);
- });
-
- imaginary_use = new int[10];
- }
- EXPECT_EQ(mallocs, 1);
-}
-
-
-__attribute__((warn_unused_result))
-DestructionAction ScopeDisallowMalloc() {
- return OnMalloc([&](size_t bytes) {
- ADD_FAILURE() << "Unexpected allocation: " << bytes;
- using android::CallStack;
- std::cout << CallStack::stackToString("UNEXPECTED ALLOCATION", CallStack::getCurrent(4 /*ignoreDepth*/).get())
- << std::endl;
- });
-}
-
-using android::IBinder;
-using android::Parcel;
-using android::String16;
-using android::defaultServiceManager;
-using android::sp;
-using android::IServiceManager;
-
-static sp<IBinder> GetRemoteBinder() {
- // This gets binder representing the service manager
- // the current IServiceManager API doesn't expose the binder, and
- // I want to avoid adding usages of the AIDL generated interface it
- // is using underneath, so to avoid people copying it.
- sp<IBinder> binder = defaultServiceManager()->checkService(String16("manager"));
- EXPECT_NE(nullptr, binder);
- return binder;
-}
-
-TEST(BinderAllocation, ParcelOnStack) {
- const auto m = ScopeDisallowMalloc();
- Parcel p;
- imaginary_use = p.data();
-}
-
-TEST(BinderAllocation, GetServiceManager) {
- defaultServiceManager(); // first call may alloc
- const auto m = ScopeDisallowMalloc();
- defaultServiceManager();
-}
-
-// note, ping does not include interface descriptor
-TEST(BinderAllocation, PingTransaction) {
- sp<IBinder> a_binder = GetRemoteBinder();
- const auto m = ScopeDisallowMalloc();
- a_binder->pingBinder();
-}
-
-TEST(BinderAllocation, SmallTransaction) {
- String16 empty_descriptor = String16("");
- sp<IServiceManager> manager = defaultServiceManager();
-
- size_t mallocs = 0;
- const auto on_malloc = OnMalloc([&](size_t bytes) {
- mallocs++;
- // Parcel should allocate a small amount by default
- EXPECT_EQ(bytes, 128);
- });
- manager->checkService(empty_descriptor);
-
- EXPECT_EQ(mallocs, 1);
-}
-
-int main(int argc, char** argv) {
- if (getenv("LIBC_HOOKS_ENABLE") == nullptr) {
- CHECK(0 == setenv("LIBC_HOOKS_ENABLE", "1", true /*overwrite*/));
- execv(argv[0], argv);
- return 1;
- }
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/libs/gralloc/types/include/gralloctypes/Gralloc4.h b/libs/gralloc/types/include/gralloctypes/Gralloc4.h
index 8d12754..1a7c2c9 100644
--- a/libs/gralloc/types/include/gralloctypes/Gralloc4.h
+++ b/libs/gralloc/types/include/gralloctypes/Gralloc4.h
@@ -431,6 +431,12 @@
static_cast<int64_t>(
aidl::android::hardware::graphics::common::PlaneLayoutComponentType::A)};
+static const aidl::android::hardware::graphics::common::ExtendableType
+ PlaneLayoutComponentType_RAW =
+ {GRALLOC4_STANDARD_PLANE_LAYOUT_COMPONENT_TYPE,
+ static_cast<int64_t>(
+ aidl::android::hardware::graphics::common::PlaneLayoutComponentType::RAW)};
+
/*---------------------------------------------------------------------------------------------*/
/**
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index f0eb34b..596f15c 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -25,7 +25,7 @@
namespace android {
namespace renderengine {
-std::unique_ptr<impl::RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) {
+std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) {
RenderEngineType renderEngineType = args.renderEngineType;
// Keep the ability to override by PROPERTIES:
@@ -41,7 +41,9 @@
switch (renderEngineType) {
case RenderEngineType::THREADED:
ALOGD("Threaded RenderEngine with GLES Backend");
- return renderengine::threaded::RenderEngineThreaded::create(args);
+ return renderengine::threaded::RenderEngineThreaded::create([&args]() {
+ return android::renderengine::gl::GLESRenderEngine::create(args);
+ });
case RenderEngineType::GLES:
default:
ALOGD("RenderEngine with GLES Backend");
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 45e19ee..b137023 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -76,7 +76,7 @@
THREADED = 2,
};
- static std::unique_ptr<impl::RenderEngine> create(const RenderEngineCreationArgs& args);
+ static std::unique_ptr<RenderEngine> create(const RenderEngineCreationArgs& args);
virtual ~RenderEngine() = 0;
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index 117af0f..69a0e19 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -28,56 +28,44 @@
using testing::Return;
struct RenderEngineThreadedTest : public ::testing::Test {
- RenderEngineThreadedTest() {
- sThreadedRE->setRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
- }
-
~RenderEngineThreadedTest() {}
- static void SetUpTestSuite() {
- sThreadedRE = renderengine::threaded::RenderEngineThreaded::create(
- renderengine::RenderEngineCreationArgs::Builder()
- .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::THREADED)
- .build());
+ void SetUp() override {
+ mThreadedRE = renderengine::threaded::RenderEngineThreaded::create(
+ [this]() { return std::unique_ptr<renderengine::RenderEngine>(mRenderEngine); });
}
- static void TearDownTestSuite() { sThreadedRE = nullptr; }
-
- // To avoid creating RE on every instantiation of the test, it is kept as a static variable.
- static std::unique_ptr<renderengine::threaded::RenderEngineThreaded> sThreadedRE;
+ std::unique_ptr<renderengine::threaded::RenderEngineThreaded> mThreadedRE;
renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
};
-std::unique_ptr<renderengine::threaded::RenderEngineThreaded>
- RenderEngineThreadedTest::sThreadedRE = nullptr;
-
TEST_F(RenderEngineThreadedTest, dump) {
std::string testString = "XYZ";
EXPECT_CALL(*mRenderEngine, dump(_));
- sThreadedRE->dump(testString);
+ mThreadedRE->dump(testString);
}
TEST_F(RenderEngineThreadedTest, primeCache) {
EXPECT_CALL(*mRenderEngine, primeCache());
- sThreadedRE->primeCache();
+ mThreadedRE->primeCache();
}
TEST_F(RenderEngineThreadedTest, genTextures) {
uint32_t texName;
EXPECT_CALL(*mRenderEngine, genTextures(1, &texName));
- sThreadedRE->genTextures(1, &texName);
+ mThreadedRE->genTextures(1, &texName);
}
TEST_F(RenderEngineThreadedTest, deleteTextures) {
uint32_t texName;
EXPECT_CALL(*mRenderEngine, deleteTextures(1, &texName));
- sThreadedRE->deleteTextures(1, &texName);
+ mThreadedRE->deleteTextures(1, &texName);
}
TEST_F(RenderEngineThreadedTest, bindExternalBuffer_nullptrBuffer) {
EXPECT_CALL(*mRenderEngine, bindExternalTextureBuffer(0, Eq(nullptr), Eq(nullptr)))
.WillOnce(Return(BAD_VALUE));
- status_t result = sThreadedRE->bindExternalTextureBuffer(0, nullptr, nullptr);
+ status_t result = mThreadedRE->bindExternalTextureBuffer(0, nullptr, nullptr);
ASSERT_EQ(BAD_VALUE, result);
}
@@ -85,119 +73,119 @@
sp<GraphicBuffer> buf = new GraphicBuffer();
EXPECT_CALL(*mRenderEngine, bindExternalTextureBuffer(0, buf, Eq(nullptr)))
.WillOnce(Return(NO_ERROR));
- status_t result = sThreadedRE->bindExternalTextureBuffer(0, buf, nullptr);
+ status_t result = mThreadedRE->bindExternalTextureBuffer(0, buf, nullptr);
ASSERT_EQ(NO_ERROR, result);
}
TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_nullptr) {
EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(Eq(nullptr)));
- sThreadedRE->cacheExternalTextureBuffer(nullptr);
+ mThreadedRE->cacheExternalTextureBuffer(nullptr);
}
TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_withBuffer) {
sp<GraphicBuffer> buf = new GraphicBuffer();
EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(buf));
- sThreadedRE->cacheExternalTextureBuffer(buf);
+ mThreadedRE->cacheExternalTextureBuffer(buf);
}
TEST_F(RenderEngineThreadedTest, unbindExternalTextureBuffer) {
EXPECT_CALL(*mRenderEngine, unbindExternalTextureBuffer(0x0));
- sThreadedRE->unbindExternalTextureBuffer(0x0);
+ mThreadedRE->unbindExternalTextureBuffer(0x0);
}
TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsBadValue) {
std::unique_ptr<renderengine::Framebuffer> framebuffer;
EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(BAD_VALUE));
- status_t result = sThreadedRE->bindFrameBuffer(framebuffer.get());
+ status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get());
ASSERT_EQ(BAD_VALUE, result);
}
TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsNoError) {
std::unique_ptr<renderengine::Framebuffer> framebuffer;
EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(NO_ERROR));
- status_t result = sThreadedRE->bindFrameBuffer(framebuffer.get());
+ status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get());
ASSERT_EQ(NO_ERROR, result);
}
TEST_F(RenderEngineThreadedTest, unbindFrameBuffer) {
std::unique_ptr<renderengine::Framebuffer> framebuffer;
EXPECT_CALL(*mRenderEngine, unbindFrameBuffer(framebuffer.get()));
- sThreadedRE->unbindFrameBuffer(framebuffer.get());
+ mThreadedRE->unbindFrameBuffer(framebuffer.get());
}
TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns20) {
size_t size = 20;
EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size));
- size_t result = sThreadedRE->getMaxTextureSize();
+ size_t result = mThreadedRE->getMaxTextureSize();
ASSERT_EQ(size, result);
}
TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns0) {
size_t size = 0;
EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size));
- size_t result = sThreadedRE->getMaxTextureSize();
+ size_t result = mThreadedRE->getMaxTextureSize();
ASSERT_EQ(size, result);
}
TEST_F(RenderEngineThreadedTest, getMaxViewportDims_returns20) {
size_t dims = 20;
EXPECT_CALL(*mRenderEngine, getMaxViewportDims()).WillOnce(Return(dims));
- size_t result = sThreadedRE->getMaxViewportDims();
+ size_t result = mThreadedRE->getMaxViewportDims();
ASSERT_EQ(dims, result);
}
TEST_F(RenderEngineThreadedTest, getMaxViewportDims_returns0) {
size_t dims = 0;
EXPECT_CALL(*mRenderEngine, getMaxViewportDims()).WillOnce(Return(dims));
- size_t result = sThreadedRE->getMaxViewportDims();
+ size_t result = mThreadedRE->getMaxViewportDims();
ASSERT_EQ(dims, result);
}
TEST_F(RenderEngineThreadedTest, isProtected_returnsFalse) {
EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(false));
- status_t result = sThreadedRE->isProtected();
+ status_t result = mThreadedRE->isProtected();
ASSERT_EQ(false, result);
}
TEST_F(RenderEngineThreadedTest, isProtected_returnsTrue) {
EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(true));
- size_t result = sThreadedRE->isProtected();
+ size_t result = mThreadedRE->isProtected();
ASSERT_EQ(true, result);
}
TEST_F(RenderEngineThreadedTest, supportsProtectedContent_returnsFalse) {
EXPECT_CALL(*mRenderEngine, supportsProtectedContent()).WillOnce(Return(false));
- status_t result = sThreadedRE->supportsProtectedContent();
+ status_t result = mThreadedRE->supportsProtectedContent();
ASSERT_EQ(false, result);
}
TEST_F(RenderEngineThreadedTest, supportsProtectedContent_returnsTrue) {
EXPECT_CALL(*mRenderEngine, supportsProtectedContent()).WillOnce(Return(true));
- status_t result = sThreadedRE->supportsProtectedContent();
+ status_t result = mThreadedRE->supportsProtectedContent();
ASSERT_EQ(true, result);
}
TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsFalse) {
EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(false));
- status_t result = sThreadedRE->useProtectedContext(false);
+ status_t result = mThreadedRE->useProtectedContext(false);
ASSERT_EQ(false, result);
}
TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsTrue) {
EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(true));
- status_t result = sThreadedRE->useProtectedContext(false);
+ status_t result = mThreadedRE->useProtectedContext(false);
ASSERT_EQ(true, result);
}
TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsFalse) {
EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return(false));
- status_t result = sThreadedRE->cleanupPostRender();
+ status_t result = mThreadedRE->cleanupPostRender();
ASSERT_EQ(false, result);
}
TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsTrue) {
EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return(true));
- status_t result = sThreadedRE->cleanupPostRender();
+ status_t result = mThreadedRE->cleanupPostRender();
ASSERT_EQ(true, result);
}
@@ -214,7 +202,7 @@
const sp<GraphicBuffer>&, const bool, base::unique_fd&&,
base::unique_fd*) -> status_t { return NO_ERROR; });
- status_t result = sThreadedRE->drawLayers(settings, layers, buffer, false,
+ status_t result = mThreadedRE->drawLayers(settings, layers, buffer, false,
std::move(bufferFence), &drawFence);
ASSERT_EQ(NO_ERROR, result);
}
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index a883ad3..ad61718 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -23,6 +23,7 @@
#include <future>
#include <android-base/stringprintf.h>
+#include <private/gui/SyncFeatures.h>
#include <utils/Trace.h>
#include "gl/GLESRenderEngine.h"
@@ -33,36 +34,15 @@
namespace renderengine {
namespace threaded {
-std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(
- const RenderEngineCreationArgs& args) {
- return std::make_unique<RenderEngineThreaded>(args);
+std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory) {
+ return std::make_unique<RenderEngineThreaded>(std::move(factory));
}
-void RenderEngineThreaded::setRenderEngine(
- std::unique_ptr<renderengine::RenderEngine> renderEngine) {
- ATRACE_CALL();
- // In order to ensure this is a thread safe call, it also needs to be put on a stack.
- std::promise<void> resultPromise;
- std::future<void> resultFuture = resultPromise.get_future();
- {
- std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push(
- [this, &resultPromise, &renderEngine](renderengine::RenderEngine& /*instance*/) {
- ATRACE_NAME("REThreaded::setRenderEngine");
- mRenderEngine = std::move(renderEngine);
- resultPromise.set_value();
- });
- }
- mCondition.notify_one();
- resultFuture.wait();
-}
-
-RenderEngineThreaded::RenderEngineThreaded(const RenderEngineCreationArgs& args)
- : renderengine::impl::RenderEngine(args) {
+RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory) {
ATRACE_CALL();
std::lock_guard lockThread(mThreadMutex);
- mThread = std::thread(&RenderEngineThreaded::threadMain, this, args);
+ mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
}
RenderEngineThreaded::~RenderEngineThreaded() {
@@ -78,8 +58,7 @@
}
// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
-void RenderEngineThreaded::threadMain(const RenderEngineCreationArgs& args)
- NO_THREAD_SAFETY_ANALYSIS {
+void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
struct sched_param param = {0};
@@ -88,7 +67,7 @@
ALOGE("Couldn't set SCHED_FIFO");
}
- mRenderEngine = renderengine::gl::GLESRenderEngine::create(args);
+ mRenderEngine = factory();
std::unique_lock<std::mutex> lock(mThreadMutex);
pthread_setname_np(pthread_self(), mThreadName);
@@ -137,6 +116,36 @@
result.assign(resultFuture.get());
}
+bool RenderEngineThreaded::useNativeFenceSync() const {
+ std::promise<bool> resultPromise;
+ std::future<bool> resultFuture = resultPromise.get_future();
+ {
+ std::lock_guard lock(mThreadMutex);
+ mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& /*instance*/) {
+ ATRACE_NAME("REThreaded::useNativeFenceSync");
+ bool returnValue = SyncFeatures::getInstance().useNativeFenceSync();
+ resultPromise.set_value(returnValue);
+ });
+ }
+ mCondition.notify_one();
+ return resultFuture.get();
+}
+
+bool RenderEngineThreaded::useWaitSync() const {
+ std::promise<bool> resultPromise;
+ std::future<bool> resultFuture = resultPromise.get_future();
+ {
+ std::lock_guard lock(mThreadMutex);
+ mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& /*instance*/) {
+ ATRACE_NAME("REThreaded::useWaitSync");
+ bool returnValue = SyncFeatures::getInstance().useWaitSync();
+ resultPromise.set_value(returnValue);
+ });
+ }
+ mCondition.notify_one();
+ return resultFuture.get();
+}
+
void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
std::promise<void> resultPromise;
std::future<void> resultFuture = resultPromise.get_future();
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 8e4431e..ec18e1f 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -28,21 +28,25 @@
namespace renderengine {
namespace threaded {
+using CreateInstanceFactory = std::function<std::unique_ptr<renderengine::RenderEngine>()>;
+
/**
* This class extends a basic RenderEngine class. It contains a thread. Each time a function of
* this class is called, we create a lambda function that is put on a queue. The main thread then
* executes the functions in order.
*/
-class RenderEngineThreaded : public impl::RenderEngine {
+class RenderEngineThreaded : public RenderEngine {
public:
- static std::unique_ptr<RenderEngineThreaded> create(const RenderEngineCreationArgs& args);
+ static std::unique_ptr<RenderEngineThreaded> create(CreateInstanceFactory factory);
- RenderEngineThreaded(const RenderEngineCreationArgs& args);
+ RenderEngineThreaded(CreateInstanceFactory factory);
~RenderEngineThreaded() override;
void primeCache() const override;
void dump(std::string& result) override;
+ bool useNativeFenceSync() const override;
+ bool useWaitSync() const override;
void genTextures(size_t count, uint32_t* names) override;
void deleteTextures(size_t count, uint32_t const* names) override;
void bindExternalTextureImage(uint32_t texName, const Image& image) override;
@@ -64,13 +68,12 @@
const std::vector<const LayerSettings*>& layers,
const sp<GraphicBuffer>& buffer, const bool useFramebufferCache,
base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
- void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>);
protected:
Framebuffer* getFramebufferForDrawing() override;
private:
- void threadMain(const RenderEngineCreationArgs& args);
+ void threadMain(CreateInstanceFactory factory);
/* ------------------------------------------------------------------------
* Threading
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 648d129..8722952 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -452,6 +452,13 @@
}
void BufferLayerConsumer::onDisconnect() {
+ Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ // Nothing to do if we're already abandoned.
+ return;
+ }
+
mLayer->onDisconnect();
}
@@ -486,6 +493,13 @@
void BufferLayerConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
FrameEventHistoryDelta* outDelta) {
+ Mutex::Autolock lock(mMutex);
+
+ if (mAbandoned) {
+ // Nothing to do if we're already abandoned.
+ return;
+ }
+
mLayer->addAndGetFrameTimestamps(newTimestamps, outDelta);
}
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index c71a1d9..5e3044f 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -331,8 +331,8 @@
// construction time.
const uint32_t mTexName;
- // The layer for this BufferLayerConsumer
- Layer* mLayer;
+ // The layer for this BufferLayerConsumer. Always check mAbandoned before accessing.
+ Layer* mLayer GUARDED_BY(mMutex);
wp<ContentsChangedListener> mContentsChangedListener;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index 5ce2fdc..f680460 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -63,6 +63,12 @@
// Sets the dataspace used for rendering the surface
virtual void setBufferDataspace(ui::Dataspace) = 0;
+ // Sets the pixel format used for rendering the surface.
+ // Changing the pixel format of the buffer will result in buffer
+ // reallocation as well as some reconfiguration of the graphics context,
+ // which are both expensive operations.
+ virtual void setBufferPixelFormat(ui::PixelFormat) = 0;
+
// Configures the protected rendering on the surface
virtual void setProtected(bool useProtected) = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 9ca7d2f..7a4f738 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -70,11 +70,13 @@
using ChangedTypes = android::HWComposer::DeviceRequestedChanges::ChangedTypes;
using DisplayRequests = android::HWComposer::DeviceRequestedChanges::DisplayRequests;
using LayerRequests = android::HWComposer::DeviceRequestedChanges::LayerRequests;
+ using ClientTargetProperty = android::HWComposer::DeviceRequestedChanges::ClientTargetProperty;
virtual bool anyLayersRequireClientComposition() const;
virtual bool allLayersRequireClientComposition() const;
virtual void applyChangedTypesToLayers(const ChangedTypes&);
virtual void applyDisplayRequests(const DisplayRequests&);
virtual void applyLayerRequestsToLayers(const LayerRequests&);
+ virtual void applyClientTargetRequests(const ClientTargetProperty&);
// Internal
virtual void setConfiguration(const compositionengine::DisplayCreationArgs&);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 692d78d..5127a6f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -49,6 +49,7 @@
const sp<Fence>& getClientTargetAcquireFence() const override;
void setBufferDataspace(ui::Dataspace) override;
+ void setBufferPixelFormat(ui::PixelFormat) override;
void setDisplaySize(const ui::Size&) override;
void setProtected(bool useProtected) override;
status_t beginFrame(bool mustRecompose) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index ed4d492..a0cae6f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -36,6 +36,7 @@
MOCK_METHOD1(setDisplaySize, void(const ui::Size&));
MOCK_METHOD1(setProtected, void(bool));
MOCK_METHOD1(setBufferDataspace, void(ui::Dataspace));
+ MOCK_METHOD1(setBufferPixelFormat, void(ui::PixelFormat));
MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
MOCK_METHOD2(prepareFrame, void(bool, bool));
MOCK_METHOD1(dequeueBuffer, sp<GraphicBuffer>(base::unique_fd*));
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index ab26939..d201104 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -259,6 +259,7 @@
applyChangedTypesToLayers(changes->changedTypes);
applyDisplayRequests(changes->displayRequests);
applyLayerRequestsToLayers(changes->layerRequests);
+ applyClientTargetRequests(changes->clientTargetProperty);
}
// Determine what type of composition we are doing from the final state
@@ -326,6 +327,16 @@
}
}
+void Display::applyClientTargetRequests(const ClientTargetProperty& clientTargetProperty) {
+ if (clientTargetProperty.dataspace == ui::Dataspace::UNKNOWN) {
+ return;
+ }
+ auto outputState = editState();
+ outputState.dataspace = clientTargetProperty.dataspace;
+ getRenderSurface()->setBufferDataspace(clientTargetProperty.dataspace);
+ getRenderSurface()->setBufferPixelFormat(clientTargetProperty.pixelFormat);
+}
+
compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
auto result = impl::Output::presentAndGetFrameFences();
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 4084653..2773fd3 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -104,6 +104,10 @@
static_cast<android_dataspace>(dataspace));
}
+void RenderSurface::setBufferPixelFormat(ui::PixelFormat pixelFormat) {
+ native_window_set_buffers_format(mNativeWindow.get(), static_cast<int32_t>(pixelFormat));
+}
+
void RenderSurface::setProtected(bool useProtected) {
uint64_t usageFlags = GRALLOC_USAGE_HW_RENDER;
if (useProtected) {
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 62977a4..09f37fb 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -654,6 +654,7 @@
{{nullptr, hal::Composition::CLIENT}},
hal::DisplayRequest::FLIP_CLIENT_TARGET,
{{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
+ {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN},
};
// Since two calls are made to anyLayersRequireClientComposition with different return
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 97eeea2..dbdffec 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -1354,6 +1354,12 @@
return error;
}
+Error Composer::getClientTargetProperty(
+ Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) {
+ mReader.takeClientTargetProperty(display, outClientTargetProperty);
+ return Error::NONE;
+}
+
CommandReader::~CommandReader()
{
resetData();
@@ -1662,10 +1668,22 @@
*state = data.presentOrValidateState;
}
+void CommandReader::takeClientTargetProperty(
+ Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) {
+ auto found = mReturnData.find(display);
+
+ // If not found, return the default values.
+ if (found == mReturnData.end()) {
+ outClientTargetProperty->pixelFormat = PixelFormat::RGBA_8888;
+ outClientTargetProperty->dataspace = Dataspace::UNKNOWN;
+ }
+
+ ReturnData& data = found->second;
+ *outClientTargetProperty = data.clientTargetProperty;
+}
+
} // namespace impl
-
} // namespace Hwc2
-
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index aa43f09..00ef782 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -240,6 +240,8 @@
const std::vector<uint8_t>& value) = 0;
virtual V2_4::Error getLayerGenericMetadataKeys(
std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) = 0;
+ virtual Error getClientTargetProperty(
+ Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) = 0;
};
namespace impl {
@@ -282,6 +284,10 @@
// Get what stage succeeded during PresentOrValidate: Present or Validate
void takePresentOrValidateStage(Display display, uint32_t * state);
+ // Get the client target properties requested by hardware composer.
+ void takeClientTargetProperty(Display display,
+ IComposerClient::ClientTargetProperty* outClientTargetProperty);
+
private:
void resetData();
@@ -479,6 +485,9 @@
bool mandatory, const std::vector<uint8_t>& value) override;
V2_4::Error getLayerGenericMetadataKeys(
std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) override;
+ Error getClientTargetProperty(
+ Display display,
+ IComposerClient::ClientTargetProperty* outClientTargetProperty) override;
private:
#if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index fb82033..af76b81 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -668,6 +668,11 @@
return static_cast<Error>(intError);
}
+Error Display::getClientTargetProperty(ClientTargetProperty* outClientTargetProperty) {
+ const auto error = mComposer.getClientTargetProperty(mId, outClientTargetProperty);
+ return static_cast<Error>(error);
+}
+
// For use by Device
void Display::setConnected(bool connected) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index f4c7fdd..6819ff4 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -234,6 +234,8 @@
[[clang::warn_unused_result]] virtual hal::Error getSupportedContentTypes(
std::vector<hal::ContentType>*) const = 0;
[[clang::warn_unused_result]] virtual hal::Error setContentType(hal::ContentType) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error getClientTargetProperty(
+ hal::ClientTargetProperty* outClientTargetProperty) = 0;
};
namespace impl {
@@ -305,6 +307,8 @@
hal::Error getSupportedContentTypes(
std::vector<hal::ContentType>* outSupportedContentTypes) const override;
hal::Error setContentType(hal::ContentType) override;
+ hal::Error getClientTargetProperty(hal::ClientTargetProperty* outClientTargetProperty) override;
+
// Other Display methods
hal::HWDisplayId getId() const override { return mId; }
bool isConnected() const override { return mIsConnected; }
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 038cec4..7a2f0f3 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -541,9 +541,12 @@
error = hwcDisplay->getRequests(&displayRequests, &layerRequests);
RETURN_IF_HWC_ERROR_FOR("getRequests", error, displayId, BAD_INDEX);
- outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
- std::move(layerRequests)});
+ DeviceRequestedChanges::ClientTargetProperty clientTargetProperty;
+ error = hwcDisplay->getClientTargetProperty(&clientTargetProperty);
+ outChanges->emplace(DeviceRequestedChanges{std::move(changedTypes), std::move(displayRequests),
+ std::move(layerRequests),
+ std::move(clientTargetProperty)});
error = hwcDisplay->acceptChanges();
RETURN_IF_HWC_ERROR_FOR("acceptChanges", error, displayId, BAD_INDEX);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index b7e9f3a..c355ebd 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -66,6 +66,18 @@
class HWComposer {
public:
+ struct DeviceRequestedChanges {
+ using ChangedTypes = std::unordered_map<HWC2::Layer*, hal::Composition>;
+ using ClientTargetProperty = hal::ClientTargetProperty;
+ using DisplayRequests = hal::DisplayRequest;
+ using LayerRequests = std::unordered_map<HWC2::Layer*, hal::LayerRequest>;
+
+ ChangedTypes changedTypes;
+ DisplayRequests displayRequests;
+ LayerRequests layerRequests;
+ ClientTargetProperty clientTargetProperty;
+ };
+
virtual ~HWComposer();
virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
@@ -88,16 +100,6 @@
// Destroy a previously created layer
virtual void destroyLayer(DisplayId displayId, HWC2::Layer* layer) = 0;
- struct DeviceRequestedChanges {
- using ChangedTypes = std::unordered_map<HWC2::Layer*, hal::Composition>;
- using DisplayRequests = hal::DisplayRequest;
- using LayerRequests = std::unordered_map<HWC2::Layer*, hal::LayerRequest>;
-
- ChangedTypes changedTypes;
- DisplayRequests displayRequests;
- LayerRequests layerRequests;
- };
-
// Gets any required composition change requests from the HWC device.
//
// Note that frameUsesClientComposition must be set correctly based on
diff --git a/services/surfaceflinger/DisplayHardware/Hal.h b/services/surfaceflinger/DisplayHardware/Hal.h
index 66ee425..bb2888e 100644
--- a/services/surfaceflinger/DisplayHardware/Hal.h
+++ b/services/surfaceflinger/DisplayHardware/Hal.h
@@ -53,6 +53,7 @@
using Connection = IComposerCallback::Connection;
using ContentType = IComposerClient::ContentType;
using Capability = IComposer::Capability;
+using ClientTargetProperty = IComposerClient::ClientTargetProperty;
using DisplayCapability = IComposerClient::DisplayCapability;
using DisplayRequest = IComposerClient::DisplayRequest;
using DisplayType = IComposerClient::DisplayType;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 4a4f9c8..e181c12 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -128,15 +128,24 @@
}
}
+ const bool hasExplicitVoteLayers =
+ explicitDefaultVoteLayers > 0 || explicitExactOrMultipleVoteLayers > 0;
+
// Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
// selected a refresh rate to see if we should apply touch boost.
- if (touchActive && explicitDefaultVoteLayers == 0 && explicitExactOrMultipleVoteLayers == 0) {
+ if (touchActive && !hasExplicitVoteLayers) {
ALOGV("TouchBoost - choose %s", getMaxRefreshRateByPolicyLocked().getName().c_str());
if (touchConsidered) *touchConsidered = true;
return getMaxRefreshRateByPolicyLocked();
}
- if (!touchActive && idle) {
+ // If the primary range consists of a single refresh rate then we can only
+ // move out the of range if layers explicitly request a different refresh
+ // rate.
+ const Policy* policy = getCurrentPolicyLocked();
+ const bool primaryRangeIsSingleRate = policy->primaryRange.min == policy->primaryRange.max;
+
+ if (!touchActive && idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
return getMinRefreshRateByPolicyLocked();
}
@@ -150,8 +159,6 @@
return getMinRefreshRateByPolicyLocked();
}
- const Policy* policy = getCurrentPolicyLocked();
-
// Find the best refresh rate based on score
std::vector<std::pair<const RefreshRate*, float>> scores;
scores.reserve(mAppRequestRefreshRates.size());
@@ -171,7 +178,8 @@
for (auto i = 0u; i < scores.size(); i++) {
bool inPrimaryRange =
scores[i].first->inPolicy(policy->primaryRange.min, policy->primaryRange.max);
- if (!inPrimaryRange && layer.vote != LayerVoteType::ExplicitDefault &&
+ if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
+ layer.vote != LayerVoteType::ExplicitDefault &&
layer.vote != LayerVoteType::ExplicitExactOrMultiple) {
// Only layers with explicit frame rate settings are allowed to score refresh rates
// outside the primary range.
@@ -263,11 +271,23 @@
? getBestRefreshRate(scores.rbegin(), scores.rend())
: getBestRefreshRate(scores.begin(), scores.end());
+ if (primaryRangeIsSingleRate) {
+ // If we never scored any layers, then choose the rate from the primary
+ // range instead of picking a random score from the app range.
+ if (std::all_of(scores.begin(), scores.end(),
+ [](std::pair<const RefreshRate*, float> p) { return p.second == 0; })) {
+ return getMaxRefreshRateByPolicyLocked();
+ } else {
+ return *bestRefreshRate;
+ }
+ }
+
// Consider the touch event if there are no ExplicitDefault layers. ExplicitDefault are mostly
// interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
// vote we should not change it if we get a touch event. Only apply touch boost if it will
// actually increase the refresh rate over the normal selection.
const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
+
if (touchActive && explicitDefaultVoteLayers == 0 &&
bestRefreshRate->fps < touchRefreshRate.fps) {
if (touchConsidered) *touchConsidered = true;
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 692f71f..c919e93 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1205,6 +1205,121 @@
}
}
+TEST_F(RefreshRateConfigsTest,
+ getBestRefreshRate_withDisplayManagerRequestingSingleRate_ignoresTouchFlag) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_90);
+
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_90, {90.f, 90.f}, {60.f, 90.f}}),
+ 0);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& lr = layers[0];
+
+ bool touchConsidered = false;
+ lr.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr.desiredRefreshRate = 60.0f;
+ lr.name = "60Hz ExplicitExactOrMultiple";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, /*idle*/ false,
+ &touchConsidered));
+ EXPECT_EQ(false, touchConsidered);
+
+ lr.vote = LayerVoteType::ExplicitDefault;
+ lr.desiredRefreshRate = 60.0f;
+ lr.name = "60Hz ExplicitDefault";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ true, /*idle*/ false,
+ &touchConsidered));
+ EXPECT_EQ(false, touchConsidered);
+}
+
+TEST_F(RefreshRateConfigsTest,
+ getBestRefreshRate_withDisplayManagerRequestingSingleRate_ignoresIdleFlag) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 90.f}}),
+ 0);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& lr = layers[0];
+
+ bool touchConsidered = false;
+ lr.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr.desiredRefreshRate = 90.0f;
+ lr.name = "90Hz ExplicitExactOrMultiple";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ true,
+ &touchConsidered));
+
+ lr.vote = LayerVoteType::ExplicitDefault;
+ lr.desiredRefreshRate = 90.0f;
+ lr.name = "90Hz ExplicitDefault";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ true,
+ &touchConsidered));
+}
+
+TEST_F(RefreshRateConfigsTest,
+ getBestRefreshRate_withDisplayManagerRequestingSingleRate_onlySwitchesRatesForExplicitLayers) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m60_90Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_90);
+
+ ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
+ {HWC_CONFIG_ID_90, {90.f, 90.f}, {60.f, 90.f}}),
+ 0);
+
+ bool touchConsidered = false;
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate({}, /*touchActive*/ false, /*idle*/ false,
+ &touchConsidered));
+ EXPECT_EQ(false, touchConsidered);
+
+ auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
+ auto& lr = layers[0];
+
+ lr.vote = LayerVoteType::ExplicitExactOrMultiple;
+ lr.desiredRefreshRate = 60.0f;
+ lr.name = "60Hz ExplicitExactOrMultiple";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
+ &touchConsidered));
+
+ lr.vote = LayerVoteType::ExplicitDefault;
+ lr.desiredRefreshRate = 60.0f;
+ lr.name = "60Hz ExplicitDefault";
+ EXPECT_EQ(mExpected60Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
+ &touchConsidered));
+
+ lr.vote = LayerVoteType::Heuristic;
+ lr.desiredRefreshRate = 60.0f;
+ lr.name = "60Hz Heuristic";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
+ &touchConsidered));
+
+ lr.vote = LayerVoteType::Max;
+ lr.desiredRefreshRate = 60.0f;
+ lr.name = "60Hz Max";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
+ &touchConsidered));
+
+ lr.vote = LayerVoteType::Min;
+ lr.desiredRefreshRate = 60.0f;
+ lr.name = "60Hz Min";
+ EXPECT_EQ(mExpected90Config,
+ refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false,
+ &touchConsidered));
+}
+
TEST_F(RefreshRateConfigsTest, groupSwitching) {
auto refreshRateConfigs =
std::make_unique<RefreshRateConfigs>(m60_90DeviceWithDifferentGroups,
@@ -1234,7 +1349,7 @@
TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) {
auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(m60_90Device,
+ std::make_unique<RefreshRateConfigs>(m30_60_90Device,
/*currentConfigId=*/HWC_CONFIG_ID_60);
auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
@@ -1253,7 +1368,7 @@
};
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
- {HWC_CONFIG_ID_60, {60.f, 60.f}, {60.f, 90.f}}),
+ {HWC_CONFIG_ID_60, {30.f, 60.f}, {30.f, 90.f}}),
0);
bool touchConsidered;
EXPECT_EQ(HWC_CONFIG_ID_60,
@@ -1262,7 +1377,7 @@
&touchConsidered)
.getConfigId());
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, 90.f));
- EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Min, 90.f));
+ EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, 90.f));
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, 90.f));
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Heuristic, 90.f));
EXPECT_EQ(HWC_CONFIG_ID_90, getFrameRate(LayerVoteType::ExplicitDefault, 90.f));
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index 2a31078..c2c5072 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -140,6 +140,7 @@
const std::vector<uint8_t>&));
MOCK_METHOD1(getLayerGenericMetadataKeys,
V2_4::Error(std::vector<IComposerClient::LayerGenericMetadataKey>*));
+ MOCK_METHOD2(getClientTargetProperty, Error(Display, IComposerClient::ClientTargetProperty*));
};
} // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
index dade9fc..fe99e77 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
@@ -93,6 +93,7 @@
MOCK_METHOD1(setAutoLowLatencyMode, hal::Error(bool on));
MOCK_CONST_METHOD1(getSupportedContentTypes, hal::Error(std::vector<hal::ContentType>*));
MOCK_METHOD1(setContentType, hal::Error(hal::ContentType));
+ MOCK_METHOD1(getClientTargetProperty, hal::Error(hal::ClientTargetProperty*));
MOCK_CONST_METHOD1(getConnectionType, hal::Error(android::DisplayConnectionType*));
MOCK_CONST_METHOD0(isVsyncPeriodSwitchSupported, bool());
};