Merge "Include SDK sandbox while calculating app and user size" into tm-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 0e9ce89..24b201f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2418,7 +2418,7 @@
// Given that bugreport is required to diagnose failures, it's better to set an arbitrary amount
// of timeout for IDumpstateDevice than to block the rest of bugreport. In the timeout case, we
// will kill the HAL and grab whatever it dumped in time.
- constexpr size_t timeout_sec = 30;
+ constexpr size_t timeout_sec = 45;
if (dumpstate_hal_handle_aidl != nullptr) {
DoDumpstateBoardAidl(dumpstate_hal_handle_aidl, dumpstate_fds, options_->bugreport_mode,
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index e1cbc19..8132d46 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -18,10 +18,13 @@
#include <errno.h>
#include <fcntl.h>
+#include <linux/memfd.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/ioctl.h>
+#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
@@ -34,6 +37,24 @@
// ---------------------------------------------------------------------------
+#ifdef __BIONIC__
+static int memfd_create_region(const char* name, size_t size) {
+ int fd = memfd_create(name, MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ if (fd == -1) {
+ ALOGE("%s: memfd_create(%s, %zd) failed: %s\n", __func__, name, size, strerror(errno));
+ return -1;
+ }
+
+ if (ftruncate(fd, size) == -1) {
+ ALOGE("%s, ftruncate(%s, %zd) failed for memfd creation: %s\n", __func__, name, size,
+ strerror(errno));
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
+#endif
+
MemoryHeapBase::MemoryHeapBase()
: mFD(-1), mSize(0), mBase(MAP_FAILED),
mDevice(nullptr), mNeedUnmap(false), mOffset(0)
@@ -45,15 +66,36 @@
mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
- size = ((size + pagesize-1) & ~(pagesize-1));
- int fd = ashmem_create_region(name == nullptr ? "MemoryHeapBase" : name, size);
- ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno));
- if (fd >= 0) {
- if (mapfd(fd, true, size) == NO_ERROR) {
- if (flags & READ_ONLY) {
- ashmem_set_prot_region(fd, PROT_READ);
- }
+ size = ((size + pagesize - 1) & ~(pagesize - 1));
+ int fd = -1;
+ if (mFlags & FORCE_MEMFD) {
+#ifdef __BIONIC__
+ ALOGV("MemoryHeapBase: Attempting to force MemFD");
+ fd = memfd_create_region(name ? name : "MemoryHeapBase", size);
+ if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
+ const int SEAL_FLAGS = ((mFlags & READ_ONLY) ? F_SEAL_FUTURE_WRITE : 0) |
+ ((mFlags & MEMFD_ALLOW_SEALING) ? 0 : F_SEAL_SEAL);
+ if (SEAL_FLAGS && (fcntl(fd, F_ADD_SEALS, SEAL_FLAGS) == -1)) {
+ ALOGE("MemoryHeapBase: MemFD %s sealing with flags %x failed with error %s", name,
+ SEAL_FLAGS, strerror(errno));
+ munmap(mBase, mSize);
+ mBase = nullptr;
+ mSize = 0;
+ close(fd);
}
+ return;
+#else
+ mFlags &= ~(FORCE_MEMFD | MEMFD_ALLOW_SEALING);
+#endif
+ }
+ if (mFlags & MEMFD_ALLOW_SEALING) {
+ LOG_ALWAYS_FATAL("Invalid Flags. MEMFD_ALLOW_SEALING only valid with FORCE_MEMFD.");
+ }
+ fd = ashmem_create_region(name ? name : "MemoryHeapBase", size);
+ ALOGE_IF(fd < 0, "MemoryHeapBase: error creating ashmem region: %s", strerror(errno));
+ if (fd < 0 || (mapfd(fd, true, size) != NO_ERROR)) return;
+ if (mFlags & READ_ONLY) {
+ ashmem_set_prot_region(fd, PROT_READ);
}
}
@@ -61,6 +103,9 @@
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
+ if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+ LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
+ }
int open_flags = O_RDWR;
if (flags & NO_CACHING)
open_flags |= O_SYNC;
@@ -80,6 +125,9 @@
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(nullptr), mNeedUnmap(false), mOffset(0)
{
+ if (flags & (FORCE_MEMFD | MEMFD_ALLOW_SEALING)) {
+ LOG_ALWAYS_FATAL("FORCE_MEMFD, MEMFD_ALLOW_SEALING only valid with creating constructor");
+ }
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), false, size, offset);
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index e79cb86..d40778a 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -853,10 +853,16 @@
}
if (session->mConnections.mOutgoing.size() == 0) {
- ALOGE("Session has no client connections. This is required for an RPC server to make "
- "any non-nested (e.g. oneway or on another thread) calls. Use: %d. Server "
- "connections: %zu",
- static_cast<int>(use), session->mConnections.mIncoming.size());
+ ALOGE("Session has no outgoing connections. This is required for an RPC server to make "
+ "any non-nested (e.g. oneway or on another thread) calls. Use code request "
+ "reason: %d. Incoming connections: %zu. %s.",
+ static_cast<int>(use), session->mConnections.mIncoming.size(),
+ (session->server()
+ ? "This is a server session, so see RpcSession::setMaxIncomingThreads "
+ "for the corresponding client"
+ : "This is a client session, so see RpcSession::setMaxOutgoingThreads "
+ "for this client or RpcServer::setMaxThreads for the corresponding "
+ "server"));
return WOULD_BLOCK;
}
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index dd76943..15dd28f 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -34,7 +34,21 @@
// memory won't be mapped locally, but will be mapped in the remote
// process.
DONT_MAP_LOCALLY = 0x00000100,
- NO_CACHING = 0x00000200
+ NO_CACHING = 0x00000200,
+ // Bypass ashmem-libcutils to create a memfd shared region.
+ // Ashmem-libcutils will eventually migrate to memfd.
+ // Memfd has security benefits and supports file sealing.
+ // Calling process will need to modify selinux permissions to
+ // open access to tmpfs files. See audioserver for examples.
+ // This is only valid for size constructor.
+ // For host compilation targets, memfd is stubbed in favor of /tmp
+ // files so sealing is not enforced.
+ FORCE_MEMFD = 0x00000400,
+ // Default opt-out of sealing behavior in memfd to avoid potential DOS.
+ // Clients of shared files can seal at anytime via syscall, leading to
+ // TOC/TOU issues if additional seals prevent access from the creating
+ // process. Alternatively, seccomp fcntl().
+ MEMFD_ALLOW_SEALING = 0x00000800
};
/*
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index ff55d6e..a3533d8 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -99,6 +99,7 @@
"binderParcelUnitTest.cpp",
"binderBinderUnitTest.cpp",
"binderStatusUnitTest.cpp",
+ "binderMemoryHeapBaseUnitTest.cpp",
],
shared_libs: [
"libbinder",
diff --git a/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
new file mode 100644
index 0000000..21cb70b
--- /dev/null
+++ b/libs/binder/tests/binderMemoryHeapBaseUnitTest.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2021 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 <binder/MemoryHeapBase.h>
+#include <cutils/ashmem.h>
+#include <fcntl.h>
+
+#include <gtest/gtest.h>
+using namespace android;
+#ifdef __BIONIC__
+TEST(MemoryHeapBase, ForceMemfdRespected) {
+ auto mHeap = sp<MemoryHeapBase>::make(10, MemoryHeapBase::FORCE_MEMFD, "Test mapping");
+ int fd = mHeap->getHeapID();
+ EXPECT_NE(fd, -1);
+ EXPECT_FALSE(ashmem_valid(fd));
+ EXPECT_NE(fcntl(fd, F_GET_SEALS), -1);
+}
+
+TEST(MemoryHeapBase, MemfdSealed) {
+ auto mHeap = sp<MemoryHeapBase>::make(8192,
+ MemoryHeapBase::FORCE_MEMFD,
+ "Test mapping");
+ int fd = mHeap->getHeapID();
+ EXPECT_NE(fd, -1);
+ EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL);
+}
+
+TEST(MemoryHeapBase, MemfdUnsealed) {
+ auto mHeap = sp<MemoryHeapBase>::make(8192,
+ MemoryHeapBase::FORCE_MEMFD |
+ MemoryHeapBase::MEMFD_ALLOW_SEALING,
+ "Test mapping");
+ int fd = mHeap->getHeapID();
+ EXPECT_NE(fd, -1);
+ EXPECT_EQ(fcntl(fd, F_GET_SEALS), 0);
+}
+
+TEST(MemoryHeapBase, MemfdSealedProtected) {
+ auto mHeap = sp<MemoryHeapBase>::make(8192,
+ MemoryHeapBase::FORCE_MEMFD |
+ MemoryHeapBase::READ_ONLY,
+ "Test mapping");
+ int fd = mHeap->getHeapID();
+ EXPECT_NE(fd, -1);
+ EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_SEAL | F_SEAL_FUTURE_WRITE);
+}
+
+TEST(MemoryHeapBase, MemfdUnsealedProtected) {
+ auto mHeap = sp<MemoryHeapBase>::make(8192,
+ MemoryHeapBase::FORCE_MEMFD |
+ MemoryHeapBase::READ_ONLY |
+ MemoryHeapBase::MEMFD_ALLOW_SEALING,
+ "Test mapping");
+ int fd = mHeap->getHeapID();
+ EXPECT_NE(fd, -1);
+ EXPECT_EQ(fcntl(fd, F_GET_SEALS), F_SEAL_FUTURE_WRITE);
+}
+
+#else
+TEST(MemoryHeapBase, HostMemfdExpected) {
+ auto mHeap = sp<MemoryHeapBase>::make(8192,
+ MemoryHeapBase::READ_ONLY,
+ "Test mapping");
+ int fd = mHeap->getHeapID();
+ void* ptr = mHeap->getBase();
+ EXPECT_NE(ptr, MAP_FAILED);
+ EXPECT_TRUE(ashmem_valid(fd));
+ EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY);
+}
+
+TEST(MemoryHeapBase,HostMemfdException) {
+ auto mHeap = sp<MemoryHeapBase>::make(8192,
+ MemoryHeapBase::FORCE_MEMFD |
+ MemoryHeapBase::READ_ONLY |
+ MemoryHeapBase::MEMFD_ALLOW_SEALING,
+ "Test mapping");
+ int fd = mHeap->getHeapID();
+ void* ptr = mHeap->getBase();
+ EXPECT_EQ(mHeap->getFlags(), MemoryHeapBase::READ_ONLY);
+ EXPECT_TRUE(ashmem_valid(fd));
+ EXPECT_NE(ptr, MAP_FAILED);
+}
+
+#endif
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index bfdd22c..06ad6a8 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -160,10 +160,7 @@
// when an application takes too long to respond and the user has pressed an app switch key.
constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
-// Amount of time to allow for an event to be dispatched (measured since its eventTime)
-// before considering it stale and dropping it.
-const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL // 10sec
- * HwTimeoutMultiplier();
+const std::chrono::duration STALE_EVENT_TIMEOUT = std::chrono::seconds(10) * HwTimeoutMultiplier();
// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
@@ -364,10 +361,6 @@
first->applicationInfo.token == second->applicationInfo.token;
}
-bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry) {
- return currentTime - entry.eventTime >= STALE_EVENT_TIMEOUT;
-}
-
std::unique_ptr<DispatchEntry> createDispatchEntry(const InputTarget& inputTarget,
std::shared_ptr<EventEntry> eventEntry,
int32_t inputTargetFlags) {
@@ -568,6 +561,10 @@
// --- InputDispatcher ---
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
+ : InputDispatcher(policy, STALE_EVENT_TIMEOUT) {}
+
+InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy,
+ std::chrono::nanoseconds staleEventTimeout)
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
@@ -586,6 +583,7 @@
mMaximumObscuringOpacityForTouch(1.0f),
mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
mWindowTokenWithPointerCapture(nullptr),
+ mStaleEventTimeout(staleEventTimeout),
mLatencyAggregator(),
mLatencyTracker(&mLatencyAggregator) {
mLooper = new Looper(false);
@@ -943,6 +941,10 @@
}
}
+bool InputDispatcher::isStaleEvent(nsecs_t currentTime, const EventEntry& entry) {
+ return std::chrono::nanoseconds(currentTime - entry.eventTime) >= mStaleEventTimeout;
+}
+
/**
* Return true if the events preceding this incoming motion event should be dropped
* Return false otherwise (the default behaviour)
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index d3e171a..3c79c98 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -84,6 +84,8 @@
static constexpr bool kDefaultInTouchMode = true;
explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy);
+ explicit InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy,
+ std::chrono::nanoseconds staleEventTimeout);
~InputDispatcher() override;
void dump(std::string& dump) override;
@@ -471,6 +473,11 @@
*/
std::optional<nsecs_t> mNoFocusedWindowTimeoutTime GUARDED_BY(mLock);
+ // Amount of time to allow for an event to be dispatched (measured since its eventTime)
+ // before considering it stale and dropping it.
+ const std::chrono::nanoseconds mStaleEventTimeout;
+ bool isStaleEvent(nsecs_t currentTime, const EventEntry& entry);
+
bool shouldPruneInboundQueueLocked(const MotionEntry& motionEntry) REQUIRES(mLock);
/**
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 470d2f6..9633932 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -65,6 +65,8 @@
// An arbitrary pid of the gesture monitor window
static constexpr int32_t MONITOR_PID = 2001;
+static constexpr std::chrono::duration STALE_EVENT_TIMEOUT = 1000ms;
+
struct PointF {
float x;
float y;
@@ -489,7 +491,7 @@
void SetUp() override {
mFakePolicy = new FakeInputDispatcherPolicy();
- mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy);
+ mDispatcher = std::make_unique<InputDispatcher>(mFakePolicy, STALE_EVENT_TIMEOUT);
mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
// Start InputDispatcher thread
ASSERT_EQ(OK, mDispatcher->start());
@@ -4451,6 +4453,38 @@
ASSERT_TRUE(mDispatcher->waitForIdle());
}
+/**
+ * Make sure the stale key is dropped before causing an ANR. So even if there's no focused window,
+ * there will not be an ANR.
+ */
+TEST_F(InputDispatcherSingleWindowAnr, StaleKeyEventDoesNotAnr) {
+ mWindow->setFocusable(false);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow}}});
+ mWindow->consumeFocusEvent(false);
+
+ KeyEvent event;
+ const nsecs_t eventTime = systemTime(SYSTEM_TIME_MONOTONIC) -
+ std::chrono::nanoseconds(STALE_EVENT_TIMEOUT).count();
+
+ // Define a valid key down event that is stale (too old).
+ event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+ INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
+ AMETA_NONE, 1 /*repeatCount*/, eventTime, eventTime);
+
+ const int32_t policyFlags = POLICY_FLAG_FILTERED | POLICY_FLAG_PASS_TO_USER;
+
+ InputEventInjectionResult result =
+ mDispatcher->injectInputEvent(&event, INJECTOR_PID, INJECTOR_UID,
+ InputEventInjectionSync::WAIT_FOR_RESULT,
+ INJECT_EVENT_TIMEOUT, policyFlags);
+ ASSERT_EQ(InputEventInjectionResult::FAILED, result)
+ << "Injection should fail because the event is stale";
+
+ ASSERT_TRUE(mDispatcher->waitForIdle());
+ mFakePolicy->assertNotifyAnrWasNotCalled();
+ mWindow->assertNoEvents();
+}
+
// We have a focused application, but no focused window
// Make sure that we don't notify policy twice about the same ANR.
TEST_F(InputDispatcherSingleWindowAnr, NoFocusedWindow_DoesNotSendDuplicateAnr) {
diff --git a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
index 1100cad..6e5e14d 100644
--- a/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalAidlBenchmarks.cpp
@@ -66,13 +66,13 @@
sp<IPower> hal = waitForVintfService<IPower>();
if (hal == nullptr) {
- ALOGI("Power HAL not available, skipping test...");
+ ALOGV("Power HAL not available, skipping test...");
return;
}
binder::Status ret = (*hal.*fn)(std::forward<Args1>(args1)...);
if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
- ALOGI("Power HAL does not support this operation, skipping test...");
+ ALOGV("Power HAL does not support this operation, skipping test...");
return;
}
@@ -93,7 +93,7 @@
sp<IPower> pwHal = waitForVintfService<IPower>();
if (pwHal == nullptr) {
- ALOGI("Power HAL not available, skipping test...");
+ ALOGV("Power HAL not available, skipping test...");
return;
}
@@ -105,13 +105,13 @@
auto status = pwHal->createHintSession(1, 0, threadIds, durationNanos, &hal);
if (hal == nullptr) {
- ALOGI("Power HAL doesn't support session, skipping test...");
+ ALOGV("Power HAL doesn't support session, skipping test...");
return;
}
binder::Status ret = (*hal.*fn)(std::forward<Args1>(args1)...);
if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
- ALOGI("Power HAL does not support this operation, skipping test...");
+ ALOGV("Power HAL does not support this operation, skipping test...");
return;
}
@@ -159,13 +159,13 @@
sp<IPower> hal = waitForVintfService<IPower>();
if (hal == nullptr) {
- ALOGI("Power HAL not available, skipping test...");
+ ALOGV("Power HAL not available, skipping test...");
return;
}
binder::Status ret = hal->createHintSession(tgid, uid, threadIds, durationNanos, &appSession);
if (ret.exceptionCode() == binder::Status::Exception::EX_UNSUPPORTED_OPERATION) {
- ALOGI("Power HAL does not support this operation, skipping test...");
+ ALOGV("Power HAL does not support this operation, skipping test...");
return;
}
diff --git a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
index 97e026b..167f3a6 100644
--- a/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
+++ b/services/powermanager/benchmarks/PowerHalHidlBenchmarks.cpp
@@ -51,7 +51,7 @@
sp<I> hal = I::getService();
if (hal == nullptr) {
- ALOGI("Power HAL HIDL not available, skipping test...");
+ ALOGV("Power HAL HIDL not available, skipping test...");
return;
}
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 0aca24a..0b23a5a 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -362,6 +362,8 @@
// composition.
if (!mBufferInfo.mFrameLatencyNeeded) return;
+ mAlreadyDisplayedThisCompose = false;
+
// Update mFrameEventHistory.
{
Mutex::Autolock lock(mFrameEventHistoryMutex);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index e6a76e8..bcae8d9 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -75,17 +75,15 @@
// -----------------------------------------------------------------------
void BufferStateLayer::onLayerDisplayed(
std::shared_future<renderengine::RenderEngineResult> futureRenderEngineResult) {
- // If a layer has been displayed again we may need to clear
- // the mLastClientComposition fence that we use for early release in setBuffer
- // (as we now have a new fence which won't pass through the client composition path in some cases
- // e.g. screenshot). We expect one call to onLayerDisplayed after receiving the GL comp fence
- // from a single composition cycle, and want to clear on the second call
- // (which we track with mLastClientCompositionDisplayed)
- if (mLastClientCompositionDisplayed) {
+ // If we are displayed on multiple displays in a single composition cycle then we would
+ // need to do careful tracking to enable the use of the mLastClientCompositionFence.
+ // For example we can only use it if all the displays are client comp, and we need
+ // to merge all the client comp fences. We could do this, but for now we just
+ // disable the optimization when a layer is composed on multiple displays.
+ if (mAlreadyDisplayedThisCompose) {
mLastClientCompositionFence = nullptr;
- mLastClientCompositionDisplayed = false;
- } else if (mLastClientCompositionFence) {
- mLastClientCompositionDisplayed = true;
+ } else {
+ mAlreadyDisplayedThisCompose = true;
}
// The previous release fence notifies the client that SurfaceFlinger is done with the previous
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 9302b7b..aefc014 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -41,10 +41,6 @@
"libtonemap",
"libtrace_proto",
"libaidlcommonsupport",
- "libprocessgroup",
- "libcgrouprc",
- "libjsoncpp",
- "libcgrouprc_format",
],
header_libs: [
"android.hardware.graphics.composer@2.1-command-buffer",
@@ -72,7 +68,6 @@
"src/DisplayColorProfile.cpp",
"src/DisplaySurface.cpp",
"src/DumpHelpers.cpp",
- "src/HwcAsyncWorker.cpp",
"src/HwcBufferCache.cpp",
"src/LayerFECompositionState.cpp",
"src/Output.cpp",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
index ca86f4c..c553fce 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
@@ -72,9 +72,6 @@
virtual void resizeBuffers(const ui::Size&) = 0;
virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
-
- // Returns true if the render surface supports client composition prediction.
- virtual bool supportsCompositionStrategyPrediction() const;
};
} // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 1555102..d8644a4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -35,7 +35,6 @@
#include <utils/Vector.h>
#include <ui/DisplayIdentification.h>
-#include "DisplayHardware/HWComposer.h"
namespace android {
@@ -55,7 +54,6 @@
namespace impl {
struct OutputCompositionState;
-struct GpuCompositionResult;
} // namespace impl
/**
@@ -264,9 +262,6 @@
// Latches the front-end layer state for each output layer
virtual void updateLayerStateFromFE(const CompositionRefreshArgs&) const = 0;
- // Enables predicting composition strategy to run client composition earlier
- virtual void setPredictCompositionStrategy(bool) = 0;
-
protected:
virtual void setDisplayColorProfile(std::unique_ptr<DisplayColorProfile>) = 0;
virtual void setRenderSurface(std::unique_ptr<RenderSurface>) = 0;
@@ -283,22 +278,13 @@
virtual void updateColorProfile(const CompositionRefreshArgs&) = 0;
virtual void beginFrame() = 0;
virtual void prepareFrame() = 0;
-
- using GpuCompositionResult = compositionengine::impl::GpuCompositionResult;
- // Runs prepare frame in another thread while running client composition using
- // the previous frame's composition strategy.
- virtual GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) = 0;
virtual void devOptRepaintFlash(const CompositionRefreshArgs&) = 0;
- virtual void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) = 0;
+ virtual void finishFrame(const CompositionRefreshArgs&) = 0;
virtual std::optional<base::unique_fd> composeSurfaces(
- const Region&, const compositionengine::CompositionRefreshArgs&,
- std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&) = 0;
+ const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) = 0;
virtual void postFramebuffer() = 0;
virtual void renderCachedSets(const CompositionRefreshArgs&) = 0;
- virtual std::optional<android::HWComposer::DeviceRequestedChanges>
- chooseCompositionStrategy() = 0;
- virtual void applyCompositionStrategy(
- const std::optional<android::HWComposer::DeviceRequestedChanges>& changes) = 0;
+ virtual void chooseCompositionStrategy() = 0;
virtual bool getSkipColorTransform() const = 0;
virtual FrameFences presentAndGetFrameFences() = 0;
virtual std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
@@ -309,7 +295,6 @@
std::vector<LayerFE::LayerSettings>& clientCompositionLayers) = 0;
virtual void setExpensiveRenderingExpected(bool enabled) = 0;
virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0;
- virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0;
};
} // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index 9ee779c..daee83b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -100,9 +100,6 @@
// Debugging - gets the page flip count for the RenderSurface
virtual std::uint32_t getPageFlipCount() const = 0;
-
- // Returns true if the render surface supports client composition prediction.
- virtual bool supportsCompositionStrategyPrediction() const = 0;
};
} // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 3b8b06f..58d2530 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -22,7 +22,6 @@
#include <compositionengine/DisplayColorProfile.h>
#include <compositionengine/DisplayCreationArgs.h>
#include <compositionengine/RenderSurface.h>
-#include <compositionengine/impl/GpuCompositionResult.h>
#include <compositionengine/impl/Output.h>
#include <ui/PixelFormat.h>
#include <ui/Size.h>
@@ -52,14 +51,11 @@
void setReleasedLayers(const CompositionRefreshArgs&) override;
void setColorTransform(const CompositionRefreshArgs&) override;
void setColorProfile(const ColorProfile&) override;
-
- using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges;
- std::optional<DeviceRequestedChanges> chooseCompositionStrategy() override;
- void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override;
+ void chooseCompositionStrategy() override;
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentAndGetFrameFences() override;
void setExpensiveRenderingExpected(bool) override;
- void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override;
+ void finishFrame(const CompositionRefreshArgs&) override;
// compositionengine::Display overrides
DisplayId getId() const override;
@@ -77,6 +73,7 @@
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&);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h
deleted file mode 100644
index ed1ddc1..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/GpuCompositionResult.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2022 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.
- */
-
-#pragma once
-
-#include <android-base/unique_fd.h>
-#include <ui/GraphicBuffer.h>
-
-namespace android::compositionengine::impl {
-
-struct GpuCompositionResult {
- // True if composition strategy was predicted successfully.
- bool succeeded = false;
-
- // Composition ready fence.
- base::unique_fd fence{};
-
- // Buffer to be used for gpu composition. If gpu composition was not successful,
- // then we want to reuse the buffer instead of dequeuing another buffer.
- std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
-
- bool bufferAvailable() const { return buffer != nullptr; };
-};
-
-} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h
deleted file mode 100644
index 11c0054..0000000
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcAsyncWorker.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2022 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.
- */
-
-#pragma once
-
-#include <android-base/thread_annotations.h>
-#include <future>
-#include <optional>
-#include <thread>
-
-#include "DisplayHardware/HWComposer.h"
-
-namespace android::compositionengine::impl {
-
-// HWC Validate call may take multiple milliseconds to complete and can account for
-// a signification amount of time in the display hotpath. This helper class allows
-// us to run the hwc validate function on a real time thread if we can predict what
-// the composition strategy will be and if composition includes client composition.
-// While the hwc validate runs, client composition is kicked off with the prediction.
-// When the worker returns with a value, the composition continues if the prediction
-// was successful otherwise the client composition is re-executed.
-//
-// Note: This does not alter the sequence between HWC and surfaceflinger.
-class HwcAsyncWorker final {
-public:
- HwcAsyncWorker();
- ~HwcAsyncWorker();
- // Runs the provided function which calls hwc validate and returns the requested
- // device changes as a future.
- std::future<std::optional<android::HWComposer::DeviceRequestedChanges>> send(
- std::function<std::optional<android::HWComposer::DeviceRequestedChanges>()>);
-
-private:
- std::mutex mMutex;
- std::condition_variable mCv GUARDED_BY(mMutex);
- bool mDone GUARDED_BY(mMutex) = false;
- bool mTaskRequested GUARDED_BY(mMutex) = false;
- std::packaged_task<std::optional<android::HWComposer::DeviceRequestedChanges>()> mTask
- GUARDED_BY(mMutex);
- std::thread mThread;
- void run();
-};
-
-} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index 0be5d01..a7a8e97 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -17,13 +17,9 @@
#pragma once
#include <compositionengine/CompositionEngine.h>
-#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/Output.h>
#include <compositionengine/impl/ClientCompositionRequestCache.h>
-#include <compositionengine/impl/GpuCompositionResult.h>
-#include <compositionengine/impl/HwcAsyncWorker.h>
#include <compositionengine/impl/OutputCompositionState.h>
-#include <compositionengine/impl/OutputLayerCompositionState.h>
#include <compositionengine/impl/planner/Planner.h>
#include <renderengine/DisplaySettings.h>
#include <renderengine/LayerSettings.h>
@@ -96,38 +92,25 @@
void updateColorProfile(const compositionengine::CompositionRefreshArgs&) override;
void beginFrame() override;
void prepareFrame() override;
- GpuCompositionResult prepareFrameAsync(const CompositionRefreshArgs&) override;
void devOptRepaintFlash(const CompositionRefreshArgs&) override;
- void finishFrame(const CompositionRefreshArgs&, GpuCompositionResult&&) override;
- std::optional<base::unique_fd> composeSurfaces(const Region&,
- const compositionengine::CompositionRefreshArgs&,
- std::shared_ptr<renderengine::ExternalTexture>,
- base::unique_fd&) override;
+ void finishFrame(const CompositionRefreshArgs&) override;
+ std::optional<base::unique_fd> composeSurfaces(
+ const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) override;
void postFramebuffer() override;
void renderCachedSets(const CompositionRefreshArgs&) override;
void cacheClientCompositionRequests(uint32_t) override;
- bool canPredictCompositionStrategy(const CompositionRefreshArgs&) override;
- void setPredictCompositionStrategy(bool) override;
// Testing
const ReleasedLayers& getReleasedLayersForTest() const;
void setDisplayColorProfileForTest(std::unique_ptr<compositionengine::DisplayColorProfile>);
void setRenderSurfaceForTest(std::unique_ptr<compositionengine::RenderSurface>);
bool plannerEnabled() const { return mPlanner != nullptr; }
- virtual bool anyLayersRequireClientComposition() const;
- virtual void updateProtectedContentState();
- virtual bool dequeueRenderBuffer(base::unique_fd*,
- std::shared_ptr<renderengine::ExternalTexture>*);
- virtual std::future<std::optional<android::HWComposer::DeviceRequestedChanges>>
- chooseCompositionStrategyAsync();
protected:
std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;
std::optional<size_t> findCurrentOutputLayerForLayer(
const sp<compositionengine::LayerFE>&) const;
- using DeviceRequestedChanges = android::HWComposer::DeviceRequestedChanges;
- std::optional<DeviceRequestedChanges> chooseCompositionStrategy() override;
- void applyCompositionStrategy(const std::optional<DeviceRequestedChanges>&) override{};
+ void chooseCompositionStrategy() override;
bool getSkipColorTransform() const override;
compositionengine::Output::FrameFences presentAndGetFrameFences() override;
std::vector<LayerFE::LayerSettings> generateClientCompositionRequests(
@@ -148,7 +131,6 @@
private:
void dirtyEntireOutput();
compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const;
- void finishPrepareFrame();
ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const;
compositionengine::Output::ColorProfile pickColorProfile(
const compositionengine::CompositionRefreshArgs&) const;
@@ -162,7 +144,6 @@
OutputLayer* mLayerRequestingBackgroundBlur = nullptr;
std::unique_ptr<ClientCompositionRequestCache> mClientCompositionRequestCache;
std::unique_ptr<planner::Planner> mPlanner;
- std::unique_ptr<HwcAsyncWorker> mHwComposerAsyncWorker;
};
// This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 92f22b6..66dd825 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -37,8 +37,6 @@
#include <ui/Region.h>
#include <ui/Transform.h>
-#include "DisplayHardware/HWComposer.h"
-
namespace android {
namespace compositionengine::impl {
@@ -116,8 +114,6 @@
// Current target dataspace
ui::Dataspace targetDataspace{ui::Dataspace::UNKNOWN};
- std::optional<android::HWComposer::DeviceRequestedChanges> previousDeviceRequestedChanges{};
-
// The earliest time to send the present command to the HAL
std::chrono::steady_clock::time_point earliestPresentTime;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index e4cb113..a8a5380 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -63,7 +63,6 @@
void queueBuffer(base::unique_fd readyFence) override;
void onPresentDisplayCompleted() override;
void flip() override;
- bool supportsCompositionStrategyPrediction() const override;
// Debugging
void dump(std::string& result) const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
index 72e6f3b..d90cc90 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Display.h
@@ -41,7 +41,6 @@
MOCK_METHOD1(createDisplayColorProfile, void(const DisplayColorProfileCreationArgs&));
MOCK_METHOD1(createRenderSurface, void(const RenderSurfaceCreationArgs&));
MOCK_METHOD1(createClientCompositionCache, void(uint32_t));
- MOCK_METHOD1(setPredictCompositionStrategy, void(bool));
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 27303a8..b68b95d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -22,7 +22,6 @@
#include <compositionengine/Output.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/RenderSurface.h>
-#include <compositionengine/impl/GpuCompositionResult.h>
#include <compositionengine/impl/OutputCompositionState.h>
#include <gmock/gmock.h>
@@ -100,22 +99,16 @@
MOCK_METHOD0(beginFrame, void());
MOCK_METHOD0(prepareFrame, void());
- MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&));
- MOCK_METHOD0(chooseCompositionStrategy,
- std::optional<android::HWComposer::DeviceRequestedChanges>());
- MOCK_METHOD1(applyCompositionStrategy,
- void(const std::optional<android::HWComposer::DeviceRequestedChanges>&));
+ MOCK_METHOD0(chooseCompositionStrategy, void());
MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
- MOCK_METHOD2(finishFrame,
- void(const compositionengine::CompositionRefreshArgs&, GpuCompositionResult&&));
+ MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
- MOCK_METHOD4(composeSurfaces,
+ MOCK_METHOD2(composeSurfaces,
std::optional<base::unique_fd>(
const Region&,
- const compositionengine::CompositionRefreshArgs& refreshArgs,
- std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
+ const compositionengine::CompositionRefreshArgs& refreshArgs));
MOCK_CONST_METHOD0(getSkipColorTransform, bool());
MOCK_METHOD0(postFramebuffer, void());
@@ -128,8 +121,6 @@
void(const Region&, std::vector<LayerFE::LayerSettings>&));
MOCK_METHOD1(setExpensiveRenderingExpected, void(bool));
MOCK_METHOD1(cacheClientCompositionRequests, void(uint32_t));
- MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
- MOCK_METHOD1(setPredictCompositionStrategy, void(bool));
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index e12aebb..fe858c2 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -45,7 +45,6 @@
MOCK_METHOD0(flip, void());
MOCK_CONST_METHOD1(dump, void(std::string& result));
MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t());
- MOCK_CONST_METHOD0(supportsCompositionStrategyPrediction, bool());
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index 09648c3..6a75283 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -221,12 +221,12 @@
setReleasedLayers(std::move(releasedLayers));
}
-std::optional<android::HWComposer::DeviceRequestedChanges> Display::chooseCompositionStrategy() {
+void Display::chooseCompositionStrategy() {
ATRACE_CALL();
ALOGV(__FUNCTION__);
if (mIsDisconnected) {
- return {};
+ return;
}
// Default to the base settings -- client composition only.
@@ -235,7 +235,7 @@
// If we don't have a HWC display, then we are done.
const auto halDisplayId = HalDisplayId::tryCast(mId);
if (!halDisplayId) {
- return {};
+ return;
}
// Get any composition changes requested by the HWC device, and apply them.
@@ -260,13 +260,8 @@
result != NO_ERROR) {
ALOGE("chooseCompositionStrategy failed for %s: %d (%s)", getName().c_str(), result,
strerror(-result));
- return {};
+ return;
}
-
- return changes;
-}
-
-void Display::applyCompositionStrategy(const std::optional<DeviceRequestedChanges>& changes) {
if (changes) {
applyChangedTypesToLayers(changes->changedTypes);
applyDisplayRequests(changes->displayRequests);
@@ -292,6 +287,12 @@
return hwc.hasCapability(Capability::SKIP_CLIENT_COLOR_TRANSFORM);
}
+bool Display::anyLayersRequireClientComposition() const {
+ const auto layers = getOutputLayersOrderedByZ();
+ return std::any_of(layers.begin(), layers.end(),
+ [](const auto& layer) { return layer->requiresClientComposition(); });
+}
+
bool Display::allLayersRequireClientComposition() const {
const auto layers = getOutputLayersOrderedByZ();
return std::all_of(layers.begin(), layers.end(),
@@ -389,8 +390,7 @@
}
}
-void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs,
- GpuCompositionResult&& result) {
+void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
// We only need to actually compose the display if:
// 1) It is being handled by hardware composer, which may need this to
// keep its virtual display state machine in sync, or
@@ -400,7 +400,7 @@
return;
}
- impl::Output::finishFrame(refreshArgs, std::move(result));
+ impl::Output::finishFrame(refreshArgs);
}
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp
index 28900af..db6d4f2 100644
--- a/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/DisplaySurface.cpp
@@ -20,8 +20,4 @@
DisplaySurface::~DisplaySurface() = default;
-bool DisplaySurface::supportsCompositionStrategyPrediction() const {
- return true;
-}
-
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp b/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp
deleted file mode 100644
index 497424a..0000000
--- a/services/surfaceflinger/CompositionEngine/src/HwcAsyncWorker.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2022 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 <compositionengine/impl/HwcAsyncWorker.h>
-#include <processgroup/sched_policy.h>
-#include <pthread.h>
-#include <sched.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
-#include <system/thread_defs.h>
-
-#include <android-base/thread_annotations.h>
-#include <cutils/sched_policy.h>
-
-namespace android::compositionengine::impl {
-
-HwcAsyncWorker::HwcAsyncWorker() {
- mThread = std::thread(&HwcAsyncWorker::run, this);
- pthread_setname_np(mThread.native_handle(), "HwcAsyncWorker");
-}
-
-HwcAsyncWorker::~HwcAsyncWorker() {
- {
- std::scoped_lock lock(mMutex);
- mDone = true;
- mCv.notify_all();
- }
- if (mThread.joinable()) {
- mThread.join();
- }
-}
-std::future<std::optional<android::HWComposer::DeviceRequestedChanges>> HwcAsyncWorker::send(
- std::function<std::optional<android::HWComposer::DeviceRequestedChanges>()> task) {
- std::unique_lock<std::mutex> lock(mMutex);
- android::base::ScopedLockAssertion assumeLock(mMutex);
- mTask = std::packaged_task<std::optional<android::HWComposer::DeviceRequestedChanges>()>(
- [task = std::move(task)]() { return task(); });
- mTaskRequested = true;
- mCv.notify_one();
- return mTask.get_future();
-}
-
-void HwcAsyncWorker::run() {
- set_sched_policy(0, SP_FOREGROUND);
- struct sched_param param = {0};
- param.sched_priority = 2;
- sched_setscheduler(gettid(), SCHED_FIFO, ¶m);
-
- std::unique_lock<std::mutex> lock(mMutex);
- android::base::ScopedLockAssertion assumeLock(mMutex);
- while (!mDone) {
- mCv.wait(lock);
- if (mTaskRequested && mTask.valid()) {
- mTask();
- mTaskRequested = false;
- }
- }
-}
-
-} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index cd10bc1..aef55d4 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -22,7 +22,6 @@
#include <compositionengine/LayerFE.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/RenderSurface.h>
-#include <compositionengine/impl/HwcAsyncWorker.h>
#include <compositionengine/impl/Output.h>
#include <compositionengine/impl/OutputCompositionState.h>
#include <compositionengine/impl/OutputLayer.h>
@@ -435,17 +434,9 @@
writeCompositionState(refreshArgs);
setColorTransform(refreshArgs);
beginFrame();
-
- GpuCompositionResult result;
- const bool predictCompositionStrategy = canPredictCompositionStrategy(refreshArgs);
- if (predictCompositionStrategy) {
- result = prepareFrameAsync(refreshArgs);
- } else {
- prepareFrame();
- }
-
+ prepareFrame();
devOptRepaintFlash(refreshArgs);
- finishFrame(refreshArgs, std::move(result));
+ finishFrame(refreshArgs);
postFramebuffer();
renderCachedSets(refreshArgs);
}
@@ -960,62 +951,19 @@
ATRACE_CALL();
ALOGV(__FUNCTION__);
- auto& outputState = editState();
+ const auto& outputState = getState();
if (!outputState.isEnabled) {
return;
}
- auto changes = chooseCompositionStrategy();
- outputState.previousDeviceRequestedChanges = changes;
- if (changes) {
- applyCompositionStrategy(changes);
- }
- finishPrepareFrame();
-}
+ chooseCompositionStrategy();
-std::future<std::optional<android::HWComposer::DeviceRequestedChanges>>
-Output::chooseCompositionStrategyAsync() {
- return mHwComposerAsyncWorker->send([&]() { return chooseCompositionStrategy(); });
-}
-
-GpuCompositionResult Output::prepareFrameAsync(const CompositionRefreshArgs& refreshArgs) {
- ATRACE_CALL();
- ALOGV(__FUNCTION__);
- auto& state = editState();
- const auto& previousChanges = state.previousDeviceRequestedChanges;
- auto hwcResult = chooseCompositionStrategyAsync();
- applyCompositionStrategy(previousChanges);
- finishPrepareFrame();
-
- base::unique_fd bufferFence;
- std::shared_ptr<renderengine::ExternalTexture> buffer;
- updateProtectedContentState();
- const bool dequeueSucceeded = dequeueRenderBuffer(&bufferFence, &buffer);
- GpuCompositionResult compositionResult;
- if (dequeueSucceeded) {
- std::optional<base::unique_fd> optFd =
- composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence);
- if (optFd) {
- compositionResult.fence = std::move(*optFd);
- }
+ if (mPlanner) {
+ mPlanner->reportFinalPlan(getOutputLayersOrderedByZ());
}
- auto changes = hwcResult.valid() ? hwcResult.get() : std::nullopt;
- const bool predictionSucceeded = dequeueSucceeded && changes == previousChanges;
- compositionResult.succeeded = predictionSucceeded;
- if (!predictionSucceeded) {
- ATRACE_NAME("CompositionStrategyPredictionMiss");
- if (changes) {
- applyCompositionStrategy(changes);
- }
- finishPrepareFrame();
- // Track the dequeued buffer to reuse so we don't need to dequeue another one.
- compositionResult.buffer = buffer;
- } else {
- ATRACE_NAME("CompositionStrategyPredictionHit");
- }
- state.previousDeviceRequestedChanges = std::move(changes);
- return compositionResult;
+ mRenderSurface->prepareFrame(outputState.usesClientComposition,
+ outputState.usesDeviceComposition);
}
void Output::devOptRepaintFlash(const compositionengine::CompositionRefreshArgs& refreshArgs) {
@@ -1025,11 +973,7 @@
if (getState().isEnabled) {
if (const auto dirtyRegion = getDirtyRegion(); !dirtyRegion.isEmpty()) {
- base::unique_fd bufferFence;
- std::shared_ptr<renderengine::ExternalTexture> buffer;
- updateProtectedContentState();
- dequeueRenderBuffer(&bufferFence, &buffer);
- static_cast<void>(composeSurfaces(dirtyRegion, refreshArgs, buffer, bufferFence));
+ static_cast<void>(composeSurfaces(dirtyRegion, refreshArgs));
mRenderSurface->queueBuffer(base::unique_fd());
}
}
@@ -1041,7 +985,7 @@
prepareFrame();
}
-void Output::finishFrame(const CompositionRefreshArgs& refreshArgs, GpuCompositionResult&& result) {
+void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
@@ -1049,25 +993,9 @@
return;
}
- std::optional<base::unique_fd> optReadyFence;
- std::shared_ptr<renderengine::ExternalTexture> buffer;
- base::unique_fd bufferFence;
- if (result.succeeded) {
- optReadyFence = std::move(result.fence);
- } else {
- if (result.bufferAvailable()) {
- buffer = std::move(result.buffer);
- bufferFence = std::move(result.fence);
- } else {
- updateProtectedContentState();
- if (!dequeueRenderBuffer(&bufferFence, &buffer)) {
- return;
- }
- }
- // Repaint the framebuffer (if needed), getting the optional fence for when
- // the composition completes.
- optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs, buffer, bufferFence);
- }
+ // Repaint the framebuffer (if needed), getting the optional fence for when
+ // the composition completes.
+ auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
if (!optReadyFence) {
return;
}
@@ -1076,8 +1004,16 @@
mRenderSurface->queueBuffer(std::move(*optReadyFence));
}
-void Output::updateProtectedContentState() {
+std::optional<base::unique_fd> Output::composeSurfaces(
+ const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) {
+ ATRACE_CALL();
+ ALOGV(__FUNCTION__);
+
const auto& outputState = getState();
+ OutputCompositionState& outputCompositionState = editState();
+ const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
+ outputState.usesClientComposition};
+
auto& renderEngine = getCompositionEngine().getRenderEngine();
const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
@@ -1099,48 +1035,29 @@
} else if (!outputState.isSecure && renderEngine.isProtected()) {
renderEngine.useProtectedContext(false);
}
-}
-bool Output::dequeueRenderBuffer(base::unique_fd* bufferFence,
- std::shared_ptr<renderengine::ExternalTexture>* tex) {
- const auto& outputState = getState();
+ base::unique_fd fd;
+
+ std::shared_ptr<renderengine::ExternalTexture> tex;
// If we aren't doing client composition on this output, but do have a
// flipClientTarget request for this frame on this output, we still need to
// dequeue a buffer.
- if (outputState.usesClientComposition || outputState.flipClientTarget) {
- *tex = mRenderSurface->dequeueBuffer(bufferFence);
- if (*tex == nullptr) {
+ if (hasClientComposition || outputState.flipClientTarget) {
+ tex = mRenderSurface->dequeueBuffer(&fd);
+ if (tex == nullptr) {
ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
"client composition for this frame",
mName.c_str());
- return false;
+ return {};
}
}
- return true;
-}
-std::optional<base::unique_fd> Output::composeSurfaces(
- const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs,
- std::shared_ptr<renderengine::ExternalTexture> tex, base::unique_fd& fd) {
- ATRACE_CALL();
- ALOGV(__FUNCTION__);
-
- const auto& outputState = getState();
- const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
- outputState.usesClientComposition};
if (!hasClientComposition) {
setExpensiveRenderingExpected(false);
return base::unique_fd();
}
- if (tex == nullptr) {
- ALOGW("Buffer not valid for display [%s], bailing out of "
- "client composition for this frame",
- mName.c_str());
- return {};
- }
-
ALOGV("hasClientComposition");
renderengine::DisplaySettings clientCompositionDisplay;
@@ -1168,8 +1085,6 @@
outputState.usesDeviceComposition || getSkipColorTransform();
// Generate the client composition requests for the layers on this output.
- auto& renderEngine = getCompositionEngine().getRenderEngine();
- const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
std::vector<LayerFE*> clientCompositionLayersFE;
std::vector<LayerFE::LayerSettings> clientCompositionLayers =
generateClientCompositionRequests(supportsProtectedContent,
@@ -1177,19 +1092,16 @@
clientCompositionLayersFE);
appendRegionFlashRequests(debugRegion, clientCompositionLayers);
- OutputCompositionState& outputCompositionState = editState();
// Check if the client composition requests were rendered into the provided graphic buffer. If
// so, we can reuse the buffer and avoid client composition.
if (mClientCompositionRequestCache) {
if (mClientCompositionRequestCache->exists(tex->getBuffer()->getId(),
clientCompositionDisplay,
clientCompositionLayers)) {
- ATRACE_NAME("ClientCompositionCacheHit");
outputCompositionState.reusedClientComposition = true;
setExpensiveRenderingExpected(false);
return base::unique_fd();
}
- ATRACE_NAME("ClientCompositionCacheMiss");
mClientCompositionRequestCache->add(tex->getBuffer()->getId(), clientCompositionDisplay,
clientCompositionLayers);
}
@@ -1441,13 +1353,12 @@
outputState.dirtyRegion.set(outputState.displaySpace.getBoundsAsRect());
}
-std::optional<android::HWComposer::DeviceRequestedChanges> Output::chooseCompositionStrategy() {
+void Output::chooseCompositionStrategy() {
// The base output implementation can only do client composition
auto& outputState = editState();
outputState.usesClientComposition = true;
outputState.usesDeviceComposition = false;
outputState.reusedClientComposition = false;
- return {};
}
bool Output::getSkipColorTransform() const {
@@ -1462,63 +1373,5 @@
return result;
}
-void Output::setPredictCompositionStrategy(bool predict) {
- if (predict) {
- mHwComposerAsyncWorker = std::make_unique<HwcAsyncWorker>();
- } else {
- mHwComposerAsyncWorker.reset(nullptr);
- }
-}
-
-bool Output::canPredictCompositionStrategy(const CompositionRefreshArgs& refreshArgs) {
- if (!getState().isEnabled || !mHwComposerAsyncWorker) {
- ALOGV("canPredictCompositionStrategy disabled");
- return false;
- }
-
- if (!getState().previousDeviceRequestedChanges) {
- ALOGV("canPredictCompositionStrategy previous changes not available");
- return false;
- }
-
- if (!mRenderSurface->supportsCompositionStrategyPrediction()) {
- ALOGV("canPredictCompositionStrategy surface does not support");
- return false;
- }
-
- if (refreshArgs.devOptFlashDirtyRegionsDelay) {
- ALOGV("canPredictCompositionStrategy devOptFlashDirtyRegionsDelay");
- return false;
- }
-
- // If no layer uses clientComposition, then don't predict composition strategy
- // because we have less work to do in parallel.
- if (!anyLayersRequireClientComposition()) {
- ALOGV("canPredictCompositionStrategy no layer uses clientComposition");
- return false;
- }
-
- if (!refreshArgs.updatingOutputGeometryThisFrame) {
- return true;
- }
-
- ALOGV("canPredictCompositionStrategy updatingOutputGeometryThisFrame");
- return false;
-}
-
-bool Output::anyLayersRequireClientComposition() const {
- const auto layers = getOutputLayersOrderedByZ();
- return std::any_of(layers.begin(), layers.end(),
- [](const auto& layer) { return layer->requiresClientComposition(); });
-}
-
-void Output::finishPrepareFrame() {
- const auto& state = getState();
- if (mPlanner) {
- mPlanner->reportFinalPlan(getOutputLayersOrderedByZ());
- }
- mRenderSurface->prepareFrame(state.usesClientComposition, state.usesDeviceComposition);
-}
-
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 5a3af7b..12c2c8e 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -289,9 +289,5 @@
return mTexture;
}
-bool RenderSurface::supportsCompositionStrategyPrediction() const {
- return mDisplaySurface->supportsCompositionStrategyPrediction();
-}
-
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
index 42c1263..aaca4fe 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -307,7 +307,12 @@
}
const auto& layerFE = mLayers[0].getState()->getOutputLayer()->getLayerFE();
- if (layerFE.getCompositionState()->forceClientComposition) {
+ const auto* compositionState = layerFE.getCompositionState();
+ if (compositionState->forceClientComposition) {
+ return false;
+ }
+
+ if (compositionState->blendMode != hal::BlendMode::NONE) {
return false;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 36b04d9..cd03235 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -30,9 +30,7 @@
#include <compositionengine/mock/OutputLayer.h>
#include <compositionengine/mock/RenderSurface.h>
#include <gtest/gtest.h>
-#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
-
#include <ui/Rect.h>
#include <ui/StaticDisplayInfo.h>
@@ -200,22 +198,6 @@
std::shared_ptr<Display> mDisplay =
createPartialMockDisplay<Display>(mCompositionEngine,
getDisplayCreationArgsForPhysicalDisplay());
-
- android::HWComposer::DeviceRequestedChanges mDeviceRequestedChanges{
- {{nullptr, Composition::CLIENT}},
- hal::DisplayRequest::FLIP_CLIENT_TARGET,
- {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
- {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN},
- -1.f,
- };
-
- void chooseCompositionStrategy(Display* display) {
- std::optional<android::HWComposer::DeviceRequestedChanges> changes =
- display->chooseCompositionStrategy();
- if (changes) {
- display->applyCompositionStrategy(changes);
- }
- }
};
struct FullDisplayImplTestCommon : public DisplayTestCommon {
@@ -232,11 +214,6 @@
std::unique_ptr<compositionengine::OutputLayer>(mLayer2.outputLayer));
mDisplay->injectOutputLayerForTest(
std::unique_ptr<compositionengine::OutputLayer>(mLayer3.outputLayer));
- mResultWithBuffer.buffer = std::make_shared<
- renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
- 1ULL /* bufferId */,
- HAL_PIXEL_FORMAT_RGBA_8888,
- 0ULL /*usage*/);
}
Layer mLayer1;
@@ -245,8 +222,6 @@
StrictMock<HWC2::mock::Layer> hwc2LayerUnknown;
std::shared_ptr<Display> mDisplay =
createDisplay<Display>(mCompositionEngine, getDisplayCreationArgsForPhysicalDisplay());
- impl::GpuCompositionResult mResultWithBuffer;
- impl::GpuCompositionResult mResultWithoutBuffer;
};
/*
@@ -579,7 +554,7 @@
createPartialMockDisplay<Display>(mCompositionEngine, args);
EXPECT_TRUE(GpuVirtualDisplayId::tryCast(gpuDisplay->getId()));
- chooseCompositionStrategy(gpuDisplay.get());
+ gpuDisplay->chooseCompositionStrategy();
auto& state = gpuDisplay->getState();
EXPECT_TRUE(state.usesClientComposition);
@@ -592,12 +567,11 @@
getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), false, _, _, _, _))
.WillOnce(Return(INVALID_OPERATION));
- chooseCompositionStrategy(mDisplay.get());
+ mDisplay->chooseCompositionStrategy();
auto& state = mDisplay->getState();
EXPECT_TRUE(state.usesClientComposition);
EXPECT_FALSE(state.usesDeviceComposition);
- EXPECT_FALSE(state.previousDeviceRequestedChanges.has_value());
}
TEST_F(DisplayChooseCompositionStrategyTest, normalOperation) {
@@ -614,16 +588,10 @@
EXPECT_CALL(mHwComposer,
getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
- .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges),
- Return(NO_ERROR)));
- EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes))
- .Times(1);
- EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1);
- EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests))
- .Times(1);
+ .WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
- chooseCompositionStrategy(mDisplay.get());
+ mDisplay->chooseCompositionStrategy();
auto& state = mDisplay->getState();
EXPECT_FALSE(state.usesClientComposition);
@@ -650,17 +618,11 @@
EXPECT_CALL(mHwComposer,
getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
- .WillOnce(testing::DoAll(testing::SetArgPointee<5>(mDeviceRequestedChanges),
- Return(NO_ERROR)));
- EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes))
- .Times(1);
- EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1);
- EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests))
- .Times(1);
+ .WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
mDisplay->setNextBrightness(kDisplayBrightness);
- chooseCompositionStrategy(mDisplay.get());
+ mDisplay->chooseCompositionStrategy();
auto& state = mDisplay->getState();
EXPECT_FALSE(state.usesClientComposition);
@@ -669,6 +631,14 @@
}
TEST_F(DisplayChooseCompositionStrategyTest, normalOperationWithChanges) {
+ android::HWComposer::DeviceRequestedChanges changes{
+ {{nullptr, Composition::CLIENT}},
+ hal::DisplayRequest::FLIP_CLIENT_TARGET,
+ {{nullptr, hal::LayerRequest::CLEAR_CLIENT_TARGET}},
+ {hal::PixelFormat::RGBA_8888, hal::Dataspace::UNKNOWN},
+ -1.f,
+ };
+
// Since two calls are made to anyLayersRequireClientComposition with different return
// values, use a Sequence to control the matching so the values are returned in a known
// order.
@@ -682,15 +652,13 @@
EXPECT_CALL(mHwComposer,
getDeviceCompositionChanges(HalDisplayId(DEFAULT_DISPLAY_ID), true, _, _, _, _))
- .WillOnce(DoAll(SetArgPointee<5>(mDeviceRequestedChanges), Return(NO_ERROR)));
- EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(mDeviceRequestedChanges.changedTypes))
- .Times(1);
- EXPECT_CALL(*mDisplay, applyDisplayRequests(mDeviceRequestedChanges.displayRequests)).Times(1);
- EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(mDeviceRequestedChanges.layerRequests))
- .Times(1);
+ .WillOnce(DoAll(SetArgPointee<5>(changes), Return(NO_ERROR)));
+ EXPECT_CALL(*mDisplay, applyChangedTypesToLayers(changes.changedTypes)).Times(1);
+ EXPECT_CALL(*mDisplay, applyDisplayRequests(changes.displayRequests)).Times(1);
+ EXPECT_CALL(*mDisplay, applyLayerRequestsToLayers(changes.layerRequests)).Times(1);
EXPECT_CALL(*mDisplay, allLayersRequireClientComposition()).WillOnce(Return(false));
- chooseCompositionStrategy(mDisplay.get());
+ mDisplay->chooseCompositionStrategy();
auto& state = mDisplay->getState();
EXPECT_FALSE(state.usesClientComposition);
@@ -954,7 +922,7 @@
mDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1));
mDisplay->editState().dirtyRegion = Region::INVALID_REGION;
- mDisplay->finishFrame({}, std::move(mResultWithBuffer));
+ mDisplay->finishFrame({});
}
TEST_F(DisplayFinishFrameTest, skipsCompositionIfNotDirty) {
@@ -972,7 +940,7 @@
gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1));
gpuDisplay->editState().dirtyRegion = Region::INVALID_REGION;
- gpuDisplay->finishFrame({}, std::move(mResultWithoutBuffer));
+ gpuDisplay->finishFrame({});
}
TEST_F(DisplayFinishFrameTest, performsCompositionIfDirty) {
@@ -989,7 +957,7 @@
gpuDisplay->editState().usesClientComposition = false;
gpuDisplay->editState().layerStackSpace.setContent(Rect(0, 0, 1, 1));
gpuDisplay->editState().dirtyRegion = Region(Rect(0, 0, 1, 1));
- gpuDisplay->finishFrame({}, std::move(mResultWithBuffer));
+ gpuDisplay->finishFrame({});
}
/*
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 719f15c..1f1dd1a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -133,6 +133,8 @@
status_t(PhysicalDisplayId,
std::optional<aidl::android::hardware::graphics::common::
DisplayDecorationSupport>* support));
+ MOCK_METHOD2(setIdleTimerEnabled, status_t(PhysicalDisplayId, std::chrono::milliseconds));
+ MOCK_METHOD1(hasDisplayIdleTimerCapability, bool(PhysicalDisplayId displayId));
};
} // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index af172d8..54eb8f8 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -28,7 +28,6 @@
#include <gtest/gtest.h>
#include <renderengine/ExternalTexture.h>
#include <renderengine/impl/ExternalTexture.h>
-#include <renderengine/mock/FakeExternalTexture.h>
#include <renderengine/mock/RenderEngine.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -990,7 +989,7 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_METHOD0(chooseCompositionStrategy, std::optional<DeviceRequestedChanges>());
+ MOCK_METHOD0(chooseCompositionStrategy, void());
};
OutputPrepareFrameTest() {
@@ -1038,133 +1037,6 @@
EXPECT_FALSE(mOutput->getState().usesDeviceComposition);
}
-struct OutputPrepareFrameAsyncTest : public testing::Test {
- struct OutputPartialMock : public OutputPartialMockBase {
- // Sets up the helper functions called by the function under test to use
- // mock implementations.
- MOCK_METHOD0(chooseCompositionStrategy, std::optional<DeviceRequestedChanges>());
- MOCK_METHOD0(updateProtectedContentState, void());
- MOCK_METHOD2(dequeueRenderBuffer,
- bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
- MOCK_METHOD0(chooseCompositionStrategyAsync,
- std::future<std::optional<android::HWComposer::DeviceRequestedChanges>>());
- MOCK_METHOD4(composeSurfaces,
- std::optional<base::unique_fd>(
- const Region&, const compositionengine::CompositionRefreshArgs&,
- std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
- };
-
- OutputPrepareFrameAsyncTest() {
- mOutput.setDisplayColorProfileForTest(
- std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
- mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
- }
-
- StrictMock<mock::CompositionEngine> mCompositionEngine;
- mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
- mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
- StrictMock<OutputPartialMock> mOutput;
- CompositionRefreshArgs mRefreshArgs;
-};
-
-TEST_F(OutputPrepareFrameAsyncTest, delegatesToChooseCompositionStrategyAndRenderSurface) {
- mOutput.editState().isEnabled = true;
- mOutput.editState().usesClientComposition = false;
- mOutput.editState().usesDeviceComposition = true;
- mOutput.editState().previousDeviceRequestedChanges =
- std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
- std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
- p.set_value(mOutput.editState().previousDeviceRequestedChanges);
-
- EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
- EXPECT_CALL(mOutput, updateProtectedContentState());
- EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true));
- EXPECT_CALL(*mRenderSurface, prepareFrame(false, true));
- EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
- EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _));
-
- impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
- EXPECT_TRUE(result.succeeded);
- EXPECT_FALSE(result.bufferAvailable());
-}
-
-TEST_F(OutputPrepareFrameAsyncTest, skipCompositionOnDequeueFailure) {
- mOutput.editState().isEnabled = true;
- mOutput.editState().usesClientComposition = false;
- mOutput.editState().usesDeviceComposition = true;
- mOutput.editState().previousDeviceRequestedChanges =
- std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
- std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
- p.set_value(mOutput.editState().previousDeviceRequestedChanges);
-
- EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
- EXPECT_CALL(mOutput, updateProtectedContentState());
- EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(false));
- EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2);
- EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
-
- impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
- EXPECT_FALSE(result.succeeded);
- EXPECT_FALSE(result.bufferAvailable());
-}
-
-// Tests that in the event of hwc error when choosing composition strategy, we would fall back
-// client composition
-TEST_F(OutputPrepareFrameAsyncTest, chooseCompositionStrategyFailureCallsPrepareFrame) {
- mOutput.editState().isEnabled = true;
- mOutput.editState().usesClientComposition = false;
- mOutput.editState().usesDeviceComposition = true;
- mOutput.editState().previousDeviceRequestedChanges =
- std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
- std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
- p.set_value({});
- std::shared_ptr<renderengine::ExternalTexture> tex =
- std::make_shared<renderengine::mock::FakeExternalTexture>(1, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- 2);
-
- EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
- EXPECT_CALL(mOutput, updateProtectedContentState());
- EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _))
- .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true)));
- EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2);
- EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
- EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _));
-
- impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
- EXPECT_FALSE(result.succeeded);
- EXPECT_TRUE(result.bufferAvailable());
-}
-
-TEST_F(OutputPrepareFrameAsyncTest, predictionMiss) {
- mOutput.editState().isEnabled = true;
- mOutput.editState().usesClientComposition = false;
- mOutput.editState().usesDeviceComposition = true;
- mOutput.editState().previousDeviceRequestedChanges =
- std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
- auto newDeviceRequestedChanges =
- std::make_optional<android::HWComposer::DeviceRequestedChanges>({});
- newDeviceRequestedChanges->clientTargetBrightness = 5.f;
- std::promise<std::optional<android::HWComposer::DeviceRequestedChanges>> p;
- p.set_value(newDeviceRequestedChanges);
- std::shared_ptr<renderengine::ExternalTexture> tex =
- std::make_shared<renderengine::mock::FakeExternalTexture>(1, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- 2);
-
- EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(0u));
- EXPECT_CALL(mOutput, updateProtectedContentState());
- EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _))
- .WillOnce(DoAll(SetArgPointee<1>(tex), Return(true)));
- EXPECT_CALL(*mRenderSurface, prepareFrame(false, true)).Times(2);
- EXPECT_CALL(mOutput, chooseCompositionStrategyAsync()).WillOnce([&] { return p.get_future(); });
- EXPECT_CALL(mOutput, composeSurfaces(_, Ref(mRefreshArgs), _, _));
-
- impl::GpuCompositionResult result = mOutput.prepareFrameAsync(mRefreshArgs);
- EXPECT_FALSE(result.succeeded);
- EXPECT_TRUE(result.bufferAvailable());
-}
-
/*
* Output::prepare()
*/
@@ -1923,14 +1795,10 @@
MOCK_METHOD1(setColorTransform, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD0(beginFrame, void());
MOCK_METHOD0(prepareFrame, void());
- MOCK_METHOD1(prepareFrameAsync, GpuCompositionResult(const CompositionRefreshArgs&));
MOCK_METHOD1(devOptRepaintFlash, void(const compositionengine::CompositionRefreshArgs&));
- MOCK_METHOD2(finishFrame,
- void(const compositionengine::CompositionRefreshArgs&,
- GpuCompositionResult&&));
+ MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD0(postFramebuffer, void());
MOCK_METHOD1(renderCachedSets, void(const compositionengine::CompositionRefreshArgs&));
- MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
};
StrictMock<OutputPartialMock> mOutput;
@@ -1946,30 +1814,9 @@
EXPECT_CALL(mOutput, writeCompositionState(Ref(args)));
EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
EXPECT_CALL(mOutput, beginFrame());
- EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(false));
EXPECT_CALL(mOutput, prepareFrame());
EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
- EXPECT_CALL(mOutput, finishFrame(Ref(args), _));
- EXPECT_CALL(mOutput, postFramebuffer());
- EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
-
- mOutput.present(args);
-}
-
-TEST_F(OutputPresentTest, predictingCompositionStrategyInvokesPrepareFrameAsync) {
- CompositionRefreshArgs args;
-
- InSequence seq;
- EXPECT_CALL(mOutput, updateColorProfile(Ref(args)));
- EXPECT_CALL(mOutput, updateCompositionState(Ref(args)));
- EXPECT_CALL(mOutput, planComposition());
- EXPECT_CALL(mOutput, writeCompositionState(Ref(args)));
- EXPECT_CALL(mOutput, setColorTransform(Ref(args)));
- EXPECT_CALL(mOutput, beginFrame());
- EXPECT_CALL(mOutput, canPredictCompositionStrategy(Ref(args))).WillOnce(Return(true));
- EXPECT_CALL(mOutput, prepareFrameAsync(Ref(args)));
- EXPECT_CALL(mOutput, devOptRepaintFlash(Ref(args)));
- EXPECT_CALL(mOutput, finishFrame(Ref(args), _));
+ EXPECT_CALL(mOutput, finishFrame(Ref(args)));
EXPECT_CALL(mOutput, postFramebuffer());
EXPECT_CALL(mOutput, renderCachedSets(Ref(args)));
@@ -2867,15 +2714,11 @@
// Sets up the helper functions called by the function under test to use
// mock implementations.
MOCK_METHOD(Region, getDirtyRegion, (), (const));
- MOCK_METHOD4(composeSurfaces,
+ MOCK_METHOD2(composeSurfaces,
std::optional<base::unique_fd>(
- const Region&, const compositionengine::CompositionRefreshArgs&,
- std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
+ const Region&, const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD0(postFramebuffer, void());
MOCK_METHOD0(prepareFrame, void());
- MOCK_METHOD0(updateProtectedContentState, void());
- MOCK_METHOD2(dequeueRenderBuffer,
- bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
};
OutputDevOptRepaintFlashTest() {
@@ -2932,9 +2775,7 @@
InSequence seq;
EXPECT_CALL(mOutput, getDirtyRegion()).WillOnce(Return(kNotEmptyRegion));
- EXPECT_CALL(mOutput, updateProtectedContentState());
- EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _));
- EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs), _, _));
+ EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs)));
EXPECT_CALL(*mRenderSurface, queueBuffer(_));
EXPECT_CALL(mOutput, postFramebuffer());
EXPECT_CALL(mOutput, prepareFrame());
@@ -2950,14 +2791,10 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_METHOD4(composeSurfaces,
+ MOCK_METHOD2(composeSurfaces,
std::optional<base::unique_fd>(
- const Region&, const compositionengine::CompositionRefreshArgs&,
- std::shared_ptr<renderengine::ExternalTexture>, base::unique_fd&));
+ const Region&, const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD0(postFramebuffer, void());
- MOCK_METHOD0(updateProtectedContentState, void());
- MOCK_METHOD2(dequeueRenderBuffer,
- bool(base::unique_fd*, std::shared_ptr<renderengine::ExternalTexture>*));
};
OutputFinishFrameTest() {
@@ -2975,63 +2812,27 @@
TEST_F(OutputFinishFrameTest, ifNotEnabledDoesNothing) {
mOutput.mState.isEnabled = false;
- impl::GpuCompositionResult result;
- mOutput.finishFrame(mRefreshArgs, std::move(result));
+ mOutput.finishFrame(mRefreshArgs);
}
TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
mOutput.mState.isEnabled = true;
- EXPECT_CALL(mOutput, updateProtectedContentState());
- EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true));
- EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _));
- impl::GpuCompositionResult result;
- mOutput.finishFrame(mRefreshArgs, std::move(result));
+ InSequence seq;
+ EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _));
+
+ mOutput.finishFrame(mRefreshArgs);
}
TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
mOutput.mState.isEnabled = true;
InSequence seq;
- EXPECT_CALL(mOutput, updateProtectedContentState());
- EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true));
- EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _, _))
+ EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _))
.WillOnce(Return(ByMove(base::unique_fd())));
EXPECT_CALL(*mRenderSurface, queueBuffer(_));
- impl::GpuCompositionResult result;
- mOutput.finishFrame(mRefreshArgs, std::move(result));
-}
-
-TEST_F(OutputFinishFrameTest, predictionSucceeded) {
- mOutput.mState.isEnabled = true;
-
- InSequence seq;
- EXPECT_CALL(*mRenderSurface, queueBuffer(_));
-
- impl::GpuCompositionResult result;
- result.succeeded = true;
- mOutput.finishFrame(mRefreshArgs, std::move(result));
-}
-
-TEST_F(OutputFinishFrameTest, predictionFailedAndBufferIsReused) {
- mOutput.mState.isEnabled = true;
-
- InSequence seq;
-
- impl::GpuCompositionResult result;
- result.succeeded = false;
- result.buffer =
- std::make_shared<renderengine::mock::FakeExternalTexture>(1, 1,
- HAL_PIXEL_FORMAT_RGBA_8888, 1,
- 2);
-
- EXPECT_CALL(mOutput,
- composeSurfaces(RegionEq(Region::INVALID_REGION), _, result.buffer,
- Eq(ByRef(result.fence))))
- .WillOnce(Return(ByMove(base::unique_fd())));
- EXPECT_CALL(*mRenderSurface, queueBuffer(_));
- mOutput.finishFrame(mRefreshArgs, std::move(result));
+ mOutput.finishFrame(mRefreshArgs);
}
/*
@@ -3278,15 +3079,8 @@
struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
auto execute() {
- base::unique_fd fence;
- std::shared_ptr<renderengine::ExternalTexture> externalTexture;
- const bool success =
- getInstance()->mOutput.dequeueRenderBuffer(&fence, &externalTexture);
- if (success) {
- getInstance()->mReadyFence =
- getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs,
- externalTexture, fence);
- }
+ getInstance()->mReadyFence =
+ getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
return nextState<FenceCheckState>();
}
};
@@ -3847,11 +3641,7 @@
EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
EXPECT_CALL(mRenderEngine, useProtectedContext(false));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) {
@@ -3859,11 +3649,7 @@
mLayer2.mLayerFEState.hasProtectedContent = true;
EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
@@ -3875,11 +3661,7 @@
EXPECT_CALL(mRenderEngine, useProtectedContext(false));
EXPECT_CALL(*mRenderSurface, setProtected(false));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
@@ -3901,11 +3683,7 @@
.WillOnce(Return(ByMove(
futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
@@ -3915,11 +3693,7 @@
EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) {
@@ -3930,11 +3704,7 @@
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
EXPECT_CALL(mRenderEngine, useProtectedContext(true));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) {
@@ -3945,11 +3715,7 @@
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
EXPECT_CALL(*mRenderSurface, setProtected(true));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
@@ -3960,11 +3726,7 @@
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
EXPECT_CALL(mRenderEngine, useProtectedContext(true));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest {
@@ -3994,11 +3756,7 @@
.WillOnce(Return(ByMove(
futureOf<renderengine::RenderEngineResult>({NO_ERROR, base::unique_fd()}))));
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
struct OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur
@@ -4033,12 +3791,7 @@
mOutput.writeCompositionState(mRefreshArgs);
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
-
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, mRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreNotExpensive) {
@@ -4048,12 +3801,7 @@
mOutput.writeCompositionState(mRefreshArgs);
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(0);
-
- base::unique_fd fd;
- std::shared_ptr<renderengine::ExternalTexture> tex;
- mOutput.updateProtectedContentState();
- mOutput.dequeueRenderBuffer(&fd, &tex);
- mOutput.composeSurfaces(kDebugRegion, mRefreshArgs, tex, fd);
+ mOutput.composeSurfaces(kDebugRegion, mRefreshArgs);
}
/*
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
index 4ae921d..8a99e4e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -539,6 +539,8 @@
TEST_F(CachedSetTest, holePunch_requiresBuffer) {
CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
+ auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
+ layerFECompositionState.blendMode = hal::BlendMode::NONE;
sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
CachedSet cachedSet(layer1);
@@ -549,7 +551,9 @@
TEST_F(CachedSetTest, holePunch_requiresRoundedCorners) {
CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
- mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
+ layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ layerFECompositionState.blendMode = hal::BlendMode::NONE;
CachedSet cachedSet(layer1);
@@ -558,7 +562,9 @@
TEST_F(CachedSetTest, holePunch_requiresSingleLayer) {
CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
- mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
+ layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ layerFECompositionState.blendMode = hal::BlendMode::NONE;
sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
@@ -575,7 +581,9 @@
mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
- mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
+ layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ layerFECompositionState.blendMode = hal::BlendMode::NONE;
sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
CachedSet cachedSet(layer);
@@ -589,7 +597,22 @@
mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
- mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
+ layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ layerFECompositionState.blendMode = hal::BlendMode::NONE;
+ sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
+
+ CachedSet cachedSet(layer);
+ EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
+
+ EXPECT_FALSE(cachedSet.requiresHolePunch());
+}
+
+TEST_F(CachedSetTest, holePunch_requiresNoBlending) {
+ CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
+ auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
+ layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ layerFECompositionState.blendMode = hal::BlendMode::PREMULTIPLIED;
sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
CachedSet cachedSet(layer);
@@ -600,7 +623,9 @@
TEST_F(CachedSetTest, requiresHolePunch) {
CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
- mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
+ layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ layerFECompositionState.blendMode = hal::BlendMode::NONE;
sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
CachedSet cachedSet(layer);
@@ -614,6 +639,7 @@
sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
layerFECompositionState.buffer = sp<GraphicBuffer>::make();
+ layerFECompositionState.blendMode = hal::BlendMode::NONE;
layerFECompositionState.forceClientComposition = true;
CachedSet cachedSet(layer);
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
index 656ef9a..96c28c9 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp
@@ -633,6 +633,7 @@
auto& layerState3 = mTestLayers[2]->layerState;
const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
+ mTestLayers[2]->layerFECompositionState.blendMode = hal::BlendMode::NONE;
EXPECT_CALL(*mTestLayers[2]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
@@ -706,6 +707,7 @@
// a rounded updating layer
auto& layerState1 = mTestLayers[1]->layerState;
const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+ mTestLayers[1]->layerFECompositionState.blendMode = hal::BlendMode::NONE;
EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
@@ -777,6 +779,7 @@
// a rounded updating layer
auto& layerState1 = mTestLayers[1]->layerState;
const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
+ mTestLayers[1]->layerFECompositionState.blendMode = hal::BlendMode::NONE;
EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 610d86f..45b98bb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -91,7 +91,6 @@
static_cast<uint32_t>(SurfaceFlinger::maxFrameBufferAcquiredBuffers));
}
- mCompositionDisplay->setPredictCompositionStrategy(mFlinger->mPredictCompositionStrategy);
mCompositionDisplay->createDisplayColorProfile(
compositionengine::DisplayColorProfileCreationArgsBuilder()
.setHasWideColorGamut(args.hasWideColorGamut)
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 80e2d99..92592f7 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -248,6 +248,7 @@
case OptionalFeature::ExpectedPresentTime:
case OptionalFeature::DisplayBrightnessCommand:
case OptionalFeature::BootDisplayConfig:
+ case OptionalFeature::KernelIdleTimer:
return true;
}
}
@@ -475,6 +476,19 @@
return Error::NONE;
}
+Error AidlComposer::hasDisplayIdleTimerCapability(Display display, bool* outSupport) {
+ std::vector<AidlDisplayCapability> capabilities;
+ const auto status =
+ mAidlComposerClient->getDisplayCapabilities(translate<int64_t>(display), &capabilities);
+ if (!status.isOk()) {
+ ALOGE("getDisplayCapabilities failed %s", status.getDescription().c_str());
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+ *outSupport = std::find(capabilities.begin(), capabilities.end(),
+ AidlDisplayCapability::DISPLAY_IDLE_TIMER) != capabilities.end();
+ return Error::NONE;
+}
+
Error AidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) {
@@ -1100,5 +1114,17 @@
}
return Error::NONE;
}
+
+Error AidlComposer::setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) {
+ const auto status =
+ mAidlComposerClient->setIdleTimerEnabled(translate<int64_t>(displayId),
+ translate<int32_t>(timeout.count()));
+ if (!status.isOk()) {
+ ALOGE("setIdleTimerEnabled failed %s", status.getDescription().c_str());
+ return static_cast<Error>(status.getServiceSpecificError());
+ }
+ return Error::NONE;
+}
+
} // namespace Hwc2
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
index 80ca8da..6c0f636 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.h
@@ -100,6 +100,7 @@
std::vector<uint32_t>* outLayerRequestMasks) override;
Error getDozeSupport(Display display, bool* outSupport) override;
+ Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance) override;
@@ -220,6 +221,7 @@
Error getPreferredBootDisplayConfig(Display displayId, Config*) override;
Error getDisplayDecorationSupport(Display display,
std::optional<DisplayDecorationSupport>* support) override;
+ Error setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) override;
private:
// Many public functions above simply write a command into the command
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 23886d4..6abe7d1 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -93,6 +93,7 @@
// Whether setDisplayBrightness is able to be applied as part of a display command.
DisplayBrightnessCommand,
BootDisplayConfig,
+ KernelIdleTimer,
};
virtual bool isSupported(OptionalFeature) const = 0;
@@ -134,6 +135,7 @@
std::vector<uint32_t>* outLayerRequestMasks) = 0;
virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
+ virtual Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) = 0;
virtual Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) = 0;
@@ -274,6 +276,7 @@
Display display,
std::optional<::aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) = 0;
+ virtual Error setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) = 0;
};
} // namespace Hwc2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index a1b663c..6501276 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -148,6 +148,12 @@
return mComposer.isSupported(android::Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
}
+bool Display::hasDisplayIdleTimerCapability() const {
+ bool isCapabilitySupported = false;
+ return mComposer.hasDisplayIdleTimerCapability(mId, &isCapabilitySupported) == Error::NONE &&
+ isCapabilitySupported;
+}
+
Error Display::getChangedCompositionTypes(std::unordered_map<HWC2::Layer*, Composition>* outTypes) {
std::vector<Hwc2::Layer> layerIds;
std::vector<Composition> types;
@@ -588,6 +594,11 @@
return static_cast<Error>(error);
}
+Error Display::setIdleTimerEnabled(std::chrono::milliseconds timeout) {
+ const auto error = mComposer.setIdleTimerEnabled(mId, timeout);
+ 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 334d6ec..c03cede 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -91,6 +91,7 @@
virtual bool hasCapability(
aidl::android::hardware::graphics::composer3::DisplayCapability) const = 0;
virtual bool isVsyncPeriodSwitchSupported() const = 0;
+ virtual bool hasDisplayIdleTimerCapability() const = 0;
virtual void onLayerDestroyed(hal::HWLayerId layerId) = 0;
[[clang::warn_unused_result]] virtual hal::Error acceptChanges() = 0;
@@ -166,6 +167,8 @@
[[clang::warn_unused_result]] virtual hal::Error getDisplayDecorationSupport(
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) = 0;
+ [[clang::warn_unused_result]] virtual hal::Error setIdleTimerEnabled(
+ std::chrono::milliseconds timeout) = 0;
};
namespace impl {
@@ -242,6 +245,7 @@
hal::Error getDisplayDecorationSupport(
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) override;
+ hal::Error setIdleTimerEnabled(std::chrono::milliseconds timeout) override;
// Other Display methods
hal::HWDisplayId getId() const override { return mId; }
@@ -250,6 +254,7 @@
bool hasCapability(aidl::android::hardware::graphics::composer3::DisplayCapability)
const override EXCLUDES(mDisplayCapabilitiesMutex);
bool isVsyncPeriodSwitchSupported() const override;
+ bool hasDisplayIdleTimerCapability() const override;
void onLayerDestroyed(hal::HWLayerId layerId) override;
private:
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index ed6e4b0..02b3772 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -971,6 +971,26 @@
}
}
+status_t HWComposer::setIdleTimerEnabled(PhysicalDisplayId displayId,
+ std::chrono::milliseconds timeout) {
+ ATRACE_CALL();
+ RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+ const auto error = mDisplayData[displayId].hwcDisplay->setIdleTimerEnabled(timeout);
+ if (error == hal::Error::UNSUPPORTED) {
+ RETURN_IF_HWC_ERROR(error, displayId, INVALID_OPERATION);
+ }
+ if (error == hal::Error::BAD_PARAMETER) {
+ RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+ }
+ RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+ return NO_ERROR;
+}
+
+bool HWComposer::hasDisplayIdleTimerCapability(PhysicalDisplayId displayId) {
+ RETURN_IF_INVALID_DISPLAY(displayId, false);
+ return mDisplayData[displayId].hwcDisplay->hasDisplayIdleTimerCapability();
+}
+
void HWComposer::loadLayerMetadataSupport() {
mSupportedLayerGenericMetadata.clear();
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index a8d439b..f9637f0 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -267,16 +267,10 @@
PhysicalDisplayId,
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) = 0;
+ virtual status_t setIdleTimerEnabled(PhysicalDisplayId, std::chrono::milliseconds timeout) = 0;
+ virtual bool hasDisplayIdleTimerCapability(PhysicalDisplayId) = 0;
};
-static inline bool operator==(const android::HWComposer::DeviceRequestedChanges& lhs,
- const android::HWComposer::DeviceRequestedChanges& rhs) {
- return lhs.changedTypes == rhs.changedTypes && lhs.displayRequests == rhs.displayRequests &&
- lhs.layerRequests == rhs.layerRequests &&
- lhs.clientTargetProperty == rhs.clientTargetProperty &&
- lhs.clientTargetBrightness == rhs.clientTargetBrightness;
-}
-
namespace impl {
class HWComposer final : public android::HWComposer {
@@ -410,6 +404,8 @@
PhysicalDisplayId,
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) override;
+ status_t setIdleTimerEnabled(PhysicalDisplayId, std::chrono::milliseconds timeout) override;
+ bool hasDisplayIdleTimerCapability(PhysicalDisplayId) override;
// for debugging ----------------------------------------------------------
void dump(std::string& out) const override;
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
index f735bba..33adceb 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.cpp
@@ -236,6 +236,7 @@
case OptionalFeature::ExpectedPresentTime:
case OptionalFeature::DisplayBrightnessCommand:
case OptionalFeature::BootDisplayConfig:
+ case OptionalFeature::KernelIdleTimer:
return false;
}
}
@@ -487,6 +488,11 @@
return error;
}
+Error HidlComposer::hasDisplayIdleTimerCapability(Display, bool*) {
+ LOG_ALWAYS_FATAL("hasDisplayIdleTimerCapability should have never been called on this as "
+ "OptionalFeature::KernelIdleTimer is not supported on HIDL");
+}
+
Error HidlComposer::getHdrCapabilities(Display display, std::vector<Hdr>* outTypes,
float* outMaxLuminance, float* outMaxAverageLuminance,
float* outMinLuminance) {
@@ -1320,6 +1326,11 @@
return Error::UNSUPPORTED;
}
+Error HidlComposer::setIdleTimerEnabled(Display, std::chrono::milliseconds) {
+ LOG_ALWAYS_FATAL("setIdleTimerEnabled should have never been called on this as "
+ "OptionalFeature::KernelIdleTimer is not supported on HIDL");
+}
+
void HidlComposer::registerCallback(ComposerCallback& callback) {
const bool vsyncSwitchingSupported =
isSupported(Hwc2::Composer::OptionalFeature::RefreshRateSwitching);
diff --git a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
index c2b60cb..a1ea4f2 100644
--- a/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/HidlComposerHal.h
@@ -208,6 +208,7 @@
std::vector<uint32_t>* outLayerRequestMasks) override;
Error getDozeSupport(Display display, bool* outSupport) override;
+ Error hasDisplayIdleTimerCapability(Display display, bool* outSupport) override;
Error getHdrCapabilities(Display display, std::vector<Hdr>* outTypes, float* outMaxLuminance,
float* outMaxAverageLuminance, float* outMinLuminance) override;
@@ -331,6 +332,7 @@
Display display,
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
support) override;
+ Error setIdleTimerEnabled(Display displayId, std::chrono::milliseconds timeout) override;
private:
class CommandWriter : public CommandWriterBase {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index e21095a..307da41 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -89,9 +89,6 @@
virtual void dumpAsString(String8& result) const;
virtual void resizeBuffers(const ui::Size&) override;
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
- // Virtual display surface needs to prepare the frame based on composition type. Skip
- // any client composition prediction.
- virtual bool supportsCompositionStrategyPrediction() const override { return false; };
private:
enum Source : size_t {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 81747d5..ec59888 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -618,15 +618,15 @@
}
}
-void SurfaceFrame::tracePredictions(int64_t displayFrameToken) const {
+void SurfaceFrame::tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
- packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+ packet->set_timestamp(static_cast<uint64_t>(mPredictions.startTime + monoBootOffset));
auto* event = packet->set_frame_timeline_event();
auto* expectedSurfaceFrameStartEvent = event->set_expected_surface_frame_start();
@@ -644,8 +644,8 @@
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
- packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+ packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime + monoBootOffset));
auto* event = packet->set_frame_timeline_event();
auto* expectedSurfaceFrameEndEvent = event->set_frame_end();
@@ -654,14 +654,14 @@
});
}
-void SurfaceFrame::traceActuals(int64_t displayFrameToken) const {
+void SurfaceFrame::traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
// Actual timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
// Actual start time is not yet available, so use expected start instead
if (mPredictionState == PredictionState::Expired) {
// If prediction is expired, we can't use the predicted start time. Instead, just use a
@@ -669,11 +669,12 @@
// frame in the trace.
nsecs_t endTime =
(mPresentState == PresentState::Dropped ? mDropTime : mActuals.endTime);
- packet->set_timestamp(
- static_cast<uint64_t>(endTime - kPredictionExpiredStartTimeDelta));
+ packet->set_timestamp(static_cast<uint64_t>(endTime - kPredictionExpiredStartTimeDelta +
+ monoBootOffset));
} else {
- packet->set_timestamp(static_cast<uint64_t>(
- mActuals.startTime == 0 ? mPredictions.startTime : mActuals.startTime));
+ packet->set_timestamp(static_cast<uint64_t>(monoBootOffset + mActuals.startTime == 0
+ ? mPredictions.startTime
+ : mActuals.startTime));
}
auto* event = packet->set_frame_timeline_event();
@@ -706,11 +707,11 @@
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
if (mPresentState == PresentState::Dropped) {
- packet->set_timestamp(static_cast<uint64_t>(mDropTime));
+ packet->set_timestamp(static_cast<uint64_t>(mDropTime + monoBootOffset));
} else {
- packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
+ packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime + monoBootOffset));
}
auto* event = packet->set_frame_timeline_event();
@@ -723,7 +724,7 @@
/**
* TODO(b/178637512): add inputEventId to the perfetto trace.
*/
-void SurfaceFrame::trace(int64_t displayFrameToken) const {
+void SurfaceFrame::trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const {
if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID ||
displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
// No packets can be traced with a missing token.
@@ -732,9 +733,9 @@
if (getPredictionState() != PredictionState::Expired) {
// Expired predictions have zeroed timestamps. This cannot be used in any meaningful way in
// a trace.
- tracePredictions(displayFrameToken);
+ tracePredictions(displayFrameToken, monoBootOffset);
}
- traceActuals(displayFrameToken);
+ traceActuals(displayFrameToken, monoBootOffset);
}
namespace impl {
@@ -760,8 +761,9 @@
}
FrameTimeline::FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
- JankClassificationThresholds thresholds)
- : mMaxDisplayFrames(kDefaultMaxDisplayFrames),
+ JankClassificationThresholds thresholds, bool useBootTimeClock)
+ : mUseBootTimeClock(useBootTimeClock),
+ mMaxDisplayFrames(kDefaultMaxDisplayFrames),
mTimeStats(std::move(timeStats)),
mSurfaceFlingerPid(surfaceFlingerPid),
mJankClassificationThresholds(thresholds) {
@@ -1016,14 +1018,16 @@
}
}
-void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid) const {
+void FrameTimeline::DisplayFrame::tracePredictions(pid_t surfaceFlingerPid,
+ nsecs_t monoBootOffset) const {
int64_t expectedTimelineCookie = mTraceCookieCounter.getCookieForTracing();
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
- packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+ packet->set_timestamp(
+ static_cast<uint64_t>(mSurfaceFlingerPredictions.startTime + monoBootOffset));
auto* event = packet->set_frame_timeline_event();
auto* expectedDisplayFrameStartEvent = event->set_expected_display_frame_start();
@@ -1037,8 +1041,9 @@
// Expected timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
- packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+ packet->set_timestamp(
+ static_cast<uint64_t>(mSurfaceFlingerPredictions.endTime + monoBootOffset));
auto* event = packet->set_frame_timeline_event();
auto* expectedDisplayFrameEndEvent = event->set_frame_end();
@@ -1047,14 +1052,16 @@
});
}
-void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid) const {
+void FrameTimeline::DisplayFrame::traceActuals(pid_t surfaceFlingerPid,
+ nsecs_t monoBootOffset) const {
int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
// Actual timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
- packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.startTime));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+ packet->set_timestamp(
+ static_cast<uint64_t>(mSurfaceFlingerActuals.startTime + monoBootOffset));
auto* event = packet->set_frame_timeline_event();
auto* actualDisplayFrameStartEvent = event->set_actual_display_frame_start();
@@ -1075,8 +1082,9 @@
// Actual timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
- packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
- packet->set_timestamp(static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime));
+ packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME);
+ packet->set_timestamp(
+ static_cast<uint64_t>(mSurfaceFlingerActuals.presentTime + monoBootOffset));
auto* event = packet->set_frame_timeline_event();
auto* actualDisplayFrameEndEvent = event->set_frame_end();
@@ -1085,7 +1093,7 @@
});
}
-void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const {
+void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const {
if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
// DisplayFrame should not have an invalid token.
ALOGE("Cannot trace DisplayFrame with invalid token");
@@ -1095,12 +1103,12 @@
if (mPredictionState == PredictionState::Valid) {
// Expired and unknown predictions have zeroed timestamps. This cannot be used in any
// meaningful way in a trace.
- tracePredictions(surfaceFlingerPid);
+ tracePredictions(surfaceFlingerPid, monoBootOffset);
}
- traceActuals(surfaceFlingerPid);
+ traceActuals(surfaceFlingerPid, monoBootOffset);
for (auto& surfaceFrame : mSurfaceFrames) {
- surfaceFrame->trace(mToken);
+ surfaceFrame->trace(mToken, monoBootOffset);
}
}
@@ -1164,6 +1172,12 @@
}
void FrameTimeline::flushPendingPresentFences() {
+ // Perfetto is using boottime clock to void drifts when the device goes
+ // to suspend.
+ const auto monoBootOffset = mUseBootTimeClock
+ ? (systemTime(SYSTEM_TIME_BOOTTIME) - systemTime(SYSTEM_TIME_MONOTONIC))
+ : 0;
+
for (size_t i = 0; i < mPendingPresentFences.size(); i++) {
const auto& pendingPresentFence = mPendingPresentFences[i];
nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID;
@@ -1175,7 +1189,7 @@
}
auto& displayFrame = pendingPresentFence.second;
displayFrame->onPresent(signalTime, mPreviousPresentTime);
- displayFrame->trace(mSurfaceFlingerPid);
+ displayFrame->trace(mSurfaceFlingerPid, monoBootOffset);
mPreviousPresentTime = signalTime;
mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 36d6290..a2305af 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -204,8 +204,9 @@
std::string miniDump() const;
// Emits a packet for perfetto tracing. The function body will be executed only if tracing is
// enabled. The displayFrameToken is needed to link the SurfaceFrame to the corresponding
- // DisplayFrame at the trace processor side.
- void trace(int64_t displayFrameToken) const;
+ // DisplayFrame at the trace processor side. monoBootOffset is the difference
+ // between SYSTEM_TIME_BOOTTIME and SYSTEM_TIME_MONOTONIC.
+ void trace(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
// Getter functions used only by FrameTimelineTests and SurfaceFrame internally
TimelineItem getActuals() const;
@@ -225,8 +226,8 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(2ms).count();
private:
- void tracePredictions(int64_t displayFrameToken) const;
- void traceActuals(int64_t displayFrameToken) const;
+ void tracePredictions(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
+ void traceActuals(int64_t displayFrameToken, nsecs_t monoBootOffset) const;
void classifyJankLocked(int32_t displayFrameJankType, const Fps& refreshRate,
nsecs_t& deadlineDelta) REQUIRES(mMutex);
@@ -369,8 +370,9 @@
// Dumpsys interface - dumps all data irrespective of jank
void dumpAll(std::string& result, nsecs_t baseTime) const;
// Emits a packet for perfetto tracing. The function body will be executed only if tracing
- // is enabled.
- void trace(pid_t surfaceFlingerPid) const;
+ // is enabled. monoBootOffset is the difference between SYSTEM_TIME_BOOTTIME
+ // and SYSTEM_TIME_MONOTONIC.
+ void trace(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
// Sets the token, vsyncPeriod, predictions and SF start time.
void onSfWakeUp(int64_t token, Fps refreshRate, std::optional<TimelineItem> predictions,
nsecs_t wakeUpTime);
@@ -401,8 +403,8 @@
private:
void dump(std::string& result, nsecs_t baseTime) const;
- void tracePredictions(pid_t surfaceFlingerPid) const;
- void traceActuals(pid_t surfaceFlingerPid) const;
+ void tracePredictions(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
+ void traceActuals(pid_t surfaceFlingerPid, nsecs_t monoBootOffset) const;
void classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
nsecs_t previousPresentTime);
@@ -442,7 +444,7 @@
};
FrameTimeline(std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid,
- JankClassificationThresholds thresholds = {});
+ JankClassificationThresholds thresholds = {}, bool useBootTimeClock = true);
~FrameTimeline() = default;
frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
@@ -484,6 +486,7 @@
TokenManager mTokenManager;
TraceCookieCounter mTraceCookieCounter;
mutable std::mutex mMutex;
+ const bool mUseBootTimeClock;
uint32_t mMaxDisplayFrames;
std::shared_ptr<TimeStats> mTimeStats;
const pid_t mSurfaceFlingerPid;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2b5e337..0fb16f2 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1049,7 +1049,7 @@
mutable bool mDrawingStateModified = false;
sp<Fence> mLastClientCompositionFence;
- bool mLastClientCompositionDisplayed = false;
+ bool mAlreadyDisplayedThisCompose = false;
private:
virtual void setTransformHint(ui::Transform::RotationFlags) {}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 15e30b3..65c8613 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -670,9 +670,9 @@
}
void RefreshRateConfigs::initializeIdleTimer() {
- if (mConfig.idleTimerTimeoutMs > 0) {
+ if (mConfig.idleTimerTimeout > 0ms) {
mIdleTimer.emplace(
- "IdleTimer", std::chrono::milliseconds(mConfig.idleTimerTimeoutMs),
+ "IdleTimer", mConfig.idleTimerTimeout,
[this] {
std::scoped_lock lock(mIdleTimerCallbacksMutex);
if (const auto callbacks = getIdleTimerCallbacks()) {
@@ -963,12 +963,24 @@
base::StringAppendF(&result, "Supports Frame Rate Override By Content: %s\n",
mSupportsFrameRateOverrideByContent ? "yes" : "no");
- base::StringAppendF(&result, "Idle timer: (%s) %s\n",
- mConfig.supportKernelIdleTimer ? "kernel" : "platform",
- mIdleTimer ? mIdleTimer->dump().c_str() : "off");
+ base::StringAppendF(&result, "Idle timer: ");
+ if (mConfig.kernelIdleTimerController.has_value()) {
+ if (mConfig.kernelIdleTimerController == KernelIdleTimerController::Sysprop) {
+ base::StringAppendF(&result, "(kernel(sysprop))");
+ } else {
+ base::StringAppendF(&result, "(kernel(hwc))");
+ }
+ } else {
+ base::StringAppendF(&result, "(platform)");
+ }
+ base::StringAppendF(&result, " %s\n", mIdleTimer ? mIdleTimer->dump().c_str() : "off");
result.append("\n");
}
+std::chrono::milliseconds RefreshRateConfigs::getIdleTimerTimeout() {
+ return mConfig.idleTimerTimeout;
+}
+
} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 14583e3..30d3edd 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -272,6 +272,8 @@
// Returns a known frame rate that is the closest to frameRate
Fps findClosestKnownFrameRate(Fps frameRate) const;
+ enum class KernelIdleTimerController { Sysprop, HwcApi };
+
// Configuration flags.
struct Config {
bool enableFrameRateOverride = false;
@@ -282,17 +284,18 @@
int frameRateMultipleThreshold = 0;
// The Idle Timer timeout. 0 timeout means no idle timer.
- int32_t idleTimerTimeoutMs = 0;
+ std::chrono::milliseconds idleTimerTimeout = 0ms;
- // Whether to use idle timer callbacks that support the kernel timer.
- bool supportKernelIdleTimer = false;
+ // The controller representing how the kernel idle timer will be configured
+ // either on the HWC api or sysprop.
+ std::optional<KernelIdleTimerController> kernelIdleTimerController;
};
RefreshRateConfigs(const DisplayModes&, DisplayModeId,
Config config = {.enableFrameRateOverride = false,
.frameRateMultipleThreshold = 0,
- .idleTimerTimeoutMs = 0,
- .supportKernelIdleTimer = false});
+ .idleTimerTimeout = 0ms,
+ .kernelIdleTimerController = {}});
RefreshRateConfigs(const RefreshRateConfigs&) = delete;
RefreshRateConfigs& operator=(const RefreshRateConfigs&) = delete;
@@ -310,6 +313,7 @@
TurnOff, // Turn off the idle timer.
TurnOn // Turn on the idle timer.
};
+
// Checks whether kernel idle timer should be active depending the policy decisions around
// refresh rates.
KernelIdleTimerAction getIdleTimerAction() const;
@@ -332,7 +336,9 @@
Fps displayFrameRate, GlobalSignals) const
EXCLUDES(mLock);
- bool supportsKernelIdleTimer() const { return mConfig.supportKernelIdleTimer; }
+ std::optional<KernelIdleTimerController> kernelIdleTimerController() {
+ return mConfig.kernelIdleTimerController;
+ }
struct IdleTimerCallbacks {
struct Callbacks {
@@ -370,7 +376,7 @@
if (!mIdleTimer) {
return;
}
- if (kernelOnly && !mConfig.supportKernelIdleTimer) {
+ if (kernelOnly && !mConfig.kernelIdleTimerController.has_value()) {
return;
}
mIdleTimer->reset();
@@ -378,6 +384,8 @@
void dump(std::string& result) const EXCLUDES(mLock);
+ std::chrono::milliseconds getIdleTimerTimeout();
+
private:
friend struct TestableRefreshRateConfigs;
@@ -437,8 +445,8 @@
std::optional<IdleTimerCallbacks::Callbacks> getIdleTimerCallbacks() const
REQUIRES(mIdleTimerCallbacksMutex) {
if (!mIdleTimerCallbacks) return {};
- return mConfig.supportKernelIdleTimer ? mIdleTimerCallbacks->kernel
- : mIdleTimerCallbacks->platform;
+ return mConfig.kernelIdleTimerController.has_value() ? mIdleTimerCallbacks->kernel
+ : mIdleTimerCallbacks->platform;
}
// The list of refresh rates, indexed by display modes ID. This may change after this
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index efaa975..425b78b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -169,6 +169,8 @@
using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
using aidl::android::hardware::graphics::composer3::Capability;
using aidl::android::hardware::graphics::composer3::DisplayCapability;
+using KernelIdleTimerController =
+ ::android::scheduler::RefreshRateConfigs::KernelIdleTimerController;
namespace android {
@@ -270,39 +272,33 @@
return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3;
}
-
-struct IdleTimerConfig {
- int32_t timeoutMs;
- bool supportKernelIdleTimer;
-};
-
-IdleTimerConfig getIdleTimerConfiguration(DisplayId displayId) {
- // TODO(adyabr): use ro.surface_flinger.* namespace
-
+std::chrono::milliseconds getIdleTimerTimeout(DisplayId displayId) {
const auto displayIdleTimerMsKey = [displayId] {
std::stringstream ss;
ss << "debug.sf.set_idle_timer_ms_" << displayId.value;
return ss.str();
}();
+ const int32_t displayIdleTimerMs = base::GetIntProperty(displayIdleTimerMsKey, 0);
+ if (displayIdleTimerMs > 0) {
+ return std::chrono::milliseconds(displayIdleTimerMs);
+ }
+
+ const int32_t setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms", 0);
+ const int32_t millis = setIdleTimerMs ? setIdleTimerMs : sysprop::set_idle_timer_ms(0);
+ return std::chrono::milliseconds(millis);
+}
+
+bool getKernelIdleTimerSyspropConfig(DisplayId displayId) {
const auto displaySupportKernelIdleTimerKey = [displayId] {
std::stringstream ss;
ss << "debug.sf.support_kernel_idle_timer_" << displayId.value;
return ss.str();
}();
- const int32_t displayIdleTimerMs = base::GetIntProperty(displayIdleTimerMsKey, 0);
const auto displaySupportKernelIdleTimer =
base::GetBoolProperty(displaySupportKernelIdleTimerKey, false);
-
- if (displayIdleTimerMs > 0) {
- return {displayIdleTimerMs, displaySupportKernelIdleTimer};
- }
-
- const int32_t setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms", 0);
- const int32_t millis = setIdleTimerMs ? setIdleTimerMs : sysprop::set_idle_timer_ms(0);
-
- return {millis, sysprop::support_kernel_idle_timer(false)};
+ return displaySupportKernelIdleTimer || sysprop::support_kernel_idle_timer(false);
}
} // namespace anonymous
@@ -480,9 +476,6 @@
property_get("debug.sf.disable_client_composition_cache", value, "0");
mDisableClientCompositionCache = atoi(value);
- property_get("debug.sf.predict_hwc_composition_strategy", value, "0");
- mPredictCompositionStrategy = atoi(value);
-
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
// comes online to attempt to read the property. The property is
@@ -2832,14 +2825,15 @@
creationArgs.connectionType = physical->type;
creationArgs.supportedModes = physical->supportedModes;
creationArgs.activeModeId = physical->activeMode->getId();
- const auto [idleTimerTimeoutMs, supportKernelIdleTimer] =
- getIdleTimerConfiguration(compositionDisplay->getId());
+ const auto [kernelIdleTimerController, idleTimerTimeoutMs] =
+ getKernelIdleTimerProperties(compositionDisplay->getId());
+
scheduler::RefreshRateConfigs::Config config =
{.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
.frameRateMultipleThreshold =
base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0),
- .idleTimerTimeoutMs = idleTimerTimeoutMs,
- .supportKernelIdleTimer = supportKernelIdleTimer};
+ .idleTimerTimeout = idleTimerTimeoutMs,
+ .kernelIdleTimerController = kernelIdleTimerController};
creationArgs.refreshRateConfigs =
std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes,
creationArgs.activeModeId, config);
@@ -3413,7 +3407,7 @@
features);
{
auto configs = display->holdRefreshRateConfigs();
- if (configs->supportsKernelIdleTimer()) {
+ if (configs->kernelIdleTimerController().has_value()) {
features |= Feature::kKernelIdleTimer;
}
@@ -6151,6 +6145,47 @@
}));
}
+std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
+SurfaceFlinger::getKernelIdleTimerProperties(DisplayId displayId) {
+ const bool isKernelIdleTimerHwcSupported = getHwComposer().getComposer()->isSupported(
+ android::Hwc2::Composer::OptionalFeature::KernelIdleTimer);
+ const auto timeout = getIdleTimerTimeout(displayId);
+ if (isKernelIdleTimerHwcSupported) {
+ if (const auto id = PhysicalDisplayId::tryCast(displayId);
+ getHwComposer().hasDisplayIdleTimerCapability(*id)) {
+ // In order to decide if we can use the HWC api for idle timer
+ // we query DisplayCapability::DISPLAY_IDLE_TIMER directly on the composer
+ // without relying on hasDisplayCapability.
+ // hasDisplayCapability relies on DisplayCapabilities
+ // which are updated after we set the PowerMode::ON.
+ // DISPLAY_IDLE_TIMER is a display driver property
+ // and is available before the PowerMode::ON
+ return {KernelIdleTimerController::HwcApi, timeout};
+ }
+ return {std::nullopt, timeout};
+ }
+ if (getKernelIdleTimerSyspropConfig(displayId)) {
+ return {KernelIdleTimerController::Sysprop, timeout};
+ }
+
+ return {std::nullopt, timeout};
+}
+
+void SurfaceFlinger::updateKernelIdleTimer(std::chrono::milliseconds timeout,
+ KernelIdleTimerController controller,
+ PhysicalDisplayId displayId) {
+ switch (controller) {
+ case KernelIdleTimerController::HwcApi: {
+ getHwComposer().setIdleTimerEnabled(displayId, timeout);
+ break;
+ }
+ case KernelIdleTimerController::Sysprop: {
+ base::SetProperty(KERNEL_IDLE_TIMER_PROP, timeout > 0ms ? "true" : "false");
+ break;
+ }
+ }
+}
+
void SurfaceFlinger::toggleKernelIdleTimer() {
using KernelIdleTimerAction = scheduler::RefreshRateConfigs::KernelIdleTimerAction;
@@ -6162,23 +6197,31 @@
// If the support for kernel idle timer is disabled for the active display,
// don't do anything.
- if (!display->refreshRateConfigs().supportsKernelIdleTimer()) {
+ const std::optional<KernelIdleTimerController> kernelIdleTimerController =
+ display->refreshRateConfigs().kernelIdleTimerController();
+ if (!kernelIdleTimerController.has_value()) {
return;
}
const KernelIdleTimerAction action = display->refreshRateConfigs().getIdleTimerAction();
+
switch (action) {
case KernelIdleTimerAction::TurnOff:
if (mKernelIdleTimerEnabled) {
ATRACE_INT("KernelIdleTimer", 0);
- base::SetProperty(KERNEL_IDLE_TIMER_PROP, "false");
+ std::chrono::milliseconds constexpr kTimerDisabledTimeout = 0ms;
+ updateKernelIdleTimer(kTimerDisabledTimeout, kernelIdleTimerController.value(),
+ display->getPhysicalId());
mKernelIdleTimerEnabled = false;
}
break;
case KernelIdleTimerAction::TurnOn:
if (!mKernelIdleTimerEnabled) {
ATRACE_INT("KernelIdleTimer", 1);
- base::SetProperty(KERNEL_IDLE_TIMER_PROP, "true");
+ const std::chrono::milliseconds timeout =
+ display->refreshRateConfigs().getIdleTimerTimeout();
+ updateKernelIdleTimer(timeout, kernelIdleTimerController.value(),
+ display->getPhysicalId());
mKernelIdleTimerEnabled = true;
}
break;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 86c8333..fa65803 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -344,11 +344,6 @@
void disableExpensiveRendering();
FloatRect getMaxDisplayBounds();
- // If set, composition engine tries to predict the composition strategy provided by HWC
- // based on the previous frame. If the strategy can be predicted, gpu composition will
- // run parallel to the hwc validateDisplay call and re-run if the predition is incorrect.
- bool mPredictCompositionStrategy = false;
-
protected:
// We're reference counted, never destroy SurfaceFlinger directly
virtual ~SurfaceFlinger();
@@ -467,6 +462,8 @@
};
using ActiveModeInfo = DisplayDevice::ActiveModeInfo;
+ using KernelIdleTimerController =
+ ::android::scheduler::RefreshRateConfigs::KernelIdleTimerController;
enum class BootStage {
BOOTLOADER,
@@ -690,6 +687,14 @@
void triggerOnFrameRateOverridesChanged() override;
// Toggles the kernel idle timer on or off depending the policy decisions around refresh rates.
void toggleKernelIdleTimer() REQUIRES(mStateLock);
+ // Get the controller and timeout that will help decide how the kernel idle timer will be
+ // configured and what value to use as the timeout.
+ std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds>
+ getKernelIdleTimerProperties(DisplayId) REQUIRES(mStateLock);
+ // Updates the kernel idle timer either through HWC or through sysprop
+ // depending on which controller is provided
+ void updateKernelIdleTimer(std::chrono::milliseconds timeoutMs, KernelIdleTimerController,
+ PhysicalDisplayId) REQUIRES(mStateLock);
// Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
// make calls to sys prop each time.
bool mKernelIdleTimerEnabled = false;
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 834a560..f1efa92 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -66,9 +66,10 @@
}
void SetUp() override {
+ constexpr bool kUseBootTimeClock = true;
mTimeStats = std::make_shared<mock::TimeStats>();
mFrameTimeline = std::make_unique<impl::FrameTimeline>(mTimeStats, kSurfaceFlingerPid,
- kTestThresholds);
+ kTestThresholds, !kUseBootTimeClock);
mFrameTimeline->registerDataSource();
mTokenManager = &mFrameTimeline->mTokenManager;
mTraceCookieCounter = &mFrameTimeline->mTraceCookieCounter;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index a1aa7e8..996f835 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -76,6 +76,7 @@
MOCK_METHOD4(getDisplayRequests,
Error(Display, uint32_t*, std::vector<Layer>*, std::vector<uint32_t>*));
MOCK_METHOD2(getDozeSupport, Error(Display, bool*));
+ MOCK_METHOD2(getKernelIdleTimerSupport, Error(Display, bool*));
MOCK_METHOD5(getHdrCapabilities, Error(Display, std::vector<Hdr>*, float*, float*, float*));
MOCK_METHOD1(getPerFrameMetadataKeys,
std::vector<IComposerClient::PerFrameMetadataKey>(Display));
@@ -157,6 +158,8 @@
Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
MOCK_METHOD2(getDisplayDecorationSupport,
Error(Display, std::optional<DisplayDecorationSupport>*));
+ MOCK_METHOD2(setIdleTimerEnabled, Error(Display, std::chrono::milliseconds));
+ MOCK_METHOD2(hasDisplayIdleTimerCapability, Error(Display, bool*));
};
} // namespace Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
index 570ffeb..d9faa06 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockHWC2.h
@@ -99,6 +99,8 @@
hal::Error, getDisplayDecorationSupport,
(std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport> *),
(override));
+ MOCK_METHOD(hal::Error, setIdleTimerEnabled, (std::chrono::milliseconds), (override));
+ MOCK_METHOD(bool, hasDisplayIdleTimerCapability, (), (const override));
};
class Layer : public HWC2::Layer {
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 60c0cb5..8cb1b21 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -632,7 +632,6 @@
switch (ext_bit) {
case ProcHook::KHR_android_surface:
case ProcHook::KHR_surface:
- case ProcHook::KHR_surface_protected_capabilities:
case ProcHook::EXT_swapchain_colorspace:
case ProcHook::KHR_get_surface_capabilities2:
case ProcHook::GOOGLE_surfaceless_query:
@@ -712,7 +711,6 @@
case ProcHook::KHR_external_fence_capabilities:
case ProcHook::KHR_get_surface_capabilities2:
case ProcHook::KHR_surface:
- case ProcHook::KHR_surface_protected_capabilities:
case ProcHook::EXT_debug_report:
case ProcHook::EXT_swapchain_colorspace:
case ProcHook::GOOGLE_surfaceless_query:
@@ -924,12 +922,8 @@
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
std::vector<VkExtensionProperties> loader_extensions;
- loader_extensions.push_back({
- VK_KHR_SURFACE_EXTENSION_NAME,
- VK_KHR_SURFACE_SPEC_VERSION});
loader_extensions.push_back(
- {VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME,
- VK_KHR_SURFACE_PROTECTED_CAPABILITIES_SPEC_VERSION});
+ {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION});
loader_extensions.push_back({
VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
VK_KHR_ANDROID_SURFACE_SPEC_VERSION});
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
index b436db1..f84fc88 100644
--- a/vulkan/libvulkan/driver_gen.cpp
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -571,7 +571,6 @@
if (strcmp(name, "VK_KHR_incremental_present") == 0) return ProcHook::KHR_incremental_present;
if (strcmp(name, "VK_KHR_shared_presentable_image") == 0) return ProcHook::KHR_shared_presentable_image;
if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
- if (strcmp(name, "VK_KHR_surface_protected_capabilities") == 0) return ProcHook::KHR_surface_protected_capabilities;
if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
if (strcmp(name, "VK_ANDROID_external_memory_android_hardware_buffer") == 0) return ProcHook::ANDROID_external_memory_android_hardware_buffer;
if (strcmp(name, "VK_KHR_bind_memory2") == 0) return ProcHook::KHR_bind_memory2;
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
index 079f9cc..6a6c5b3 100644
--- a/vulkan/libvulkan/driver_gen.h
+++ b/vulkan/libvulkan/driver_gen.h
@@ -47,7 +47,6 @@
KHR_incremental_present,
KHR_shared_presentable_image,
KHR_surface,
- KHR_surface_protected_capabilities,
KHR_swapchain,
ANDROID_external_memory_android_hardware_buffer,
KHR_bind_memory2,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 0be4403..20a0aad 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -865,12 +865,6 @@
.supportedUsageFlags;
} break;
- case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
- VkSurfaceProtectedCapabilitiesKHR* protected_caps =
- reinterpret_cast<VkSurfaceProtectedCapabilitiesKHR*>(caps);
- protected_caps->supportsProtected = VK_TRUE;
- } break;
-
default:
// Ignore all other extension structs
break;
diff --git a/vulkan/scripts/driver_generator.py b/vulkan/scripts/driver_generator.py
index af56764..cd25dd8 100644
--- a/vulkan/scripts/driver_generator.py
+++ b/vulkan/scripts/driver_generator.py
@@ -33,7 +33,6 @@
'VK_KHR_incremental_present',
'VK_KHR_shared_presentable_image',
'VK_KHR_surface',
- 'VK_KHR_surface_protected_capabilities',
'VK_KHR_swapchain',
]