Merge "Pass unique_ptr of InputChannel to Connection" into main
diff --git a/include/android/performance_hint.h b/include/android/performance_hint.h
index 08d339b..3c82d88 100644
--- a/include/android/performance_hint.h
+++ b/include/android/performance_hint.h
@@ -233,11 +233,11 @@
* @param workDuration The {@link AWorkDuration} structure of times the thread group took to
* complete its last task in nanoseconds breaking down into different components.
*
- * The work period start timestamp, actual total duration and actual CPU duration must be
- * positive.
+ * The work period start timestamp and actual total duration must be greater than zero.
*
- * The actual GPU duration must be non-negative. If the actual GPU duration is 0, it means
- * the actual GPU duration is not measured.
+ * The actual CPU and GPU durations must be greater than or equal to zero, and at least one
+ * of them must be greater than zero. When one of them is equal to zero, it means that type
+ * of work was not measured for this workload.
*
* @return 0 on success.
* EINVAL if any duration is an invalid number.
@@ -289,7 +289,8 @@
*
* @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}
* @param actualCpuDurationNanos The actual CPU work duration in nanoseconds. This number must be
- * greater than zero.
+ * greater than or equal to zero. If it is equal to zero, that means the CPU was not
+ * measured.
*/
void AWorkDuration_setActualCpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
int64_t actualCpuDurationNanos) __INTRODUCED_IN(__ANDROID_API_V__);
@@ -299,7 +300,7 @@
*
* @param aWorkDuration The {@link AWorkDuration} created by calling {@link AWorkDuration_create()}.
* @param actualGpuDurationNanos The actual GPU work duration in nanoseconds, the number must be
- * non-negative. If the actual GPU duration is 0, it means the actual GPU duration is
+ * greater than or equal to zero. If it is equal to zero, that means the GPU was not
* measured.
*/
void AWorkDuration_setActualGpuDurationNanos(AWorkDuration* _Nonnull aWorkDuration,
diff --git a/include/ftl/fake_guard.h b/include/ftl/fake_guard.h
index bacd1b2..e601251 100644
--- a/include/ftl/fake_guard.h
+++ b/include/ftl/fake_guard.h
@@ -85,6 +85,5 @@
#define FTL_MAKE_FAKE_GUARD(arg1, arg2, guard, ...) guard
-// The void argument suppresses a warning about zero variadic macro arguments.
#define FTL_FAKE_GUARD(...) \
- FTL_MAKE_FAKE_GUARD(__VA_ARGS__, FTL_FAKE_GUARD2, FTL_FAKE_GUARD1, void)(__VA_ARGS__)
+ FTL_MAKE_FAKE_GUARD(__VA_ARGS__, FTL_FAKE_GUARD2, FTL_FAKE_GUARD1, )(__VA_ARGS__)
diff --git a/include/ftl/small_map.h b/include/ftl/small_map.h
index 49cde7f..83d5967 100644
--- a/include/ftl/small_map.h
+++ b/include/ftl/small_map.h
@@ -107,12 +107,20 @@
template <typename Q, typename W, std::size_t M, typename E>
SmallMap(SmallMap<Q, W, M, E> other) : map_(std::move(other.map_)) {}
+ static constexpr size_type static_capacity() { return N; }
+
size_type max_size() const { return map_.max_size(); }
size_type size() const { return map_.size(); }
bool empty() const { return map_.empty(); }
// Returns whether the map is backed by static or dynamic storage.
- bool dynamic() const { return map_.dynamic(); }
+ bool dynamic() const {
+ if constexpr (static_capacity() > 0) {
+ return map_.dynamic();
+ } else {
+ return true;
+ }
+ }
iterator begin() { return map_.begin(); }
const_iterator begin() const { return cbegin(); }
@@ -171,9 +179,15 @@
return {it, false};
}
- auto& ref = map_.emplace_back(std::piecewise_construct, std::forward_as_tuple(key),
- std::forward_as_tuple(std::forward<Args>(args)...));
- return {&ref, true};
+ decltype(auto) ref_or_it =
+ map_.emplace_back(std::piecewise_construct, std::forward_as_tuple(key),
+ std::forward_as_tuple(std::forward<Args>(args)...));
+
+ if constexpr (static_capacity() > 0) {
+ return {&ref_or_it, true};
+ } else {
+ return {ref_or_it, true};
+ }
}
// Replaces a mapping if it exists, and returns an iterator to it. Returns the end() iterator
diff --git a/include/ftl/small_vector.h b/include/ftl/small_vector.h
index 11294c3..43e9fac 100644
--- a/include/ftl/small_vector.h
+++ b/include/ftl/small_vector.h
@@ -124,30 +124,29 @@
DISPATCH(size_type, size, const)
DISPATCH(bool, empty, const)
- // noexcept to suppress warning about zero variadic macro arguments.
- DISPATCH(iterator, begin, noexcept)
+ DISPATCH(iterator, begin, )
DISPATCH(const_iterator, begin, const)
DISPATCH(const_iterator, cbegin, const)
- DISPATCH(iterator, end, noexcept)
+ DISPATCH(iterator, end, )
DISPATCH(const_iterator, end, const)
DISPATCH(const_iterator, cend, const)
- DISPATCH(reverse_iterator, rbegin, noexcept)
+ DISPATCH(reverse_iterator, rbegin, )
DISPATCH(const_reverse_iterator, rbegin, const)
DISPATCH(const_reverse_iterator, crbegin, const)
- DISPATCH(reverse_iterator, rend, noexcept)
+ DISPATCH(reverse_iterator, rend, )
DISPATCH(const_reverse_iterator, rend, const)
DISPATCH(const_reverse_iterator, crend, const)
- DISPATCH(iterator, last, noexcept)
+ DISPATCH(iterator, last, )
DISPATCH(const_iterator, last, const)
- DISPATCH(reference, front, noexcept)
+ DISPATCH(reference, front, )
DISPATCH(const_reference, front, const)
- DISPATCH(reference, back, noexcept)
+ DISPATCH(reference, back, )
DISPATCH(const_reference, back, const)
reference operator[](size_type i) {
@@ -211,13 +210,13 @@
//
// The last() and end() iterators are invalidated.
//
- DISPATCH(void, pop_back, noexcept)
+ DISPATCH(void, pop_back, )
// Removes all elements.
//
// All iterators are invalidated.
//
- DISPATCH(void, clear, noexcept)
+ DISPATCH(void, clear, )
#undef DISPATCH
diff --git a/libs/ftl/small_map_test.cpp b/libs/ftl/small_map_test.cpp
index 634877f..e96d70d 100644
--- a/libs/ftl/small_map_test.cpp
+++ b/libs/ftl/small_map_test.cpp
@@ -189,9 +189,20 @@
}
}
-TEST(SmallMap, TryEmplace) {
- SmallMap<int, std::string, 3> map;
- using Pair = decltype(map)::value_type;
+template <typename Capacity>
+struct SmallMapTest : testing::Test {
+ static constexpr std::size_t kCapacity = Capacity{}();
+};
+
+template <std::size_t N>
+using Capacity = std::integral_constant<std::size_t, N>;
+
+using Capacities = testing::Types<Capacity<3>, Capacity<0>>;
+TYPED_TEST_SUITE(SmallMapTest, Capacities, );
+
+TYPED_TEST(SmallMapTest, TryEmplace) {
+ SmallMap<int, std::string, TestFixture::kCapacity> map;
+ using Pair = typename decltype(map)::value_type;
{
const auto [it, ok] = map.try_emplace(123, "abc");
@@ -207,14 +218,22 @@
const auto [it, ok] = map.try_emplace(-1);
ASSERT_TRUE(ok);
EXPECT_EQ(*it, Pair(-1, std::string()));
- EXPECT_FALSE(map.dynamic());
+ if constexpr (map.static_capacity() > 0) {
+ EXPECT_FALSE(map.dynamic());
+ } else {
+ EXPECT_TRUE(map.dynamic());
+ }
}
{
// Insertion fails if mapping exists.
const auto [it, ok] = map.try_emplace(42, "!!!");
EXPECT_FALSE(ok);
EXPECT_EQ(*it, Pair(42, "???"));
- EXPECT_FALSE(map.dynamic());
+ if constexpr (map.static_capacity() > 0) {
+ EXPECT_FALSE(map.dynamic());
+ } else {
+ EXPECT_TRUE(map.dynamic());
+ }
}
{
// Insertion at capacity promotes the map.
@@ -240,9 +259,9 @@
} // namespace
-TEST(SmallMap, TryReplace) {
- SmallMap<int, String, 3> map = ftl::init::map(1, "a")(2, "B");
- using Pair = decltype(map)::value_type;
+TYPED_TEST(SmallMapTest, TryReplace) {
+ SmallMap<int, String, TestFixture::kCapacity> map = ftl::init::map(1, "a")(2, "B");
+ using Pair = typename decltype(map)::value_type;
{
// Replacing fails unless mapping exists.
@@ -260,7 +279,12 @@
EXPECT_EQ(*it, Pair(2, "b"));
}
- EXPECT_FALSE(map.dynamic());
+ if constexpr (map.static_capacity() > 0) {
+ EXPECT_FALSE(map.dynamic());
+ } else {
+ EXPECT_TRUE(map.dynamic());
+ }
+
EXPECT_TRUE(map.try_emplace(3, "abc").second);
EXPECT_TRUE(map.try_emplace(4, "d").second);
EXPECT_TRUE(map.dynamic());
@@ -284,9 +308,9 @@
EXPECT_EQ(map, SmallMap(ftl::init::map(4, "d"s)(3, "c"s)(2, "b"s)(1, "a"s)));
}
-TEST(SmallMap, EmplaceOrReplace) {
- SmallMap<int, String, 3> map = ftl::init::map(1, "a")(2, "B");
- using Pair = decltype(map)::value_type;
+TYPED_TEST(SmallMapTest, EmplaceOrReplace) {
+ SmallMap<int, String, TestFixture::kCapacity> map = ftl::init::map(1, "a")(2, "B");
+ using Pair = typename decltype(map)::value_type;
{
// New mapping is emplaced.
@@ -305,7 +329,12 @@
EXPECT_EQ(*it, Pair(2, "b"));
}
- EXPECT_FALSE(map.dynamic());
+ if constexpr (map.static_capacity() > 0) {
+ EXPECT_FALSE(map.dynamic());
+ } else {
+ EXPECT_TRUE(map.dynamic());
+ }
+
EXPECT_FALSE(map.emplace_or_replace(3, "abc").second); // Replace.
EXPECT_TRUE(map.emplace_or_replace(4, "d").second); // Emplace.
EXPECT_TRUE(map.dynamic());
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 2d6838b..d244b1a 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -14,6 +14,7 @@
// Default flags to be used throughout all libraries in inputflinger.
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index e200f8b..2d12574 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -1,4 +1,5 @@
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 582eeeb..6d71acc 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index f954370..ba586d7 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index d207ed1..65f69c5 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -164,8 +164,9 @@
configureOnChangeDisplayInfo(readerConfig);
}
+ // Pointer speed settings depend on display settings.
if (!changes.any() || changes.test(InputReaderConfiguration::Change::POINTER_SPEED) ||
- configurePointerCapture) {
+ changes.test(InputReaderConfiguration::Change::DISPLAY_INFO) || configurePointerCapture) {
configureOnChangePointerSpeed(readerConfig);
}
return out;
@@ -515,7 +516,11 @@
mNewPointerVelocityControl.setCurve(
createAccelerationCurveForPointerSensitivity(config.mousePointerSpeed));
} else {
- mOldPointerVelocityControl.setParameters(config.pointerVelocityControlParameters);
+ mOldPointerVelocityControl.setParameters(
+ (config.displaysWithMousePointerAccelerationDisabled.count(
+ mDisplayId.value_or(ADISPLAY_ID_NONE)) == 0)
+ ? config.pointerVelocityControlParameters
+ : FLAT_VELOCITY_CONTROL_PARAMS);
}
mWheelXVelocityControl.setParameters(config.wheelVelocityControlParameters);
mWheelYVelocityControl.setParameters(config.wheelVelocityControlParameters);
diff --git a/services/inputflinger/reporter/Android.bp b/services/inputflinger/reporter/Android.bp
index b1e1aee..e85a104 100644
--- a/services/inputflinger/reporter/Android.bp
+++ b/services/inputflinger/reporter/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 553cb70..0544757 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"
@@ -44,7 +45,6 @@
"EventHub_test.cpp",
"FakeEventHub.cpp",
"FakeInputReaderPolicy.cpp",
- "FakeInputTracingBackend.cpp",
"FakePointerController.cpp",
"FocusResolver_test.cpp",
"GestureConverter_test.cpp",
diff --git a/services/inputflinger/tests/FakeInputTracingBackend.cpp b/services/inputflinger/tests/FakeInputTracingBackend.cpp
deleted file mode 100644
index 1d27107..0000000
--- a/services/inputflinger/tests/FakeInputTracingBackend.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright 2024 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 "FakeInputTracingBackend.h"
-
-#include <android-base/logging.h>
-#include <utils/Errors.h>
-
-namespace android::inputdispatcher {
-
-namespace {
-
-// Use a larger timeout while waiting for events to be traced, compared to the timeout used while
-// waiting to receive events through the input channel. Events are traced from a separate thread,
-// which does not have the same high thread priority as the InputDispatcher's thread, so the tracer
-// is expected to lag behind the Dispatcher at times.
-constexpr auto TRACE_TIMEOUT = std::chrono::seconds(5);
-
-base::ResultError<> error(const std::ostringstream& ss) {
- return base::ResultError(ss.str(), BAD_VALUE);
-}
-
-} // namespace
-
-// --- VerifyingTrace ---
-
-void VerifyingTrace::expectKeyDispatchTraced(const KeyEvent& event) {
- std::scoped_lock lock(mLock);
- mExpectedEvents.emplace_back(event);
-}
-
-void VerifyingTrace::expectMotionDispatchTraced(const MotionEvent& event) {
- std::scoped_lock lock(mLock);
- mExpectedEvents.emplace_back(event);
-}
-
-void VerifyingTrace::verifyExpectedEventsTraced() {
- std::unique_lock lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- base::Result<void> result;
- mEventTracedCondition.wait_for(lock, TRACE_TIMEOUT, [&]() REQUIRES(mLock) {
- for (const auto& expectedEvent : mExpectedEvents) {
- std::visit([&](const auto& event)
- REQUIRES(mLock) { result = verifyEventTraced(event); },
- expectedEvent);
- if (!result.ok()) {
- return false;
- }
- }
- return true;
- });
-
- EXPECT_TRUE(result.ok())
- << "Timed out waiting for all expected events to be traced successfully: "
- << result.error().message();
-}
-
-void VerifyingTrace::reset() {
- std::scoped_lock lock(mLock);
- mTracedEvents.clear();
- mExpectedEvents.clear();
-}
-
-template <typename Event>
-base::Result<void> VerifyingTrace::verifyEventTraced(const Event& expectedEvent) const {
- std::ostringstream msg;
-
- auto tracedEventsIt = mTracedEvents.find(expectedEvent.getId());
- if (tracedEventsIt == mTracedEvents.end()) {
- msg << "Expected event with ID 0x" << std::hex << expectedEvent.getId()
- << " to be traced, but it was not.\n"
- << "Expected event: " << expectedEvent;
- return error(msg);
- }
-
- return {};
-}
-
-// --- FakeInputTracingBackend ---
-
-void FakeInputTracingBackend::traceKeyEvent(const trace::TracedKeyEvent& event) const {
- {
- std::scoped_lock lock(mTrace->mLock);
- mTrace->mTracedEvents.emplace(event.id);
- }
- mTrace->mEventTracedCondition.notify_all();
-}
-
-void FakeInputTracingBackend::traceMotionEvent(const trace::TracedMotionEvent& event) const {
- {
- std::scoped_lock lock(mTrace->mLock);
- mTrace->mTracedEvents.emplace(event.id);
- }
- mTrace->mEventTracedCondition.notify_all();
-}
-
-} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/FakeInputTracingBackend.h b/services/inputflinger/tests/FakeInputTracingBackend.h
deleted file mode 100644
index e5dd546..0000000
--- a/services/inputflinger/tests/FakeInputTracingBackend.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2024 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 "../dispatcher/trace/InputTracingBackendInterface.h"
-
-#include <android-base/result.h>
-#include <android-base/thread_annotations.h>
-#include <gtest/gtest.h>
-#include <input/Input.h>
-#include <condition_variable>
-#include <memory>
-#include <mutex>
-#include <unordered_set>
-#include <vector>
-
-namespace android::inputdispatcher {
-
-/**
- * A class representing an input trace, used to make assertions on what was traced by
- * InputDispatcher in tests. This class is thread-safe.
- */
-class VerifyingTrace {
-public:
- VerifyingTrace() = default;
-
- /** Add an expectation for a key event to be traced. */
- void expectKeyDispatchTraced(const KeyEvent& event);
-
- /** Add an expectation for a motion event to be traced. */
- void expectMotionDispatchTraced(const MotionEvent& event);
-
- /**
- * Wait and verify that all expected events are traced.
- * This is a lenient verifier that does not expect the events to be traced in the order
- * that the events were expected, and does not fail if there are events that are traced that
- * were not expected. Verifying does not clear the expectations.
- */
- void verifyExpectedEventsTraced();
-
- /** Reset the trace and clear all expectations. */
- void reset();
-
-private:
- 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);
-
- 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);
-};
-
-/**
- * A backend implementation for input tracing that records events to the provided
- * VerifyingTrace used for testing.
- */
-class FakeInputTracingBackend : public trace::InputTracingBackendInterface {
-public:
- FakeInputTracingBackend(std::shared_ptr<VerifyingTrace> trace) : mTrace(trace) {}
-
-private:
- std::shared_ptr<VerifyingTrace> mTrace;
-
- void traceKeyEvent(const trace::TracedKeyEvent& entry) const override;
- void traceMotionEvent(const trace::TracedMotionEvent& 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 e826ddc..163eab0 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -17,7 +17,6 @@
#include "../dispatcher/InputDispatcher.h"
#include "../BlockingQueue.h"
#include "FakeApplicationHandle.h"
-#include "FakeInputTracingBackend.h"
#include "TestEventMatchers.h"
#include <NotifyArgsBuilders.h>
@@ -659,22 +658,14 @@
// --- InputDispatcherTest ---
-// The trace is a global variable for now, to avoid having to pass it into all of the
-// FakeWindowHandles created throughout the tests.
-// TODO(b/210460522): Update the tests to avoid the need to have the trace be a global variable.
-static std::shared_ptr<VerifyingTrace> gVerifyingTrace = std::make_shared<VerifyingTrace>();
-
class InputDispatcherTest : public testing::Test {
protected:
std::unique_ptr<FakeInputDispatcherPolicy> mFakePolicy;
std::unique_ptr<InputDispatcher> mDispatcher;
void SetUp() override {
- gVerifyingTrace->reset();
mFakePolicy = std::make_unique<FakeInputDispatcherPolicy>();
- mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy,
- std::make_unique<FakeInputTracingBackend>(
- gVerifyingTrace));
+ mDispatcher = std::make_unique<InputDispatcher>(*mFakePolicy, nullptr);
mDispatcher->setInputDispatchMode(/*enabled=*/true, /*frozen=*/false);
// Start InputDispatcher thread
@@ -685,7 +676,6 @@
ASSERT_EQ(OK, mDispatcher->stop());
mFakePolicy.reset();
mDispatcher.reset();
- ASSERT_NO_FATAL_FAILURE(gVerifyingTrace->verifyExpectedEventsTraced());
}
/**
@@ -1405,7 +1395,11 @@
}
std::pair<std::optional<uint32_t>, std::unique_ptr<InputEvent>> receiveEvent() {
- return receive();
+ if (mInputReceiver == nullptr) {
+ ADD_FAILURE() << "Invalid receive event on window with no receiver";
+ return std::make_pair(std::nullopt, nullptr);
+ }
+ return mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
}
void finishEvent(uint32_t sequenceNum) {
@@ -1450,7 +1444,6 @@
static std::atomic<int32_t> sId; // each window gets a unique id, like in surfaceflinger
friend class sp<FakeWindowHandle>;
- // FakeWindowHandle uses this consume method to ensure received events are added to the trace.
std::unique_ptr<InputEvent> consume(std::chrono::milliseconds timeout, bool handled = true) {
if (mInputReceiver == nullptr) {
LOG(FATAL) << "Cannot consume event from a window with no input event receiver";
@@ -1459,40 +1452,8 @@
if (event == nullptr) {
ADD_FAILURE() << "Consume failed: no event";
}
- expectReceivedEventTraced(event);
return event;
}
-
- // FakeWindowHandle uses this receive method to ensure received events are added to the trace.
- std::pair<std::optional<uint32_t /*seq*/>, std::unique_ptr<InputEvent>> receive() {
- if (mInputReceiver == nullptr) {
- ADD_FAILURE() << "Invalid receive event on window with no receiver";
- return std::make_pair(std::nullopt, nullptr);
- }
- auto out = mInputReceiver->receiveEvent(CONSUME_TIMEOUT_EVENT_EXPECTED);
- const auto& [_, event] = out;
- expectReceivedEventTraced(event);
- return std::move(out);
- }
-
- void expectReceivedEventTraced(const std::unique_ptr<InputEvent>& event) {
- if (!event) {
- return;
- }
-
- switch (event->getType()) {
- case InputEventType::KEY: {
- gVerifyingTrace->expectKeyDispatchTraced(static_cast<KeyEvent&>(*event));
- break;
- }
- case InputEventType::MOTION: {
- gVerifyingTrace->expectMotionDispatchTraced(static_cast<MotionEvent&>(*event));
- break;
- }
- default:
- break;
- }
- }
};
std::atomic<int32_t> FakeWindowHandle::sId{1};
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp
index 8a4f6f0..81c3353 100644
--- a/services/inputflinger/tests/fuzzers/Android.bp
+++ b/services/inputflinger/tests/fuzzers/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_input_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"
diff --git a/services/surfaceflinger/Display/DisplayModeRequest.h b/services/surfaceflinger/Display/DisplayModeRequest.h
index d07cdf5..c0e77bb 100644
--- a/services/surfaceflinger/Display/DisplayModeRequest.h
+++ b/services/surfaceflinger/Display/DisplayModeRequest.h
@@ -27,6 +27,9 @@
// Whether to emit DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE.
bool emitEvent = false;
+
+ // Whether to force the request to be applied, even if the mode is unchanged.
+ bool force = false;
};
inline bool operator==(const DisplayModeRequest& lhs, const DisplayModeRequest& rhs) {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 5f20cd9..45f08a4 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -24,6 +24,7 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+#include <common/FlagManager.h>
#include <compositionengine/CompositionEngine.h>
#include <compositionengine/Display.h>
#include <compositionengine/DisplayColorProfile.h>
@@ -214,6 +215,17 @@
bool DisplayDevice::initiateModeChange(display::DisplayModeRequest&& desiredMode,
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline& outTimeline) {
+ // TODO(b/255635711): Flow the DisplayModeRequest through the desired/pending/active states. For
+ // now, `desiredMode` and `mDesiredModeOpt` are one and the same, but the latter is not cleared
+ // until the next `SF::initiateDisplayModeChanges`. However, the desired mode has been consumed
+ // at this point, so clear the `force` flag to prevent an endless loop of `initiateModeChange`.
+ if (FlagManager::getInstance().connected_display()) {
+ std::scoped_lock lock(mDesiredModeLock);
+ if (mDesiredModeOpt) {
+ mDesiredModeOpt->force = false;
+ }
+ }
+
mPendingModeOpt = std::move(desiredMode);
mIsModeSetPending = true;
@@ -517,8 +529,7 @@
}
}
-auto DisplayDevice::setDesiredMode(display::DisplayModeRequest&& desiredMode, bool force)
- -> DesiredModeAction {
+auto DisplayDevice::setDesiredMode(display::DisplayModeRequest&& desiredMode) -> DesiredModeAction {
ATRACE_CALL();
const auto& desiredModePtr = desiredMode.mode.modePtr;
@@ -526,20 +537,26 @@
LOG_ALWAYS_FATAL_IF(getPhysicalId() != desiredModePtr->getPhysicalDisplayId(),
"DisplayId mismatch");
- ALOGV("%s(%s)", __func__, to_string(*desiredModePtr).c_str());
+ // TODO (b/318533819): Stringize DisplayModeRequest.
+ ALOGD("%s(%s, force=%s)", __func__, to_string(*desiredModePtr).c_str(),
+ desiredMode.force ? "true" : "false");
std::scoped_lock lock(mDesiredModeLock);
if (mDesiredModeOpt) {
// A mode transition was already scheduled, so just override the desired mode.
const bool emitEvent = mDesiredModeOpt->emitEvent;
+ const bool force = mDesiredModeOpt->force;
mDesiredModeOpt = std::move(desiredMode);
mDesiredModeOpt->emitEvent |= emitEvent;
+ if (FlagManager::getInstance().connected_display()) {
+ mDesiredModeOpt->force |= force;
+ }
return DesiredModeAction::None;
}
// If the desired mode is already active...
const auto activeMode = refreshRateSelector().getActiveMode();
- if (!force && activeMode.modePtr->getId() == desiredModePtr->getId()) {
+ if (!desiredMode.force && activeMode.modePtr->getId() == desiredModePtr->getId()) {
if (activeMode == desiredMode.mode) {
return DesiredModeAction::None;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 4ab6321..edd57cc 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -189,8 +189,7 @@
enum class DesiredModeAction { None, InitiateDisplayModeSwitch, InitiateRenderRateSwitch };
- DesiredModeAction setDesiredMode(display::DisplayModeRequest&&, bool force = false)
- EXCLUDES(mDesiredModeLock);
+ DesiredModeAction setDesiredMode(display::DisplayModeRequest&&) EXCLUDES(mDesiredModeLock);
using DisplayModeRequestOpt = ftl::Optional<display::DisplayModeRequest>;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 704ece5..db66f5b 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -27,6 +27,7 @@
#include "HWC2.h"
#include <android/configuration.h>
+#include <common/FlagManager.h>
#include <ui/Fence.h>
#include <ui/FloatRect.h>
#include <ui/GraphicBuffer.h>
@@ -416,7 +417,19 @@
VsyncPeriodChangeTimeline* outTimeline) {
ALOGV("[%" PRIu64 "] setActiveConfigWithConstraints", mId);
- if (isVsyncPeriodSwitchSupported()) {
+ // FIXME (b/319505580): At least the first config set on an external display must be
+ // `setActiveConfig`, so skip over the block that calls `setActiveConfigWithConstraints`
+ // for simplicity.
+ ui::DisplayConnectionType type = ui::DisplayConnectionType::Internal;
+ const bool connected_display = FlagManager::getInstance().connected_display();
+ if (connected_display) {
+ if (auto err = getConnectionType(&type); err != Error::NONE) {
+ return err;
+ }
+ }
+
+ if (isVsyncPeriodSwitchSupported() &&
+ (!connected_display || type != ui::DisplayConnectionType::External)) {
Hwc2::IComposerClient::VsyncPeriodChangeConstraints hwc2Constraints;
hwc2Constraints.desiredTimeNanos = constraints.desiredTimeNanos;
hwc2Constraints.seamlessRequired = constraints.seamlessRequired;
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index a0c943b..ee6d37b 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -48,6 +48,7 @@
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;
@@ -206,9 +207,12 @@
bool PowerAdvisor::ensurePowerHintSessionRunning() {
if (mHintSession == nullptr && !mHintSessionThreadIds.empty() && usePowerHintSession()) {
- auto ret = getPowerHal().createHintSession(getpid(), static_cast<int32_t>(getuid()),
- mHintSessionThreadIds, mTargetDuration.ns());
-
+ auto ret =
+ getPowerHal().createHintSessionWithConfig(getpid(), static_cast<int32_t>(getuid()),
+ mHintSessionThreadIds,
+ mTargetDuration.ns(),
+ SessionTag::SURFACEFLINGER,
+ &mSessionConfig);
if (ret.isOk()) {
mHintSession = ret.value();
}
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index bbe51cc0..d6ffb2a 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -292,6 +292,9 @@
// 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/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ffda2c5..89a341f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1230,8 +1230,10 @@
return NO_ERROR;
}
-void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& request, bool force) {
- const auto displayId = request.mode.modePtr->getPhysicalDisplayId();
+void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& desiredMode) {
+ const auto mode = desiredMode.mode;
+ const auto displayId = mode.modePtr->getPhysicalDisplayId();
+
ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str());
const auto display = getDisplayDeviceLocked(displayId);
@@ -1240,10 +1242,9 @@
return;
}
- const auto mode = request.mode;
- const bool emitEvent = request.emitEvent;
+ const bool emitEvent = desiredMode.emitEvent;
- switch (display->setDesiredMode(std::move(request), force)) {
+ switch (display->setDesiredMode(std::move(desiredMode))) {
case DisplayDevice::DesiredModeAction::InitiateDisplayModeSwitch:
// DisplayDevice::setDesiredMode updated the render rate, so inform Scheduler.
mScheduler->setRenderRate(displayId,
@@ -1429,7 +1430,8 @@
to_string(displayModePtrOpt->get()->getVsyncRate()).c_str(),
to_string(display->getId()).c_str());
- if (display->getActiveMode() == desiredModeOpt->mode) {
+ if ((!FlagManager::getInstance().connected_display() || !desiredModeOpt->force) &&
+ display->getActiveMode() == desiredModeOpt->mode) {
applyActiveMode(display);
continue;
}
@@ -3284,13 +3286,88 @@
std::vector<HWComposer::HWCDisplayMode> hwcModes;
std::optional<hal::HWConfigId> activeModeHwcIdOpt;
+ const bool isExternalDisplay = FlagManager::getInstance().connected_display() &&
+ getHwComposer().getDisplayConnectionType(displayId) ==
+ ui::DisplayConnectionType::External;
+
int attempt = 0;
constexpr int kMaxAttempts = 3;
do {
hwcModes = getHwComposer().getModes(displayId,
scheduler::RefreshRateSelector::kMinSupportedFrameRate
.getPeriodNsecs());
- activeModeHwcIdOpt = getHwComposer().getActiveMode(displayId).value_opt();
+ const auto activeModeHwcIdExp = getHwComposer().getActiveMode(displayId);
+ activeModeHwcIdOpt = activeModeHwcIdExp.value_opt();
+
+ if (isExternalDisplay &&
+ activeModeHwcIdExp.has_error([](status_t error) { return error == NO_INIT; })) {
+ constexpr nsecs_t k59HzVsyncPeriod = 16949153;
+ constexpr nsecs_t k60HzVsyncPeriod = 16666667;
+
+ // DM sets the initial mode for an external display to 1080p@60, but
+ // this comes after SF creates its own state (including the
+ // DisplayDevice). For now, pick the same mode in order to avoid
+ // inconsistent state and unnecessary mode switching.
+ // TODO (b/318534874): Let DM decide the initial mode.
+ //
+ // Try to find 1920x1080 @ 60 Hz
+ if (const auto iter = std::find_if(hwcModes.begin(), hwcModes.end(),
+ [](const auto& mode) {
+ return mode.width == 1920 &&
+ mode.height == 1080 &&
+ mode.vsyncPeriod == k60HzVsyncPeriod;
+ });
+ iter != hwcModes.end()) {
+ activeModeHwcIdOpt = iter->hwcId;
+ break;
+ }
+
+ // Try to find 1920x1080 @ 59-60 Hz
+ if (const auto iter = std::find_if(hwcModes.begin(), hwcModes.end(),
+ [](const auto& mode) {
+ return mode.width == 1920 &&
+ mode.height == 1080 &&
+ mode.vsyncPeriod >= k60HzVsyncPeriod &&
+ mode.vsyncPeriod <= k59HzVsyncPeriod;
+ });
+ iter != hwcModes.end()) {
+ activeModeHwcIdOpt = iter->hwcId;
+ break;
+ }
+
+ // The display does not support 1080p@60, and this is the last attempt to pick a display
+ // mode. Prefer 60 Hz if available, with the closest resolution to 1080p.
+ if (attempt + 1 == kMaxAttempts) {
+ std::vector<HWComposer::HWCDisplayMode> hwcModeOpts;
+
+ for (const auto& mode : hwcModes) {
+ if (mode.width <= 1920 && mode.height <= 1080 &&
+ mode.vsyncPeriod >= k60HzVsyncPeriod &&
+ mode.vsyncPeriod <= k59HzVsyncPeriod) {
+ hwcModeOpts.push_back(mode);
+ }
+ }
+
+ if (const auto iter = std::max_element(hwcModeOpts.begin(), hwcModeOpts.end(),
+ [](const auto& a, const auto& b) {
+ const auto aSize = a.width * a.height;
+ const auto bSize = b.width * b.height;
+ if (aSize < bSize)
+ return true;
+ else if (aSize == bSize)
+ return a.vsyncPeriod > b.vsyncPeriod;
+ else
+ return false;
+ });
+ iter != hwcModeOpts.end()) {
+ activeModeHwcIdOpt = iter->hwcId;
+ break;
+ }
+
+ // hwcModeOpts was empty, use hwcModes[0] as the last resort
+ activeModeHwcIdOpt = hwcModes[0].hwcId;
+ }
+ }
const auto isActiveMode = [activeModeHwcIdOpt](const HWComposer::HWCDisplayMode& mode) {
return mode.hwcId == activeModeHwcIdOpt;
@@ -3351,6 +3428,10 @@
return pair.second->getHwcId() == activeModeHwcIdOpt;
})->second;
+ if (isExternalDisplay) {
+ ALOGI("External display %s initial mode: {%s}", to_string(displayId).c_str(),
+ to_string(*activeMode).c_str());
+ }
return {modes, activeMode};
}
@@ -3655,6 +3736,27 @@
}
mDisplays.try_emplace(displayToken, std::move(display));
+
+ // For an external display, loadDisplayModes already attempted to select the same mode
+ // as DM, but SF still needs to be updated to match.
+ // TODO (b/318534874): Let DM decide the initial mode.
+ if (const auto& physical = state.physical;
+ mScheduler && physical && FlagManager::getInstance().connected_display()) {
+ const bool isInternalDisplay = mPhysicalDisplays.get(physical->id)
+ .transform(&PhysicalDisplay::isInternal)
+ .value_or(false);
+
+ if (!isInternalDisplay) {
+ auto activeModePtr = physical->activeMode;
+ const auto fps = activeModePtr->getPeakFps();
+
+ setDesiredMode(
+ {.mode = scheduler::FrameRateMode{fps,
+ ftl::as_non_null(std::move(activeModePtr))},
+ .emitEvent = false,
+ .force = true});
+ }
+ }
}
void SurfaceFlinger::processDisplayRemoved(const wp<IBinder>& displayToken) {
@@ -8379,7 +8481,7 @@
return INVALID_OPERATION;
}
- setDesiredMode({std::move(preferredMode), .emitEvent = true}, force);
+ setDesiredMode({std::move(preferredMode), .emitEvent = true, .force = force});
// Update the frameRateOverride list as the display render rate might have changed
if (mScheduler->updateFrameRateOverrides(scheduler::GlobalSignals{}, preferredFps)) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 992bc00..be05797 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -716,7 +716,7 @@
// Show hdr sdr ratio overlay
bool mHdrSdrRatioOverlay = false;
- void setDesiredMode(display::DisplayModeRequest&&, bool force = false) REQUIRES(mStateLock);
+ void setDesiredMode(display::DisplayModeRequest&&) REQUIRES(mStateLock);
status_t setActiveModeFromBackdoor(const sp<display::DisplayToken>&, DisplayModeId, Fps minFps,
Fps maxFps);
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 387d2f2..f26336a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -461,9 +461,11 @@
? IComposerClient::DisplayConnectionType::INTERNAL
: IComposerClient::DisplayConnectionType::EXTERNAL;
+ using ::testing::AtLeast;
EXPECT_CALL(*test->mComposer, getDisplayConnectionType(HWC_DISPLAY_ID, _))
- .WillOnce(DoAll(SetArgPointee<1>(CONNECTION_TYPE),
- Return(hal::V2_4::Error::NONE)));
+ .Times(AtLeast(1))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(CONNECTION_TYPE),
+ Return(hal::V2_4::Error::NONE)));
}
EXPECT_CALL(*test->mComposer, setClientTargetSlotCount(_))
diff --git a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
index 9c66a97..415b0d2 100644
--- a/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/PowerAdvisorTest.cpp
@@ -74,12 +74,14 @@
void PowerAdvisorTest::startPowerHintSession(bool returnValidSession) {
mMockPowerHintSession = ndk::SharedRefBase::make<NiceMock<MockIPowerHintSession>>();
if (returnValidSession) {
- ON_CALL(*mMockPowerHalController, createHintSession)
- .WillByDefault(
- Return(HalResult<std::shared_ptr<IPowerHintSession>>::
- fromStatus(binder::Status::ok(), mMockPowerHintSession)));
+ 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))));
} else {
- ON_CALL(*mMockPowerHalController, createHintSession)
+ ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
.WillByDefault(Return(HalResult<std::shared_ptr<IPowerHintSession>>::
fromStatus(binder::Status::ok(), nullptr)));
}
@@ -283,7 +285,7 @@
}
TEST_F(PowerAdvisorTest, hintSessionOnlyCreatedOnce) {
- EXPECT_CALL(*mMockPowerHalController, createHintSession(_, _, _, _)).Times(1);
+ EXPECT_CALL(*mMockPowerHalController, createHintSessionWithConfig(_, _, _, _, _, _)).Times(1);
mPowerAdvisor->onBootFinished();
startPowerHintSession();
mPowerAdvisor->startPowerHintSession({1, 2, 3});
@@ -335,7 +337,7 @@
return ndk::ScopedAStatus::fromExceptionCode(-127);
});
- ON_CALL(*mMockPowerHalController, createHintSession)
+ ON_CALL(*mMockPowerHalController, createHintSessionWithConfig)
.WillByDefault(Return(
HalResult<std::shared_ptr<IPowerHintSession>>::
fromStatus(ndk::ScopedAStatus::fromExceptionCode(-127), nullptr)));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 8b16a8a..82b4ad0 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -21,9 +21,13 @@
#include "mock/DisplayHardware/MockDisplayMode.h"
#include "mock/MockDisplayModeSpecs.h"
+#include <com_android_graphics_surfaceflinger_flags.h>
+#include <common/test/FlagUtils.h>
#include <ftl/fake_guard.h>
#include <scheduler/Fps.h>
+using namespace com::android::graphics::surfaceflinger;
+
namespace android {
namespace {
@@ -360,6 +364,13 @@
}
TEST_F(DisplayModeSwitchingTest, innerXorOuterDisplay) {
+ SET_FLAG_FOR_TEST(flags::connected_display, true);
+
+ // For the inner display, this is handled by setupHwcHotplugCallExpectations.
+ EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _))
+ .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL),
+ Return(hal::V2_4::Error::NONE)));
+
const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
EXPECT_TRUE(innerDisplay->isPoweredOn());
@@ -429,6 +440,12 @@
}
TEST_F(DisplayModeSwitchingTest, innerAndOuterDisplay) {
+ SET_FLAG_FOR_TEST(flags::connected_display, true);
+
+ // For the inner display, this is handled by setupHwcHotplugCallExpectations.
+ EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _))
+ .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL),
+ Return(hal::V2_4::Error::NONE)));
const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
EXPECT_TRUE(innerDisplay->isPoweredOn());
@@ -512,6 +529,13 @@
}
TEST_F(DisplayModeSwitchingTest, powerOffDuringConcurrentModeSet) {
+ SET_FLAG_FOR_TEST(flags::connected_display, true);
+
+ // For the inner display, this is handled by setupHwcHotplugCallExpectations.
+ EXPECT_CALL(*mComposer, getDisplayConnectionType(kOuterDisplayHwcId, _))
+ .WillOnce(DoAll(SetArgPointee<1>(IComposerClient::DisplayConnectionType::INTERNAL),
+ Return(hal::V2_4::Error::NONE)));
+
const auto [innerDisplay, outerDisplay] = injectOuterDisplay();
EXPECT_TRUE(innerDisplay->isPoweredOn());
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index 3294724..be71dc2 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_haptics_framework",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_native_license"