Merge "ui: Restore DisplayIdentification_test" into main
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 3e6d2e0..a3e29a8 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -317,7 +317,7 @@
# Only create the tracing instance if persist.mm_events.enabled
# Attempting to remove the tracing instance after it has been created
# will likely fail with EBUSY as it would be in use by traced_probes.
-on post-fs-data && property:persist.mm_events.enabled=true
+on mm_events_property_available && property:persist.mm_events.enabled=true
# Create MM Events Tracing Instance for Kmem Activity Trigger
mkdir /sys/kernel/debug/tracing/instances/mm_events 0755 system system
mkdir /sys/kernel/tracing/instances/mm_events 0755 system system
@@ -402,6 +402,9 @@
chmod 0666 /sys/kernel/debug/tracing/instances/mm_events/per_cpu/cpu23/trace
chmod 0666 /sys/kernel/tracing/instances/mm_events/per_cpu/cpu23/trace
+on property:ro.persistent_properties.ready=true
+ trigger mm_events_property_available
+
# Handle hyp tracing instance
on late-init && property:ro.boot.hypervisor.vm.supported=1
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index aba2319..2f0987f 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -100,9 +100,14 @@
enabled: true,
platform_apis: true,
},
+
+ // TODO: switch from FileDescriptor to ParcelFileDescriptor
ndk: {
enabled: false,
},
+ rust: {
+ enabled: false,
+ },
},
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 3e999c7..6719006 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2089,13 +2089,23 @@
// pile up.
ALOGW("Canceling events for %s because it is unresponsive",
connection->getInputChannelName().c_str());
- if (connection->status == Connection::Status::NORMAL) {
- CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS,
- "application not responding");
- synthesizeCancelationEventsForConnectionLocked(connection, options,
- getWindowHandleLocked(
- connection->getToken()));
+ if (connection->status != Connection::Status::NORMAL) {
+ return;
}
+ CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS,
+ "application not responding");
+
+ sp<WindowInfoHandle> windowHandle;
+ if (!connection->monitor) {
+ windowHandle = getWindowHandleLocked(connection->getToken());
+ if (windowHandle == nullptr) {
+ // The window that is receiving this ANR was removed, so there is no need to generate
+ // cancellations, because the cancellations would have already been generated when
+ // the window was removed.
+ return;
+ }
+ }
+ synthesizeCancelationEventsForConnectionLocked(connection, options, windowHandle);
}
void InputDispatcher::resetNoFocusedWindowTimeoutLocked() {
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 65f69c5..45f09ae 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -23,6 +23,7 @@
#include <optional>
#include <com_android_input_flags.h>
+#include <ftl/enum.h>
#include <input/AccelerationCurve.h>
#include "CursorButtonAccumulator.h"
@@ -136,7 +137,7 @@
dump += StringPrintf(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
dump += StringPrintf(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
dump += StringPrintf(INDENT3 "DisplayId: %s\n", toString(mDisplayId).c_str());
- dump += StringPrintf(INDENT3 "Orientation: %d\n", mOrientation);
+ dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(mOrientation).c_str());
dump += StringPrintf(INDENT3 "ButtonState: 0x%08x\n", mButtonState);
dump += StringPrintf(INDENT3 "Down: %s\n", toString(isPointerDown(mButtonState)));
dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 9e7e956..738517b 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -20,6 +20,7 @@
#include "KeyboardInputMapper.h"
+#include <ftl/enum.h>
#include <ui/Rotation.h>
namespace android {
@@ -143,7 +144,7 @@
dump += INDENT2 "Keyboard Input Mapper:\n";
dumpParameters(dump);
dump += StringPrintf(INDENT3 "KeyboardType: %d\n", mKeyboardType);
- dump += StringPrintf(INDENT3 "Orientation: %d\n", getOrientation());
+ dump += StringPrintf(INDENT3 "Orientation: %s\n", ftl::enum_string(getOrientation()).c_str());
dump += StringPrintf(INDENT3 "KeyDowns: %zu keys currently down\n", mKeyDowns.size());
dump += StringPrintf(INDENT3 "MetaState: 0x%0x\n", mMetaState);
dump += INDENT3 "KeyboardLayoutInfo: ";
diff --git a/services/inputflinger/tests/FakeInputTracingBackend.cpp b/services/inputflinger/tests/FakeInputTracingBackend.cpp
index 1d27107..f4a06f7 100644
--- a/services/inputflinger/tests/FakeInputTracingBackend.cpp
+++ b/services/inputflinger/tests/FakeInputTracingBackend.cpp
@@ -33,18 +33,22 @@
return base::ResultError(ss.str(), BAD_VALUE);
}
+inline auto getId(const trace::TracedEvent& v) {
+ return std::visit([](const auto& event) { return event.id; }, v);
+}
+
} // namespace
// --- VerifyingTrace ---
-void VerifyingTrace::expectKeyDispatchTraced(const KeyEvent& event) {
+void VerifyingTrace::expectKeyDispatchTraced(const KeyEvent& event, int32_t windowId) {
std::scoped_lock lock(mLock);
- mExpectedEvents.emplace_back(event);
+ mExpectedEvents.emplace_back(event, windowId);
}
-void VerifyingTrace::expectMotionDispatchTraced(const MotionEvent& event) {
+void VerifyingTrace::expectMotionDispatchTraced(const MotionEvent& event, int32_t windowId) {
std::scoped_lock lock(mLock);
- mExpectedEvents.emplace_back(event);
+ mExpectedEvents.emplace_back(event, windowId);
}
void VerifyingTrace::verifyExpectedEventsTraced() {
@@ -53,9 +57,9 @@
base::Result<void> result;
mEventTracedCondition.wait_for(lock, TRACE_TIMEOUT, [&]() REQUIRES(mLock) {
- for (const auto& expectedEvent : mExpectedEvents) {
+ for (const auto& [expectedEvent, windowId] : mExpectedEvents) {
std::visit([&](const auto& event)
- REQUIRES(mLock) { result = verifyEventTraced(event); },
+ REQUIRES(mLock) { result = verifyEventTraced(event, windowId); },
expectedEvent);
if (!result.ok()) {
return false;
@@ -72,11 +76,13 @@
void VerifyingTrace::reset() {
std::scoped_lock lock(mLock);
mTracedEvents.clear();
+ mTracedWindowDispatches.clear();
mExpectedEvents.clear();
}
template <typename Event>
-base::Result<void> VerifyingTrace::verifyEventTraced(const Event& expectedEvent) const {
+base::Result<void> VerifyingTrace::verifyEventTraced(const Event& expectedEvent,
+ int32_t expectedWindowId) const {
std::ostringstream msg;
auto tracedEventsIt = mTracedEvents.find(expectedEvent.getId());
@@ -87,6 +93,19 @@
return error(msg);
}
+ auto tracedDispatchesIt =
+ std::find_if(mTracedWindowDispatches.begin(), mTracedWindowDispatches.end(),
+ [&](const WindowDispatchArgs& args) {
+ return args.windowId == expectedWindowId &&
+ getId(args.eventEntry) == expectedEvent.getId();
+ });
+ if (tracedDispatchesIt == mTracedWindowDispatches.end()) {
+ msg << "Expected dispatch of event with ID 0x" << std::hex << expectedEvent.getId()
+ << " to window with ID 0x" << expectedWindowId << " to be traced, but it was not."
+ << "\nExpected event: " << expectedEvent;
+ return error(msg);
+ }
+
return {};
}
@@ -108,4 +127,12 @@
mTrace->mEventTracedCondition.notify_all();
}
+void FakeInputTracingBackend::traceWindowDispatch(const WindowDispatchArgs& args) const {
+ {
+ std::scoped_lock lock(mTrace->mLock);
+ mTrace->mTracedWindowDispatches.push_back(args);
+ }
+ mTrace->mEventTracedCondition.notify_all();
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/FakeInputTracingBackend.h b/services/inputflinger/tests/FakeInputTracingBackend.h
index e5dd546..40ca3a2 100644
--- a/services/inputflinger/tests/FakeInputTracingBackend.h
+++ b/services/inputflinger/tests/FakeInputTracingBackend.h
@@ -39,10 +39,10 @@
VerifyingTrace() = default;
/** Add an expectation for a key event to be traced. */
- void expectKeyDispatchTraced(const KeyEvent& event);
+ void expectKeyDispatchTraced(const KeyEvent& event, int32_t windowId);
/** Add an expectation for a motion event to be traced. */
- void expectMotionDispatchTraced(const MotionEvent& event);
+ void expectMotionDispatchTraced(const MotionEvent& event, int32_t windowId);
/**
* Wait and verify that all expected events are traced.
@@ -59,14 +59,17 @@
std::mutex mLock;
std::condition_variable mEventTracedCondition;
std::unordered_set<uint32_t /*eventId*/> mTracedEvents GUARDED_BY(mLock);
- std::vector<std::variant<KeyEvent, MotionEvent>> mExpectedEvents GUARDED_BY(mLock);
+ using WindowDispatchArgs = trace::InputTracingBackendInterface::WindowDispatchArgs;
+ std::vector<WindowDispatchArgs> mTracedWindowDispatches GUARDED_BY(mLock);
+ std::vector<std::pair<std::variant<KeyEvent, MotionEvent>, int32_t /*windowId*/>>
+ mExpectedEvents GUARDED_BY(mLock);
friend class FakeInputTracingBackend;
// Helper to verify that the given event appears as expected in the trace. If the verification
// fails, the error message describes why.
template <typename Event>
- base::Result<void> verifyEventTraced(const Event&) const REQUIRES(mLock);
+ base::Result<void> verifyEventTraced(const Event&, int32_t windowId) const REQUIRES(mLock);
};
/**
@@ -82,7 +85,7 @@
void traceKeyEvent(const trace::TracedKeyEvent& entry) const override;
void traceMotionEvent(const trace::TracedMotionEvent& entry) const override;
- void traceWindowDispatch(const WindowDispatchArgs& entry) const override {}
+ void traceWindowDispatch(const WindowDispatchArgs& entry) const override;
};
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 1c37da0..4c455f7 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -155,7 +155,7 @@
class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
struct AnrResult {
sp<IBinder> token{};
- gui::Pid pid{gui::Pid::INVALID};
+ std::optional<gui::Pid> pid{};
};
/* Stores data about a user-activity-poke event from the dispatcher. */
struct UserActivityPokeEvent {
@@ -260,7 +260,7 @@
void assertNotifyWindowUnresponsiveWasCalled(std::chrono::nanoseconds timeout,
const sp<IBinder>& expectedToken,
- gui::Pid expectedPid) {
+ std::optional<gui::Pid> expectedPid) {
std::unique_lock lock(mLock);
android::base::ScopedLockAssertion assumeLocked(mLock);
AnrResult result;
@@ -280,7 +280,7 @@
}
void assertNotifyWindowResponsiveWasCalled(const sp<IBinder>& expectedToken,
- gui::Pid expectedPid) {
+ std::optional<gui::Pid> expectedPid) {
std::unique_lock lock(mLock);
android::base::ScopedLockAssertion assumeLocked(mLock);
AnrResult result;
@@ -524,16 +524,14 @@
void notifyWindowUnresponsive(const sp<IBinder>& connectionToken, std::optional<gui::Pid> pid,
const std::string&) override {
std::scoped_lock lock(mLock);
- ASSERT_TRUE(pid.has_value());
- mAnrWindows.push({connectionToken, *pid});
+ mAnrWindows.push({connectionToken, pid});
mNotifyAnr.notify_all();
}
void notifyWindowResponsive(const sp<IBinder>& connectionToken,
std::optional<gui::Pid> pid) override {
std::scoped_lock lock(mLock);
- ASSERT_TRUE(pid.has_value());
- mResponsiveWindows.push({connectionToken, *pid});
+ mResponsiveWindows.push({connectionToken, pid});
mNotifyAnr.notify_all();
}
@@ -1484,11 +1482,12 @@
switch (event->getType()) {
case InputEventType::KEY: {
- gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event));
+ gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event), mInfo.id);
break;
}
case InputEventType::MOTION: {
- gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event));
+ gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event),
+ mInfo.id);
break;
}
default:
@@ -9059,6 +9058,61 @@
mWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
}
+// Send an event to the app and have the app not respond right away. Then remove the app window.
+// When the window is removed, the dispatcher will cancel the events for that window.
+// So InputDispatcher will enqueue ACTION_CANCEL event as well.
+TEST_F(InputDispatcherSingleWindowAnr, AnrAfterWindowRemoval) {
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {WINDOW_LOCATION}));
+
+ const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
+ ASSERT_TRUE(sequenceNum);
+
+ // Remove the window, but the input channel should remain alive.
+ mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
+
+ const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
+ // Since the window was removed, Dispatcher does not know the PID associated with the window
+ // anymore, so the policy is notified without the PID.
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow->getToken(),
+ /*pid=*/std::nullopt);
+
+ mWindow->finishEvent(*sequenceNum);
+ // The cancellation was generated when the window was removed, along with the focus event.
+ mWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+ mWindow->consumeFocusEvent(false);
+ ASSERT_TRUE(mDispatcher->waitForIdle());
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
+}
+
+// Send an event to the app and have the app not respond right away. Wait for the policy to be
+// notified of the unresponsive window, then remove the app window.
+TEST_F(InputDispatcherSingleWindowAnr, AnrFollowedByWindowRemoval) {
+ mDispatcher->notifyMotion(generateMotionArgs(AMOTION_EVENT_ACTION_DOWN,
+ AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {WINDOW_LOCATION}));
+
+ const auto [sequenceNum, _] = mWindow->receiveEvent(); // ACTION_DOWN
+ ASSERT_TRUE(sequenceNum);
+ const std::chrono::duration timeout = mWindow->getDispatchingTimeout(DISPATCHING_TIMEOUT);
+ mFakePolicy->assertNotifyWindowUnresponsiveWasCalled(timeout, mWindow);
+
+ // Remove the window, but the input channel should remain alive.
+ mDispatcher->onWindowInfosChanged({{}, {}, 0, 0});
+
+ mWindow->finishEvent(*sequenceNum);
+ // The cancellation was generated during the ANR, and the window lost focus when it was removed.
+ mWindow->consumeMotionEvent(
+ AllOf(WithMotionAction(ACTION_CANCEL), WithDisplayId(ADISPLAY_ID_DEFAULT)));
+ mWindow->consumeFocusEvent(false);
+ ASSERT_TRUE(mDispatcher->waitForIdle());
+ // Since the window was removed, Dispatcher does not know the PID associated with the window
+ // becoming responsive, so the policy is notified without the PID.
+ mFakePolicy->assertNotifyWindowResponsiveWasCalled(mWindow->getToken(), /*pid=*/std::nullopt);
+}
+
class InputDispatcherMultiWindowAnr : public InputDispatcherTest {
virtual void SetUp() override {
InputDispatcherTest::SetUp();
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index ee6d37b..a0c943b 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -48,7 +48,6 @@
using aidl::android::hardware::power::Boost;
using aidl::android::hardware::power::Mode;
using aidl::android::hardware::power::SessionHint;
-using aidl::android::hardware::power::SessionTag;
using aidl::android::hardware::power::WorkDuration;
PowerAdvisor::~PowerAdvisor() = default;
@@ -207,12 +206,9 @@
bool PowerAdvisor::ensurePowerHintSessionRunning() {
if (mHintSession == nullptr && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
- auto ret =
- getPowerHal().createHintSessionWithConfig(getpid(), static_cast<int32_t>(getuid()),
- mHintSessionThreadIds,
- mTargetDuration.ns(),
- SessionTag::SURFACEFLINGER,
- &mSessionConfig);
+ auto ret = getPowerHal().createHintSession(getpid(), static_cast<int32_t>(getuid()),
+ mHintSessionThreadIds, mTargetDuration.ns());
+
if (ret.isOk()) {
mHintSession = ret.value();
}
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index d6ffb2a..bbe51cc0 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -292,9 +292,6 @@
// Whether we should send reportActualWorkDuration calls
static const bool sUseReportActualDuration;
- // Metadata about the session returned from PowerHAL
- aidl::android::hardware::power::SessionConfig mSessionConfig;
-
// How long we expect hwc to run after the present call until it waits for the fence
static constexpr const Duration kFenceWaitStartDelayValidated{150us};
static constexpr const Duration kFenceWaitStartDelaySkippedValidate{250us};
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index eeca6be..e696e8c 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -855,7 +855,7 @@
ALOGV("Touch Boost");
ATRACE_FORMAT_INSTANT("%s (Touch Boost [late])",
to_string(touchRefreshRates.front().frameRateMode.fps).c_str());
- return {touchRefreshRates, GlobalSignals{.touch = signals.touch}};
+ return {touchRefreshRates, GlobalSignals{.touch = true}};
}
// If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
index 415b0d2..9c66a97 100644
--- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -74,14 +74,12 @@
void PowerAdvisorTest::startPowerHintSession(bool returnValidSession) {
mMockPowerHintSession = ndk::SharedRefBase::make<NiceMock<MockIPowerHintSession>>();
if (returnValidSession) {
- ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
- .WillByDefault(DoAll(SetArgPointee<5>(aidl::android::hardware::power::SessionConfig{
- .id = 12}),
- Return(HalResult<std::shared_ptr<IPowerHintSession>>::
- fromStatus(binder::Status::ok(),
- mMockPowerHintSession))));
+ ON_CALL(*mMockPowerHalController, createHintSession)
+ .WillByDefault(
+ Return(HalResult<std::shared_ptr<IPowerHintSession>>::
+ fromStatus(binder::Status::ok(), mMockPowerHintSession)));
} else {
- ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
+ ON_CALL(*mMockPowerHalController, createHintSession)
.WillByDefault(Return(HalResult<std::shared_ptr<IPowerHintSession>>::
fromStatus(binder::Status::ok(), nullptr)));
}
@@ -285,7 +283,7 @@
}
TEST_F(PowerAdvisorTest, hintSessionOnlyCreatedOnce) {
- EXPECT_CALL(*mMockPowerHalController, createHintSessionWithConfig(_, _, _, _, _, _)).Times(1);
+ EXPECT_CALL(*mMockPowerHalController, createHintSession(_, _, _, _)).Times(1);
mPowerAdvisor->onBootFinished();
startPowerHintSession();
mPowerAdvisor->startPowerHintSession({1, 2, 3});
@@ -337,7 +335,7 @@
return ndk::ScopedAStatus::fromExceptionCode(-127);
});
- ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
+ ON_CALL(*mMockPowerHalController, createHintSession)
.WillByDefault(Return(
HalResult<std::shared_ptr<IPowerHintSession>>::
fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127), nullptr)));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index c03cbd7..39a8aac 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -103,7 +103,7 @@
auto& mutableGetRankedRefreshRatesCache() { return mGetRankedFrameRatesCache; }
auto getRankedFrameRates(const std::vector<LayerRequirement>& layers,
- GlobalSignals signals) const {
+ GlobalSignals signals = {}) const {
const auto result = RefreshRateSelector::getRankedFrameRates(layers, signals);
EXPECT_TRUE(std::is_sorted(result.ranking.begin(), result.ranking.end(),
@@ -1619,10 +1619,11 @@
lr1.name = "ExplicitCategory HighHint";
lr2.vote = LayerVoteType::NoVote;
lr2.name = "NoVote";
- auto actualFrameRateMode = selector.getBestFrameRateMode(layers);
+ auto actualRankedFrameRates = selector.getRankedFrameRates(layers);
// Gets touch boost
- EXPECT_EQ(120_Hz, actualFrameRateMode.fps);
- EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId());
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
// No touch boost, for example a game that uses setFrameRate(30, default compatibility).
lr1.vote = LayerVoteType::ExplicitCategory;
@@ -1631,9 +1632,10 @@
lr2.vote = LayerVoteType::ExplicitDefault;
lr2.desiredRefreshRate = 30_Hz;
lr2.name = "30Hz ExplicitDefault";
- actualFrameRateMode = selector.getBestFrameRateMode(layers);
- EXPECT_EQ(30_Hz, actualFrameRateMode.fps);
- EXPECT_EQ(kModeId30, actualFrameRateMode.modePtr->getId());
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
+ EXPECT_EQ(30_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId30, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitCategory;
lr1.frameRateCategory = FrameRateCategory::HighHint;
@@ -1641,10 +1643,11 @@
lr2.vote = LayerVoteType::ExplicitCategory;
lr2.frameRateCategory = FrameRateCategory::HighHint;
lr2.name = "ExplicitCategory HighHint#2";
- actualFrameRateMode = selector.getBestFrameRateMode(layers);
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
// Gets touch boost
- EXPECT_EQ(120_Hz, actualFrameRateMode.fps);
- EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId());
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitCategory;
lr1.frameRateCategory = FrameRateCategory::HighHint;
@@ -1652,10 +1655,11 @@
lr2.vote = LayerVoteType::ExplicitCategory;
lr2.frameRateCategory = FrameRateCategory::Low;
lr2.name = "ExplicitCategory Low";
- actualFrameRateMode = selector.getBestFrameRateMode(layers);
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
// Gets touch boost
- EXPECT_EQ(120_Hz, actualFrameRateMode.fps);
- EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId());
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitCategory;
lr1.frameRateCategory = FrameRateCategory::HighHint;
@@ -1663,10 +1667,11 @@
lr2.vote = LayerVoteType::ExplicitExactOrMultiple;
lr2.desiredRefreshRate = 30_Hz;
lr2.name = "30Hz ExplicitExactOrMultiple";
- actualFrameRateMode = selector.getBestFrameRateMode(layers);
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
// Gets touch boost
- EXPECT_EQ(120_Hz, actualFrameRateMode.fps);
- EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId());
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
lr1.vote = LayerVoteType::ExplicitCategory;
lr1.frameRateCategory = FrameRateCategory::HighHint;
@@ -1674,14 +1679,17 @@
lr2.vote = LayerVoteType::ExplicitExact;
lr2.desiredRefreshRate = 30_Hz;
lr2.name = "30Hz ExplicitExact";
- actualFrameRateMode = selector.getBestFrameRateMode(layers);
+ actualRankedFrameRates = selector.getRankedFrameRates(layers);
if (selector.supportsAppFrameRateOverrideByContent()) {
// Gets touch boost
- EXPECT_EQ(120_Hz, actualFrameRateMode.fps);
- EXPECT_EQ(kModeId120, actualFrameRateMode.modePtr->getId());
+ EXPECT_EQ(120_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId120,
+ actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_TRUE(actualRankedFrameRates.consideredSignals.touch);
} else {
- EXPECT_EQ(30_Hz, actualFrameRateMode.fps);
- EXPECT_EQ(kModeId30, actualFrameRateMode.modePtr->getId());
+ EXPECT_EQ(30_Hz, actualRankedFrameRates.ranking.front().frameRateMode.fps);
+ EXPECT_EQ(kModeId30, actualRankedFrameRates.ranking.front().frameRateMode.modePtr->getId());
+ EXPECT_FALSE(actualRankedFrameRates.consideredSignals.touch);
}
}
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 10c5848..b059525 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -339,6 +339,61 @@
EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
}
+TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) {
+ mScheduler->registerDisplay(kDisplayId1,
+ std::make_shared<RefreshRateSelector>(kDisplay1Modes,
+ kDisplay1Mode60->getId()));
+
+ using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
+
+ std::vector<RefreshRateSelector::LayerRequirement> layers =
+ std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+
+ // Scenario that is similar to game. Expects no touch boost.
+ lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitDefault;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitDefault";
+ mScheduler->setContentRequirements(layers);
+ auto modeChoices = mScheduler->chooseDisplayModes();
+ ASSERT_EQ(1u, modeChoices.size());
+ auto choice = modeChoices.get(kDisplayId1);
+ ASSERT_TRUE(choice);
+ EXPECT_EQ(choice->get(), DisplayModeChoice({60_Hz, kDisplay1Mode60}, {.touch = false}));
+
+ // Scenario that is similar to video playback and interaction. Expects touch boost.
+ lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitExactOrMultiple;
+ lr2.desiredRefreshRate = 30_Hz;
+ lr2.name = "30Hz ExplicitExactOrMultiple";
+ mScheduler->setContentRequirements(layers);
+ modeChoices = mScheduler->chooseDisplayModes();
+ ASSERT_EQ(1u, modeChoices.size());
+ choice = modeChoices.get(kDisplayId1);
+ ASSERT_TRUE(choice);
+ EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
+
+ // Scenario with explicit category and HighHint. Expects touch boost.
+ lr1.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
+ lr1.frameRateCategory = FrameRateCategory::HighHint;
+ lr1.name = "ExplicitCategory HighHint";
+ lr2.vote = RefreshRateSelector::LayerVoteType::ExplicitCategory;
+ lr2.frameRateCategory = FrameRateCategory::Low;
+ lr2.name = "ExplicitCategory Low";
+ mScheduler->setContentRequirements(layers);
+ modeChoices = mScheduler->chooseDisplayModes();
+ ASSERT_EQ(1u, modeChoices.size());
+ choice = modeChoices.get(kDisplayId1);
+ ASSERT_TRUE(choice);
+ EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, {.touch = true}));
+}
+
TEST_F(SchedulerTest, chooseDisplayModesMultipleDisplays) {
mScheduler->registerDisplay(kDisplayId1,
std::make_shared<RefreshRateSelector>(kDisplay1Modes,
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 892cd19..1314193 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include "vulkan/vulkan_core.h"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <aidl/android/hardware/graphics/common/Dataspace.h>
@@ -158,6 +159,25 @@
}
}
+const static VkColorSpaceKHR colorSpaceSupportedByVkEXTSwapchainColorspace[] = {
+ VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT,
+ VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT,
+ VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT,
+ VK_COLOR_SPACE_BT709_LINEAR_EXT,
+ VK_COLOR_SPACE_BT709_NONLINEAR_EXT,
+ VK_COLOR_SPACE_BT2020_LINEAR_EXT,
+ VK_COLOR_SPACE_HDR10_ST2084_EXT,
+ VK_COLOR_SPACE_HDR10_HLG_EXT,
+ VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT,
+ VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT,
+ VK_COLOR_SPACE_PASS_THROUGH_EXT,
+ VK_COLOR_SPACE_DCI_P3_LINEAR_EXT};
+
+const static VkColorSpaceKHR
+ colorSpaceSupportedByVkEXTSwapchainColorspaceOnFP16SurfaceOnly[] = {
+ VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT,
+ VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT};
+
class TimingInfo {
public:
TimingInfo(const VkPresentTimeGOOGLE* qp, uint64_t nativeFrameId)
@@ -745,16 +765,22 @@
};
if (colorspace_ext) {
- all_formats.emplace_back(VkSurfaceFormatKHR{
- VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_PASS_THROUGH_EXT});
- all_formats.emplace_back(VkSurfaceFormatKHR{
- VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_PASS_THROUGH_EXT});
- all_formats.emplace_back(VkSurfaceFormatKHR{
- VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_BT709_LINEAR_EXT});
- all_formats.emplace_back(VkSurfaceFormatKHR{
- VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
- all_formats.emplace_back(VkSurfaceFormatKHR{
- VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ for (VkColorSpaceKHR colorSpace :
+ colorSpaceSupportedByVkEXTSwapchainColorspace) {
+ if (GetNativeDataspace(colorSpace, GetNativePixelFormat(
+ VK_FORMAT_R8G8B8A8_UNORM)) !=
+ DataSpace::UNKNOWN) {
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_R8G8B8A8_UNORM, colorSpace});
+ }
+
+ if (GetNativeDataspace(colorSpace, GetNativePixelFormat(
+ VK_FORMAT_R8G8B8A8_SRGB)) !=
+ DataSpace::UNKNOWN) {
+ all_formats.emplace_back(
+ VkSurfaceFormatKHR{VK_FORMAT_R8G8B8A8_SRGB, colorSpace});
+ }
+ }
}
// NOTE: Any new formats that are added must be coordinated across different
@@ -766,9 +792,16 @@
all_formats.emplace_back(VkSurfaceFormatKHR{
VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
if (colorspace_ext) {
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_R5G6B5_UNORM_PACK16,
- VK_COLOR_SPACE_PASS_THROUGH_EXT});
+ for (VkColorSpaceKHR colorSpace :
+ colorSpaceSupportedByVkEXTSwapchainColorspace) {
+ if (GetNativeDataspace(
+ colorSpace,
+ GetNativePixelFormat(VK_FORMAT_R5G6B5_UNORM_PACK16)) !=
+ DataSpace::UNKNOWN) {
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R5G6B5_UNORM_PACK16, colorSpace});
+ }
+ }
}
}
@@ -777,18 +810,28 @@
all_formats.emplace_back(VkSurfaceFormatKHR{
VK_FORMAT_R16G16B16A16_SFLOAT, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
if (colorspace_ext) {
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
- VK_COLOR_SPACE_PASS_THROUGH_EXT});
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
- VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT});
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
- VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT});
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_R16G16B16A16_SFLOAT,
- VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ for (VkColorSpaceKHR colorSpace :
+ colorSpaceSupportedByVkEXTSwapchainColorspace) {
+ if (GetNativeDataspace(
+ colorSpace,
+ GetNativePixelFormat(VK_FORMAT_R16G16B16A16_SFLOAT)) !=
+ DataSpace::UNKNOWN) {
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R16G16B16A16_SFLOAT, colorSpace});
+ }
+ }
+
+ for (
+ VkColorSpaceKHR colorSpace :
+ colorSpaceSupportedByVkEXTSwapchainColorspaceOnFP16SurfaceOnly) {
+ if (GetNativeDataspace(
+ colorSpace,
+ GetNativePixelFormat(VK_FORMAT_R16G16B16A16_SFLOAT)) !=
+ DataSpace::UNKNOWN) {
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R16G16B16A16_SFLOAT, colorSpace});
+ }
+ }
}
}
@@ -798,12 +841,16 @@
VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
if (colorspace_ext) {
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
- VK_COLOR_SPACE_PASS_THROUGH_EXT});
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_A2B10G10R10_UNORM_PACK32,
- VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ for (VkColorSpaceKHR colorSpace :
+ colorSpaceSupportedByVkEXTSwapchainColorspace) {
+ if (GetNativeDataspace(
+ colorSpace, GetNativePixelFormat(
+ VK_FORMAT_A2B10G10R10_UNORM_PACK32)) !=
+ DataSpace::UNKNOWN) {
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_A2B10G10R10_UNORM_PACK32, colorSpace});
+ }
+ }
}
}
@@ -836,12 +883,18 @@
VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
VK_COLOR_SPACE_SRGB_NONLINEAR_KHR});
if (colorspace_ext) {
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
- VK_COLOR_SPACE_PASS_THROUGH_EXT});
- all_formats.emplace_back(
- VkSurfaceFormatKHR{VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
- VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT});
+ for (VkColorSpaceKHR colorSpace :
+ colorSpaceSupportedByVkEXTSwapchainColorspace) {
+ if (GetNativeDataspace(
+ colorSpace,
+ GetNativePixelFormat(
+ VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16)) !=
+ DataSpace::UNKNOWN) {
+ all_formats.emplace_back(VkSurfaceFormatKHR{
+ VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
+ colorSpace});
+ }
+ }
}
}