Merge "CursorInputMapper_test: Verify acceleration updated on display change" into main
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 481c28e..5ee6b15 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1563,6 +1563,13 @@
RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"});
RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"});
+
+ printf("========================================================\n");
+ printf("== ANR Traces\n");
+ printf("========================================================\n");
+
+ AddAnrTraceFiles();
+
printf("========================================================\n");
printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(),
ds.progress_->GetMax(), ds.progress_->GetInitialMax());
diff --git a/cmds/lshal/Timeout.h b/cmds/lshal/Timeout.h
index d97ba89..37f41be 100644
--- a/cmds/lshal/Timeout.h
+++ b/cmds/lshal/Timeout.h
@@ -16,44 +16,83 @@
#pragma once
+#include <condition_variable>
#include <chrono>
-#include <future>
+#include <functional>
+#include <mutex>
+#include <thread>
#include <hidl/Status.h>
-#include <utils/Errors.h>
namespace android {
namespace lshal {
-// Call function on interfaceObject and wait for result until the given timeout has reached.
-// Callback functions pass to timeoutIPC() may be executed after the this function
-// has returned, especially if deadline has been reached. Hence, care must be taken when passing
-// data between the background thread and the main thread. See b/311143089.
+class BackgroundTaskState {
+public:
+ explicit BackgroundTaskState(std::function<void(void)> &&func)
+ : mFunc(std::forward<decltype(func)>(func)) {}
+ void notify() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mFinished = true;
+ lock.unlock();
+ mCondVar.notify_all();
+ }
+ template<class C, class D>
+ bool wait(std::chrono::time_point<C, D> end) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mCondVar.wait_until(lock, end, [this](){ return this->mFinished; });
+ return mFinished;
+ }
+ void operator()() {
+ mFunc();
+ }
+private:
+ std::mutex mMutex;
+ std::condition_variable mCondVar;
+ bool mFinished = false;
+ std::function<void(void)> mFunc;
+};
+
+void *callAndNotify(void *data) {
+ BackgroundTaskState &state = *static_cast<BackgroundTaskState *>(data);
+ state();
+ state.notify();
+ return nullptr;
+}
+
+template<class R, class P>
+bool timeout(std::chrono::duration<R, P> delay, std::function<void(void)> &&func) {
+ auto now = std::chrono::system_clock::now();
+ BackgroundTaskState state{std::forward<decltype(func)>(func)};
+ pthread_t thread;
+ if (pthread_create(&thread, nullptr, callAndNotify, &state)) {
+ std::cerr << "FATAL: could not create background thread." << std::endl;
+ return false;
+ }
+ bool success = state.wait(now + delay);
+ if (!success) {
+ pthread_kill(thread, SIGINT);
+ }
+ pthread_join(thread, nullptr);
+ return success;
+}
+
template<class R, class P, class Function, class I, class... Args>
typename std::invoke_result<Function, I *, Args...>::type
timeoutIPC(std::chrono::duration<R, P> wait, const sp<I> &interfaceObject, Function &&func,
Args &&... args) {
using ::android::hardware::Status;
-
- // Execute on a background thread but do not defer execution.
- auto future =
- std::async(std::launch::async, func, interfaceObject, std::forward<Args>(args)...);
- auto status = future.wait_for(wait);
- if (status == std::future_status::ready) {
- return future.get();
- }
-
- // This future belongs to a background thread that we no longer care about.
- // Putting this in the global list avoids std::future::~future() that may wait for the
- // result to come back.
- // This leaks memory, but lshal is a debugging tool, so this is fine.
- static std::vector<decltype(future)> gDeadPool{};
- gDeadPool.emplace_back(std::move(future));
-
- if (status == std::future_status::timeout) {
+ typename std::result_of<Function(I *, Args...)>::type ret{Status::ok()};
+ auto boundFunc = std::bind(std::forward<Function>(func),
+ interfaceObject.get(), std::forward<Args>(args)...);
+ bool success = timeout(wait, [&ret, &boundFunc] {
+ ret = std::move(boundFunc());
+ });
+ if (!success) {
return Status::fromStatusT(TIMED_OUT);
}
- return Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE, "Illegal future_status");
+ return ret;
}
-} // namespace lshal
-} // namespace android
+
+} // namespace lshal
+} // namespace android
diff --git a/cmds/lshal/main.cpp b/cmds/lshal/main.cpp
index bd5fa32..366c938 100644
--- a/cmds/lshal/main.cpp
+++ b/cmds/lshal/main.cpp
@@ -18,6 +18,5 @@
int main(int argc, char **argv) {
using namespace ::android::lshal;
- // Use _exit() to force terminate background threads in Timeout.h
- _exit(Lshal{}.main(Arg{argc, argv}));
+ return Lshal{}.main(Arg{argc, argv});
}
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index c24f827..cba7c4b 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-#include <chrono>
-#include <future>
-#include <mutex>
-#include "android/hidl/base/1.0/IBase.h"
#define LOG_TAG "Lshal"
#include <android-base/logging.h>
@@ -40,8 +36,6 @@
using namespace testing;
-using std::chrono_literals::operator""ms;
-
using ::android::hidl::base::V1_0::DebugInfo;
using ::android::hidl::base::V1_0::IBase;
using ::android::hidl::manager::V1_0::IServiceManager;
@@ -940,9 +934,12 @@
return hardware::Void();
}));
EXPECT_CALL(*serviceManager, get(_, _))
- .WillRepeatedly(Invoke([&](const hidl_string&, const hidl_string&) -> sp<IBase> {
- return sp<IBase>(service);
- }));
+ .WillRepeatedly(
+ Invoke([&](const hidl_string&, const hidl_string& instance) -> sp<IBase> {
+ int id = getIdFromInstanceName(instance);
+ if (id > inheritanceLevel) return nullptr;
+ return sp<IBase>(service);
+ }));
const std::string expected = "[fake description 0]\n"
"Interface\n"
@@ -960,110 +957,6 @@
EXPECT_EQ("", err.str());
}
-// In SlowService, everything goes slooooooow. Each IPC call will wait for
-// the specified time before calling the callback function or returning.
-class SlowService : public IBase {
-public:
- explicit SlowService(std::chrono::milliseconds wait) : mWait(wait) {}
- android::hardware::Return<void> interfaceDescriptor(interfaceDescriptor_cb cb) override {
- std::this_thread::sleep_for(mWait);
- cb(getInterfaceName(1));
- storeHistory("interfaceDescriptor");
- return hardware::Void();
- }
- android::hardware::Return<void> interfaceChain(interfaceChain_cb cb) override {
- std::this_thread::sleep_for(mWait);
- std::vector<hidl_string> ret;
- ret.push_back(getInterfaceName(1));
- ret.push_back(IBase::descriptor);
- cb(ret);
- storeHistory("interfaceChain");
- return hardware::Void();
- }
- android::hardware::Return<void> getHashChain(getHashChain_cb cb) override {
- std::this_thread::sleep_for(mWait);
- std::vector<hidl_hash> ret;
- ret.push_back(getHashFromId(0));
- ret.push_back(getHashFromId(0xff));
- cb(ret);
- storeHistory("getHashChain");
- return hardware::Void();
- }
- android::hardware::Return<void> debug(const hidl_handle&,
- const hidl_vec<hidl_string>&) override {
- std::this_thread::sleep_for(mWait);
- storeHistory("debug");
- return Void();
- }
-
- template <class R, class P, class Pred>
- bool waitForHistory(std::chrono::duration<R, P> wait, Pred predicate) {
- std::unique_lock<std::mutex> lock(mLock);
- return mCv.wait_for(lock, wait, [&]() { return predicate(mCallHistory); });
- }
-
-private:
- void storeHistory(std::string hist) {
- {
- std::lock_guard<std::mutex> lock(mLock);
- mCallHistory.emplace_back(std::move(hist));
- }
- mCv.notify_all();
- }
-
- const std::chrono::milliseconds mWait;
- std::mutex mLock;
- std::condition_variable mCv;
- // List of functions that have finished being called on this interface.
- std::vector<std::string> mCallHistory;
-};
-
-class TimeoutTest : public ListTest {
-public:
- void setMockServiceManager(sp<IBase> service) {
- EXPECT_CALL(*serviceManager, list(_))
- .WillRepeatedly(Invoke([&](IServiceManager::list_cb cb) {
- std::vector<hidl_string> ret;
- ret.push_back(getInterfaceName(1) + "/default");
- cb(ret);
- return hardware::Void();
- }));
- EXPECT_CALL(*serviceManager, get(_, _))
- .WillRepeatedly(Invoke([&](const hidl_string&, const hidl_string&) -> sp<IBase> {
- return service;
- }));
- }
-};
-
-TEST_F(TimeoutTest, BackgroundThreadIsKept) {
- auto lshalIpcTimeout = 100ms;
- auto serviceIpcTimeout = 200ms;
- lshal->setWaitTimeForTest(lshalIpcTimeout, lshalIpcTimeout);
- sp<SlowService> service = new SlowService(serviceIpcTimeout);
- setMockServiceManager(service);
-
- optind = 1; // mimic Lshal::parseArg()
- EXPECT_NE(0u, mockList->main(createArg({"lshal", "--types=b", "-i", "--neat"})));
- EXPECT_THAT(err.str(), HasSubstr("Skipping \"a.h.foo1@1.0::IFoo/default\""));
- EXPECT_TRUE(service->waitForHistory(serviceIpcTimeout * 5, [](const auto& hist) {
- return hist.size() == 1 && hist[0] == "interfaceChain";
- })) << "The background thread should continue after the main thread moves on, but it is killed";
-}
-
-TEST_F(TimeoutTest, BackgroundThreadDoesNotBlockMainThread) {
- auto lshalIpcTimeout = 100ms;
- auto serviceIpcTimeout = 2000ms;
- auto start = std::chrono::system_clock::now();
- lshal->setWaitTimeForTest(lshalIpcTimeout, lshalIpcTimeout);
- sp<SlowService> service = new SlowService(serviceIpcTimeout);
- setMockServiceManager(service);
-
- optind = 1; // mimic Lshal::parseArg()
- EXPECT_NE(0u, mockList->main(createArg({"lshal", "--types=b", "-i", "--neat"})));
- EXPECT_LE(std::chrono::system_clock::now(), start + 5 * lshalIpcTimeout)
- << "The main thread should not be blocked by the background task";
-}
-
class ListVintfTest : public ListTest {
public:
virtual void SetUp() override {
@@ -1186,6 +1079,5 @@
int main(int argc, char **argv) {
::testing::InitGoogleMock(&argc, argv);
- // Use _exit() to force terminate background threads in Timeout.h
- _exit(RUN_ALL_TESTS());
+ return RUN_ALL_TESTS();
}
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/include/input/InputDevice.h b/include/input/InputDevice.h
index b7751f7..57b659d 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -75,6 +75,17 @@
bool operator!=(const InputDeviceIdentifier&) const = default;
};
+/**
+ * Holds View related behaviors for an InputDevice.
+ */
+struct InputDeviceViewBehavior {
+ /**
+ * The smooth scroll behavior that applies for all source/axis, if defined by the device.
+ * Empty optional if the device has not specified the default smooth scroll behavior.
+ */
+ std::optional<bool> shouldSmoothScroll;
+};
+
/* Types of input device sensors. Keep sync with core/java/android/hardware/Sensor.java */
enum class InputDeviceSensorType : int32_t {
ACCELEROMETER = ASENSOR_TYPE_ACCELEROMETER,
@@ -266,7 +277,8 @@
void initialize(int32_t id, int32_t generation, int32_t controllerNumber,
const InputDeviceIdentifier& identifier, const std::string& alias,
- bool isExternal, bool hasMic, int32_t associatedDisplayId);
+ bool isExternal, bool hasMic, int32_t associatedDisplayId,
+ InputDeviceViewBehavior viewBehavior = {{}});
inline int32_t getId() const { return mId; }
inline int32_t getControllerNumber() const { return mControllerNumber; }
@@ -298,6 +310,8 @@
return mKeyboardLayoutInfo;
}
+ inline const InputDeviceViewBehavior& getViewBehavior() const { return mViewBehavior; }
+
inline void setKeyCharacterMap(const std::shared_ptr<KeyCharacterMap> value) {
mKeyCharacterMap = value;
}
@@ -359,6 +373,8 @@
std::unordered_map<int32_t, InputDeviceLightInfo> mLights;
/* Map from battery ID to battery info */
std::unordered_map<int32_t, InputDeviceBatteryInfo> mBatteries;
+ /** The View related behaviors for the device. */
+ InputDeviceViewBehavior mViewBehavior;
};
/* Types of input device configuration files. */
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index d53e8c6..42dcd3c 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -301,6 +301,15 @@
void copyTo(android::os::InputChannelCore& outChannel) const;
/**
+ * Similar to "copyTo", but it takes ownership of the provided InputChannel (and after this is
+ * called, it destroys it).
+ * @param from the InputChannel that should be converted to InputChannelCore
+ * @param outChannel the pre-allocated InputChannelCore to which to transfer the 'from' channel
+ */
+ static void moveChannel(std::unique_ptr<InputChannel> from,
+ android::os::InputChannelCore& outChannel);
+
+ /**
* The connection token is used to identify the input connection, i.e.
* the pair of input channels that were created simultaneously. Input channels
* are always created in pairs, and the token can be used to find the server-side
@@ -333,7 +342,7 @@
~InputPublisher();
/* Gets the underlying input channel. */
- inline std::shared_ptr<InputChannel> getChannel() const { return mChannel; }
+ inline InputChannel& getChannel() const { return *mChannel; }
/* Publishes a key event to the input channel.
*
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/libs/gui/Choreographer.cpp b/libs/gui/Choreographer.cpp
index 7d37fd3..4518b67 100644
--- a/libs/gui/Choreographer.cpp
+++ b/libs/gui/Choreographer.cpp
@@ -116,7 +116,7 @@
std::lock_guard<std::mutex> _l(gChoreographers.lock);
gChoreographers.ptrs.erase(std::remove_if(gChoreographers.ptrs.begin(),
gChoreographers.ptrs.end(),
- [=](Choreographer* c) { return c == this; }),
+ [=, this](Choreographer* c) { return c == this; }),
gChoreographers.ptrs.end());
// Only poke DisplayManagerGlobal to unregister if we previously registered
// callbacks.
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 38fab9c..7564c26 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -199,7 +199,7 @@
SAFE_PARCEL(output.writeParcelable, trustedPresentationListener);
SAFE_PARCEL(output.writeFloat, currentHdrSdrRatio);
SAFE_PARCEL(output.writeFloat, desiredHdrSdrRatio);
- SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(cachingHint))
+ SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(cachingHint));
return NO_ERROR;
}
@@ -484,6 +484,12 @@
flags &= ~eLayerIsDisplayDecoration;
ALOGE("Stripped attempt to set LayerIsDisplayDecoration in sanitize");
}
+ if ((mask & eCanOccludePresentation) &&
+ !(permissions & Permission::ACCESS_SURFACE_FLINGER)) {
+ flags &= ~eCanOccludePresentation;
+ mask &= ~eCanOccludePresentation;
+ ALOGE("Stripped attempt to set eCanOccludePresentation in sanitize");
+ }
}
if (what & layer_state_t::eInputInfoChanged) {
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 95b2641..9429d2c 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -109,7 +109,8 @@
info.inputConfig == inputConfig && info.displayId == displayId &&
info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
info.applicationInfo == applicationInfo && info.layoutParamsType == layoutParamsType &&
- info.layoutParamsFlags == layoutParamsFlags;
+ info.layoutParamsFlags == layoutParamsFlags &&
+ info.canOccludePresentation == canOccludePresentation;
}
status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
@@ -158,8 +159,9 @@
parcel->write(touchableRegion) ?:
parcel->writeBool(replaceTouchableRegionWithCrop) ?:
parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
- parcel->writeStrongBinder(windowToken);
- parcel->writeStrongBinder(focusTransferTarget);
+ parcel->writeStrongBinder(windowToken) ?:
+ parcel->writeStrongBinder(focusTransferTarget) ?:
+ parcel->writeBool(canOccludePresentation);
// clang-format on
return status;
}
@@ -210,7 +212,8 @@
parcel->readBool(&replaceTouchableRegionWithCrop) ?:
parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?:
parcel->readNullableStrongBinder(&windowToken) ?:
- parcel->readNullableStrongBinder(&focusTransferTarget);
+ parcel->readNullableStrongBinder(&focusTransferTarget) ?:
+ parcel->readBool(&canOccludePresentation);
// clang-format on
@@ -273,6 +276,7 @@
<< "ms, token=" << info.token.get()
<< ", touchOcclusionMode=" << ftl::enum_string(info.touchOcclusionMode) << "\n"
<< transform;
+ if (info.canOccludePresentation) out << " canOccludePresentation";
return out;
}
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 6b8e824..920310e 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -161,6 +161,9 @@
// See SurfaceView scaling behavior for more details.
eIgnoreDestinationFrame = 0x400,
eLayerIsRefreshRateIndicator = 0x800, // REFRESH_RATE_INDICATOR
+ // Sets a property on this layer indicating that its visible region should be considered
+ // when computing TrustedPresentation Thresholds.
+ eCanOccludePresentation = 0x1000,
};
enum {
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index e72fd59..32d60be 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -246,6 +246,10 @@
// any other window.
sp<IBinder> focusTransferTarget;
+ // Sets a property on this window indicating that its visible region should be considered when
+ // computing TrustedPresentation Thresholds.
+ bool canOccludePresentation = false;
+
void setInputConfig(ftl::Flags<InputConfig> config, bool value);
void addTouchableRegion(const Rect& region);
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 8eaff00..0d29b4d 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -374,7 +374,7 @@
out << ", deviceId=" << event.getDeviceId();
out << ", source=" << inputEventSourceToString(event.getSource());
out << ", displayId=" << event.getDisplayId();
- out << ", eventId=" << event.getId();
+ out << ", eventId=0x" << std::hex << event.getId() << std::dec;
out << "}";
return out;
}
@@ -1051,7 +1051,7 @@
out << ", deviceId=" << event.getDeviceId();
out << ", source=" << inputEventSourceToString(event.getSource());
out << ", displayId=" << event.getDisplayId();
- out << ", eventId=" << event.getId();
+ out << ", eventId=0x" << std::hex << event.getId() << std::dec;
out << "}";
return out;
}
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 9c7c0c1..d4dbc45 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -190,14 +190,16 @@
mHasSensor(other.mHasSensor),
mMotionRanges(other.mMotionRanges),
mSensors(other.mSensors),
- mLights(other.mLights) {}
+ mLights(other.mLights),
+ mViewBehavior(other.mViewBehavior) {}
InputDeviceInfo::~InputDeviceInfo() {
}
void InputDeviceInfo::initialize(int32_t id, int32_t generation, int32_t controllerNumber,
const InputDeviceIdentifier& identifier, const std::string& alias,
- bool isExternal, bool hasMic, int32_t associatedDisplayId) {
+ bool isExternal, bool hasMic, int32_t associatedDisplayId,
+ InputDeviceViewBehavior viewBehavior) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
@@ -212,6 +214,7 @@
mHasBattery = false;
mHasButtonUnderPad = false;
mHasSensor = false;
+ mViewBehavior = viewBehavior;
mUsiVersion.reset();
mMotionRanges.clear();
mSensors.clear();
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 0e0e80d..e49f4eb 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -584,6 +584,13 @@
outChannel.token = getConnectionToken();
}
+void InputChannel::moveChannel(std::unique_ptr<InputChannel> from,
+ android::os::InputChannelCore& outChannel) {
+ outChannel.name = from->getName();
+ outChannel.fd = android::os::ParcelFileDescriptor(std::move(from->fd));
+ outChannel.token = from->getConnectionToken();
+}
+
sp<IBinder> InputChannel::getConnectionToken() const {
return token;
}
@@ -591,7 +598,7 @@
// --- InputPublisher ---
InputPublisher::InputPublisher(const std::shared_ptr<InputChannel>& channel)
- : mChannel(channel), mInputVerifier(channel->getName()) {}
+ : mChannel(channel), mInputVerifier(mChannel->getName()) {}
InputPublisher::~InputPublisher() {
}
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 174464d..ec7a284 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -111,3 +111,10 @@
description: "Move user-activity poke rate-limiting from PowerManagerService to InputDispatcher."
bug: "320499729"
}
+
+flag {
+ name: "input_device_view_behavior_api"
+ namespace: "input"
+ description: "Controls the API to provide InputDevice view behavior."
+ bug: "246946631"
+}
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 2000335..3543020 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -220,7 +220,6 @@
class InputPublisherAndConsumerTest : public testing::Test {
protected:
- std::shared_ptr<InputChannel> mServerChannel, mClientChannel;
std::unique_ptr<InputPublisher> mPublisher;
std::unique_ptr<InputConsumer> mConsumer;
PreallocatedInputEventFactory mEventFactory;
@@ -230,11 +229,9 @@
status_t result = InputChannel::openInputChannelPair("channel name",
serverChannel, clientChannel);
ASSERT_EQ(OK, result);
- mServerChannel = std::move(serverChannel);
- mClientChannel = std::move(clientChannel);
- mPublisher = std::make_unique<InputPublisher>(mServerChannel);
- mConsumer = std::make_unique<InputConsumer>(mClientChannel);
+ mPublisher = std::make_unique<InputPublisher>(std::move(serverChannel));
+ mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel));
}
void publishAndConsumeKeyEvent();
@@ -254,11 +251,7 @@
};
TEST_F(InputPublisherAndConsumerTest, GetChannel_ReturnsTheChannel) {
- ASSERT_NE(nullptr, mPublisher->getChannel());
- ASSERT_NE(nullptr, mConsumer->getChannel());
- EXPECT_EQ(mServerChannel.get(), mPublisher->getChannel().get());
- EXPECT_EQ(mClientChannel.get(), mConsumer->getChannel().get());
- ASSERT_EQ(mPublisher->getChannel()->getConnectionToken(),
+ ASSERT_EQ(mPublisher->getChannel().getConnectionToken(),
mConsumer->getChannel()->getConnectionToken());
}
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index ba2eb7d..9494ee5 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -53,6 +53,13 @@
export_include_dirs: ["include"],
}
+// Needed by FlagManager to access a #define.
+cc_library_static {
+ name: "librenderengine_includes",
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+}
+
filegroup {
name: "librenderengine_sources",
srcs: [
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 7fd9c3a..f73fa5d 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -22,8 +22,10 @@
mkdir -p out/javax/microedition/khronos/opengles
mkdir -p out/com/google/android/gles_jni
+mkdir -p out/android/annotation
mkdir -p out/android/app
mkdir -p out/android/graphics
+mkdir -p out/android/hardware
mkdir -p out/android/view
mkdir -p out/android/opengl
mkdir -p out/android/content
@@ -34,18 +36,20 @@
echo "package android.graphics;" > out/android/graphics/Canvas.java
echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
+echo "package android.annotation; public @interface NonNull {}" > out/android/annotation/NonNull.java
echo "package android.app; import android.content.pm.IPackageManager; public class AppGlobals { public static IPackageManager getPackageManager() { return null;} }" > out/android/app/AppGlobals.java
# echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags, java.lang.String userId) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
-echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;}; }" > out/android/os/Build.java
+echo "package android.hardware; import android.os.ParcelFileDescriptor; public class SyncFence { public static SyncFence create(ParcelFileDescriptor w) { return null; } public static SyncFence createEmpty() { return null; } }" > out/android/hardware/SyncFence.java
+echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 0; public static final int R = 0; }; }" > out/android/os/Build.java
+echo "package android.os; public class ParcelFileDescriptor { public static ParcelFileDescriptor adoptFd(int fd) { return null; } }" > out/android/os/ParcelFileDescriptor.java
echo "package android.os; public class UserHandle {public static String myUserId() { return \"\"; } }" > out/android/os/UserHandle.java
echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
-echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
+echo "package android.util; public class Log {public static void d(String a, String b) {} public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
echo "package android.opengl; public abstract class EGLObjectHandle { public int getHandle() { return 0; } }" > out/android/opengl/EGLObjectHandle.java
-
echo "package android.graphics;" > out/android/graphics/SurfaceTexture.java
echo "public interface SurfaceTexture {}" >> out/android/graphics/SurfaceTexture.java
echo "package android.view;" > out/android/view/SurfaceView.java
diff --git a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
index 951ecff..695b571 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
+++ b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
@@ -20,6 +20,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.SurfaceTexture;
+import android.os.Build;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
index b2ea041..ea55179 100644
--- a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
index 6dffac5..8e452fb 100644
--- a/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGL15cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
index 523bc57..75e1704 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
+++ b/opengl/tools/glgen/stubs/egl/EGLExtHeader.java-if
@@ -18,6 +18,11 @@
package android.opengl;
+import android.annotation.NonNull;
+import android.hardware.SyncFence;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
/**
* EGL Extensions
*/
@@ -30,8 +35,44 @@
public static final int EGL_OPENGL_ES3_BIT_KHR = 0x0040;
public static final int EGL_RECORDABLE_ANDROID = 0x3142;
+ // EGL_ANDROID_native_fence_sync
+ public static final int EGL_SYNC_NATIVE_FENCE_ANDROID = 0x3144;
+ public static final int EGL_SYNC_NATIVE_FENCE_FD_ANDROID = 0x3145;
+ public static final int EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID = 0x3146;
+ public static final int EGL_NO_NATIVE_FENCE_FD_ANDROID = -1;
+
native private static void _nativeClassInit();
static {
_nativeClassInit();
}
+ /**
+ * Retrieves the SyncFence for an EGLSync created with EGL_SYNC_NATIVE_FENCE_ANDROID
+ *
+ * See <a href="https://www.khronos.org/registry/EGL/extensions/ANDROID/EGL_ANDROID_native_fence_sync.txt">
+ * EGL_ANDROID_native_fence_sync</a> extension for more details
+ * @param display The EGLDisplay connection
+ * @param sync The EGLSync to fetch the SyncFence from
+ * @return A SyncFence representing the native fence.
+ * * If <sync> is not a valid sync object for <display>,
+ * an {@link SyncFence#isValid() invalid} SyncFence is returned and an EGL_BAD_PARAMETER
+ * error is generated.
+ * * If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute of <sync> is
+ * EGL_NO_NATIVE_FENCE_FD_ANDROID, an {@link SyncFence#isValid() invalid} SyncFence is
+ * returned and an EGL_BAD_PARAMETER error is generated.
+ * * If <display> does not match the display passed to eglCreateSync
+ * when <sync> was created, the behaviour is undefined.
+ */
+ public static @NonNull SyncFence eglDupNativeFenceFDANDROID(@NonNull EGLDisplay display,
+ @NonNull EGLSync sync) {
+ int fd = eglDupNativeFenceFDANDROIDImpl(display, sync);
+ Log.d("EGL", "eglDupNativeFence returned " + fd);
+ if (fd >= 0) {
+ return SyncFence.create(ParcelFileDescriptor.adoptFd(fd));
+ } else {
+ return SyncFence.createEmpty();
+ }
+ }
+
+ private static native int eglDupNativeFenceFDANDROIDImpl(EGLDisplay display, EGLSync sync);
+
diff --git a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
index be8b3e3..f1f0ac5 100644
--- a/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/egl/EGLExtcHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
@@ -37,25 +38,12 @@
#include <ui/ANativeObjectBase.h>
static jclass egldisplayClass;
-static jclass eglcontextClass;
static jclass eglsurfaceClass;
-static jclass eglconfigClass;
+static jclass eglsyncClass;
static jmethodID egldisplayGetHandleID;
-static jmethodID eglcontextGetHandleID;
static jmethodID eglsurfaceGetHandleID;
-static jmethodID eglconfigGetHandleID;
-
-static jmethodID egldisplayConstructor;
-static jmethodID eglcontextConstructor;
-static jmethodID eglsurfaceConstructor;
-static jmethodID eglconfigConstructor;
-
-static jobject eglNoContextObject;
-static jobject eglNoDisplayObject;
-static jobject eglNoSurfaceObject;
-
-
+static jmethodID eglsyncGetHandleID;
/* Cache method IDs each time the class is loaded. */
@@ -64,37 +52,14 @@
{
jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay");
egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal);
- jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext");
- eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal);
jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
- jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
- eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
+ jclass eglsyncClassLocal = _env->FindClass("android/opengl/EGLSync");
+ eglsyncClass = (jclass) _env->NewGlobalRef(eglsyncClassLocal);
egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getNativeHandle", "()J");
- eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getNativeHandle", "()J");
eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getNativeHandle", "()J");
- eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getNativeHandle", "()J");
-
-
- egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(J)V");
- eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(J)V");
- eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(J)V");
- eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(J)V");
-
-
- jclass eglClass = _env->FindClass("android/opengl/EGL14");
- jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
- jobject localeglNoContextObject = _env->GetStaticObjectField(eglClass, noContextFieldID);
- eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
-
- jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
- jobject localeglNoDisplayObject = _env->GetStaticObjectField(eglClass, noDisplayFieldID);
- eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
-
- jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
- jobject localeglNoSurfaceObject = _env->GetStaticObjectField(eglClass, noSurfaceFieldID);
- eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
+ eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J");
}
static void *
@@ -108,24 +73,12 @@
return reinterpret_cast<void*>(_env->CallLongMethod(obj, mid));
}
-static jobject
-toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) {
- if (cls == eglcontextClass &&
- (EGLContext)handle == EGL_NO_CONTEXT) {
- return eglNoContextObject;
- }
+// TODO: this should be generated from the .spec file, but needs to be renamed and made private
+static jint android_eglDupNativeFenceFDANDROID(JNIEnv *env, jobject, jobject dpy, jobject sync) {
+ EGLDisplay dpy_native = (EGLDisplay)fromEGLHandle(env, egldisplayGetHandleID, dpy);
+ EGLSync sync_native = (EGLSync)fromEGLHandle(env, eglsyncGetHandleID, sync);
- if (cls == egldisplayClass &&
- (EGLDisplay)handle == EGL_NO_DISPLAY) {
- return eglNoDisplayObject;
- }
-
- if (cls == eglsurfaceClass &&
- (EGLSurface)handle == EGL_NO_SURFACE) {
- return eglNoSurfaceObject;
- }
-
- return _env->NewObject(cls, con, reinterpret_cast<jlong>(handle));
+ return eglDupNativeFenceFDANDROID(dpy_native, sync_native);
}
// --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
index 85f743d..78b0819 100755
--- a/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
+++ b/opengl/tools/glgen/stubs/egl/eglGetDisplay.java
@@ -7,7 +7,7 @@
/**
* {@hide}
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static native EGLDisplay eglGetDisplay(
long display_id
);
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index dd17ca4..1fa9275 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES/gl.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
index b2bbdf6..4004a7d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES2/gl2.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
index b039bc9..c5bdf32 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES30cHeader.cpp
@@ -18,6 +18,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES3/gl3.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
index dd00e92..2260a80 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31ExtcHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <GLES3/gl31.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
index 88e00be..130612d 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES31cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <stdint.h>
diff --git a/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
index 3e7ec8b..5446fc2 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include <stdint.h>
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index 9cab1d6..c3534bf 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -17,6 +17,7 @@
// This source file is automatically generated
#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni.h"
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/InputManager.cpp b/services/inputflinger/InputManager.cpp
index 823df67..ae066c0 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -277,7 +277,7 @@
return binder::Status::fromExceptionCode(exceptionCodeFromStatusT(channel.error().code()),
channel.error().message().c_str());
}
- (*channel)->copyTo(*outChannel);
+ InputChannel::moveChannel(std::move(*channel), *outChannel);
return binder::Status::ok();
}
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/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp
index 6c603d4..9dee66f 100644
--- a/services/inputflinger/dispatcher/Connection.cpp
+++ b/services/inputflinger/dispatcher/Connection.cpp
@@ -20,26 +20,15 @@
namespace android::inputdispatcher {
-Connection::Connection(const std::shared_ptr<InputChannel>& inputChannel, bool monitor,
+Connection::Connection(std::unique_ptr<InputChannel> inputChannel, bool monitor,
const IdGenerator& idGenerator)
: status(Status::NORMAL),
- inputChannel(inputChannel),
monitor(monitor),
- inputPublisher(inputChannel),
+ inputPublisher(std::move(inputChannel)),
inputState(idGenerator) {}
-const std::string Connection::getWindowName() const {
- if (inputChannel != nullptr) {
- return inputChannel->getName();
- }
- if (monitor) {
- return "monitor";
- }
- return "?";
-}
-
sp<IBinder> Connection::getToken() const {
- return inputPublisher.getChannel()->getConnectionToken();
+ return inputPublisher.getChannel().getConnectionToken();
};
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h
index d4fb9b5..a834a8c 100644
--- a/services/inputflinger/dispatcher/Connection.h
+++ b/services/inputflinger/dispatcher/Connection.h
@@ -42,7 +42,6 @@
};
Status status;
- std::shared_ptr<InputChannel> inputChannel; // never null
bool monitor;
InputPublisher inputPublisher;
InputState inputState;
@@ -59,14 +58,14 @@
// yet received a "finished" response from the application.
std::deque<std::unique_ptr<DispatchEntry>> waitQueue;
- Connection(const std::shared_ptr<InputChannel>& inputChannel, bool monitor,
+ Connection(std::unique_ptr<InputChannel> inputChannel, bool monitor,
const IdGenerator& idGenerator);
- inline const std::string getInputChannelName() const { return inputChannel->getName(); }
+ inline const std::string getInputChannelName() const {
+ return inputPublisher.getChannel().getName();
+ }
sp<IBinder> getToken() const;
-
- const std::string getWindowName() const;
};
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index d46c059..af72eb9 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -436,15 +436,6 @@
return dispatchEntry;
}
-status_t openInputChannelPair(const std::string& name, std::shared_ptr<InputChannel>& serverChannel,
- std::unique_ptr<InputChannel>& clientChannel) {
- std::unique_ptr<InputChannel> uniqueServerChannel;
- status_t result = InputChannel::openInputChannelPair(name, uniqueServerChannel, clientChannel);
-
- serverChannel = std::move(uniqueServerChannel);
- return result;
-}
-
template <typename T>
bool sharedPointersEqual(const std::shared_ptr<T>& lhs, const std::shared_ptr<T>& rhs) {
if (lhs == nullptr && rhs == nullptr) {
@@ -2084,7 +2075,7 @@
// sending new pointers to the connection when it blocked, but focused events will continue to
// pile up.
ALOGW("Canceling events for %s because it is unresponsive",
- connection->inputChannel->getName().c_str());
+ connection->getInputChannelName().c_str());
if (connection->status == Connection::Status::NORMAL) {
CancelationOptions options(CancelationOptions::Mode::CANCEL_ALL_EVENTS,
"application not responding");
@@ -2271,7 +2262,7 @@
std::shared_ptr<Connection> connection = monitor.connection;
if (!connection->responsive) {
ALOGW("Unresponsive monitor %s will not get the new gesture",
- connection->inputChannel->getName().c_str());
+ connection->getInputChannelName().c_str());
return false;
}
return true;
@@ -3586,7 +3577,7 @@
std::string targetList;
for (const std::shared_ptr<Connection>& connection : newConnections) {
- targetList += connection->getWindowName() + ", ";
+ targetList += connection->getInputChannelName() + ", ";
}
std::string message = "Interaction with: " + targetList;
if (targetList.empty()) {
@@ -5803,11 +5794,10 @@
if (!mConnectionsByToken.empty()) {
dump += INDENT "Connections:\n";
for (const auto& [token, connection] : mConnectionsByToken) {
- dump += StringPrintf(INDENT2 "%i: channelName='%s', windowName='%s', "
+ dump += StringPrintf(INDENT2 "%i: channelName='%s', "
"status=%s, monitor=%s, responsive=%s\n",
- connection->inputChannel->getFd(),
+ connection->inputPublisher.getChannel().getFd(),
connection->getInputChannelName().c_str(),
- connection->getWindowName().c_str(),
ftl::enum_string(connection->status).c_str(),
toString(connection->monitor), toString(connection->responsive));
@@ -5917,9 +5907,9 @@
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputMonitor(int32_t displayId,
const std::string& name,
gui::Pid pid) {
- std::shared_ptr<InputChannel> serverChannel;
+ std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
- status_t result = openInputChannelPair(name, serverChannel, clientChannel);
+ status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
if (result) {
return base::Error(result) << "Failed to open input channel pair with name " << name;
}
@@ -5932,10 +5922,11 @@
<< " without a specified display.";
}
- std::shared_ptr<Connection> connection =
- std::make_shared<Connection>(serverChannel, /*monitor=*/true, mIdGenerator);
const sp<IBinder>& token = serverChannel->getConnectionToken();
const int fd = serverChannel->getFd();
+ std::shared_ptr<Connection> connection =
+ std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/true,
+ mIdGenerator);
auto [_, inserted] = mConnectionsByToken.emplace(token, connection);
if (!inserted) {
@@ -5986,7 +5977,7 @@
removeMonitorChannelLocked(connectionToken);
}
- mLooper->removeFd(connection->inputChannel->getFd());
+ mLooper->removeFd(connection->inputPublisher.getChannel().getFd());
nsecs_t currentTime = now();
abortBrokenDispatchCycleLocked(currentTime, connection, notify);
@@ -6180,7 +6171,7 @@
const nsecs_t eventDuration = finishTime - dispatchEntry.deliveryTime;
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
- ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(),
+ ALOGI("%s spent %" PRId64 "ms processing %s", connection->getInputChannelName().c_str(),
ns2ms(eventDuration), dispatchEntry.eventEntry->getDescription().c_str());
}
if (shouldReportFinishedEvent(dispatchEntry, *connection)) {
@@ -6251,7 +6242,7 @@
// is already healthy again. Don't raise ANR in this situation
if (connection->waitQueue.empty()) {
ALOGI("Not raising ANR because the connection %s has recovered",
- connection->inputChannel->getName().c_str());
+ connection->getInputChannelName().c_str());
return;
}
/**
@@ -6266,7 +6257,7 @@
const nsecs_t currentWait = now() - oldestEntry.deliveryTime;
std::string reason =
android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s",
- connection->inputChannel->getName().c_str(),
+ connection->getInputChannelName().c_str(),
ns2ms(currentWait),
oldestEntry.eventEntry->getDescription().c_str());
sp<IBinder> connectionToken = connection->getToken();
@@ -6371,12 +6362,12 @@
const sp<IBinder>& connectionToken = connection.getToken();
std::optional<gui::Pid> pid;
if (connection.monitor) {
- ALOGW("Monitor %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
+ ALOGW("Monitor %s is unresponsive: %s", connection.getInputChannelName().c_str(),
reason.c_str());
pid = findMonitorPidByTokenLocked(connectionToken);
} else {
// The connection is a window
- ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
+ ALOGW("Window %s is unresponsive: %s", connection.getInputChannelName().c_str(),
reason.c_str());
const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
if (handle != nullptr) {
@@ -6595,7 +6586,8 @@
void InputDispatcher::traceOutboundQueueLength(const Connection& connection) {
if (ATRACE_ENABLED()) {
char counterName[40];
- snprintf(counterName, sizeof(counterName), "oq:%s", connection.getWindowName().c_str());
+ snprintf(counterName, sizeof(counterName), "oq:%s",
+ connection.getInputChannelName().c_str());
ATRACE_INT(counterName, connection.outboundQueue.size());
}
}
@@ -6603,7 +6595,8 @@
void InputDispatcher::traceWaitQueueLength(const Connection& connection) {
if (ATRACE_ENABLED()) {
char counterName[40];
- snprintf(counterName, sizeof(counterName), "wq:%s", connection.getWindowName().c_str());
+ snprintf(counterName, sizeof(counterName), "wq:%s",
+ connection.getInputChannelName().c_str());
ATRACE_INT(counterName, connection.waitQueue.size());
}
}
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/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index a41064b..f3f15df 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -251,6 +251,7 @@
mAssociatedDeviceType =
getValueByKey(readerConfig.deviceTypeAssociations, mIdentifier.location);
mIsWaking = mConfiguration.getBool("device.wake").value_or(false);
+ mShouldSmoothScroll = mConfiguration.getBool("device.viewBehavior_smoothScroll");
}
if (!changes.any() || changes.test(Change::DEVICE_ALIAS)) {
@@ -401,7 +402,8 @@
InputDeviceInfo InputDevice::getDeviceInfo() {
InputDeviceInfo outDeviceInfo;
outDeviceInfo.initialize(mId, mGeneration, mControllerNumber, mIdentifier, mAlias, mIsExternal,
- mHasMic, getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE));
+ mHasMic, getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE),
+ {mShouldSmoothScroll});
for_each_mapper(
[&outDeviceInfo](InputMapper& mapper) { mapper.populateDeviceInfo(outDeviceInfo); });
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index ba7234b..0719b0c 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -199,6 +199,7 @@
std::optional<DisplayViewport> mAssociatedViewport;
bool mHasMic;
bool mDropUntilNextSync;
+ std::optional<bool> mShouldSmoothScroll;
typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
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 77d35fb..0000000
--- a/services/inputflinger/tests/FakeInputTracingBackend.cpp
+++ /dev/null
@@ -1,107 +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 {
-
-constexpr auto TRACE_TIMEOUT = std::chrono::milliseconds(100);
-
-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/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 460a7b1..c1dc7ff 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -2706,6 +2706,31 @@
ASSERT_NO_FATAL_FAILURE(mapper2.assertProcessWasCalled());
}
+TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorNotSet) {
+ // Set some behavior to force the configuration to be update.
+ mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+
+ std::list<NotifyArgs> unused =
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ /*changes=*/{});
+
+ ASSERT_FALSE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.has_value());
+}
+
+TEST_F(InputDeviceTest, Configure_SmoothScrollViewBehaviorEnabled) {
+ mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.viewBehavior_smoothScroll", "1");
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, mFakePolicy->getReaderConfiguration(),
+ AINPUT_SOURCE_KEYBOARD);
+
+ std::list<NotifyArgs> unused =
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ /*changes=*/{});
+
+ ASSERT_TRUE(mDevice->getDeviceInfo().getViewBehavior().shouldSmoothScroll.value_or(false));
+}
+
TEST_F(InputDeviceTest, WakeDevice_AddsWakeFlagToProcessNotifyArgs) {
mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "device.wake", "1");
FakeInputMapper& mapper =
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/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index 38974a2..3ef9e69 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -315,6 +315,7 @@
if (obj.hasInputInfo()) {
out << "\n input{"
<< "(" << obj.inputInfo.inputConfig.string() << ")";
+ if (obj.inputInfo.canOccludePresentation) out << " canOccludePresentation";
if (obj.touchCropId != UNASSIGNED_LAYER_ID) out << " touchCropId=" << obj.touchCropId;
if (obj.inputInfo.replaceTouchableRegionWithCrop) out << " replaceTouchableRegionWithCrop";
auto touchableRegion = obj.inputInfo.touchableRegion.getBounds();
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
index 8df5d8c..0966fe0 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.cpp
@@ -1044,6 +1044,8 @@
snapshot.inputInfo.touchOcclusionMode = requested.hasInputInfo()
? requested.windowInfoHandle->getInfo()->touchOcclusionMode
: parentSnapshot.inputInfo.touchOcclusionMode;
+ snapshot.inputInfo.canOccludePresentation = parentSnapshot.inputInfo.canOccludePresentation ||
+ (requested.flags & layer_state_t::eCanOccludePresentation);
if (requested.dropInputMode == gui::DropInputMode::ALL ||
parentSnapshot.dropInputMode == gui::DropInputMode::ALL) {
snapshot.dropInputMode = gui::DropInputMode::ALL;
diff --git a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
index 209df79..2cf4c1b 100644
--- a/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
+++ b/services/surfaceflinger/FrontEnd/RequestedLayerState.cpp
@@ -170,6 +170,9 @@
if ((oldFlags ^ flags) & layer_state_t::eIgnoreDestinationFrame) {
changes |= RequestedLayerState::Changes::Geometry;
}
+ if ((oldFlags ^ flags) & layer_state_t::eCanOccludePresentation) {
+ changes |= RequestedLayerState::Changes::Input;
+ }
}
if (clientState.what & layer_state_t::eBufferChanged) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7f50168..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) {
@@ -3764,6 +3866,9 @@
mVisibleRegionsDirty = true;
mUpdateInputInfo = true;
+ // Apply the current color matrix to any added or changed display.
+ mCurrentState.colorMatrixChanged = true;
+
// find the displays that were removed
// (ie: in drawing state but not in current state)
// also handle displays that changed
@@ -4308,7 +4413,6 @@
}
mDrawingState = mCurrentState;
- // clear the "changed" flags in current state
mCurrentState.colorMatrixChanged = false;
if (mVisibleRegionsDirty) {
@@ -8377,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/common/Android.bp b/services/surfaceflinger/common/Android.bp
index 5ef22b5..e125bbe 100644
--- a/services/surfaceflinger/common/Android.bp
+++ b/services/surfaceflinger/common/Android.bp
@@ -18,7 +18,7 @@
"server_configurable_flags",
],
static_libs: [
- "librenderengine",
+ "librenderengine_includes",
],
srcs: [
"FlagManager.cpp",
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 5809ea0..7c191a5 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -95,6 +95,7 @@
"MessageQueueTest.cpp",
"PowerAdvisorTest.cpp",
"SmallAreaDetectionAllowMappingsTest.cpp",
+ "SurfaceFlinger_ColorMatrixTest.cpp",
"SurfaceFlinger_CreateDisplayTest.cpp",
"SurfaceFlinger_DestroyDisplayTest.cpp",
"SurfaceFlinger_DisplayModeSwitching.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h b/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h
new file mode 100644
index 0000000..34e4ba5
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/CommitAndCompositeTest.h
@@ -0,0 +1,86 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <compositionengine/Display.h>
+#include <compositionengine/mock/DisplaySurface.h>
+#include <renderengine/mock/RenderEngine.h>
+
+#include "TestableSurfaceFlinger.h"
+#include "mock/DisplayHardware/MockComposer.h"
+#include "mock/DisplayHardware/MockPowerAdvisor.h"
+#include "mock/MockTimeStats.h"
+#include "mock/system/window/MockNativeWindow.h"
+
+namespace android {
+
+// Minimal setup to use TestableSurfaceFlinger::commitAndComposite.
+struct CommitAndCompositeTest : testing::Test {
+ void SetUp() override {
+ mFlinger.setupMockScheduler({.displayId = DEFAULT_DISPLAY_ID});
+ mComposer = new Hwc2::mock::Composer();
+ mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
+ mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
+ mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
+ mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
+ mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));
+
+ constexpr bool kIsPrimary = true;
+ FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, kIsPrimary)
+ .setPowerMode(hal::PowerMode::ON)
+ .inject(&mFlinger, mComposer);
+ auto compostionEngineDisplayArgs =
+ compositionengine::DisplayCreationArgsBuilder()
+ .setId(DEFAULT_DISPLAY_ID)
+ .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
+ .setPowerAdvisor(mPowerAdvisor)
+ .setName("Internal display")
+ .build();
+ auto compositionDisplay =
+ compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
+ std::move(compostionEngineDisplayArgs));
+ mDisplay = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
+ ui::DisplayConnectionType::Internal, HWC_DISPLAY,
+ kIsPrimary)
+ .setDisplaySurface(mDisplaySurface)
+ .setNativeWindow(mNativeWindow)
+ .setPowerMode(hal::PowerMode::ON)
+ .setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector())
+ .skipRegisterDisplay()
+ .inject();
+ }
+
+ using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
+ using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
+
+ static constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
+ static constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
+ static constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
+ static constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
+
+ TestableSurfaceFlinger mFlinger;
+ renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
+ sp<DisplayDevice> mDisplay;
+ sp<compositionengine::mock::DisplaySurface> mDisplaySurface =
+ sp<compositionengine::mock::DisplaySurface>::make();
+ sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
+ mock::TimeStats* mTimeStats = new mock::TimeStats();
+ Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;
+ Hwc2::mock::Composer* mComposer = nullptr;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index beb2147..7d8a30a 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -25,6 +25,7 @@
#include <compositionengine/Display.h>
#include <compositionengine/mock/DisplaySurface.h>
+#include <ftl/future.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gui/IProducerListener.h>
@@ -227,14 +228,6 @@
LayerCase::cleanup(this);
}
-template <class T>
-std::future<T> futureOf(T obj) {
- std::promise<T> resultPromise;
- std::future<T> resultFuture = resultPromise.get_future();
- resultPromise.set_value(std::move(obj));
- return resultFuture;
-}
-
/* ------------------------------------------------------------------------
* Variants for each display configuration which can be tested
*/
@@ -327,13 +320,13 @@
.WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&,
- base::unique_fd&&) -> std::future<FenceResult> {
+ base::unique_fd&&) -> ftl::Future<FenceResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.clip);
- return futureOf<FenceResult>(Fence::NO_FENCE);
+ return ftl::yield<FenceResult>(Fence::NO_FENCE);
});
}
@@ -378,14 +371,14 @@
.WillRepeatedly([&](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>&,
const std::shared_ptr<renderengine::ExternalTexture>&,
- base::unique_fd&&) -> std::future<FenceResult> {
+ base::unique_fd&&) -> ftl::Future<FenceResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.clip);
EXPECT_EQ(ui::Dataspace::UNKNOWN, displaySettings.outputDataspace);
- return futureOf<FenceResult>(Fence::NO_FENCE);
+ return ftl::yield<FenceResult>(Fence::NO_FENCE);
});
}
@@ -578,7 +571,7 @@
.WillOnce([&](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
const std::shared_ptr<renderengine::ExternalTexture>&,
- base::unique_fd&&) -> std::future<FenceResult> {
+ base::unique_fd&&) -> ftl::Future<FenceResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -586,7 +579,8 @@
displaySettings.clip);
// screen capture adds an additional color layer as an alpha
// prefill, so gtet the back layer.
- std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE);
+ ftl::Future<FenceResult> resultFuture =
+ ftl::yield<FenceResult>(Fence::NO_FENCE);
if (layerSettings.empty()) {
ADD_FAILURE() << "layerSettings was not expected to be empty in "
"setupREBufferCompositionCommonCallExpectations "
@@ -627,7 +621,7 @@
.WillOnce([&](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
const std::shared_ptr<renderengine::ExternalTexture>&,
- base::unique_fd&&) -> std::future<FenceResult> {
+ base::unique_fd&&) -> ftl::Future<FenceResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -635,7 +629,8 @@
displaySettings.clip);
// screen capture adds an additional color layer as an alpha
// prefill, so get the back layer.
- std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE);
+ ftl::Future<FenceResult> resultFuture =
+ ftl::yield<FenceResult>(Fence::NO_FENCE);
if (layerSettings.empty()) {
ADD_FAILURE()
<< "layerSettings was not expected to be empty in "
@@ -709,7 +704,7 @@
.WillOnce([&](const renderengine::DisplaySettings& displaySettings,
const std::vector<renderengine::LayerSettings>& layerSettings,
const std::shared_ptr<renderengine::ExternalTexture>&,
- base::unique_fd&&) -> std::future<FenceResult> {
+ base::unique_fd&&) -> ftl::Future<FenceResult> {
EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
displaySettings.physicalDisplay);
@@ -717,7 +712,8 @@
displaySettings.clip);
// screen capture adds an additional color layer as an alpha
// prefill, so get the back layer.
- std::future<FenceResult> resultFuture = futureOf<FenceResult>(Fence::NO_FENCE);
+ ftl::Future<FenceResult> resultFuture =
+ ftl::yield<FenceResult>(Fence::NO_FENCE);
if (layerSettings.empty()) {
ADD_FAILURE() << "layerSettings was not expected to be empty in "
"setupInsecureREBufferCompositionCommonCallExpectations "
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/LayerSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
index 13b47ff..3baa48d 100644
--- a/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerSnapshotTest.cpp
@@ -1237,4 +1237,25 @@
EXPECT_TRUE(foundInputLayer);
}
+TEST_F(LayerSnapshotTest, canOccludePresentation) {
+ setFlags(12, layer_state_t::eCanOccludePresentation, layer_state_t::eCanOccludePresentation);
+ LayerSnapshotBuilder::Args args{.root = mHierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = mLifecycleManager,
+ .includeMetadata = false,
+ .displays = mFrontEndDisplayInfos,
+ .displayChanges = false,
+ .globalShadowSettings = globalShadowSettings,
+ .supportsBlur = true,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
+ UPDATE_AND_VERIFY(mSnapshotBuilder, STARTING_ZORDER);
+
+ EXPECT_EQ(getSnapshot(1)->inputInfo.canOccludePresentation, false);
+
+ // ensure we can set the property on the window info for layer and all its children
+ EXPECT_EQ(getSnapshot(12)->inputInfo.canOccludePresentation, true);
+ EXPECT_EQ(getSnapshot(121)->inputInfo.canOccludePresentation, true);
+ EXPECT_EQ(getSnapshot(1221)->inputInfo.canOccludePresentation, true);
+}
+
} // namespace android::surfaceflinger::frontend
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_ColorMatrixTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
new file mode 100644
index 0000000..f127213
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_ColorMatrixTest.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include "CommitAndCompositeTest.h"
+
+#define EXPECT_COLOR_MATRIX_CHANGED(current, drawing) \
+ EXPECT_EQ(current, mFlinger.currentState().colorMatrixChanged); \
+ EXPECT_EQ(drawing, mFlinger.drawingState().colorMatrixChanged);
+
+namespace android {
+
+class ColorMatrixTest : public CommitAndCompositeTest {};
+
+TEST_F(ColorMatrixTest, colorMatrixChanged) {
+ EXPECT_COLOR_MATRIX_CHANGED(true, true);
+ mFlinger.mutableTransactionFlags() |= eTransactionNeeded;
+
+ mFlinger.commitAndComposite();
+ EXPECT_COLOR_MATRIX_CHANGED(false, false);
+
+ mFlinger.setDaltonizerType(ColorBlindnessType::Deuteranomaly);
+ EXPECT_COLOR_MATRIX_CHANGED(true, false);
+
+ mFlinger.commit();
+ EXPECT_COLOR_MATRIX_CHANGED(false, true);
+
+ mFlinger.commitAndComposite();
+ EXPECT_COLOR_MATRIX_CHANGED(false, false);
+}
+
+TEST_F(ColorMatrixTest, colorMatrixChangedAfterDisplayTransaction) {
+ EXPECT_COLOR_MATRIX_CHANGED(true, true);
+ mFlinger.mutableTransactionFlags() |= eTransactionNeeded;
+
+ mFlinger.commitAndComposite();
+ EXPECT_COLOR_MATRIX_CHANGED(false, false);
+
+ mFlinger.createDisplay(String8("Test Display"), false);
+
+ mFlinger.commit();
+ EXPECT_COLOR_MATRIX_CHANGED(false, true);
+
+ mFlinger.commitAndComposite();
+ EXPECT_COLOR_MATRIX_CHANGED(false, false);
+}
+
+} // namespace android
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/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp
index 93c2829..19f8deb 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_FoldableTest.cpp
@@ -17,11 +17,15 @@
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
+#include <com_android_graphics_surfaceflinger_flags.h>
+#include <common/test/FlagUtils.h>
#include "DualDisplayTransactionTest.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+using namespace com::android::graphics::surfaceflinger;
+
namespace android {
namespace {
@@ -163,6 +167,7 @@
}
TEST_F(FoldableTest, requestVsyncOnPowerOn) {
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kInnerDisplayId, true))
.Times(1);
EXPECT_CALL(mFlinger.scheduler()->mockRequestHardwareVsync, Call(kOuterDisplayId, true))
@@ -173,6 +178,7 @@
}
TEST_F(FoldableTest, disableVsyncOnPowerOffPacesetter) {
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
// When the device boots, the inner display should be the pacesetter.
ASSERT_EQ(mFlinger.scheduler()->pacesetterDisplayId(), kInnerDisplayId);
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp
index 29acfaa..4e9fba7 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_GetDisplayStatsTest.cpp
@@ -17,79 +17,16 @@
#undef LOG_TAG
#define LOG_TAG "SurfaceFlingerGetDisplayStatsTest"
-#include <compositionengine/Display.h>
-#include <compositionengine/mock/DisplaySurface.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <renderengine/mock/RenderEngine.h>
#include <ui/DisplayStatInfo.h>
-#include "TestableSurfaceFlinger.h"
-#include "mock/DisplayHardware/MockComposer.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
-#include "mock/MockTimeStats.h"
-#include "mock/system/window/MockNativeWindow.h"
-using namespace android;
-using namespace testing;
+#include "CommitAndCompositeTest.h"
namespace android {
namespace {
-using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
-using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
-constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
-constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
-constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
-constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
-
-class SurfaceFlingerGetDisplayStatsTest : public Test {
-public:
- void SetUp() override;
-
-protected:
- TestableSurfaceFlinger mFlinger;
- renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
- sp<DisplayDevice> mDisplay;
- sp<compositionengine::mock::DisplaySurface> mDisplaySurface =
- sp<compositionengine::mock::DisplaySurface>::make();
- sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
- mock::TimeStats* mTimeStats = new mock::TimeStats();
- Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;
- Hwc2::mock::Composer* mComposer = nullptr;
-};
-
-void SurfaceFlingerGetDisplayStatsTest::SetUp() {
- mFlinger.setupMockScheduler({.displayId = DEFAULT_DISPLAY_ID});
- mComposer = new Hwc2::mock::Composer();
- mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
- mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
- mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
- mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
- mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));
- static constexpr bool kIsPrimary = true;
- FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, kIsPrimary)
- .setPowerMode(hal::PowerMode::ON)
- .inject(&mFlinger, mComposer);
- auto compostionEngineDisplayArgs =
- compositionengine::DisplayCreationArgsBuilder()
- .setId(DEFAULT_DISPLAY_ID)
- .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
- .setPowerAdvisor(mPowerAdvisor)
- .setName("injected display")
- .build();
- auto compositionDisplay =
- compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
- std::move(compostionEngineDisplayArgs));
- mDisplay =
- FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
- ui::DisplayConnectionType::Internal, HWC_DISPLAY, kIsPrimary)
- .setDisplaySurface(mDisplaySurface)
- .setNativeWindow(mNativeWindow)
- .setPowerMode(hal::PowerMode::ON)
- .setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector())
- .skipRegisterDisplay()
- .inject();
-}
+struct SurfaceFlingerGetDisplayStatsTest : CommitAndCompositeTest {};
// TODO (b/277364366): Clients should be updated to pass in the display they want.
TEST_F(SurfaceFlingerGetDisplayStatsTest, nullptrSucceeds) {
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
index b80cb66..c3934e6 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_PowerHintTest.cpp
@@ -17,84 +17,18 @@
#undef LOG_TAG
#define LOG_TAG "SurfaceFlingerPowerHintTest"
-#include <compositionengine/Display.h>
-#include <compositionengine/mock/DisplaySurface.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <renderengine/mock/RenderEngine.h>
-#include <algorithm>
#include <chrono>
-#include <memory>
-#include "TestableSurfaceFlinger.h"
-#include "mock/DisplayHardware/MockComposer.h"
-#include "mock/DisplayHardware/MockPowerAdvisor.h"
-#include "mock/MockTimeStats.h"
-#include "mock/system/window/MockNativeWindow.h"
-using namespace android;
-using namespace android::Hwc2::mock;
-using namespace android::hardware::power;
+#include "CommitAndCompositeTest.h"
+
using namespace std::chrono_literals;
-using namespace testing;
+using testing::_;
+using testing::Return;
namespace android {
namespace {
-using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
-using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
-constexpr hal::HWDisplayId HWC_DISPLAY = FakeHwcDisplayInjector::DEFAULT_HWC_DISPLAY_ID;
-constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(42u);
-constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
-constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
-
-class SurfaceFlingerPowerHintTest : public Test {
-public:
- void SetUp() override;
-
-protected:
- TestableSurfaceFlinger mFlinger;
- renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
- sp<DisplayDevice> mDisplay;
- sp<compositionengine::mock::DisplaySurface> mDisplaySurface =
- sp<compositionengine::mock::DisplaySurface>::make();
- sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
- mock::TimeStats* mTimeStats = new mock::TimeStats();
- Hwc2::mock::PowerAdvisor* mPowerAdvisor = nullptr;
- Hwc2::mock::Composer* mComposer = nullptr;
-};
-
-void SurfaceFlingerPowerHintTest::SetUp() {
- mFlinger.setupMockScheduler({.displayId = DEFAULT_DISPLAY_ID});
- mComposer = new Hwc2::mock::Composer();
- mPowerAdvisor = new Hwc2::mock::PowerAdvisor();
- mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine));
- mFlinger.setupTimeStats(std::shared_ptr<TimeStats>(mTimeStats));
- mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
- mFlinger.setupPowerAdvisor(std::unique_ptr<Hwc2::PowerAdvisor>(mPowerAdvisor));
- static constexpr bool kIsPrimary = true;
- FakeHwcDisplayInjector(DEFAULT_DISPLAY_ID, hal::DisplayType::PHYSICAL, kIsPrimary)
- .setPowerMode(hal::PowerMode::ON)
- .inject(&mFlinger, mComposer);
- auto compostionEngineDisplayArgs =
- compositionengine::DisplayCreationArgsBuilder()
- .setId(DEFAULT_DISPLAY_ID)
- .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
- .setPowerAdvisor(mPowerAdvisor)
- .setName("injected display")
- .build();
- auto compositionDisplay =
- compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
- std::move(compostionEngineDisplayArgs));
- mDisplay =
- FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
- ui::DisplayConnectionType::Internal, HWC_DISPLAY, kIsPrimary)
- .setDisplaySurface(mDisplaySurface)
- .setNativeWindow(mNativeWindow)
- .setPowerMode(hal::PowerMode::ON)
- .setRefreshRateSelector(mFlinger.scheduler()->refreshRateSelector())
- .skipRegisterDisplay()
- .inject();
-}
+class SurfaceFlingerPowerHintTest : public CommitAndCompositeTest {};
TEST_F(SurfaceFlingerPowerHintTest, sendDurationsIncludingHwcWaitTime) {
ON_CALL(*mPowerAdvisor, usePowerHintSession()).WillByDefault(Return(true));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
index 15fe600..83e2f98 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetPowerModeInternalTest.cpp
@@ -17,11 +17,15 @@
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
+#include <com_android_graphics_surfaceflinger_flags.h>
+#include <common/test/FlagUtils.h>
#include "DisplayTransactionTestHelpers.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+using namespace com::android::graphics::surfaceflinger;
+
namespace android {
namespace {
@@ -453,6 +457,7 @@
}
TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOffToOnExternalDisplay) {
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOffToOnVariant>>();
}
@@ -461,6 +466,7 @@
}
TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToOffExternalDisplay) {
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToOffVariant>>();
}
@@ -473,6 +479,7 @@
}
TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToDozeExternalDisplay) {
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToDozeVariant>>();
}
@@ -481,10 +488,12 @@
}
TEST_F(SetPowerModeInternalTest, transitionsDisplayFromDozeSuspendToOnExternalDisplay) {
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
transitionDisplayCommon<ExternalDisplayPowerCase<TransitionDozeSuspendToOnVariant>>();
}
TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToDozeSuspendExternalDisplay) {
+ SET_FLAG_FOR_TEST(flags::multithreaded_present, true);
transitionDisplayCommon<ExternalDisplayPowerCase<TransitionOnToDozeSuspendVariant>>();
}
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"