Merge "Plumb through dimming stage into RenderEngine."
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 1c3a4f2..13c09a3 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -179,6 +179,8 @@
chmod 0666 /sys/kernel/tracing/events/clk/clk_enable/enable
chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_set_rate/enable
chmod 0666 /sys/kernel/tracing/events/clk/clk_set_rate/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/printk/console/enable
+ chmod 0666 /sys/kernel/tracing/events/printk/console/enable
# disk
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 24b201f..890c15f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2733,8 +2733,8 @@
const android::base::unique_fd& screenshot_fd_in,
bool is_screenshot_requested) {
// Duplicate the fds because the passed in fds don't outlive the binder transaction.
- bugreport_fd.reset(dup(bugreport_fd_in.get()));
- screenshot_fd.reset(dup(screenshot_fd_in.get()));
+ bugreport_fd.reset(fcntl(bugreport_fd_in.get(), F_DUPFD_CLOEXEC, 0));
+ screenshot_fd.reset(fcntl(screenshot_fd_in.get(), F_DUPFD_CLOEXEC, 0));
SetOptionsFromMode(bugreport_mode, this, is_screenshot_requested);
}
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index c104fea..4e12579 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1176,6 +1176,25 @@
return res;
}
+binder::Status InstalldNativeService::deleteReferenceProfile(const std::string& packageName,
+ const std::string& profileName) {
+ ENFORCE_UID(AID_SYSTEM);
+ CHECK_ARGUMENT_PACKAGE_NAME(packageName);
+ LOCK_PACKAGE();
+
+ // This function only supports primary dex'es.
+ std::string path =
+ create_reference_profile_path(packageName, profileName, /*is_secondary_dex=*/false);
+ if (unlink(path.c_str()) != 0) {
+ if (errno == ENOENT) {
+ return ok();
+ } else {
+ return error("Failed to delete profile " + profileName + " for " + packageName);
+ }
+ }
+ return ok();
+}
+
binder::Status InstalldNativeService::destroyAppData(const std::optional<std::string>& uuid,
const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode) {
ENFORCE_UID(AID_SYSTEM);
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 87a9206..0432222 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -140,6 +140,8 @@
bool* _aidl_return);
binder::Status clearAppProfiles(const std::string& packageName, const std::string& profileName);
binder::Status destroyAppProfiles(const std::string& packageName);
+ binder::Status deleteReferenceProfile(const std::string& packageName,
+ const std::string& profileName);
binder::Status createProfileSnapshot(int32_t appId, const std::string& packageName,
const std::string& profileName, const std::string& classpath, bool* _aidl_return);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index 79c02e8..db03411 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -82,6 +82,7 @@
@utf8InCpp String packageName, @utf8InCpp String profileName);
void clearAppProfiles(@utf8InCpp String packageName, @utf8InCpp String profileName);
void destroyAppProfiles(@utf8InCpp String packageName);
+ void deleteReferenceProfile(@utf8InCpp String packageName, @utf8InCpp String profileName);
boolean createProfileSnapshot(int appId, @utf8InCpp String packageName,
@utf8InCpp String profileName, @utf8InCpp String classpath);
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 9801a9b..45aeab6 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -707,16 +707,16 @@
auto temp_dir_path =
base::StringPrintf("%s/%s", Dirname(pathname).c_str(), temp_dir_name.c_str());
- if (::rename(pathname.c_str(), temp_dir_path.c_str())) {
+ auto dir_to_delete = temp_dir_path.c_str();
+ if (::rename(pathname.c_str(), dir_to_delete)) {
if (ignore_if_missing && (errno == ENOENT)) {
return 0;
}
- ALOGE("Couldn't rename %s -> %s: %s \n", pathname.c_str(), temp_dir_path.c_str(),
- strerror(errno));
- return -errno;
+ ALOGE("Couldn't rename %s -> %s: %s \n", pathname.c_str(), dir_to_delete, strerror(errno));
+ dir_to_delete = pathname.c_str();
}
- return delete_dir_contents(temp_dir_path.c_str(), 1, exclusion_predicate, ignore_if_missing);
+ return delete_dir_contents(dir_to_delete, 1, exclusion_predicate, ignore_if_missing);
}
bool is_renamed_deleted_dir(const std::string& path) {
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index 4c83a14..ee392fc 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -235,7 +235,7 @@
*
* Available since API level 33.
*/
-int android_tag_socket_with_uid(int sockfd, int tag, uid_t uid) __INTRODUCED_IN(33);
+int android_tag_socket_with_uid(int sockfd, uint32_t tag, uid_t uid) __INTRODUCED_IN(33);
/*
* Set the socket tag for traffic statistics on the specified socket.
@@ -245,14 +245,26 @@
* opened by another UID or was previously tagged by another UID. Subsequent
* calls always replace any existing parameters. The socket tag is kept when the
* socket is sent to another process using binder IPCs or other mechanisms such
- * as UNIX socket fd passing.
+ * as UNIX socket fd passing. The tag is a value defined by the caller and used
+ * together with uid for data traffic accounting, so that the function callers
+ * can account different types of data usage for a uid.
*
* Returns 0 on success, or a negative POSIX error code (see errno.h) on
* failure.
*
+ * Some possible error codes:
+ * -EBADF Bad socketfd.
+ * -EPERM No permission.
+ * -EAFNOSUPPORT Socket family is neither AF_INET nor AF_INET6.
+ * -EPROTONOSUPPORT Socket protocol is neither IPPROTO_UDP nor IPPROTO_TCP.
+ * -EMFILE Too many stats entries.
+ * There are still other error codes that may provided by -errno of
+ * [getsockopt()](https://man7.org/linux/man-pages/man2/getsockopt.2.html) or by
+ * BPF maps read/write sys calls, which are set appropriately.
+ *
* Available since API level 33.
*/
-int android_tag_socket(int sockfd, int tag) __INTRODUCED_IN(33);
+int android_tag_socket(int sockfd, uint32_t tag) __INTRODUCED_IN(33);
/*
* Untag a network socket.
@@ -267,6 +279,12 @@
* Returns 0 on success, or a negative POSIX error code (see errno.h) on
* failure.
*
+ * One of possible error code:
+ * -EBADF Bad socketfd.
+ * Other error codes are either provided by -errno of
+ * [getsockopt()](https://man7.org/linux/man-pages/man2/getsockopt.2.html) or by
+ * BPF map element deletion sys call, which are set appropriately.
+ *
* Available since API level 33.
*/
int android_untag_socket(int sockfd) __INTRODUCED_IN(33);
diff --git a/include/ftl/enum.h b/include/ftl/enum.h
index 5234c05..82af1d6 100644
--- a/include/ftl/enum.h
+++ b/include/ftl/enum.h
@@ -261,10 +261,10 @@
const auto value = to_underlying(v);
// TODO: Replace with std::popcount and std::countr_zero in C++20.
- if (__builtin_popcountl(value) != 1) return {};
+ if (__builtin_popcountll(value) != 1) return {};
constexpr auto kRange = details::EnumRange<E, details::FlagName>{};
- return kRange.values[__builtin_ctzl(value)];
+ return kRange.values[__builtin_ctzll(value)];
}
// Returns a stringified enumerator, or its integral value if not named.
diff --git a/include/ftl/fake_guard.h b/include/ftl/fake_guard.h
new file mode 100644
index 0000000..bacd1b2
--- /dev/null
+++ b/include/ftl/fake_guard.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#define FTL_ATTRIBUTE(a) __attribute__((a))
+
+namespace android::ftl {
+
+// Granular alternative to [[clang::no_thread_safety_analysis]]. Given a std::mutex-like object,
+// FakeGuard suppresses enforcement of thread-safe access to guarded variables within its scope.
+// While FakeGuard is scoped to a block, there are macro shorthands for a single expression, as
+// well as function/lambda scope (though calls must be indirect, e.g. virtual or std::function):
+//
+// struct {
+// std::mutex mutex;
+// int x FTL_ATTRIBUTE(guarded_by(mutex)) = -1;
+//
+// int f() {
+// {
+// ftl::FakeGuard guard(mutex);
+// x = 0;
+// }
+//
+// return FTL_FAKE_GUARD(mutex, x + 1);
+// }
+//
+// std::function<int()> g() const {
+// return [this]() FTL_FAKE_GUARD(mutex) { return x; };
+// }
+// } s;
+//
+// assert(s.f() == 1);
+// assert(s.g()() == 0);
+//
+// An example of a situation where FakeGuard helps is a mutex that guards writes on Thread 1, and
+// reads on Thread 2. Reads on Thread 1, which is the only writer, need not be under lock, so can
+// use FakeGuard to appease the thread safety analyzer. Another example is enforcing and documenting
+// exclusive access by a single thread. This is done by defining a global constant that represents a
+// thread context, and annotating guarded variables as if it were a mutex (though without any effect
+// at run time):
+//
+// constexpr class [[clang::capability("mutex")]] {
+// } kMainThreadContext;
+//
+template <typename Mutex>
+struct [[clang::scoped_lockable]] FakeGuard final {
+ explicit FakeGuard(const Mutex& mutex) FTL_ATTRIBUTE(acquire_capability(mutex)) {}
+ [[clang::release_capability()]] ~FakeGuard() {}
+
+ FakeGuard(const FakeGuard&) = delete;
+ FakeGuard& operator=(const FakeGuard&) = delete;
+};
+
+} // namespace android::ftl
+
+// TODO: Enable in C++23 once standard attributes can be used on lambdas.
+#if 0
+#define FTL_FAKE_GUARD1(mutex) [[using clang: acquire_capability(mutex), release_capability(mutex)]]
+#else
+#define FTL_FAKE_GUARD1(mutex) \
+ FTL_ATTRIBUTE(acquire_capability(mutex)) \
+ FTL_ATTRIBUTE(release_capability(mutex))
+#endif
+
+// The parentheses around `expr` are needed to deduce an lvalue or rvalue reference.
+#define FTL_FAKE_GUARD2(mutex, expr) \
+ [&]() -> decltype(auto) { \
+ const android::ftl::FakeGuard guard(mutex); \
+ return (expr); \
+ }()
+
+#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__)
diff --git a/include/ftl/Flags.h b/include/ftl/flags.h
similarity index 81%
rename from include/ftl/Flags.h
rename to include/ftl/flags.h
index 708eaf5..70aaa0e 100644
--- a/include/ftl/Flags.h
+++ b/include/ftl/flags.h
@@ -19,16 +19,15 @@
#include <ftl/enum.h>
#include <ftl/string.h>
+#include <bitset>
#include <cstdint>
#include <iterator>
#include <string>
#include <type_traits>
-#include "utils/BitSet.h"
+// TODO(b/185536303): Align with FTL style.
-// TODO(b/185536303): Align with FTL style and namespace.
-
-namespace android {
+namespace android::ftl {
/* A class for handling flags defined by an enum or enum class in a type-safe way. */
template <typename F>
@@ -49,28 +48,29 @@
// should force them to be explicitly constructed from their underlying types to make full use
// of the type checker.
template <typename T = U>
- constexpr Flags(T t, std::enable_if_t<!ftl::is_scoped_enum_v<F>, T>* = nullptr) : mFlags(t) {}
+ constexpr Flags(T t, std::enable_if_t<!is_scoped_enum_v<F>, T>* = nullptr) : mFlags(t) {}
template <typename T = U>
- explicit constexpr Flags(T t, std::enable_if_t<ftl::is_scoped_enum_v<F>, T>* = nullptr)
+ explicit constexpr Flags(T t, std::enable_if_t<is_scoped_enum_v<F>, T>* = nullptr)
: mFlags(t) {}
class Iterator {
- // The type can't be larger than 64-bits otherwise it won't fit in BitSet64.
- static_assert(sizeof(U) <= sizeof(uint64_t));
+ using Bits = std::uint64_t;
+ static_assert(sizeof(U) <= sizeof(Bits));
public:
+ constexpr Iterator() = default;
Iterator(Flags<F> flags) : mRemainingFlags(flags.mFlags) { (*this)++; }
- Iterator() : mRemainingFlags(0), mCurrFlag(static_cast<F>(0)) {}
// Pre-fix ++
Iterator& operator++() {
- if (mRemainingFlags.isEmpty()) {
- mCurrFlag = static_cast<F>(0);
+ if (mRemainingFlags.none()) {
+ mCurrFlag = 0;
} else {
- uint64_t bit = mRemainingFlags.clearLastMarkedBit(); // counts from left
- const U flag = 1 << (64 - bit - 1);
- mCurrFlag = static_cast<F>(flag);
+ // TODO: Replace with std::countr_zero in C++20.
+ const Bits bit = static_cast<Bits>(__builtin_ctzll(mRemainingFlags.to_ullong()));
+ mRemainingFlags.reset(static_cast<std::size_t>(bit));
+ mCurrFlag = static_cast<U>(static_cast<Bits>(1) << bit);
}
return *this;
}
@@ -88,7 +88,7 @@
bool operator!=(Iterator other) const { return !(*this == other); }
- F operator*() { return mCurrFlag; }
+ F operator*() const { return F{mCurrFlag}; }
// iterator traits
@@ -107,8 +107,8 @@
using pointer = void;
private:
- BitSet64 mRemainingFlags;
- F mCurrFlag;
+ std::bitset<sizeof(Bits) * 8> mRemainingFlags;
+ U mCurrFlag = 0;
};
/*
@@ -175,7 +175,7 @@
bool first = true;
U unstringified = 0;
for (const F f : *this) {
- if (const auto flagName = ftl::flag_name(f)) {
+ if (const auto flagName = flag_name(f)) {
appendFlag(result, flagName.value(), first);
} else {
unstringified |= static_cast<U>(f);
@@ -183,8 +183,8 @@
}
if (unstringified != 0) {
- constexpr auto radix = sizeof(U) == 1 ? ftl::Radix::kBin : ftl::Radix::kHex;
- appendFlag(result, ftl::to_string(unstringified, radix), first);
+ constexpr auto radix = sizeof(U) == 1 ? Radix::kBin : Radix::kHex;
+ appendFlag(result, to_string(unstringified, radix), first);
}
if (first) {
@@ -211,15 +211,15 @@
// as flags. In order to use these, add them via a `using namespace` declaration.
namespace flag_operators {
-template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>>
+template <typename F, typename = std::enable_if_t<is_scoped_enum_v<F>>>
inline Flags<F> operator~(F f) {
- return static_cast<F>(~ftl::to_underlying(f));
+ return static_cast<F>(~to_underlying(f));
}
-template <typename F, typename = std::enable_if_t<ftl::is_scoped_enum_v<F>>>
+template <typename F, typename = std::enable_if_t<is_scoped_enum_v<F>>>
Flags<F> operator|(F lhs, F rhs) {
- return static_cast<F>(ftl::to_underlying(lhs) | ftl::to_underlying(rhs));
+ return static_cast<F>(to_underlying(lhs) | to_underlying(rhs));
}
} // namespace flag_operators
-} // namespace android
+} // namespace android::ftl
diff --git a/include/input/PrintTools.h b/include/input/PrintTools.h
new file mode 100644
index 0000000..7c3b29b
--- /dev/null
+++ b/include/input/PrintTools.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <map>
+#include <set>
+#include <string>
+
+namespace android {
+
+template <typename T>
+std::string constToString(const T& v) {
+ return std::to_string(v);
+}
+
+/**
+ * Convert a set of integral types to string.
+ */
+template <typename T>
+std::string dumpSet(const std::set<T>& v, std::string (*toString)(const T&) = constToString) {
+ std::string out;
+ for (const T& entry : v) {
+ out += out.empty() ? "{" : ", ";
+ out += toString(entry);
+ }
+ return out.empty() ? "{}" : (out + "}");
+}
+
+/**
+ * Convert a map to string. Both keys and values of the map should be integral type.
+ */
+template <typename K, typename V>
+std::string dumpMap(const std::map<K, V>& map, std::string (*keyToString)(const K&) = constToString,
+ std::string (*valueToString)(const V&) = constToString) {
+ std::string out;
+ for (const auto& [k, v] : map) {
+ if (!out.empty()) {
+ out += "\n";
+ }
+ out += keyToString(k) + ":" + valueToString(v);
+ }
+ return out;
+}
+
+const char* toString(bool value);
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 01b25d3..39befbe 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -582,6 +582,10 @@
BBinder::~BBinder()
{
+ if (!wasParceled() && getExtension()) {
+ ALOGW("Binder %p destroyed with extension attached before being parceled.", this);
+ }
+
Extras* e = mExtras.load(std::memory_order_relaxed);
if (e) delete e;
}
diff --git a/libs/binder/IUidObserver.cpp b/libs/binder/IUidObserver.cpp
index a1b08db..d952dc7 100644
--- a/libs/binder/IUidObserver.cpp
+++ b/libs/binder/IUidObserver.cpp
@@ -57,8 +57,7 @@
}
virtual void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
- int32_t capability)
- {
+ int32_t capability) {
Parcel data, reply;
data.writeInterfaceToken(IUidObserver::getInterfaceDescriptor());
data.writeInt32((int32_t) uid);
@@ -67,6 +66,12 @@
data.writeInt32(capability);
remote()->transact(ON_UID_STATE_CHANGED_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ virtual void onUidProcAdjChanged(uid_t uid) {
+ Parcel data, reply;
+ data.writeInt32((int32_t)uid);
+ remote()->transact(ON_UID_PROC_ADJ_CHANGED_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
// ----------------------------------------------------------------------
@@ -102,6 +107,7 @@
onUidIdle(uid, disabled);
return NO_ERROR;
} break;
+
case ON_UID_STATE_CHANGED_TRANSACTION: {
CHECK_INTERFACE(IUidObserver, data, reply);
uid_t uid = data.readInt32();
@@ -111,6 +117,14 @@
onUidStateChanged(uid, procState, procStateSeq, capability);
return NO_ERROR;
} break;
+
+ case ON_UID_PROC_ADJ_CHANGED_TRANSACTION: {
+ CHECK_INTERFACE(IUidObserver, data, reply);
+ uid_t uid = data.readInt32();
+ onUidProcAdjChanged(uid);
+ return NO_ERROR;
+ } break;
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index be50a75..58b0b35 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1584,6 +1584,7 @@
template<class T>
status_t Parcel::readAligned(T *pArg) const {
static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
+ static_assert(std::is_trivially_copyable_v<T>);
if ((mDataPos+sizeof(T)) <= mDataSize) {
if (mObjectsSize > 0) {
@@ -1595,9 +1596,8 @@
}
}
- const void* data = mData+mDataPos;
+ memcpy(pArg, mData + mDataPos, sizeof(T));
mDataPos += sizeof(T);
- *pArg = *reinterpret_cast<const T*>(data);
return NO_ERROR;
} else {
return NOT_ENOUGH_DATA;
@@ -1617,10 +1617,11 @@
template<class T>
status_t Parcel::writeAligned(T val) {
static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
+ static_assert(std::is_trivially_copyable_v<T>);
if ((mDataPos+sizeof(val)) <= mDataCapacity) {
restart_write:
- *reinterpret_cast<T*>(mData+mDataPos) = val;
+ memcpy(mData + mDataPos, &val, sizeof(val));
return finishWrite(sizeof(val));
}
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 2e7084e..6d89064 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -313,7 +313,8 @@
const sp<RpcSession>& session, const char* what, iovec* iovs, int niovs,
const std::function<status_t()>& altPoll) {
for (int i = 0; i < niovs; i++) {
- LOG_RPC_DETAIL("Sending %s on RpcTransport %p: %s", what, connection->rpcTransport.get(),
+ LOG_RPC_DETAIL("Sending %s (part %d of %d) on RpcTransport %p: %s",
+ what, i + 1, niovs, connection->rpcTransport.get(),
android::base::HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
}
@@ -343,7 +344,8 @@
}
for (int i = 0; i < niovs; i++) {
- LOG_RPC_DETAIL("Received %s on RpcTransport %p: %s", what, connection->rpcTransport.get(),
+ LOG_RPC_DETAIL("Received %s (part %d of %d) on RpcTransport %p: %s",
+ what, i + 1, niovs, connection->rpcTransport.get(),
android::base::HexString(iovs[i].iov_base, iovs[i].iov_len).c_str());
}
return OK;
@@ -660,8 +662,14 @@
status_t RpcState::drainCommands(const sp<RpcSession::RpcConnection>& connection,
const sp<RpcSession>& session, CommandType type) {
uint8_t buf;
- while (connection->rpcTransport->peek(&buf, sizeof(buf)).value_or(0) > 0) {
- status_t status = getAndExecuteCommand(connection, session, type);
+ while (true) {
+ size_t num_bytes;
+ status_t status = connection->rpcTransport->peek(&buf, sizeof(buf), &num_bytes);
+ if (status == WOULD_BLOCK) break;
+ if (status != OK) return status;
+ if (!num_bytes) break;
+
+ status = getAndExecuteCommand(connection, session, type);
if (status != OK) return status;
}
return OK;
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 636e5d0..7cfc780 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -24,9 +24,6 @@
#include "FdTrigger.h"
#include "RpcState.h"
-using android::base::ErrnoError;
-using android::base::Result;
-
namespace android {
namespace {
@@ -35,12 +32,20 @@
class RpcTransportRaw : public RpcTransport {
public:
explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
- Result<size_t> peek(void *buf, size_t size) override {
+ status_t peek(void* buf, size_t size, size_t* out_size) override {
ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK));
if (ret < 0) {
- return ErrnoError() << "recv(MSG_PEEK)";
+ int savedErrno = errno;
+ if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
+ return WOULD_BLOCK;
+ }
+
+ LOG_RPC_DETAIL("RpcTransport peek(): %s", strerror(savedErrno));
+ return -savedErrno;
}
- return ret;
+
+ *out_size = static_cast<size_t>(ret);
+ return OK;
}
template <typename SendOrReceive>
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
index 3936204..bc68c37 100644
--- a/libs/binder/RpcTransportTls.cpp
+++ b/libs/binder/RpcTransportTls.cpp
@@ -37,10 +37,6 @@
#define LOG_TLS_DETAIL(...) ALOGV(__VA_ARGS__) // for type checking
#endif
-using android::base::ErrnoError;
-using android::base::Error;
-using android::base::Result;
-
namespace android {
namespace {
@@ -165,17 +161,8 @@
return ret;
}
- // |sslError| should be from Ssl::getError().
- // If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise
- // return error. Also return error if |fdTrigger| is triggered before or during poll().
- status_t pollForSslError(android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger,
- const char* fnString, int additionalEvent,
- const std::function<status_t()>& altPoll) {
+ status_t toStatus(int sslError, const char* fnString) {
switch (sslError) {
- case SSL_ERROR_WANT_READ:
- return handlePoll(POLLIN | additionalEvent, fd, fdTrigger, fnString, altPoll);
- case SSL_ERROR_WANT_WRITE:
- return handlePoll(POLLOUT | additionalEvent, fd, fdTrigger, fnString, altPoll);
case SSL_ERROR_SYSCALL: {
auto queue = toString();
LOG_TLS_DETAIL("%s(): %s. Treating as DEAD_OBJECT. Error queue: %s", fnString,
@@ -191,6 +178,22 @@
}
}
+ // |sslError| should be from Ssl::getError().
+ // If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise
+ // return error. Also return error if |fdTrigger| is triggered before or during poll().
+ status_t pollForSslError(android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger,
+ const char* fnString, int additionalEvent,
+ const std::function<status_t()>& altPoll) {
+ switch (sslError) {
+ case SSL_ERROR_WANT_READ:
+ return handlePoll(POLLIN | additionalEvent, fd, fdTrigger, fnString, altPoll);
+ case SSL_ERROR_WANT_WRITE:
+ return handlePoll(POLLOUT | additionalEvent, fd, fdTrigger, fnString, altPoll);
+ default:
+ return toStatus(sslError, fnString);
+ }
+ }
+
private:
bool mHandled = false;
@@ -274,7 +277,7 @@
public:
RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
: mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
- Result<size_t> peek(void* buf, size_t size) override;
+ status_t peek(void* buf, size_t size, size_t* out_size) override;
status_t interruptableWriteFully(FdTrigger* fdTrigger, iovec* iovs, int niovs,
const std::function<status_t()>& altPoll) override;
status_t interruptableReadFully(FdTrigger* fdTrigger, iovec* iovs, int niovs,
@@ -286,7 +289,7 @@
};
// Error code is errno.
-Result<size_t> RpcTransportTls::peek(void* buf, size_t size) {
+status_t RpcTransportTls::peek(void* buf, size_t size, size_t* out_size) {
size_t todo = std::min<size_t>(size, std::numeric_limits<int>::max());
auto [ret, errorQueue] = mSsl.call(SSL_peek, buf, static_cast<int>(todo));
if (ret < 0) {
@@ -294,13 +297,15 @@
if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
// Seen EAGAIN / EWOULDBLOCK on recv(2) / send(2).
// Like RpcTransportRaw::peek(), don't handle it here.
- return Error(EWOULDBLOCK) << "SSL_peek(): " << errorQueue.toString();
+ errorQueue.clear();
+ return WOULD_BLOCK;
}
- return Error() << "SSL_peek(): " << errorQueue.toString();
+ return errorQueue.toStatus(err, "SSL_peek");
}
errorQueue.clear();
LOG_TLS_DETAIL("TLS: Peeked %d bytes!", ret);
- return ret;
+ *out_size = static_cast<size_t>(ret);
+ return OK;
}
status_t RpcTransportTls::interruptableWriteFully(FdTrigger* fdTrigger, iovec* iovs, int niovs,
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index ade2d94..751c4f9 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -22,7 +22,6 @@
#include <memory>
#include <string>
-#include <android-base/result.h>
#include <android-base/unique_fd.h>
#include <utils/Errors.h>
@@ -41,7 +40,7 @@
virtual ~RpcTransport() = default;
// replacement of ::recv(MSG_PEEK). Error code may not be set if TLS is enabled.
- [[nodiscard]] virtual android::base::Result<size_t> peek(void *buf, size_t size) = 0;
+ [[nodiscard]] virtual status_t peek(void *buf, size_t size, size_t *out_size) = 0;
/**
* Read (or write), but allow to be interrupted by a trigger.
diff --git a/libs/binder/include_activitymanager/binder/ActivityManager.h b/libs/binder/include_activitymanager/binder/ActivityManager.h
index abc7f1d..5dfbd44 100644
--- a/libs/binder/include_activitymanager/binder/ActivityManager.h
+++ b/libs/binder/include_activitymanager/binder/ActivityManager.h
@@ -31,20 +31,21 @@
class ActivityManager
{
public:
-
enum {
// Flag for registerUidObserver: report uid state changed
- UID_OBSERVER_PROCSTATE = 1<<0,
+ UID_OBSERVER_PROCSTATE = 1 << 0,
// Flag for registerUidObserver: report uid gone
- UID_OBSERVER_GONE = 1<<1,
+ UID_OBSERVER_GONE = 1 << 1,
// Flag for registerUidObserver: report uid has become idle
- UID_OBSERVER_IDLE = 1<<2,
+ UID_OBSERVER_IDLE = 1 << 2,
// Flag for registerUidObserver: report uid has become active
- UID_OBSERVER_ACTIVE = 1<<3,
+ UID_OBSERVER_ACTIVE = 1 << 3,
// Flag for registerUidObserver: report uid cached state has changed
- UID_OBSERVER_CACHED = 1<<4,
+ UID_OBSERVER_CACHED = 1 << 4,
// Flag for registerUidObserver: report uid capability has changed
- UID_OBSERVER_CAPABILITY = 1<<5,
+ UID_OBSERVER_CAPABILITY = 1 << 5,
+ // Flag for registerUidObserver: report pid oom adj has changed
+ UID_OBSERVER_PROC_OOM_ADJ = 1 << 6,
};
// PROCESS_STATE_* must come from frameworks/base/core/java/android/app/ProcessStateEnum.aidl.
diff --git a/libs/binder/include_activitymanager/binder/IUidObserver.h b/libs/binder/include_activitymanager/binder/IUidObserver.h
index 9291c0b..17f03a9 100644
--- a/libs/binder/include_activitymanager/binder/IUidObserver.h
+++ b/libs/binder/include_activitymanager/binder/IUidObserver.h
@@ -33,13 +33,15 @@
virtual void onUidActive(uid_t uid) = 0;
virtual void onUidIdle(uid_t uid, bool disabled) = 0;
virtual void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
- int32_t capability) = 0;
+ int32_t capability) = 0;
+ virtual void onUidProcAdjChanged(uid_t uid) = 0;
enum {
ON_UID_GONE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
ON_UID_ACTIVE_TRANSACTION,
ON_UID_IDLE_TRANSACTION,
- ON_UID_STATE_CHANGED_TRANSACTION
+ ON_UID_STATE_CHANGED_TRANSACTION,
+ ON_UID_PROC_ADJ_CHANGED_TRANSACTION
};
};
diff --git a/libs/binder/tests/binderBinderUnitTest.cpp b/libs/binder/tests/binderBinderUnitTest.cpp
index 1be0c59..ce2770f 100644
--- a/libs/binder/tests/binderBinderUnitTest.cpp
+++ b/libs/binder/tests/binderBinderUnitTest.cpp
@@ -41,3 +41,10 @@
EXPECT_EQ(kObject1, binder->detachObject(kObjectId1));
EXPECT_EQ(nullptr, binder->attachObject(kObjectId1, kObject2, nullptr, nullptr));
}
+
+TEST(Binder, AttachExtension) {
+ auto binder = sp<BBinder>::make();
+ auto ext = sp<BBinder>::make();
+ binder->setExtension(ext);
+ EXPECT_EQ(ext, binder->getExtension());
+}
diff --git a/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
index 094addd..50d12c4 100644
--- a/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
+++ b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
@@ -18,6 +18,7 @@
#include <memory>
#include <mutex>
+#include <vector>
#include <binder/RpcAuth.h>
#include <binder/RpcCertificateFormat.h>
diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp
index c5d3a32..5f145a1 100644
--- a/libs/bufferqueueconverter/Android.bp
+++ b/libs/bufferqueueconverter/Android.bp
@@ -22,6 +22,7 @@
double_loadable: true,
srcs: [
+ ":libgui_frame_event_aidl",
"BufferQueueConverter.cpp",
],
diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp
index bc2eb23..c010a2e 100644
--- a/libs/ftl/Android.bp
+++ b/libs/ftl/Android.bp
@@ -14,10 +14,11 @@
address: true,
},
srcs: [
- "Flags_test.cpp",
"cast_test.cpp",
"concat_test.cpp",
"enum_test.cpp",
+ "fake_guard_test.cpp",
+ "flags_test.cpp",
"future_test.cpp",
"small_map_test.cpp",
"small_vector_test.cpp",
@@ -29,13 +30,6 @@
"-Werror",
"-Wextra",
"-Wpedantic",
- ],
-
- header_libs: [
- "libbase_headers",
- ],
-
- shared_libs: [
- "libbase",
+ "-Wthread-safety",
],
}
diff --git a/libs/ftl/enum_test.cpp b/libs/ftl/enum_test.cpp
index d8ce7a5..5592a01 100644
--- a/libs/ftl/enum_test.cpp
+++ b/libs/ftl/enum_test.cpp
@@ -143,6 +143,16 @@
EXPECT_EQ(ftl::flag_string(Flags::kNone), "0b0");
EXPECT_EQ(ftl::flag_string(Flags::kMask), "0b10010010");
EXPECT_EQ(ftl::flag_string(Flags::kAll), "0b11111111");
+
+ enum class Flags64 : std::uint64_t {
+ kFlag0 = 0b1ull,
+ kFlag63 = 0x8000'0000'0000'0000ull,
+ kMask = kFlag0 | kFlag63
+ };
+
+ EXPECT_EQ(ftl::flag_string(Flags64::kFlag0), "kFlag0");
+ EXPECT_EQ(ftl::flag_string(Flags64::kFlag63), "kFlag63");
+ EXPECT_EQ(ftl::flag_string(Flags64::kMask), "0x8000000000000001");
}
{
EXPECT_EQ(ftl::enum_string(Planet::kEarth), "kEarth");
diff --git a/libs/ftl/fake_guard_test.cpp b/libs/ftl/fake_guard_test.cpp
new file mode 100644
index 0000000..9d36e69
--- /dev/null
+++ b/libs/ftl/fake_guard_test.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ftl/fake_guard.h>
+#include <gtest/gtest.h>
+
+#include <functional>
+#include <mutex>
+
+namespace android::test {
+
+// Keep in sync with example usage in header file.
+TEST(FakeGuard, Example) {
+ struct {
+ std::mutex mutex;
+ int x FTL_ATTRIBUTE(guarded_by(mutex)) = -1;
+
+ int f() {
+ {
+ ftl::FakeGuard guard(mutex);
+ x = 0;
+ }
+
+ return FTL_FAKE_GUARD(mutex, x + 1);
+ }
+
+ std::function<int()> g() const {
+ return [this]() FTL_FAKE_GUARD(mutex) { return x; };
+ }
+ } s;
+
+ EXPECT_EQ(s.f(), 1);
+ EXPECT_EQ(s.g()(), 0);
+}
+
+} // namespace android::test
diff --git a/libs/ftl/Flags_test.cpp b/libs/ftl/flags_test.cpp
similarity index 98%
rename from libs/ftl/Flags_test.cpp
rename to libs/ftl/flags_test.cpp
index d241fa2..eea052b 100644
--- a/libs/ftl/Flags_test.cpp
+++ b/libs/ftl/flags_test.cpp
@@ -14,14 +14,15 @@
* limitations under the License.
*/
+#include <ftl/flags.h>
#include <gtest/gtest.h>
-#include <ftl/Flags.h>
#include <type_traits>
namespace android::test {
-using namespace android::flag_operators;
+using ftl::Flags;
+using namespace ftl::flag_operators;
enum class TestFlags : uint8_t { ONE = 0x1, TWO = 0x2, THREE = 0x4 };
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index d634c58..6b64ac8 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -120,6 +120,12 @@
path: "aidl/",
}
+filegroup {
+ name: "libgui_frame_event_aidl",
+ srcs: ["aidl/android/gui/FrameEvent.aidl"],
+ path: "aidl/",
+}
+
cc_library_static {
name: "libgui_aidl_static",
vendor_available: true,
@@ -405,6 +411,7 @@
],
srcs: [
+ ":libgui_frame_event_aidl",
"mock/GraphicBufferConsumer.cpp",
"mock/GraphicBufferProducer.cpp",
],
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index c5de09a..a10a2f0 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -26,7 +26,6 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
-#include <gui/LayerDebugInfo.h>
#include <gui/LayerState.h>
#include <private/gui/ParcelUtils.h>
#include <stdint.h>
@@ -159,49 +158,6 @@
return result != 0;
}
- status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override {
- if (!outSupported) {
- return UNEXPECTED_NULL;
- }
- outSupported->clear();
-
- Parcel data, reply;
-
- status_t err = data.writeInterfaceToken(
- ISurfaceComposer::getInterfaceDescriptor());
- if (err != NO_ERROR) {
- return err;
- }
-
- err = remote()->transact(
- BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS,
- data, &reply);
- if (err != NO_ERROR) {
- return err;
- }
-
- int32_t result = 0;
- err = reply.readInt32(&result);
- if (err != NO_ERROR) {
- return err;
- }
- if (result != NO_ERROR) {
- return result;
- }
-
- std::vector<int32_t> supported;
- err = reply.readInt32Vector(&supported);
- if (err != NO_ERROR) {
- return err;
- }
-
- outSupported->reserve(supported.size());
- for (int32_t s : supported) {
- outSupported->push_back(static_cast<FrameEvent>(s));
- }
- return NO_ERROR;
- }
-
sp<IDisplayEventConnection> createDisplayEventConnection(
VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) override {
Parcel data, reply;
@@ -225,316 +181,6 @@
return result;
}
- status_t getDynamicDisplayInfo(const sp<IBinder>& display,
- ui::DynamicDisplayInfo* info) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- remote()->transact(BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO, data, &reply);
- const status_t result = reply.readInt32();
- if (result != NO_ERROR) return result;
- return reply.read(*info);
- }
-
- status_t getDisplayNativePrimaries(const sp<IBinder>& display,
- ui::DisplayPrimaries& primaries) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to writeStrongBinder: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_NATIVE_PRIMARIES, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to transact: %d", result);
- return result;
- }
- result = reply.readInt32();
- if (result == NO_ERROR) {
- memcpy(&primaries, reply.readInplace(sizeof(ui::DisplayPrimaries)),
- sizeof(ui::DisplayPrimaries));
- }
- return result;
- }
-
- status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result);
- return result;
- }
- result = data.writeInt32(static_cast<int32_t>(colorMode));
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to writeInt32: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::SET_ACTIVE_COLOR_MODE, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to transact: %d", result);
- return result;
- }
- return static_cast<status_t>(reply.readInt32());
- }
-
- status_t setBootDisplayMode(const sp<IBinder>& display,
- ui::DisplayModeId displayModeId) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to writeStrongBinder: %d", result);
- return result;
- }
- result = data.writeInt32(displayModeId);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to writeIint32: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::SET_BOOT_DISPLAY_MODE, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to transact: %d", result);
- }
- return result;
- }
-
- status_t clearAnimationFrameStats() override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("clearAnimationFrameStats failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("clearAnimationFrameStats failed to transact: %d", result);
- return result;
- }
- return reply.readInt32();
- }
-
- status_t getAnimationFrameStats(FrameStats* outStats) const override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply);
- reply.read(*outStats);
- return reply.readInt32();
- }
-
- virtual status_t overrideHdrTypes(const sp<IBinder>& display,
- const std::vector<ui::Hdr>& hdrTypes) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, display);
-
- std::vector<int32_t> hdrTypesVector;
- for (ui::Hdr i : hdrTypes) {
- hdrTypesVector.push_back(static_cast<int32_t>(i));
- }
- SAFE_PARCEL(data.writeInt32Vector, hdrTypesVector);
-
- status_t result = remote()->transact(BnSurfaceComposer::OVERRIDE_HDR_TYPES, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("overrideHdrTypes failed to transact: %d", result);
- return result;
- }
- return result;
- }
-
- status_t onPullAtom(const int32_t atomId, std::string* pulledData, bool* success) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeInt32, atomId);
-
- status_t err = remote()->transact(BnSurfaceComposer::ON_PULL_ATOM, data, &reply);
- if (err != NO_ERROR) {
- ALOGE("onPullAtom failed to transact: %d", err);
- return err;
- }
-
- int32_t size = 0;
- SAFE_PARCEL(reply.readInt32, &size);
- const void* dataPtr = reply.readInplace(size);
- if (dataPtr == nullptr) {
- return UNEXPECTED_NULL;
- }
- pulledData->assign((const char*)dataPtr, size);
- SAFE_PARCEL(reply.readBool, success);
- return NO_ERROR;
- }
-
- status_t enableVSyncInjections(bool enable) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeBool(enable);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to writeBool: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS, data, &reply,
- IBinder::FLAG_ONEWAY);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to transact: %d", result);
- return result;
- }
- return result;
- }
-
- status_t injectVSync(nsecs_t when) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("injectVSync failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeInt64(when);
- if (result != NO_ERROR) {
- ALOGE("injectVSync failed to writeInt64: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::INJECT_VSYNC, data, &reply,
- IBinder::FLAG_ONEWAY);
- if (result != NO_ERROR) {
- ALOGE("injectVSync failed to transact: %d", result);
- return result;
- }
- return result;
- }
-
- status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override {
- if (!outLayers) {
- return UNEXPECTED_NULL;
- }
-
- Parcel data, reply;
-
- status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (err != NO_ERROR) {
- return err;
- }
-
- err = remote()->transact(BnSurfaceComposer::GET_LAYER_DEBUG_INFO, data, &reply);
- if (err != NO_ERROR) {
- return err;
- }
-
- int32_t result = 0;
- err = reply.readInt32(&result);
- if (err != NO_ERROR) {
- return err;
- }
- if (result != NO_ERROR) {
- return result;
- }
-
- outLayers->clear();
- return reply.readParcelableVector(outLayers);
- }
-
- status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
- ui::PixelFormat* defaultPixelFormat,
- ui::Dataspace* wideColorGamutDataspace,
- ui::PixelFormat* wideColorGamutPixelFormat) const override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::GET_COMPOSITION_PREFERENCE, data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
- error = static_cast<status_t>(reply.readInt32());
- if (error == NO_ERROR) {
- *defaultDataspace = static_cast<ui::Dataspace>(reply.readInt32());
- *defaultPixelFormat = static_cast<ui::PixelFormat>(reply.readInt32());
- *wideColorGamutDataspace = static_cast<ui::Dataspace>(reply.readInt32());
- *wideColorGamutPixelFormat = static_cast<ui::PixelFormat>(reply.readInt32());
- }
- return error;
- }
-
- status_t getColorManagement(bool* outGetColorManagement) const override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::GET_COLOR_MANAGEMENT, data, &reply);
- bool result;
- status_t err = reply.readBool(&result);
- if (err == NO_ERROR) {
- *outGetColorManagement = result;
- }
- return err;
- }
-
- status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
- ui::PixelFormat* outFormat,
- ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const override {
- if (!outFormat || !outDataspace || !outComponentMask) return BAD_VALUE;
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
-
- status_t error =
- remote()->transact(BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
- data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
-
- uint32_t value = 0;
- error = reply.readUint32(&value);
- if (error != NO_ERROR) {
- return error;
- }
- *outFormat = static_cast<ui::PixelFormat>(value);
-
- error = reply.readUint32(&value);
- if (error != NO_ERROR) {
- return error;
- }
- *outDataspace = static_cast<ui::Dataspace>(value);
-
- error = reply.readUint32(&value);
- if (error != NO_ERROR) {
- return error;
- }
- *outComponentMask = static_cast<uint8_t>(value);
- return error;
- }
-
- status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask, uint64_t maxFrames) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- data.writeBool(enable);
- data.writeByte(static_cast<int8_t>(componentMask));
- data.writeUint64(maxFrames);
- status_t result =
- remote()->transact(BnSurfaceComposer::SET_DISPLAY_CONTENT_SAMPLING_ENABLED, data,
- &reply);
- return result;
- }
-
status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
uint64_t timestamp,
DisplayedFrameStats* outStats) const override {
@@ -574,18 +220,6 @@
return result;
}
- status_t getProtectedContentSupport(bool* outSupported) const override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- status_t error =
- remote()->transact(BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT, data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
- error = reply.readBool(outSupported);
- return error;
- }
-
status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) override {
Parcel data, reply;
@@ -1103,25 +737,6 @@
reply->writeInt32(result);
return NO_ERROR;
}
- case GET_SUPPORTED_FRAME_TIMESTAMPS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- std::vector<FrameEvent> supportedTimestamps;
- status_t result = getSupportedFrameTimestamps(&supportedTimestamps);
- status_t err = reply->writeInt32(result);
- if (err != NO_ERROR) {
- return err;
- }
- if (result != NO_ERROR) {
- return result;
- }
-
- std::vector<int32_t> supported;
- supported.reserve(supportedTimestamps.size());
- for (FrameEvent s : supportedTimestamps) {
- supported.push_back(static_cast<int32_t>(s));
- }
- return reply->writeInt32Vector(supported);
- }
case CREATE_DISPLAY_EVENT_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
@@ -1133,195 +748,6 @@
reply->writeStrongBinder(IInterface::asBinder(connection));
return NO_ERROR;
}
- case GET_DYNAMIC_DISPLAY_INFO: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::DynamicDisplayInfo info;
- const sp<IBinder> display = data.readStrongBinder();
- const status_t result = getDynamicDisplayInfo(display, &info);
- SAFE_PARCEL(reply->writeInt32, result);
- if (result != NO_ERROR) return result;
- SAFE_PARCEL(reply->write, info);
- return NO_ERROR;
- }
- case GET_DISPLAY_NATIVE_PRIMARIES: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::DisplayPrimaries primaries;
- sp<IBinder> display = nullptr;
-
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to readStrongBinder: %d", result);
- return result;
- }
-
- result = getDisplayNativePrimaries(display, primaries);
- reply->writeInt32(result);
- if (result == NO_ERROR) {
- memcpy(reply->writeInplace(sizeof(ui::DisplayPrimaries)), &primaries,
- sizeof(ui::DisplayPrimaries));
- }
-
- return NO_ERROR;
- }
- case SET_ACTIVE_COLOR_MODE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
- return result;
- }
- int32_t colorModeInt = 0;
- result = data.readInt32(&colorModeInt);
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to readInt32: %d", result);
- return result;
- }
- result = setActiveColorMode(display,
- static_cast<ColorMode>(colorModeInt));
- result = reply->writeInt32(result);
- return result;
- }
- case SET_BOOT_DISPLAY_MODE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to readStrongBinder: %d", result);
- return result;
- }
- ui::DisplayModeId displayModeId;
- result = data.readInt32(&displayModeId);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to readInt32: %d", result);
- return result;
- }
- return setBootDisplayMode(display, displayModeId);
- }
- case CLEAR_ANIMATION_FRAME_STATS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- status_t result = clearAnimationFrameStats();
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case GET_ANIMATION_FRAME_STATS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- FrameStats stats;
- status_t result = getAnimationFrameStats(&stats);
- reply->write(stats);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case ENABLE_VSYNC_INJECTIONS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bool enable = false;
- status_t result = data.readBool(&enable);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to readBool: %d", result);
- return result;
- }
- return enableVSyncInjections(enable);
- }
- case INJECT_VSYNC: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int64_t when = 0;
- status_t result = data.readInt64(&when);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to readInt64: %d", result);
- return result;
- }
- return injectVSync(when);
- }
- case GET_LAYER_DEBUG_INFO: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- std::vector<LayerDebugInfo> outLayers;
- status_t result = getLayerDebugInfo(&outLayers);
- reply->writeInt32(result);
- if (result == NO_ERROR)
- {
- result = reply->writeParcelableVector(outLayers);
- }
- return result;
- }
- case GET_COMPOSITION_PREFERENCE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::Dataspace defaultDataspace;
- ui::PixelFormat defaultPixelFormat;
- ui::Dataspace wideColorGamutDataspace;
- ui::PixelFormat wideColorGamutPixelFormat;
- status_t error =
- getCompositionPreference(&defaultDataspace, &defaultPixelFormat,
- &wideColorGamutDataspace, &wideColorGamutPixelFormat);
- reply->writeInt32(error);
- if (error == NO_ERROR) {
- reply->writeInt32(static_cast<int32_t>(defaultDataspace));
- reply->writeInt32(static_cast<int32_t>(defaultPixelFormat));
- reply->writeInt32(static_cast<int32_t>(wideColorGamutDataspace));
- reply->writeInt32(static_cast<int32_t>(wideColorGamutPixelFormat));
- }
- return error;
- }
- case GET_COLOR_MANAGEMENT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bool result;
- status_t error = getColorManagement(&result);
- if (error == NO_ERROR) {
- reply->writeBool(result);
- }
- return error;
- }
- case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
- sp<IBinder> display = data.readStrongBinder();
- ui::PixelFormat format;
- ui::Dataspace dataspace;
- uint8_t component = 0;
- auto result =
- getDisplayedContentSamplingAttributes(display, &format, &dataspace, &component);
- if (result == NO_ERROR) {
- reply->writeUint32(static_cast<uint32_t>(format));
- reply->writeUint32(static_cast<uint32_t>(dataspace));
- reply->writeUint32(static_cast<uint32_t>(component));
- }
- return result;
- }
- case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
- sp<IBinder> display = nullptr;
- bool enable = false;
- int8_t componentMask = 0;
- uint64_t maxFrames = 0;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading Display token: %d",
- result);
- return result;
- }
-
- result = data.readBool(&enable);
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading enable: %d", result);
- return result;
- }
-
- result = data.readByte(static_cast<int8_t*>(&componentMask));
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading component mask: %d",
- result);
- return result;
- }
-
- result = data.readUint64(&maxFrames);
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading max frames: %d", result);
- return result;
- }
-
- return setDisplayContentSamplingEnabled(display, enable,
- static_cast<uint8_t>(componentMask), maxFrames);
- }
case GET_DISPLAYED_CONTENT_SAMPLE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -1352,15 +778,6 @@
}
return result;
}
- case GET_PROTECTED_CONTENT_SUPPORT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bool result;
- status_t error = getProtectedContentSupport(&result);
- if (error == NO_ERROR) {
- reply->writeBool(result);
- }
- return error;
- }
case ADD_REGION_SAMPLING_LISTENER: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
Rect samplingArea;
@@ -1664,33 +1081,6 @@
SAFE_PARCEL(reply->writeInt32, buffers);
return NO_ERROR;
}
- case OVERRIDE_HDR_TYPES: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- SAFE_PARCEL(data.readStrongBinder, &display);
-
- std::vector<int32_t> hdrTypes;
- SAFE_PARCEL(data.readInt32Vector, &hdrTypes);
-
- std::vector<ui::Hdr> hdrTypesVector;
- for (int i : hdrTypes) {
- hdrTypesVector.push_back(static_cast<ui::Hdr>(i));
- }
- return overrideHdrTypes(display, hdrTypesVector);
- }
- case ON_PULL_ATOM: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int32_t atomId = 0;
- SAFE_PARCEL(data.readInt32, &atomId);
-
- std::string pulledData;
- bool success;
- status_t err = onPullAtom(atomId, &pulledData, &success);
- SAFE_PARCEL(reply->writeByteArray, pulledData.size(),
- reinterpret_cast<const uint8_t*>(pulledData.data()));
- SAFE_PARCEL(reply->writeBool, success);
- return err;
- }
case ADD_WINDOW_INFOS_LISTENER: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IWindowInfosListener> listener;
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index ea5fb29..15b2221 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -27,7 +27,7 @@
#define RETURN_ON_ERROR(X) do {status_t res = (X); if (res != NO_ERROR) return res;} while(false)
-namespace android {
+namespace android::gui {
status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const {
RETURN_ON_ERROR(parcel->writeCString(mName.c_str()));
@@ -149,4 +149,4 @@
return result;
}
-} // android
+} // namespace android::gui
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 34db5b1..f7cd5c4 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -134,6 +134,7 @@
SAFE_PARCEL(output.writeByte, changeFrameRateStrategy);
SAFE_PARCEL(output.writeUint32, fixedTransformHint);
SAFE_PARCEL(output.writeBool, autoRefresh);
+ SAFE_PARCEL(output.writeBool, dimmingEnabled);
SAFE_PARCEL(output.writeUint32, blurRegions.size());
for (auto region : blurRegions) {
@@ -243,6 +244,7 @@
SAFE_PARCEL(input.readUint32, &tmpUint32);
fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
SAFE_PARCEL(input.readBool, &autoRefresh);
+ SAFE_PARCEL(input.readBool, &dimmingEnabled);
uint32_t numRegions = 0;
SAFE_PARCEL(input.readUint32, &numRegions);
@@ -598,6 +600,10 @@
what |= eColorSpaceAgnosticChanged;
colorSpaceAgnostic = other.colorSpaceAgnostic;
}
+ if (other.what & eDimmingEnabledChanged) {
+ what |= eDimmingEnabledChanged;
+ dimmingEnabled = other.dimmingEnabled;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
"other.what=0x%" PRIX64 " what=0x%" PRIX64 " unmerged flags=0x%" PRIX64,
@@ -815,7 +821,7 @@
status_t BufferData::readFromParcel(const Parcel* input) {
int32_t tmpInt32;
SAFE_PARCEL(input->readInt32, &tmpInt32);
- flags = Flags<BufferDataChange>(tmpInt32);
+ flags = ftl::Flags<BufferDataChange>(tmpInt32);
bool tmpBool = false;
SAFE_PARCEL(input->readBool, &tmpBool);
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 0f0a5c8..a40837c 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -366,12 +366,13 @@
return NAME_NOT_FOUND;
}
- ui::DynamicDisplayInfo info;
- if (status_t err = composerService()->getDynamicDisplayInfo(display, &info); err != NO_ERROR) {
- return err;
+ gui::DynamicDisplayInfo info;
+ if (binder::Status status = composerServiceAIDL()->getDynamicDisplayInfo(display, &info);
+ !status.isOk()) {
+ return status.transactionError();
}
- *supported = !info.hdrCapabilities.getSupportedHdrTypes().empty();
+ *supported = !info.hdrCapabilities.supportedHdrTypes.empty();
return NO_ERROR;
}
@@ -1101,6 +1102,17 @@
*out = input;
}
+void Surface::applyGrallocMetadataLocked(
+ android_native_buffer_t* buffer,
+ const IGraphicBufferProducer::QueueBufferInput& queueBufferInput) {
+ ATRACE_CALL();
+ auto& mapper = GraphicBufferMapper::get();
+ mapper.setDataspace(buffer->handle, static_cast<ui::Dataspace>(queueBufferInput.dataSpace));
+ mapper.setSmpte2086(buffer->handle, queueBufferInput.getHdrMetadata().getSmpte2086());
+ mapper.setCta861_3(buffer->handle, queueBufferInput.getHdrMetadata().getCta8613());
+ mapper.setSmpte2094_40(buffer->handle, queueBufferInput.getHdrMetadata().getHdr10Plus());
+}
+
void Surface::onBufferQueuedLocked(int slot, sp<Fence> fence,
const IGraphicBufferProducer::QueueBufferOutput& output) {
mDequeuedSlots.erase(slot);
@@ -1171,9 +1183,11 @@
IGraphicBufferProducer::QueueBufferOutput output;
IGraphicBufferProducer::QueueBufferInput input;
getQueueBufferInputLocked(buffer, fenceFd, mTimestamp, &input);
+ applyGrallocMetadataLocked(buffer, input);
sp<Fence> fence = input.fence;
nsecs_t now = systemTime();
+
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
mLastQueueDuration = systemTime() - now;
if (err != OK) {
@@ -1243,10 +1257,10 @@
mQueriedSupportedTimestamps = true;
std::vector<FrameEvent> supportedFrameTimestamps;
- status_t err = composerService()->getSupportedFrameTimestamps(
- &supportedFrameTimestamps);
+ binder::Status status =
+ composerServiceAIDL()->getSupportedFrameTimestamps(&supportedFrameTimestamps);
- if (err != NO_ERROR) {
+ if (!status.isOk()) {
return;
}
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 23a94fc..ca48ce6 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1224,6 +1224,20 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDimmingEnabled(
+ const sp<SurfaceControl>& sc, bool dimmingEnabled) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eDimmingEnabledChanged;
+ s->dimmingEnabled = dimmingEnabled;
+
+ registerSurfaceControlForCallback(sc);
+ return *this;
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setAlpha(
const sp<SurfaceControl>& sc, float alpha) {
layer_state_t* s = getLayerState(sc);
@@ -2104,13 +2118,15 @@
// ----------------------------------------------------------------------------
status_t SurfaceComposerClient::enableVSyncInjections(bool enable) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- return sf->enableVSyncInjections(enable);
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ binder::Status status = sf->enableVSyncInjections(enable);
+ return status.transactionError();
}
status_t SurfaceComposerClient::injectVSync(nsecs_t when) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- return sf->injectVSync(when);
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ binder::Status status = sf->injectVSync(when);
+ return status.transactionError();
}
status_t SurfaceComposerClient::getDisplayState(const sp<IBinder>& display,
@@ -2173,8 +2189,53 @@
}
status_t SurfaceComposerClient::getDynamicDisplayInfo(const sp<IBinder>& display,
- ui::DynamicDisplayInfo* info) {
- return ComposerService::getComposerService()->getDynamicDisplayInfo(display, info);
+ ui::DynamicDisplayInfo* outInfo) {
+ gui::DynamicDisplayInfo ginfo;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDynamicDisplayInfo(display, &ginfo);
+ if (status.isOk()) {
+ // convert gui::DynamicDisplayInfo to ui::DynamicDisplayInfo
+ outInfo->supportedDisplayModes.clear();
+ outInfo->supportedDisplayModes.reserve(ginfo.supportedDisplayModes.size());
+ for (const auto& mode : ginfo.supportedDisplayModes) {
+ ui::DisplayMode outMode;
+ outMode.id = mode.id;
+ outMode.resolution.width = mode.resolution.width;
+ outMode.resolution.height = mode.resolution.height;
+ outMode.xDpi = mode.xDpi;
+ outMode.yDpi = mode.yDpi;
+ outMode.refreshRate = mode.refreshRate;
+ outMode.appVsyncOffset = mode.appVsyncOffset;
+ outMode.sfVsyncOffset = mode.sfVsyncOffset;
+ outMode.presentationDeadline = mode.presentationDeadline;
+ outMode.group = mode.group;
+ outInfo->supportedDisplayModes.push_back(outMode);
+ }
+
+ outInfo->activeDisplayModeId = ginfo.activeDisplayModeId;
+
+ outInfo->supportedColorModes.clear();
+ outInfo->supportedColorModes.reserve(ginfo.supportedColorModes.size());
+ for (const auto& cmode : ginfo.supportedColorModes) {
+ outInfo->supportedColorModes.push_back(static_cast<ui::ColorMode>(cmode));
+ }
+
+ outInfo->activeColorMode = static_cast<ui::ColorMode>(ginfo.activeColorMode);
+
+ std::vector<ui::Hdr> types;
+ types.reserve(ginfo.hdrCapabilities.supportedHdrTypes.size());
+ for (const auto& hdr : ginfo.hdrCapabilities.supportedHdrTypes) {
+ types.push_back(static_cast<ui::Hdr>(hdr));
+ }
+ outInfo->hdrCapabilities = HdrCapabilities(types, ginfo.hdrCapabilities.maxLuminance,
+ ginfo.hdrCapabilities.maxAverageLuminance,
+ ginfo.hdrCapabilities.minLuminance);
+
+ outInfo->autoLowLatencyModeSupported = ginfo.autoLowLatencyModeSupported;
+ outInfo->gameContentTypeSupported = ginfo.gameContentTypeSupported;
+ outInfo->preferredBootDisplayMode = ginfo.preferredBootDisplayMode;
+ }
+ return status.transactionError();
}
status_t SurfaceComposerClient::getActiveDisplayMode(const sp<IBinder>& display,
@@ -2219,12 +2280,35 @@
status_t SurfaceComposerClient::getDisplayNativePrimaries(const sp<IBinder>& display,
ui::DisplayPrimaries& outPrimaries) {
- return ComposerService::getComposerService()->getDisplayNativePrimaries(display, outPrimaries);
+ gui::DisplayPrimaries primaries;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDisplayNativePrimaries(display,
+ &primaries);
+ if (status.isOk()) {
+ outPrimaries.red.X = primaries.red.X;
+ outPrimaries.red.Y = primaries.red.Y;
+ outPrimaries.red.Z = primaries.red.Z;
+
+ outPrimaries.green.X = primaries.green.X;
+ outPrimaries.green.Y = primaries.green.Y;
+ outPrimaries.green.Z = primaries.green.Z;
+
+ outPrimaries.blue.X = primaries.blue.X;
+ outPrimaries.blue.Y = primaries.blue.Y;
+ outPrimaries.blue.Z = primaries.blue.Z;
+
+ outPrimaries.white.X = primaries.white.X;
+ outPrimaries.white.Y = primaries.white.Y;
+ outPrimaries.white.Z = primaries.white.Z;
+ }
+ return status.transactionError();
}
status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
ColorMode colorMode) {
- return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
+ binder::Status status = ComposerServiceAIDL::getComposerService()
+ ->setActiveColorMode(display, static_cast<int>(colorMode));
+ return status.transactionError();
}
status_t SurfaceComposerClient::getBootDisplayModeSupport(bool* support) {
@@ -2235,7 +2319,9 @@
status_t SurfaceComposerClient::setBootDisplayMode(const sp<IBinder>& display,
ui::DisplayModeId displayModeId) {
- return ComposerService::getComposerService()->setBootDisplayMode(display, displayModeId);
+ binder::Status status = ComposerServiceAIDL::getComposerService()
+ ->setBootDisplayMode(display, static_cast<int>(displayModeId));
+ return status.transactionError();
}
status_t SurfaceComposerClient::clearBootDisplayMode(const sp<IBinder>& display) {
@@ -2264,50 +2350,103 @@
status_t SurfaceComposerClient::getCompositionPreference(
ui::Dataspace* defaultDataspace, ui::PixelFormat* defaultPixelFormat,
ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat) {
- return ComposerService::getComposerService()
- ->getCompositionPreference(defaultDataspace, defaultPixelFormat,
- wideColorGamutDataspace, wideColorGamutPixelFormat);
+ gui::CompositionPreference pref;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getCompositionPreference(&pref);
+ if (status.isOk()) {
+ *defaultDataspace = static_cast<ui::Dataspace>(pref.defaultDataspace);
+ *defaultPixelFormat = static_cast<ui::PixelFormat>(pref.defaultPixelFormat);
+ *wideColorGamutDataspace = static_cast<ui::Dataspace>(pref.wideColorGamutDataspace);
+ *wideColorGamutPixelFormat = static_cast<ui::PixelFormat>(pref.wideColorGamutPixelFormat);
+ }
+ return status.transactionError();
}
bool SurfaceComposerClient::getProtectedContentSupport() {
bool supported = false;
- ComposerService::getComposerService()->getProtectedContentSupport(&supported);
+ ComposerServiceAIDL::getComposerService()->getProtectedContentSupport(&supported);
return supported;
}
status_t SurfaceComposerClient::clearAnimationFrameStats() {
- return ComposerService::getComposerService()->clearAnimationFrameStats();
+ binder::Status status = ComposerServiceAIDL::getComposerService()->clearAnimationFrameStats();
+ return status.transactionError();
}
status_t SurfaceComposerClient::getAnimationFrameStats(FrameStats* outStats) {
- return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
+ gui::FrameStats stats;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getAnimationFrameStats(&stats);
+ if (status.isOk()) {
+ outStats->refreshPeriodNano = stats.refreshPeriodNano;
+ outStats->desiredPresentTimesNano.setCapacity(stats.desiredPresentTimesNano.size());
+ for (const auto& t : stats.desiredPresentTimesNano) {
+ outStats->desiredPresentTimesNano.add(t);
+ }
+ outStats->actualPresentTimesNano.setCapacity(stats.actualPresentTimesNano.size());
+ for (const auto& t : stats.actualPresentTimesNano) {
+ outStats->actualPresentTimesNano.add(t);
+ }
+ outStats->frameReadyTimesNano.setCapacity(stats.frameReadyTimesNano.size());
+ for (const auto& t : stats.frameReadyTimesNano) {
+ outStats->frameReadyTimesNano.add(t);
+ }
+ }
+ return status.transactionError();
}
status_t SurfaceComposerClient::overrideHdrTypes(const sp<IBinder>& display,
const std::vector<ui::Hdr>& hdrTypes) {
- return ComposerService::getComposerService()->overrideHdrTypes(display, hdrTypes);
+ std::vector<int32_t> hdrTypesVector;
+ hdrTypesVector.reserve(hdrTypes.size());
+ for (auto t : hdrTypes) {
+ hdrTypesVector.push_back(static_cast<int32_t>(t));
+ }
+
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->overrideHdrTypes(display, hdrTypesVector);
+ return status.transactionError();
}
status_t SurfaceComposerClient::onPullAtom(const int32_t atomId, std::string* outData,
bool* success) {
- return ComposerService::getComposerService()->onPullAtom(atomId, outData, success);
+ gui::PullAtomData pad;
+ binder::Status status = ComposerServiceAIDL::getComposerService()->onPullAtom(atomId, &pad);
+ if (status.isOk()) {
+ outData->assign((const char*)pad.data.data(), pad.data.size());
+ *success = pad.success;
+ }
+ return status.transactionError();
}
status_t SurfaceComposerClient::getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask) {
- return ComposerService::getComposerService()
- ->getDisplayedContentSamplingAttributes(display, outFormat, outDataspace,
- outComponentMask);
+ if (!outFormat || !outDataspace || !outComponentMask) {
+ return BAD_VALUE;
+ }
+
+ gui::ContentSamplingAttributes attrs;
+ binder::Status status = ComposerServiceAIDL::getComposerService()
+ ->getDisplayedContentSamplingAttributes(display, &attrs);
+ if (status.isOk()) {
+ *outFormat = static_cast<ui::PixelFormat>(attrs.format);
+ *outDataspace = static_cast<ui::Dataspace>(attrs.dataspace);
+ *outComponentMask = static_cast<uint8_t>(attrs.componentMask);
+ }
+ return status.transactionError();
}
status_t SurfaceComposerClient::setDisplayContentSamplingEnabled(const sp<IBinder>& display,
bool enable, uint8_t componentMask,
uint64_t maxFrames) {
- return ComposerService::getComposerService()->setDisplayContentSamplingEnabled(display, enable,
- componentMask,
- maxFrames);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()
+ ->setDisplayContentSamplingEnabled(display, enable,
+ static_cast<int8_t>(componentMask),
+ static_cast<int64_t>(maxFrames));
+ return status.transactionError();
}
status_t SurfaceComposerClient::getDisplayedContentSample(const sp<IBinder>& display,
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 2312a8c..804ce4f 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-#include <type_traits>
#define LOG_TAG "WindowInfo"
#define LOG_NDEBUG 0
+#include <type_traits>
+
#include <binder/Parcel.h>
#include <gui/WindowInfo.h>
@@ -25,8 +26,7 @@
namespace android::gui {
-// --- WindowInfo ---
-void WindowInfo::setInputConfig(Flags<InputConfig> config, bool value) {
+void WindowInfo::setInputConfig(ftl::Flags<InputConfig> config, bool value) {
if (value) {
inputConfig |= config;
return;
@@ -182,18 +182,16 @@
return status;
}
- layoutParamsFlags = Flags<Flag>(lpFlags);
+ layoutParamsFlags = ftl::Flags<Flag>(lpFlags);
layoutParamsType = static_cast<Type>(lpType);
transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
touchOcclusionMode = static_cast<TouchOcclusionMode>(touchOcclusionModeInt);
- inputConfig = Flags<InputConfig>(inputConfigInt);
+ inputConfig = ftl::Flags<InputConfig>(inputConfigInt);
touchableRegionCropHandle = touchableRegionCropHandleSp;
return OK;
}
-// --- WindowInfoHandle ---
-
WindowInfoHandle::WindowInfoHandle() {}
WindowInfoHandle::~WindowInfoHandle() {}
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/CompositionPreference.aidl
similarity index 69%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/gui/aidl/android/gui/CompositionPreference.aidl
index d75777b..b615824 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/CompositionPreference.aidl
@@ -16,11 +16,10 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
-
/** @hide */
-parcelable DisplayModelId {
- int id;
+parcelable CompositionPreference {
+ int /*ui::Dataspace*/ defaultDataspace;
+ int /*ui::PixelFormat*/ defaultPixelFormat;
+ int /*ui::Dataspace*/ wideColorGamutDataspace;
+ int /*ui::PixelFormat*/ wideColorGamutPixelFormat;
}
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/ContentSamplingAttributes.aidl
similarity index 69%
rename from libs/gui/aidl/android/gui/DisplayModelId.aidl
rename to libs/gui/aidl/android/gui/ContentSamplingAttributes.aidl
index d75777b..5d913b1 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/ContentSamplingAttributes.aidl
@@ -16,11 +16,9 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
-
/** @hide */
-parcelable DisplayModelId {
- int id;
+parcelable ContentSamplingAttributes {
+ int /*ui::PixelFormat*/ format;
+ int /*ui::Dataspace*/ dataspace;
+ byte componentMask;
}
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/DisplayMode.aidl
similarity index 65%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/gui/aidl/android/gui/DisplayMode.aidl
index d75777b..3cd77f8 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/DisplayMode.aidl
@@ -16,11 +16,21 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+import android.gui.Size;
+
+// Mode supported by physical display.
+// Make sure to sync with libui DisplayMode.h
/** @hide */
-parcelable DisplayModelId {
+parcelable DisplayMode {
int id;
+ Size resolution;
+ float xDpi = 0.0f;
+ float yDpi = 0.0f;
+
+ float refreshRate = 0.0f;
+ long appVsyncOffset = 0;
+ long sfVsyncOffset = 0;
+ long presentationDeadline = 0;
+ int group = -1;
}
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/DisplayPrimaries.aidl
similarity index 69%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/gui/aidl/android/gui/DisplayPrimaries.aidl
index d75777b..dbf668c 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/DisplayPrimaries.aidl
@@ -16,11 +16,18 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+// copied from libui ConfigStoreTypes.h
/** @hide */
-parcelable DisplayModelId {
- int id;
+parcelable DisplayPrimaries {
+ parcelable CieXyz {
+ float X;
+ float Y;
+ float Z;
+ }
+
+ CieXyz red;
+ CieXyz green;
+ CieXyz blue;
+ CieXyz white;
}
diff --git a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
new file mode 100644
index 0000000..57e6081
--- /dev/null
+++ b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gui;
+
+import android.gui.DisplayMode;
+import android.gui.HdrCapabilities;
+
+// Information about a physical display which may change on hotplug reconnect.
+// Make sure to sync with libui DynamicDisplayInfo.h
+
+/** @hide */
+parcelable DynamicDisplayInfo {
+ List<DisplayMode> supportedDisplayModes;
+
+ int activeDisplayModeId;
+
+ int[] supportedColorModes;
+ int activeColorMode;
+ HdrCapabilities hdrCapabilities;
+
+ // True if the display reports support for HDMI 2.1 Auto Low Latency Mode.
+ // For more information, see the HDMI 2.1 specification.
+ boolean autoLowLatencyModeSupported;
+
+ // True if the display reports support for Game Content Type.
+ // For more information, see the HDMI 1.4 specification.
+ boolean gameContentTypeSupported;
+
+ // The boot display mode preferred by the implementation.
+ int preferredBootDisplayMode;
+}
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/FrameEvent.aidl
similarity index 63%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/gui/aidl/android/gui/FrameEvent.aidl
index d75777b..aaabdb5 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/FrameEvent.aidl
@@ -16,11 +16,20 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+// Identifiers for all the events that may be recorded or reported.
/** @hide */
-parcelable DisplayModelId {
- int id;
+@Backing(type="int")
+enum FrameEvent {
+ POSTED = 0,
+ REQUESTED_PRESENT = 1,
+ LATCH = 2,
+ ACQUIRE = 3,
+ FIRST_REFRESH_START = 4,
+ LAST_REFRESH_START = 5,
+ GPU_COMPOSITION_DONE = 6,
+ DISPLAY_PRESENT = 7,
+ DEQUEUE_READY = 8,
+ RELEASE = 9,
+ EVENT_COUNT = 10 // Not an actual event.
}
diff --git a/libs/gui/aidl/android/gui/FrameStats.aidl b/libs/gui/aidl/android/gui/FrameStats.aidl
new file mode 100644
index 0000000..a145e74
--- /dev/null
+++ b/libs/gui/aidl/android/gui/FrameStats.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gui;
+
+// Make sure to sync with libui FrameStats.h
+
+/** @hide */
+parcelable FrameStats {
+ /*
+ * Approximate refresh time, in nanoseconds.
+ */
+ long refreshPeriodNano;
+
+ /*
+ * The times in nanoseconds for when the frame contents were posted by the producer (e.g.
+ * the application). They are either explicitly set or defaulted to the time when
+ * Surface::queueBuffer() was called.
+ */
+ long[] desiredPresentTimesNano;
+
+ /*
+ * The times in milliseconds for when the frame contents were presented on the screen.
+ */
+ long[] actualPresentTimesNano;
+
+ /*
+ * The times in nanoseconds for when the frame contents were ready to be presented. Note that
+ * a frame can be posted and still it contents being rendered asynchronously in GL. In such a
+ * case these are the times when the frame contents were completely rendered (i.e. their fences
+ * signaled).
+ */
+ long[] frameReadyTimesNano;
+}
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/HdrCapabilities.aidl
similarity index 69%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/gui/aidl/android/gui/HdrCapabilities.aidl
index d75777b..9d06da9 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/HdrCapabilities.aidl
@@ -16,11 +16,12 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+// Make sure to sync with libui HdrCapabilities.h
/** @hide */
-parcelable DisplayModelId {
- int id;
+parcelable HdrCapabilities {
+ int[] supportedHdrTypes;
+ float maxLuminance;
+ float maxAverageLuminance;
+ float minLuminance;
}
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index f6cd5ec..dc77416 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -16,50 +16,69 @@
package android.gui;
+import android.gui.CompositionPreference;
+import android.gui.ContentSamplingAttributes;
import android.gui.DisplayCaptureArgs;
import android.gui.DisplayBrightness;
+import android.gui.DisplayPrimaries;
import android.gui.DisplayState;
import android.gui.DisplayStatInfo;
+import android.gui.FrameEvent;
+import android.gui.FrameStats;
+import android.gui.LayerDebugInfo;
+import android.gui.PullAtomData;
import android.gui.StaticDisplayInfo;
+import android.gui.DynamicDisplayInfo;
import android.gui.IHdrLayerInfoListener;
import android.gui.LayerCaptureArgs;
import android.gui.IScreenCaptureListener;
/** @hide */
interface ISurfaceComposer {
- /* create a virtual display
+ /**
+ * Create a virtual display
* requires ACCESS_SURFACE_FLINGER permission.
*/
@nullable IBinder createDisplay(@utf8InCpp String displayName, boolean secure);
- /* destroy a virtual display
+ /**
+ * Destroy a virtual display
* requires ACCESS_SURFACE_FLINGER permission.
*/
void destroyDisplay(IBinder display);
- /* get stable IDs for connected physical displays.
+ /**
+ * Get stable IDs for connected physical displays.
*/
long[] getPhysicalDisplayIds();
long getPrimaryPhysicalDisplayId();
- /* get token for a physical display given its stable ID obtained via getPhysicalDisplayIds or a
- * DisplayEventReceiver hotplug event.
+ /**
+ * Get token for a physical display given its stable ID obtained via getPhysicalDisplayIds or
+ * a DisplayEventReceiver hotplug event.
*/
@nullable IBinder getPhysicalDisplayToken(long displayId);
- /* set display power mode. depending on the mode, it can either trigger
+ /**
+ * Returns the frame timestamps supported by SurfaceFlinger.
+ */
+ FrameEvent[] getSupportedFrameTimestamps();
+
+ /**
+ * Set display power mode. depending on the mode, it can either trigger
* screen on, off or low power mode and wait for it to complete.
* requires ACCESS_SURFACE_FLINGER permission.
*/
void setPowerMode(IBinder display, int mode);
- /* returns display statistics for a given display
+ /**
+ * Returns display statistics for a given display
* intended to be used by the media framework to properly schedule
* video frames */
DisplayStatInfo getDisplayStats(IBinder display);
- /**
+ /**
* Get transactional state of given display.
*/
DisplayState getDisplayState(IBinder display);
@@ -70,6 +89,20 @@
StaticDisplayInfo getStaticDisplayInfo(IBinder display);
/**
+ * Gets dynamic information about given physical display.
+ */
+ DynamicDisplayInfo getDynamicDisplayInfo(IBinder display);
+
+ DisplayPrimaries getDisplayNativePrimaries(IBinder display);
+
+ void setActiveColorMode(IBinder display, int colorMode);
+
+ /**
+ * Sets the user-preferred display mode that a device should boot in.
+ */
+ void setBootDisplayMode(IBinder display, int displayModeId);
+
+ /**
* Clears the user-preferred display mode. The device should now boot in system preferred
* display mode.
*/
@@ -114,7 +147,9 @@
* match the size of the output buffer.
*/
void captureDisplay(in DisplayCaptureArgs args, IScreenCaptureListener listener);
+
void captureDisplayById(long displayId, IScreenCaptureListener listener);
+
/**
* Capture a subtree of the layer hierarchy, potentially ignoring the root node.
* This requires READ_FRAME_BUFFER permission. This function will fail if there
@@ -122,13 +157,80 @@
*/
void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener);
- /*
+ /**
+ * Clears the frame statistics for animations.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ void clearAnimationFrameStats();
+
+ /**
+ * Gets the frame statistics for animations.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ FrameStats getAnimationFrameStats();
+
+ /**
+ * Overrides the supported HDR modes for the given display device.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ void overrideHdrTypes(IBinder display, in int[] hdrTypes);
+
+ /**
+ * Pulls surfaceflinger atoms global stats and layer stats to pipe to statsd.
+ *
+ * Requires the calling uid be from system server.
+ */
+ PullAtomData onPullAtom(int atomId);
+
+ oneway void enableVSyncInjections(boolean enable);
+
+ oneway void injectVSync(long when);
+
+ /**
+ * Gets the list of active layers in Z order for debugging purposes
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ List<LayerDebugInfo> getLayerDebugInfo();
+
+ boolean getColorManagement();
+
+ /**
+ * Gets the composition preference of the default data space and default pixel format,
+ * as well as the wide color gamut data space and wide color gamut pixel format.
+ * If the wide color gamut data space is V0_SRGB, then it implies that the platform
+ * has no wide color gamut support.
+ *
+ */
+ CompositionPreference getCompositionPreference();
+
+ /**
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ ContentSamplingAttributes getDisplayedContentSamplingAttributes(IBinder display);
+
+ /**
+ * Turns on the color sampling engine on the display.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ void setDisplayContentSamplingEnabled(IBinder display, boolean enable, byte componentMask, long maxFrames);
+
+ /**
+ * Gets whether SurfaceFlinger can support protected content in GPU composition.
+ */
+ boolean getProtectedContentSupport();
+
+ /**
* Queries whether the given display is a wide color display.
* Requires the ACCESS_SURFACE_FLINGER permission.
*/
boolean isWideColorDisplay(IBinder token);
- /*
+ /**
* Gets whether brightness operations are supported on a display.
*
* displayToken
@@ -142,7 +244,7 @@
*/
boolean getDisplayBrightnessSupport(IBinder displayToken);
- /*
+ /**
* Sets the brightness of a display.
*
* displayToken
@@ -157,7 +259,7 @@
*/
void setDisplayBrightness(IBinder displayToken, in DisplayBrightness brightness);
- /*
+ /**
* Adds a listener that receives HDR layer information. This is used in combination
* with setDisplayBrightness to adjust the display brightness depending on factors such
* as whether or not HDR is in use.
@@ -166,7 +268,7 @@
*/
void addHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener);
- /*
+ /**
* Removes a listener that was added with addHdrLayerInfoListener.
*
* Returns NO_ERROR upon success, NAME_NOT_FOUND if the display is invalid, and BAD_VALUE if
@@ -175,7 +277,7 @@
*/
void removeHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener);
- /*
+ /**
* Sends a power boost to the composer. This function is asynchronous.
*
* boostId
@@ -183,5 +285,5 @@
*
* Returns NO_ERROR upon success.
*/
- void notifyPowerBoost(int boostId);
+ oneway void notifyPowerBoost(int boostId);
}
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/LayerDebugInfo.aidl
similarity index 68%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/gui/aidl/android/gui/LayerDebugInfo.aidl
index d75777b..faca980 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/LayerDebugInfo.aidl
@@ -16,11 +16,4 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
-
-/** @hide */
-parcelable DisplayModelId {
- int id;
-}
+parcelable LayerDebugInfo cpp_header "gui/LayerDebugInfo.h";
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/gui/aidl/android/gui/PullAtomData.aidl
similarity index 69%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/gui/aidl/android/gui/PullAtomData.aidl
index d75777b..14d33c6 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/gui/aidl/android/gui/PullAtomData.aidl
@@ -16,11 +16,8 @@
package android.gui;
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
-
/** @hide */
-parcelable DisplayModelId {
- int id;
+parcelable PullAtomData {
+ @utf8InCpp String data;
+ boolean success;
}
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index dd3de58..f73bc3b 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
#define ANDROID_GUI_FRAMETIMESTAMPS_H
+#include <android/gui/FrameEvent.h>
+
#include <ui/FenceTime.h>
#include <utils/Flattenable.h>
#include <utils/StrongPointer.h>
@@ -31,22 +33,7 @@
struct FrameEvents;
class FrameEventHistoryDelta;
-
-// Identifiers for all the events that may be recorded or reported.
-enum class FrameEvent {
- POSTED,
- REQUESTED_PRESENT,
- LATCH,
- ACQUIRE,
- FIRST_REFRESH_START,
- LAST_REFRESH_START,
- GPU_COMPOSITION_DONE,
- DISPLAY_PRESENT,
- DEQUEUE_READY,
- RELEASE,
- EVENT_COUNT, // Not an actual event.
-};
-
+using gui::FrameEvent;
// A collection of timestamps corresponding to a single frame.
struct FrameEvents {
diff --git a/libs/gui/include/gui/HdrMetadata.h b/libs/gui/include/gui/HdrMetadata.h
index 0bdffac..98a07a3 100644
--- a/libs/gui/include/gui/HdrMetadata.h
+++ b/libs/gui/include/gui/HdrMetadata.h
@@ -17,6 +17,8 @@
#pragma once
#include <stdint.h>
+#include <ui/GraphicTypes.h>
+#include <optional>
#include <vector>
#include <system/graphics.h>
@@ -43,6 +45,27 @@
status_t flatten(void* buffer, size_t size) const;
status_t unflatten(void const* buffer, size_t size);
+ std::optional<ui::Smpte2086> getSmpte2086() const {
+ if (validTypes & Type::SMPTE2086) {
+ return ui::translate(smpte2086);
+ }
+ return {};
+ }
+
+ std::optional<ui::Cta861_3> getCta8613() const {
+ if (validTypes & Type::CTA861_3) {
+ return ui::translate(cta8613);
+ }
+ return {};
+ }
+
+ std::optional<std::vector<uint8_t>> getHdr10Plus() const {
+ if (validTypes & Type::HDR10PLUS) {
+ return hdr10plus;
+ }
+ return {};
+ }
+
bool operator==(const HdrMetadata& rhs) const;
bool operator!=(const HdrMetadata& rhs) const { return !(*this == rhs); }
};
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 29e38b8..7f59a5a 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -27,7 +27,7 @@
#include <android/gui/IWindowInfosListener.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
-#include <ftl/Flags.h>
+#include <ftl/flags.h>
#include <gui/FrameTimelineInfo.h>
#include <gui/ITransactionCompletedListener.h>
#include <gui/SpHash.h>
@@ -61,12 +61,10 @@
struct DisplayStatInfo;
struct DisplayState;
struct InputWindowCommands;
-class LayerDebugInfo;
class HdrCapabilities;
class IGraphicBufferProducer;
class ISurfaceComposerClient;
class Rect;
-enum class FrameEvent;
using gui::IDisplayEventConnection;
using gui::IRegionSamplingListener;
@@ -77,6 +75,7 @@
struct DisplayCaptureArgs;
struct LayerCaptureArgs;
+class LayerDebugInfo;
} // namespace gui
@@ -125,7 +124,7 @@
frameRateOverride = 1 << 1,
};
- using EventRegistrationFlags = Flags<EventRegistration>;
+ using EventRegistrationFlags = ftl::Flags<EventRegistration>;
/*
* Create a connection with SurfaceFlinger.
@@ -155,90 +154,6 @@
virtual bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& surface) const = 0;
- /* Returns the frame timestamps supported by SurfaceFlinger.
- */
- virtual status_t getSupportedFrameTimestamps(
- std::vector<FrameEvent>* outSupported) const = 0;
-
- /**
- * Gets dynamic information about given physical display.
- */
- virtual status_t getDynamicDisplayInfo(const sp<IBinder>& display, ui::DynamicDisplayInfo*) = 0;
-
- virtual status_t getDisplayNativePrimaries(const sp<IBinder>& display,
- ui::DisplayPrimaries& primaries) = 0;
- virtual status_t setActiveColorMode(const sp<IBinder>& display,
- ui::ColorMode colorMode) = 0;
-
- /**
- * Sets the user-preferred display mode that a device should boot in.
- */
- virtual status_t setBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId) = 0;
-
- /* Clears the frame statistics for animations.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t clearAnimationFrameStats() = 0;
-
- /* Gets the frame statistics for animations.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
-
- /* Overrides the supported HDR modes for the given display device.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t overrideHdrTypes(const sp<IBinder>& display,
- const std::vector<ui::Hdr>& hdrTypes) = 0;
-
- /* Pulls surfaceflinger atoms global stats and layer stats to pipe to statsd.
- *
- * Requires the calling uid be from system server.
- */
- virtual status_t onPullAtom(const int32_t atomId, std::string* outData, bool* success) = 0;
-
- virtual status_t enableVSyncInjections(bool enable) = 0;
-
- virtual status_t injectVSync(nsecs_t when) = 0;
-
- /* Gets the list of active layers in Z order for debugging purposes
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) = 0;
-
- virtual status_t getColorManagement(bool* outGetColorManagement) const = 0;
-
- /* Gets the composition preference of the default data space and default pixel format,
- * as well as the wide color gamut data space and wide color gamut pixel format.
- * If the wide color gamut data space is V0_SRGB, then it implies that the platform
- * has no wide color gamut support.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
- ui::PixelFormat* defaultPixelFormat,
- ui::Dataspace* wideColorGamutDataspace,
- ui::PixelFormat* wideColorGamutPixelFormat) const = 0;
- /*
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
- ui::PixelFormat* outFormat,
- ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const = 0;
-
- /* Turns on the color sampling engine on the display.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask,
- uint64_t maxFrames) = 0;
-
/* Returns statistics on the color profile of the last frame displayed for a given display
*
* Requires the ACCESS_SURFACE_FLINGER permission.
@@ -247,12 +162,6 @@
uint64_t timestamp,
DisplayedFrameStats* outStats) const = 0;
- /*
- * Gets whether SurfaceFlinger can support protected content in GPU composition.
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getProtectedContentSupport(bool* outSupported) const = 0;
-
/* Registers a listener to stream median luma updates from SurfaceFlinger.
*
* The sampling area is bounded by both samplingArea and the given stopLayerHandle
@@ -444,32 +353,32 @@
GET_PHYSICAL_DISPLAY_TOKEN, // Deprecated. Autogenerated by .aidl now.
SET_TRANSACTION_STATE,
AUTHENTICATE_SURFACE,
- GET_SUPPORTED_FRAME_TIMESTAMPS,
- GET_DISPLAY_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- GET_ACTIVE_DISPLAY_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ GET_SUPPORTED_FRAME_TIMESTAMPS, // Deprecated. Autogenerated by .aidl now.
+ GET_DISPLAY_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ GET_ACTIVE_DISPLAY_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
GET_DISPLAY_STATE,
- CAPTURE_DISPLAY, // Deprecated. Autogenerated by .aidl now.
- CAPTURE_LAYERS, // Deprecated. Autogenerated by .aidl now.
- CLEAR_ANIMATION_FRAME_STATS,
- GET_ANIMATION_FRAME_STATS,
- SET_POWER_MODE, // Deprecated. Autogenerated by .aidl now.
+ CAPTURE_DISPLAY, // Deprecated. Autogenerated by .aidl now.
+ CAPTURE_LAYERS, // Deprecated. Autogenerated by .aidl now.
+ CLEAR_ANIMATION_FRAME_STATS, // Deprecated. Autogenerated by .aidl now.
+ GET_ANIMATION_FRAME_STATS, // Deprecated. Autogenerated by .aidl now.
+ SET_POWER_MODE, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAY_STATS,
- GET_HDR_CAPABILITIES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- GET_ACTIVE_COLOR_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- SET_ACTIVE_COLOR_MODE,
- ENABLE_VSYNC_INJECTIONS,
- INJECT_VSYNC,
- GET_LAYER_DEBUG_INFO,
- GET_COMPOSITION_PREFERENCE,
- GET_COLOR_MANAGEMENT,
- GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
- SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
+ GET_HDR_CAPABILITIES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ GET_ACTIVE_COLOR_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ SET_ACTIVE_COLOR_MODE, // Deprecated. Autogenerated by .aidl now.
+ ENABLE_VSYNC_INJECTIONS, // Deprecated. Autogenerated by .aidl now.
+ INJECT_VSYNC, // Deprecated. Autogenerated by .aidl now.
+ GET_LAYER_DEBUG_INFO, // Deprecated. Autogenerated by .aidl now.
+ GET_COMPOSITION_PREFERENCE, // Deprecated. Autogenerated by .aidl now.
+ GET_COLOR_MANAGEMENT, // Deprecated. Autogenerated by .aidl now.
+ GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, // Deprecated. Autogenerated by .aidl now.
+ SET_DISPLAY_CONTENT_SAMPLING_ENABLED, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAYED_CONTENT_SAMPLE,
- GET_PROTECTED_CONTENT_SUPPORT,
- IS_WIDE_COLOR_DISPLAY, // Deprecated. Autogenerated by .aidl now.
- GET_DISPLAY_NATIVE_PRIMARIES,
- GET_PHYSICAL_DISPLAY_IDS, // Deprecated. Autogenerated by .aidl now.
+ GET_PROTECTED_CONTENT_SUPPORT, // Deprecated. Autogenerated by .aidl now.
+ IS_WIDE_COLOR_DISPLAY, // Deprecated. Autogenerated by .aidl now.
+ GET_DISPLAY_NATIVE_PRIMARIES, // Deprecated. Autogenerated by .aidl now.
+ GET_PHYSICAL_DISPLAY_IDS, // Deprecated. Autogenerated by .aidl now.
ADD_REGION_SAMPLING_LISTENER,
REMOVE_REGION_SAMPLING_LISTENER,
SET_DESIRED_DISPLAY_MODE_SPECS,
@@ -490,13 +399,13 @@
ADD_TRANSACTION_TRACE_LISTENER,
GET_GPU_CONTEXT_PRIORITY,
GET_MAX_ACQUIRED_BUFFER_COUNT,
- GET_DYNAMIC_DISPLAY_INFO,
+ GET_DYNAMIC_DISPLAY_INFO, // Deprecated. Autogenerated by .aidl now.
ADD_FPS_LISTENER,
REMOVE_FPS_LISTENER,
- OVERRIDE_HDR_TYPES,
+ OVERRIDE_HDR_TYPES, // Deprecated. Autogenerated by .aidl now.
ADD_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
REMOVE_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
- ON_PULL_ATOM,
+ ON_PULL_ATOM, // Deprecated. Autogenerated by .aidl now.
ADD_TUNNEL_MODE_ENABLED_LISTENER,
REMOVE_TUNNEL_MODE_ENABLED_LISTENER,
ADD_WINDOW_INFOS_LISTENER,
@@ -504,8 +413,8 @@
GET_PRIMARY_PHYSICAL_DISPLAY_ID, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAY_DECORATION_SUPPORT,
GET_BOOT_DISPLAY_MODE_SUPPORT, // Deprecated. Autogenerated by .aidl now.
- SET_BOOT_DISPLAY_MODE,
- CLEAR_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now.
+ SET_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now.
+ CLEAR_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now.
SET_OVERRIDE_FRAME_RATE,
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index af834d7..1c1bbef 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -25,7 +25,7 @@
#include <string>
#include <math/vec4.h>
-namespace android {
+namespace android::gui {
/* Class for transporting debug info from SurfaceFlinger to authorized
* recipients. The class is intended to be a data container. There are
@@ -71,4 +71,4 @@
std::string to_string(const LayerDebugInfo& info);
-} // namespace android
+} // namespace android::gui
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 0f37dab..0a9b75a 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -29,6 +29,7 @@
#include <android/gui/DropInputMode.h>
#include <android/gui/FocusRequest.h>
+#include <ftl/flags.h>
#include <gui/DisplayCaptureArgs.h>
#include <gui/ISurfaceComposer.h>
#include <gui/LayerCaptureArgs.h>
@@ -102,7 +103,7 @@
// was called with.
sp<IBinder> releaseBufferEndpoint;
- Flags<BufferDataChange> flags;
+ ftl::Flags<BufferDataChange> flags;
client_cache_t cachedBuffer;
@@ -150,7 +151,7 @@
eTransparentRegionChanged = 0x00000020,
eFlagsChanged = 0x00000040,
eLayerStackChanged = 0x00000080,
- /* unused 0x00000400, */
+ eDimmingEnabledChanged = 0x00000400,
eShadowRadiusChanged = 0x00000800,
/* unused 0x00001000, */
eBufferCropChanged = 0x00002000,
@@ -187,7 +188,7 @@
eAutoRefreshChanged = 0x1000'00000000,
eStretchChanged = 0x2000'00000000,
eTrustedOverlayChanged = 0x4000'00000000,
- eDropInputModeChanged = 0x8000'00000000,
+ eDropInputModeChanged = 0x8000'00000000
};
layer_state_t();
@@ -298,6 +299,8 @@
// Force inputflinger to drop all input events for the layer and its children.
gui::DropInputMode dropInputMode;
+
+ bool dimmingEnabled;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index ba9ee6c..ab9ebaa 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -403,6 +403,13 @@
void getQueueBufferInputLocked(android_native_buffer_t* buffer, int fenceFd, nsecs_t timestamp,
IGraphicBufferProducer::QueueBufferInput* out);
+ // For easing in adoption of gralloc4 metadata by vendor components, as well as for supporting
+ // the public ANativeWindow api, allow setting relevant metadata when queueing a buffer through
+ // a native window
+ void applyGrallocMetadataLocked(
+ android_native_buffer_t* buffer,
+ const IGraphicBufferProducer::QueueBufferInput& queueBufferInput);
+
void onBufferQueuedLocked(int slot, sp<Fence> fence,
const IGraphicBufferProducer::QueueBufferOutput& output);
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index b17902d..a30a3fa 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -492,6 +492,7 @@
uint32_t flags, uint32_t mask);
Transaction& setTransparentRegionHint(const sp<SurfaceControl>& sc,
const Region& transparentRegion);
+ Transaction& setDimmingEnabled(const sp<SurfaceControl>& sc, bool dimmingEnabled);
Transaction& setAlpha(const sp<SurfaceControl>& sc,
float alpha);
Transaction& setMatrix(const sp<SurfaceControl>& sc,
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index ef0b98b..0e1d258 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -20,7 +20,7 @@
#include <android/os/InputConfig.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
-#include <ftl/Flags.h>
+#include <ftl/flags.h>
#include <gui/constants.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -224,7 +224,7 @@
int32_t ownerPid = -1;
int32_t ownerUid = -1;
std::string packageName;
- Flags<InputConfig> inputConfig;
+ ftl::Flags<InputConfig> inputConfig;
int32_t displayId = ADISPLAY_ID_NONE;
InputApplicationInfo applicationInfo;
bool replaceTouchableRegionWithCrop = false;
@@ -232,9 +232,9 @@
// The window's layout params flags and type set by WM.
Type layoutParamsType = Type::UNKNOWN;
- Flags<Flag> layoutParamsFlags;
+ ftl::Flags<Flag> layoutParamsFlags;
- void setInputConfig(Flags<InputConfig> config, bool value);
+ void setInputConfig(ftl::Flags<InputConfig> config, bool value);
void addTouchableRegion(const Rect& region);
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index e02299d..58964d6 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -714,84 +714,12 @@
return false;
}
- status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported)
- const override {
- *outSupported = {
- FrameEvent::REQUESTED_PRESENT,
- FrameEvent::ACQUIRE,
- FrameEvent::LATCH,
- FrameEvent::FIRST_REFRESH_START,
- FrameEvent::LAST_REFRESH_START,
- FrameEvent::GPU_COMPOSITION_DONE,
- FrameEvent::DEQUEUE_READY,
- FrameEvent::RELEASE
- };
- if (mSupportsPresent) {
- outSupported->push_back(
- FrameEvent::DISPLAY_PRESENT);
- }
- return NO_ERROR;
- }
-
- status_t getDynamicDisplayInfo(const sp<IBinder>& /*display*/,
- ui::DynamicDisplayInfo*) override {
- return NO_ERROR;
- }
- status_t getDisplayNativePrimaries(const sp<IBinder>& /*display*/,
- ui::DisplayPrimaries& /*primaries*/) override {
- return NO_ERROR;
- }
- status_t setActiveColorMode(const sp<IBinder>& /*display*/,
- ColorMode /*colorMode*/) override { return NO_ERROR; }
- status_t setBootDisplayMode(const sp<IBinder>& /*display*/, ui::DisplayModeId /*id*/) override {
- return NO_ERROR;
- }
-
- status_t clearAnimationFrameStats() override { return NO_ERROR; }
- status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
- return NO_ERROR;
- }
- status_t overrideHdrTypes(const sp<IBinder>& /*display*/,
- const std::vector<ui::Hdr>& /*hdrTypes*/) override {
- return NO_ERROR;
- }
- status_t onPullAtom(const int32_t /*atomId*/, std::string* /*outData*/,
- bool* /*success*/) override {
- return NO_ERROR;
- }
- status_t enableVSyncInjections(bool /*enable*/) override {
- return NO_ERROR;
- }
- status_t injectVSync(nsecs_t /*when*/) override { return NO_ERROR; }
- status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* /*layers*/) override {
- return NO_ERROR;
- }
- status_t getCompositionPreference(
- ui::Dataspace* /*outDefaultDataspace*/, ui::PixelFormat* /*outDefaultPixelFormat*/,
- ui::Dataspace* /*outWideColorGamutDataspace*/,
- ui::PixelFormat* /*outWideColorGamutPixelFormat*/) const override {
- return NO_ERROR;
- }
- status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& /*display*/,
- ui::PixelFormat* /*outFormat*/,
- ui::Dataspace* /*outDataspace*/,
- uint8_t* /*outComponentMask*/) const override {
- return NO_ERROR;
- }
- status_t setDisplayContentSamplingEnabled(const sp<IBinder>& /*display*/, bool /*enable*/,
- uint8_t /*componentMask*/,
- uint64_t /*maxFrames*/) override {
- return NO_ERROR;
- }
status_t getDisplayedContentSample(const sp<IBinder>& /*display*/, uint64_t /*maxFrames*/,
uint64_t /*timestamp*/,
DisplayedFrameStats* /*outStats*/) const override {
return NO_ERROR;
}
- status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; }
- status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; }
-
status_t addRegionSamplingListener(const Rect& /*samplingArea*/,
const sp<IBinder>& /*stopLayerHandle*/,
const sp<IRegionSamplingListener>& /*listener*/) override {
@@ -916,6 +844,21 @@
return binder::Status::ok();
}
+ binder::Status getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) override {
+ *outSupported = {FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE};
+ if (mSupportsPresent) {
+ outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
+ }
+ return binder::Status::ok();
+ }
+
binder::Status getDisplayStats(const sp<IBinder>& /*display*/,
gui::DisplayStatInfo* /*outStatInfo*/) override {
return binder::Status::ok();
@@ -931,6 +874,25 @@
return binder::Status::ok();
}
+ binder::Status getDynamicDisplayInfo(const sp<IBinder>& /*display*/,
+ gui::DynamicDisplayInfo* /*outInfo*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayNativePrimaries(const sp<IBinder>& /*display*/,
+ gui::DisplayPrimaries* /*outPrimaries*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setActiveColorMode(const sp<IBinder>& /*display*/, int /*colorMode*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setBootDisplayMode(const sp<IBinder>& /*display*/,
+ int /*displayModeId*/) override {
+ return binder::Status::ok();
+ }
+
binder::Status clearBootDisplayMode(const sp<IBinder>& /*display*/) override {
return binder::Status::ok();
}
@@ -961,6 +923,52 @@
return binder::Status::ok();
}
+ binder::Status clearAnimationFrameStats() override { return binder::Status::ok(); }
+
+ binder::Status getAnimationFrameStats(gui::FrameStats* /*outStats*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status overrideHdrTypes(const sp<IBinder>& /*display*/,
+ const std::vector<int32_t>& /*hdrTypes*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status onPullAtom(int32_t /*atomId*/, gui::PullAtomData* /*outPullData*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status enableVSyncInjections(bool /*enable*/) override { return binder::Status::ok(); }
+
+ binder::Status injectVSync(int64_t /*when*/) override { return binder::Status::ok(); }
+
+ binder::Status getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* /*outLayers*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getColorManagement(bool* /*outGetColorManagement*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getCompositionPreference(gui::CompositionPreference* /*outPref*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayedContentSamplingAttributes(
+ const sp<IBinder>& /*display*/, gui::ContentSamplingAttributes* /*outAttrs*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setDisplayContentSamplingEnabled(const sp<IBinder>& /*display*/, bool /*enable*/,
+ int8_t /*componentMask*/,
+ int64_t /*maxFrames*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getProtectedContentSupport(bool* /*outSupporte*/) override {
+ return binder::Status::ok();
+ }
+
binder::Status isWideColorDisplay(const sp<IBinder>& /*token*/,
bool* /*outIsWideColorDisplay*/) override {
return binder::Status::ok();
@@ -1035,10 +1043,10 @@
class TestSurface : public Surface {
public:
- TestSurface(const sp<IGraphicBufferProducer>& bufferProducer,
- FenceToFenceTimeMap* fenceMap)
- : Surface(bufferProducer),
- mFakeSurfaceComposer(new FakeSurfaceComposer) {
+ TestSurface(const sp<IGraphicBufferProducer>& bufferProducer, FenceToFenceTimeMap* fenceMap)
+ : Surface(bufferProducer),
+ mFakeSurfaceComposer(new FakeSurfaceComposer),
+ mFakeSurfaceComposerAIDL(new FakeSurfaceComposerAIDL) {
mFakeFrameEventHistory = new FakeProducerFrameEventHistory(fenceMap);
mFrameEventHistory.reset(mFakeFrameEventHistory);
}
@@ -1049,6 +1057,10 @@
return mFakeSurfaceComposer;
}
+ sp<gui::ISurfaceComposer> composerServiceAIDL() const override {
+ return mFakeSurfaceComposerAIDL;
+ }
+
nsecs_t now() const override {
return mNow;
}
@@ -1059,6 +1071,7 @@
public:
sp<FakeSurfaceComposer> mFakeSurfaceComposer;
+ sp<FakeSurfaceComposerAIDL> mFakeSurfaceComposerAIDL;
nsecs_t mNow = 0;
// mFrameEventHistory owns the instance of FakeProducerFrameEventHistory,
@@ -1425,6 +1438,7 @@
TEST_F(GetFrameTimestampsTest, QueryPresentSupported) {
bool displayPresentSupported = true;
mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+ mSurface->mFakeSurfaceComposerAIDL->setSupportsPresent(displayPresentSupported);
// Verify supported bits are forwarded.
int supportsPresent = -1;
@@ -1436,6 +1450,7 @@
TEST_F(GetFrameTimestampsTest, QueryPresentNotSupported) {
bool displayPresentSupported = false;
mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+ mSurface->mFakeSurfaceComposerAIDL->setSupportsPresent(displayPresentSupported);
// Verify supported bits are forwarded.
int supportsPresent = -1;
@@ -2013,6 +2028,7 @@
TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) {
enableFrameTimestamps();
mSurface->mFakeSurfaceComposer->setSupportsPresent(false);
+ mSurface->mFakeSurfaceComposerAIDL->setSupportsPresent(false);
// Dequeue and queue frame 1.
const uint64_t fId1 = getNextFrameId();
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 18fb7c1..1d4fc1f 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -50,6 +50,7 @@
"Keyboard.cpp",
"KeyCharacterMap.cpp",
"KeyLayoutMap.cpp",
+ "PrintTools.cpp",
"PropertyMap.cpp",
"TouchVideoFrame.cpp",
"VelocityControl.cpp",
@@ -102,6 +103,9 @@
sanitize: {
misc_undefined: ["integer"],
+ diag: {
+ misc_undefined: ["integer"],
+ },
},
},
host: {
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/libs/input/PrintTools.cpp
similarity index 60%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to libs/input/PrintTools.cpp
index d75777b..5d6ae4e 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/libs/input/PrintTools.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
* limitations under the License.
*/
-package android.gui;
+#define LOG_TAG "PrintTools"
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+#include <input/PrintTools.h>
-/** @hide */
-parcelable DisplayModelId {
- int id;
+namespace android {
+
+const char* toString(bool value) {
+ return value ? "true" : "false";
}
+
+} // namespace android
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index ed728dc..e3fad3d 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -33,7 +33,7 @@
cc_library_headers {
name: "libnativedisplay_headers",
- export_include_dirs: ["include",],
+ export_include_dirs: ["include"],
}
cc_library_shared {
@@ -55,6 +55,7 @@
version_script: "libnativedisplay.map.txt",
srcs: [
+ ":libgui_frame_event_aidl",
"AChoreographer.cpp",
"ADisplay.cpp",
"surfacetexture/surface_texture.cpp",
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 576941f..f3009dd 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -207,7 +207,11 @@
if (result == 0) {
outPlanes->planeCount = 3;
outPlanes->planes[0].data = yuvData.y;
- outPlanes->planes[0].pixelStride = 1;
+ if (format == AHARDWAREBUFFER_FORMAT_YCbCr_P010) {
+ outPlanes->planes[0].pixelStride = 2;
+ } else {
+ outPlanes->planes[0].pixelStride = 1;
+ }
outPlanes->planes[0].rowStride = yuvData.ystride;
outPlanes->planes[1].data = yuvData.cb;
outPlanes->planes[1].pixelStride = yuvData.chroma_step;
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 1a1c3b4..4ea2af2 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -57,6 +57,7 @@
#include <gui/TraceUtils.h>
#include <sync/sync.h>
#include <ui/BlurRegion.h>
+#include <ui/DataspaceUtils.h>
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
#include <utils/Trace.h>
@@ -1128,9 +1129,15 @@
? layerDimmingRatio
: 1.f}));
- // Turn on dithering when dimming beyond this threshold.
+ // Turn on dithering when dimming beyond this (arbitrary) threshold...
static constexpr float kDimmingThreshold = 0.2f;
- if (layerDimmingRatio <= kDimmingThreshold) {
+ // ...or we're rendering an HDR layer down to an 8-bit target
+ // Most HDR standards require at least 10-bits of color depth for source content, so we
+ // can just extract the transfer function rather than dig into precise gralloc layout.
+ // Furthermore, we can assume that the only 8-bit target we support is RGBA8888.
+ const bool requiresDownsample = isHdrDataspace(layer.sourceDataspace) &&
+ buffer->getPixelFormat() == PIXEL_FORMAT_RGBA_8888;
+ if (layerDimmingRatio <= kDimmingThreshold || requiresDownsample) {
paint.setDither(true);
}
paint.setAlphaf(layer.alpha);
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 4af38c5..0a85fe0 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -129,7 +129,6 @@
"DebugUtils.cpp",
"DeviceProductInfo.cpp",
"DisplayIdentification.cpp",
- "DisplayMode.cpp",
"DynamicDisplayInfo.cpp",
"Fence.cpp",
"FenceTime.cpp",
@@ -141,7 +140,6 @@
"GraphicBuffer.cpp",
"GraphicBufferAllocator.cpp",
"GraphicBufferMapper.cpp",
- "HdrCapabilities.cpp",
"PixelFormat.cpp",
"PublicFormat.cpp",
"StaticAsserts.cpp",
diff --git a/libs/ui/DisplayMode.cpp b/libs/ui/DisplayMode.cpp
deleted file mode 100644
index cf05dbf..0000000
--- a/libs/ui/DisplayMode.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ui/DisplayMode.h>
-
-#include <cstdint>
-
-#include <ui/FlattenableHelpers.h>
-
-#define RETURN_IF_ERROR(op) \
- if (const status_t status = (op); status != OK) return status;
-
-namespace android::ui {
-
-size_t DisplayMode::getFlattenedSize() const {
- return FlattenableHelpers::getFlattenedSize(id) +
- FlattenableHelpers::getFlattenedSize(resolution) +
- FlattenableHelpers::getFlattenedSize(xDpi) +
- FlattenableHelpers::getFlattenedSize(yDpi) +
- FlattenableHelpers::getFlattenedSize(refreshRate) +
- FlattenableHelpers::getFlattenedSize(appVsyncOffset) +
- FlattenableHelpers::getFlattenedSize(sfVsyncOffset) +
- FlattenableHelpers::getFlattenedSize(presentationDeadline) +
- FlattenableHelpers::getFlattenedSize(group);
-}
-
-status_t DisplayMode::flatten(void* buffer, size_t size) const {
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, id));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, resolution));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, xDpi));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, yDpi));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, refreshRate));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, appVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, sfVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, presentationDeadline));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, group));
- return OK;
-}
-
-status_t DisplayMode::unflatten(const void* buffer, size_t size) {
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &id));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &resolution));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &xDpi));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &yDpi));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &refreshRate));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &appVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &sfVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &presentationDeadline));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &group));
- return OK;
-}
-
-} // namespace android::ui
diff --git a/libs/ui/DynamicDisplayInfo.cpp b/libs/ui/DynamicDisplayInfo.cpp
index 78ba996..f5feea9 100644
--- a/libs/ui/DynamicDisplayInfo.cpp
+++ b/libs/ui/DynamicDisplayInfo.cpp
@@ -18,11 +18,6 @@
#include <cstdint>
-#include <ui/FlattenableHelpers.h>
-
-#define RETURN_IF_ERROR(op) \
- if (const status_t status = (op); status != OK) return status;
-
namespace android::ui {
std::optional<ui::DisplayMode> DynamicDisplayInfo::getActiveDisplayMode() const {
@@ -34,42 +29,4 @@
return {};
}
-size_t DynamicDisplayInfo::getFlattenedSize() const {
- return FlattenableHelpers::getFlattenedSize(supportedDisplayModes) +
- FlattenableHelpers::getFlattenedSize(activeDisplayModeId) +
- FlattenableHelpers::getFlattenedSize(supportedColorModes) +
- FlattenableHelpers::getFlattenedSize(activeColorMode) +
- FlattenableHelpers::getFlattenedSize(hdrCapabilities) +
- FlattenableHelpers::getFlattenedSize(autoLowLatencyModeSupported) +
- FlattenableHelpers::getFlattenedSize(gameContentTypeSupported) +
- FlattenableHelpers::getFlattenedSize(preferredBootDisplayMode);
-}
-
-status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const {
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedDisplayModes));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeDisplayModeId));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedColorModes));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeColorMode));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, hdrCapabilities));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, autoLowLatencyModeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, gameContentTypeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, preferredBootDisplayMode));
- return OK;
-}
-
-status_t DynamicDisplayInfo::unflatten(const void* buffer, size_t size) {
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedDisplayModes));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeDisplayModeId));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedColorModes));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeColorMode));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &hdrCapabilities));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &autoLowLatencyModeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &gameContentTypeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &preferredBootDisplayMode));
- return OK;
-}
-
} // namespace android::ui
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index 1a42642..1fce31d 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -22,6 +22,7 @@
#include <aidlcommonsupport/NativeHandle.h>
#include <android/binder_enums.h>
#include <android/binder_manager.h>
+#include <gralloctypes/Gralloc4.h>
#include <hidl/ServiceManagement.h>
#include <hwbinder/IPCThreadState.h>
#include <ui/Gralloc4.h>
@@ -358,20 +359,19 @@
if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
continue;
}
- if (0 != planeLayoutComponent.offsetInBits % 8) {
- unlock(bufferHandle);
- return BAD_VALUE;
- }
- uint8_t* tmpData = static_cast<uint8_t*>(data) + planeLayout.offsetInBytes +
- (planeLayoutComponent.offsetInBits / 8);
+ uint8_t* tmpData = static_cast<uint8_t*>(data) + planeLayout.offsetInBytes;
+
+ // Note that `offsetInBits` may not be a multiple of 8 for packed formats (e.g. P010)
+ // but we still want to point to the start of the first byte.
+ tmpData += (planeLayoutComponent.offsetInBits / 8);
+
uint64_t sampleIncrementInBytes;
auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
switch (type) {
case PlaneLayoutComponentType::Y:
- if ((ycbcr.y != nullptr) || (planeLayoutComponent.sizeInBits != 8) ||
- (planeLayout.sampleIncrementInBits != 8)) {
+ if ((ycbcr.y != nullptr) || (planeLayout.sampleIncrementInBits % 8 != 0)) {
unlock(bufferHandle);
return BAD_VALUE;
}
@@ -387,7 +387,8 @@
}
sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
- if ((sampleIncrementInBytes != 1) && (sampleIncrementInBytes != 2)) {
+ if ((sampleIncrementInBytes != 1) && (sampleIncrementInBytes != 2) &&
+ (sampleIncrementInBytes != 4)) {
unlock(bufferHandle);
return BAD_VALUE;
}
@@ -524,6 +525,37 @@
return decodeFunction(vec, outMetadata);
}
+template <class T>
+status_t Gralloc4Mapper::set(buffer_handle_t bufferHandle, const MetadataType& metadataType,
+ const T& metadata, EncodeFunction<T> encodeFunction) const {
+ hidl_vec<uint8_t> encodedMetadata;
+ if (const status_t status = encodeFunction(metadata, &encodedMetadata); status != OK) {
+ ALOGE("Encoding metadata(%s) failed with %d", metadataType.name.c_str(), status);
+ return status;
+ }
+ hidl_vec<uint8_t> vec;
+ auto ret =
+ mMapper->set(const_cast<native_handle_t*>(bufferHandle), metadataType, encodedMetadata);
+
+ const Error error = ret.withDefault(kTransactionError);
+ switch (error) {
+ case Error::BAD_DESCRIPTOR:
+ case Error::BAD_BUFFER:
+ case Error::BAD_VALUE:
+ case Error::NO_RESOURCES:
+ ALOGE("set(%s, %" PRIu64 ", ...) failed with %d", metadataType.name.c_str(),
+ metadataType.value, error);
+ break;
+ // It is not an error to attempt to set metadata that a particular gralloc implementation
+ // happens to not support.
+ case Error::UNSUPPORTED:
+ case Error::NONE:
+ break;
+ }
+
+ return static_cast<status_t>(error);
+}
+
status_t Gralloc4Mapper::getBufferId(buffer_handle_t bufferHandle, uint64_t* outBufferId) const {
return get(bufferHandle, gralloc4::MetadataType_BufferId, gralloc4::decodeBufferId,
outBufferId);
@@ -673,6 +705,12 @@
return NO_ERROR;
}
+status_t Gralloc4Mapper::setDataspace(buffer_handle_t bufferHandle, ui::Dataspace dataspace) const {
+ return set(bufferHandle, gralloc4::MetadataType_Dataspace,
+ static_cast<aidl::android::hardware::graphics::common::Dataspace>(dataspace),
+ gralloc4::encodeDataspace);
+}
+
status_t Gralloc4Mapper::getBlendMode(buffer_handle_t bufferHandle,
ui::BlendMode* outBlendMode) const {
return get(bufferHandle, gralloc4::MetadataType_BlendMode, gralloc4::decodeBlendMode,
@@ -685,24 +723,47 @@
outSmpte2086);
}
+status_t Gralloc4Mapper::setSmpte2086(buffer_handle_t bufferHandle,
+ std::optional<ui::Smpte2086> smpte2086) const {
+ return set(bufferHandle, gralloc4::MetadataType_Smpte2086, smpte2086,
+ gralloc4::encodeSmpte2086);
+}
+
status_t Gralloc4Mapper::getCta861_3(buffer_handle_t bufferHandle,
std::optional<ui::Cta861_3>* outCta861_3) const {
return get(bufferHandle, gralloc4::MetadataType_Cta861_3, gralloc4::decodeCta861_3,
outCta861_3);
}
+status_t Gralloc4Mapper::setCta861_3(buffer_handle_t bufferHandle,
+ std::optional<ui::Cta861_3> cta861_3) const {
+ return set(bufferHandle, gralloc4::MetadataType_Cta861_3, cta861_3, gralloc4::encodeCta861_3);
+}
+
status_t Gralloc4Mapper::getSmpte2094_40(
buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>>* outSmpte2094_40) const {
return get(bufferHandle, gralloc4::MetadataType_Smpte2094_40, gralloc4::decodeSmpte2094_40,
outSmpte2094_40);
}
+status_t Gralloc4Mapper::setSmpte2094_40(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_40) const {
+ return set(bufferHandle, gralloc4::MetadataType_Smpte2094_40, smpte2094_40,
+ gralloc4::encodeSmpte2094_40);
+}
+
status_t Gralloc4Mapper::getSmpte2094_10(
buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>>* outSmpte2094_10) const {
return get(bufferHandle, gralloc4::MetadataType_Smpte2094_10, gralloc4::decodeSmpte2094_10,
outSmpte2094_10);
}
+status_t Gralloc4Mapper::setSmpte2094_10(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_10) const {
+ return set(bufferHandle, gralloc4::MetadataType_Smpte2094_10, smpte2094_10,
+ gralloc4::encodeSmpte2094_10);
+}
+
template <class T>
status_t Gralloc4Mapper::getDefault(uint32_t width, uint32_t height, PixelFormat format,
uint32_t layerCount, uint64_t usage,
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 82d6cd5..a98e697 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -281,6 +281,10 @@
return mMapper->getDataspace(bufferHandle, outDataspace);
}
+status_t GraphicBufferMapper::setDataspace(buffer_handle_t bufferHandle, ui::Dataspace dataspace) {
+ return mMapper->setDataspace(bufferHandle, dataspace);
+}
+
status_t GraphicBufferMapper::getBlendMode(buffer_handle_t bufferHandle,
ui::BlendMode* outBlendMode) {
return mMapper->getBlendMode(bufferHandle, outBlendMode);
@@ -291,21 +295,41 @@
return mMapper->getSmpte2086(bufferHandle, outSmpte2086);
}
+status_t GraphicBufferMapper::setSmpte2086(buffer_handle_t bufferHandle,
+ std::optional<ui::Smpte2086> smpte2086) {
+ return mMapper->setSmpte2086(bufferHandle, smpte2086);
+}
+
status_t GraphicBufferMapper::getCta861_3(buffer_handle_t bufferHandle,
std::optional<ui::Cta861_3>* outCta861_3) {
return mMapper->getCta861_3(bufferHandle, outCta861_3);
}
+status_t GraphicBufferMapper::setCta861_3(buffer_handle_t bufferHandle,
+ std::optional<ui::Cta861_3> cta861_3) {
+ return mMapper->setCta861_3(bufferHandle, cta861_3);
+}
+
status_t GraphicBufferMapper::getSmpte2094_40(
buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>>* outSmpte2094_40) {
return mMapper->getSmpte2094_40(bufferHandle, outSmpte2094_40);
}
+status_t GraphicBufferMapper::setSmpte2094_40(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_40) {
+ return mMapper->setSmpte2094_40(bufferHandle, smpte2094_40);
+}
+
status_t GraphicBufferMapper::getSmpte2094_10(
buffer_handle_t bufferHandle, std::optional<std::vector<uint8_t>>* outSmpte2094_10) {
return mMapper->getSmpte2094_10(bufferHandle, outSmpte2094_10);
}
+status_t GraphicBufferMapper::setSmpte2094_10(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_10) {
+ return mMapper->setSmpte2094_10(bufferHandle, smpte2094_10);
+}
+
status_t GraphicBufferMapper::getDefaultPixelFormatFourCC(uint32_t width, uint32_t height,
PixelFormat format, uint32_t layerCount,
uint64_t usage,
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
deleted file mode 100644
index aec2fac..0000000
--- a/libs/ui/HdrCapabilities.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2016 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 <ui/HdrCapabilities.h>
-
-namespace android {
-
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wundefined-reinterpret-cast"
-#endif
-
-size_t HdrCapabilities::getFlattenedSize() const {
- return sizeof(mMaxLuminance) +
- sizeof(mMaxAverageLuminance) +
- sizeof(mMinLuminance) +
- sizeof(int32_t) +
- mSupportedHdrTypes.size() * sizeof(ui::Hdr);
-}
-
-status_t HdrCapabilities::flatten(void* buffer, size_t size) const {
-
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
-
- int32_t* const buf = static_cast<int32_t*>(buffer);
- reinterpret_cast<float&>(buf[0]) = mMaxLuminance;
- reinterpret_cast<float&>(buf[1]) = mMaxAverageLuminance;
- reinterpret_cast<float&>(buf[2]) = mMinLuminance;
- buf[3] = static_cast<int32_t>(mSupportedHdrTypes.size());
- for (size_t i = 0, c = mSupportedHdrTypes.size(); i < c; ++i) {
- buf[4 + i] = static_cast<int32_t>(mSupportedHdrTypes[i]);
- }
- return NO_ERROR;
-}
-
-status_t HdrCapabilities::unflatten(void const* buffer, size_t size) {
-
- size_t minSize = sizeof(mMaxLuminance) +
- sizeof(mMaxAverageLuminance) +
- sizeof(mMinLuminance) +
- sizeof(int32_t);
-
- if (size < minSize) {
- return NO_MEMORY;
- }
-
- int32_t const * const buf = static_cast<int32_t const *>(buffer);
- const size_t itemCount = size_t(buf[3]);
-
- // check the buffer is large enough
- if (size < minSize + itemCount * sizeof(int32_t)) {
- return BAD_VALUE;
- }
-
- mMaxLuminance = reinterpret_cast<float const&>(buf[0]);
- mMaxAverageLuminance = reinterpret_cast<float const&>(buf[1]);
- mMinLuminance = reinterpret_cast<float const&>(buf[2]);
- if (itemCount) {
- mSupportedHdrTypes.resize(itemCount);
- for (size_t i = 0; i < itemCount; ++i) {
- mSupportedHdrTypes[i] = static_cast<ui::Hdr>(buf[4 + i]);
- }
- }
- return NO_ERROR;
-}
-
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
-} // namespace android
diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h
index 56f68e7..a2791a6 100644
--- a/libs/ui/include/ui/DisplayMode.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -29,7 +29,7 @@
using DisplayModeId = int32_t;
// Mode supported by physical display.
-struct DisplayMode : LightFlattenable<DisplayMode> {
+struct DisplayMode {
DisplayModeId id;
ui::Size resolution;
float xDpi = 0;
@@ -40,11 +40,6 @@
nsecs_t sfVsyncOffset = 0;
nsecs_t presentationDeadline = 0;
int32_t group = -1;
-
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(const void* buffer, size_t size);
};
} // namespace android::ui
diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h
index ce75a65..8c9fe4c 100644
--- a/libs/ui/include/ui/DynamicDisplayInfo.h
+++ b/libs/ui/include/ui/DynamicDisplayInfo.h
@@ -24,12 +24,11 @@
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
-#include <utils/Flattenable.h>
namespace android::ui {
// Information about a physical display which may change on hotplug reconnect.
-struct DynamicDisplayInfo : LightFlattenable<DynamicDisplayInfo> {
+struct DynamicDisplayInfo {
std::vector<ui::DisplayMode> supportedDisplayModes;
// This struct is going to be serialized over binder, so
@@ -53,11 +52,6 @@
ui::DisplayModeId preferredBootDisplayMode;
std::optional<ui::DisplayMode> getActiveDisplayMode() const;
-
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(const void* buffer, size_t size);
};
} // namespace android::ui
diff --git a/libs/ui/include/ui/Gralloc.h b/libs/ui/include/ui/Gralloc.h
index 753b0a6..6101d4b 100644
--- a/libs/ui/include/ui/Gralloc.h
+++ b/libs/ui/include/ui/Gralloc.h
@@ -161,6 +161,10 @@
ui::Dataspace* /*outDataspace*/) const {
return INVALID_OPERATION;
}
+ virtual status_t setDataspace(buffer_handle_t /*bufferHandle*/,
+ ui::Dataspace /*dataspace*/) const {
+ return INVALID_OPERATION;
+ }
virtual status_t getBlendMode(buffer_handle_t /*bufferHandle*/,
ui::BlendMode* /*outBlendMode*/) const {
return INVALID_OPERATION;
@@ -169,21 +173,36 @@
std::optional<ui::Smpte2086>* /*outSmpte2086*/) const {
return INVALID_OPERATION;
}
+ virtual status_t setSmpte2086(buffer_handle_t /*bufferHandle*/,
+ std::optional<ui::Smpte2086> /*smpte2086*/) const {
+ return INVALID_OPERATION;
+ }
virtual status_t getCta861_3(buffer_handle_t /*bufferHandle*/,
std::optional<ui::Cta861_3>* /*outCta861_3*/) const {
return INVALID_OPERATION;
}
+ virtual status_t setCta861_3(buffer_handle_t /*bufferHandle*/,
+ std::optional<ui::Cta861_3> /*cta861_3*/) const {
+ return INVALID_OPERATION;
+ }
virtual status_t getSmpte2094_40(
buffer_handle_t /*bufferHandle*/,
std::optional<std::vector<uint8_t>>* /*outSmpte2094_40*/) const {
return INVALID_OPERATION;
}
+ virtual status_t setSmpte2094_40(buffer_handle_t /*bufferHandle*/,
+ std::optional<std::vector<uint8_t>> /*smpte2094_40*/) const {
+ return INVALID_OPERATION;
+ }
virtual status_t getSmpte2094_10(
buffer_handle_t /*bufferHandle*/,
std::optional<std::vector<uint8_t>>* /*outSmpte2094_10*/) const {
return INVALID_OPERATION;
}
-
+ virtual status_t setSmpte2094_10(buffer_handle_t /*bufferHandle*/,
+ std::optional<std::vector<uint8_t>> /*smpte2094_10*/) const {
+ return INVALID_OPERATION;
+ }
virtual status_t getDefaultPixelFormatFourCC(uint32_t /*width*/, uint32_t /*height*/,
PixelFormat /*format*/, uint32_t /*layerCount*/,
uint64_t /*usage*/,
diff --git a/libs/ui/include/ui/Gralloc4.h b/libs/ui/include/ui/Gralloc4.h
index fe38709..cf023c9 100644
--- a/libs/ui/include/ui/Gralloc4.h
+++ b/libs/ui/include/ui/Gralloc4.h
@@ -102,16 +102,24 @@
status_t getPlaneLayouts(buffer_handle_t bufferHandle,
std::vector<ui::PlaneLayout>* outPlaneLayouts) const override;
status_t getDataspace(buffer_handle_t bufferHandle, ui::Dataspace* outDataspace) const override;
+ status_t setDataspace(buffer_handle_t bufferHandle, ui::Dataspace dataspace) const override;
status_t getBlendMode(buffer_handle_t bufferHandle, ui::BlendMode* outBlendMode) const override;
status_t getSmpte2086(buffer_handle_t bufferHandle,
std::optional<ui::Smpte2086>* outSmpte2086) const override;
+ status_t setSmpte2086(buffer_handle_t bufferHandle,
+ std::optional<ui::Smpte2086> smpte2086) const override;
status_t getCta861_3(buffer_handle_t bufferHandle,
std::optional<ui::Cta861_3>* outCta861_3) const override;
+ status_t setCta861_3(buffer_handle_t bufferHandle,
+ std::optional<ui::Cta861_3> cta861_3) const override;
status_t getSmpte2094_40(buffer_handle_t bufferHandle,
std::optional<std::vector<uint8_t>>* outSmpte2094_40) const override;
+ status_t setSmpte2094_40(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_40) const override;
status_t getSmpte2094_10(buffer_handle_t bufferHandle,
std::optional<std::vector<uint8_t>>* outSmpte2094_10) const override;
-
+ status_t setSmpte2094_10(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_10) const override;
status_t getDefaultPixelFormatFourCC(uint32_t width, uint32_t height, PixelFormat format,
uint32_t layerCount, uint64_t usage,
uint32_t* outPixelFormatFourCC) const override;
@@ -157,6 +165,8 @@
template <class T>
using DecodeFunction = status_t (*)(const hardware::hidl_vec<uint8_t>& input, T* output);
+ template <class T>
+ using EncodeFunction = status_t (*)(const T& input, hardware::hidl_vec<uint8_t>* output);
template <class T>
status_t get(
@@ -165,6 +175,12 @@
DecodeFunction<T> decodeFunction, T* outMetadata) const;
template <class T>
+ status_t set(
+ buffer_handle_t bufferHandle,
+ const android::hardware::graphics::mapper::V4_0::IMapper::MetadataType& metadataType,
+ const T& metadata, EncodeFunction<T> encodeFunction) const;
+
+ template <class T>
status_t getDefault(
uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
uint64_t usage,
diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
index 257c155..507fa35 100644
--- a/libs/ui/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -121,13 +121,20 @@
status_t getPlaneLayouts(buffer_handle_t bufferHandle,
std::vector<ui::PlaneLayout>* outPlaneLayouts);
status_t getDataspace(buffer_handle_t bufferHandle, ui::Dataspace* outDataspace);
+ status_t setDataspace(buffer_handle_t bufferHandle, ui::Dataspace dataspace);
status_t getBlendMode(buffer_handle_t bufferHandle, ui::BlendMode* outBlendMode);
status_t getSmpte2086(buffer_handle_t bufferHandle, std::optional<ui::Smpte2086>* outSmpte2086);
+ status_t setSmpte2086(buffer_handle_t bufferHandle, std::optional<ui::Smpte2086> smpte2086);
status_t getCta861_3(buffer_handle_t bufferHandle, std::optional<ui::Cta861_3>* outCta861_3);
+ status_t setCta861_3(buffer_handle_t bufferHandle, std::optional<ui::Cta861_3> cta861_3);
status_t getSmpte2094_40(buffer_handle_t bufferHandle,
std::optional<std::vector<uint8_t>>* outSmpte2094_40);
+ status_t setSmpte2094_40(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_40);
status_t getSmpte2094_10(buffer_handle_t bufferHandle,
std::optional<std::vector<uint8_t>>* outSmpte2094_10);
+ status_t setSmpte2094_10(buffer_handle_t bufferHandle,
+ std::optional<std::vector<uint8_t>> smpte2094_10);
/**
* Gets the default metadata for a gralloc buffer allocated with the given parameters.
diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h
index 4bdacb0..8661c36 100644
--- a/libs/ui/include/ui/GraphicTypes.h
+++ b/libs/ui/include/ui/GraphicTypes.h
@@ -62,5 +62,23 @@
using Compression = aidl::android::hardware::graphics::common::Compression;
using Interlaced = aidl::android::hardware::graphics::common::Interlaced;
+inline aidl::android::hardware::graphics::common::XyColor translate(const android_xy_color& color) {
+ return aidl::android::hardware::graphics::common::XyColor{.x = color.x, .y = color.y};
+}
+
+inline Smpte2086 translate(const android_smpte2086_metadata& metadata) {
+ return Smpte2086{.primaryRed = translate(metadata.displayPrimaryRed),
+ .primaryGreen = translate(metadata.displayPrimaryGreen),
+ .primaryBlue = translate(metadata.displayPrimaryBlue),
+ .whitePoint = translate(metadata.whitePoint),
+ .maxLuminance = metadata.maxLuminance,
+ .minLuminance = metadata.minLuminance};
+}
+
+inline Cta861_3 translate(const android_cta861_3_metadata& metadata) {
+ return Cta861_3{.maxContentLightLevel = metadata.maxContentLightLevel,
+ .maxFrameAverageLightLevel = metadata.maxFrameAverageLightLevel};
+}
+
} // namespace ui
} // namespace android
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 813adde..ae54223 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -22,12 +22,10 @@
#include <vector>
#include <ui/GraphicTypes.h>
-#include <utils/Flattenable.h>
namespace android {
-class HdrCapabilities : public LightFlattenable<HdrCapabilities>
-{
+class HdrCapabilities {
public:
HdrCapabilities(const std::vector<ui::Hdr>& types,
float maxLuminance, float maxAverageLuminance, float minLuminance)
@@ -49,12 +47,6 @@
float getDesiredMaxAverageLuminance() const { return mMaxAverageLuminance; }
float getDesiredMinLuminance() const { return mMinLuminance; }
- // Flattenable protocol
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(void const* buffer, size_t size);
-
private:
std::vector<ui::Hdr> mSupportedHdrTypes;
float mMaxLuminance;
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 3a4b6c5..2a3924b 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -202,9 +202,11 @@
coords += "}";
}
return StringPrintf("NotifyMotionArgs(id=%" PRId32 ", eventTime=%" PRId64 ", deviceId=%" PRId32
- ", source=%s, action=%s, pointerCount=%" PRIu32 " pointers=%s)",
+ ", source=%s, action=%s, pointerCount=%" PRIu32
+ " pointers=%s, flags=0x%08x)",
id, eventTime, deviceId, inputEventSourceToString(source).c_str(),
- MotionEvent::actionToString(action).c_str(), pointerCount, coords.c_str());
+ MotionEvent::actionToString(action).c_str(), pointerCount, coords.c_str(),
+ flags);
}
void NotifyMotionArgs::notify(InputListenerInterface& listener) const {
diff --git a/services/inputflinger/PreferStylusOverTouchBlocker.cpp b/services/inputflinger/PreferStylusOverTouchBlocker.cpp
index ad639b4..beec2e1 100644
--- a/services/inputflinger/PreferStylusOverTouchBlocker.cpp
+++ b/services/inputflinger/PreferStylusOverTouchBlocker.cpp
@@ -15,78 +15,163 @@
*/
#include "PreferStylusOverTouchBlocker.h"
-
-#include <android-base/stringprintf.h>
-
-using android::base::StringPrintf;
-
-static const char* toString(bool value) {
- return value ? "true" : "false";
-}
+#include <input/PrintTools.h>
namespace android {
-ftl::StaticVector<NotifyMotionArgs, 2> PreferStylusOverTouchBlocker::processMotion(
- const NotifyMotionArgs& args) {
- const bool isStylusEvent = isFromSource(args.source, AINPUT_SOURCE_STYLUS);
- if (isStylusEvent) {
- for (size_t i = 0; i < args.pointerCount; i++) {
- // Make sure we are canceling stylus pointers
- const int32_t toolType = args.pointerProperties[i].toolType;
- LOG_ALWAYS_FATAL_IF(toolType != AMOTION_EVENT_TOOL_TYPE_STYLUS &&
- toolType != AMOTION_EVENT_TOOL_TYPE_ERASER,
- "The pointer %zu has toolType=%i, but the source is STYLUS. If "
- "simultaneous touch and stylus is supported, "
- "'PreferStylusOverTouchBlocker' should be disabled.",
- i, toolType);
+static std::pair<bool, bool> checkToolType(const NotifyMotionArgs& args) {
+ bool hasStylus = false;
+ bool hasTouch = false;
+ for (size_t i = 0; i < args.pointerCount; i++) {
+ // Make sure we are canceling stylus pointers
+ const int32_t toolType = args.pointerProperties[i].toolType;
+ if (toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS ||
+ toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
+ hasStylus = true;
+ }
+ if (toolType == AMOTION_EVENT_TOOL_TYPE_FINGER) {
+ hasTouch = true;
}
}
- const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
+ return std::make_pair(hasTouch, hasStylus);
+}
+
+/**
+ * Intersect two sets in-place, storing the result in 'set1'.
+ * Find elements in set1 that are not present in set2 and delete them,
+ * relying on the fact that the two sets are ordered.
+ */
+template <typename T>
+static void intersectInPlace(std::set<T>& set1, const std::set<T>& set2) {
+ typename std::set<T>::iterator it1 = set1.begin();
+ typename std::set<T>::const_iterator it2 = set2.begin();
+ while (it1 != set1.end() && it2 != set2.end()) {
+ const T& element1 = *it1;
+ const T& element2 = *it2;
+ if (element1 < element2) {
+ // This element is not present in set2. Remove it from set1.
+ it1 = set1.erase(it1);
+ continue;
+ }
+ if (element2 < element1) {
+ it2++;
+ }
+ if (element1 == element2) {
+ it1++;
+ it2++;
+ }
+ }
+ // Remove the rest of the elements in set1 because set2 is already exhausted.
+ set1.erase(it1, set1.end());
+}
+
+/**
+ * Same as above, but prune a map
+ */
+template <typename K, class V>
+static void intersectInPlace(std::map<K, V>& map, const std::set<K>& set2) {
+ typename std::map<K, V>::iterator it1 = map.begin();
+ typename std::set<K>::const_iterator it2 = set2.begin();
+ while (it1 != map.end() && it2 != set2.end()) {
+ const auto& [key, _] = *it1;
+ const K& element2 = *it2;
+ if (key < element2) {
+ // This element is not present in set2. Remove it from map.
+ it1 = map.erase(it1);
+ continue;
+ }
+ if (element2 < key) {
+ it2++;
+ }
+ if (key == element2) {
+ it1++;
+ it2++;
+ }
+ }
+ // Remove the rest of the elements in map because set2 is already exhausted.
+ map.erase(it1, map.end());
+}
+
+// -------------------------------- PreferStylusOverTouchBlocker -----------------------------------
+
+std::vector<NotifyMotionArgs> PreferStylusOverTouchBlocker::processMotion(
+ const NotifyMotionArgs& args) {
+ const auto [hasTouch, hasStylus] = checkToolType(args);
const bool isUpOrCancel =
args.action == AMOTION_EVENT_ACTION_UP || args.action == AMOTION_EVENT_ACTION_CANCEL;
+
+ if (hasTouch && hasStylus) {
+ mDevicesWithMixedToolType.insert(args.deviceId);
+ }
+ // Handle the case where mixed touch and stylus pointers are reported. Add this device to the
+ // ignore list, since it clearly supports simultaneous touch and stylus.
+ if (mDevicesWithMixedToolType.find(args.deviceId) != mDevicesWithMixedToolType.end()) {
+ // This event comes from device with mixed stylus and touch event. Ignore this device.
+ if (mCanceledDevices.find(args.deviceId) != mCanceledDevices.end()) {
+ // If we started to cancel events from this device, continue to do so to keep
+ // the stream consistent. It should happen at most once per "mixed" device.
+ if (isUpOrCancel) {
+ mCanceledDevices.erase(args.deviceId);
+ mLastTouchEvents.erase(args.deviceId);
+ }
+ return {};
+ }
+ return {args};
+ }
+
+ const bool isStylusEvent = hasStylus;
+ const bool isDown = args.action == AMOTION_EVENT_ACTION_DOWN;
+
if (isStylusEvent) {
if (isDown) {
// Reject all touch while stylus is down
- mIsStylusDown = true;
- if (mIsTouchDown && !mCurrentTouchIsCanceled) {
- // Cancel touch!
- mCurrentTouchIsCanceled = true;
- mLastTouchEvent.action = AMOTION_EVENT_ACTION_CANCEL;
- mLastTouchEvent.flags |= AMOTION_EVENT_FLAG_CANCELED;
- mLastTouchEvent.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
- return {mLastTouchEvent, args};
+ mActiveStyli.insert(args.deviceId);
+
+ // Cancel all current touch!
+ std::vector<NotifyMotionArgs> result;
+ for (auto& [deviceId, lastTouchEvent] : mLastTouchEvents) {
+ if (mCanceledDevices.find(deviceId) != mCanceledDevices.end()) {
+ // Already canceled, go to next one.
+ continue;
+ }
+ // Not yet canceled. Cancel it.
+ lastTouchEvent.action = AMOTION_EVENT_ACTION_CANCEL;
+ lastTouchEvent.flags |= AMOTION_EVENT_FLAG_CANCELED;
+ lastTouchEvent.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
+ result.push_back(lastTouchEvent);
+ mCanceledDevices.insert(deviceId);
}
+ result.push_back(args);
+ return result;
}
if (isUpOrCancel) {
- mIsStylusDown = false;
+ mActiveStyli.erase(args.deviceId);
}
// Never drop stylus events
return {args};
}
- const bool isTouchEvent =
- isFromSource(args.source, AINPUT_SOURCE_TOUCHSCREEN) && !isStylusEvent;
+ const bool isTouchEvent = hasTouch;
if (isTouchEvent) {
- if (mIsStylusDown) {
- mCurrentTouchIsCanceled = true;
+ // Suppress the current gesture if any stylus is still down
+ if (!mActiveStyli.empty()) {
+ mCanceledDevices.insert(args.deviceId);
}
+
+ const bool shouldDrop = mCanceledDevices.find(args.deviceId) != mCanceledDevices.end();
+ if (isUpOrCancel) {
+ mCanceledDevices.erase(args.deviceId);
+ mLastTouchEvents.erase(args.deviceId);
+ }
+
// If we already canceled the current gesture, then continue to drop events from it, even if
// the stylus has been lifted.
- if (mCurrentTouchIsCanceled) {
- if (isUpOrCancel) {
- mCurrentTouchIsCanceled = false;
- }
+ if (shouldDrop) {
return {};
}
- // Update state
- mLastTouchEvent = args;
- if (isDown) {
- mIsTouchDown = true;
- }
- if (isUpOrCancel) {
- mIsTouchDown = false;
- mCurrentTouchIsCanceled = false;
+ if (!isUpOrCancel) {
+ mLastTouchEvents[args.deviceId] = args;
}
return {args};
}
@@ -95,12 +180,36 @@
return {args};
}
-std::string PreferStylusOverTouchBlocker::dump() {
+void PreferStylusOverTouchBlocker::notifyInputDevicesChanged(
+ const std::vector<InputDeviceInfo>& inputDevices) {
+ std::set<int32_t> presentDevices;
+ for (const InputDeviceInfo& device : inputDevices) {
+ presentDevices.insert(device.getId());
+ }
+ // Only keep the devices that are still present.
+ intersectInPlace(mDevicesWithMixedToolType, presentDevices);
+ intersectInPlace(mLastTouchEvents, presentDevices);
+ intersectInPlace(mCanceledDevices, presentDevices);
+ intersectInPlace(mActiveStyli, presentDevices);
+}
+
+void PreferStylusOverTouchBlocker::notifyDeviceReset(const NotifyDeviceResetArgs& args) {
+ mDevicesWithMixedToolType.erase(args.deviceId);
+ mLastTouchEvents.erase(args.deviceId);
+ mCanceledDevices.erase(args.deviceId);
+ mActiveStyli.erase(args.deviceId);
+}
+
+static std::string dumpArgs(const NotifyMotionArgs& args) {
+ return args.dump();
+}
+
+std::string PreferStylusOverTouchBlocker::dump() const {
std::string out;
- out += StringPrintf("mIsTouchDown: %s\n", toString(mIsTouchDown));
- out += StringPrintf("mIsStylusDown: %s\n", toString(mIsStylusDown));
- out += StringPrintf("mLastTouchEvent: %s\n", mLastTouchEvent.dump().c_str());
- out += StringPrintf("mCurrentTouchIsCanceled: %s\n", toString(mCurrentTouchIsCanceled));
+ out += "mActiveStyli: " + dumpSet(mActiveStyli) + "\n";
+ out += "mLastTouchEvents: " + dumpMap(mLastTouchEvents, constToString, dumpArgs) + "\n";
+ out += "mDevicesWithMixedToolType: " + dumpSet(mDevicesWithMixedToolType) + "\n";
+ out += "mCanceledDevices: " + dumpSet(mCanceledDevices) + "\n";
return out;
}
diff --git a/services/inputflinger/PreferStylusOverTouchBlocker.h b/services/inputflinger/PreferStylusOverTouchBlocker.h
index 3f56161..716dc4d 100644
--- a/services/inputflinger/PreferStylusOverTouchBlocker.h
+++ b/services/inputflinger/PreferStylusOverTouchBlocker.h
@@ -16,66 +16,50 @@
#pragma once
-#include <ftl/static_vector.h>
#include <optional>
+#include <set>
#include "InputListener.h"
namespace android {
/**
- * When stylus is down, we ignore all touch.
+ * When stylus is down, all touch is ignored.
* TODO(b/210159205): delete this when simultaneous stylus and touch is supported
*/
class PreferStylusOverTouchBlocker {
public:
/**
- * Process the provided event and emit up to 2 events in response.
+ * Process the provided event and emit 0 or more events that should be used instead of it.
* In the majority of cases, the returned result will just be the provided args (array with
* only 1 element), unmodified.
*
* If the gesture should be blocked, the returned result may be:
*
* a) An empty array, if the current event should just be ignored completely
- * b) An array of 2 elements, containing an event with ACTION_CANCEL and the current event.
+ * b) An array of N elements, containing N-1 events with ACTION_CANCEL and the current event.
*
- * bool is set to 'true'.
- * NotifyMotionArgs potentially contains an event that should be used to cancel the existing
- * gesture.
- *
- * If the event should not be blocked, bool contains 'false'.
+ * The returned result is intended to be reinjected into the original event stream in
+ * replacement of the incoming event.
*/
- ftl::StaticVector<NotifyMotionArgs, 2> processMotion(const NotifyMotionArgs& args);
- std::string dump();
+ std::vector<NotifyMotionArgs> processMotion(const NotifyMotionArgs& args);
+ std::string dump() const;
+
+ void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices);
+
+ void notifyDeviceReset(const NotifyDeviceResetArgs& args);
private:
- bool mIsTouchDown = false;
- bool mIsStylusDown = false;
- // Provide some default values for the stored MotionEvent to allow printint the event before
- // any real event is received.
- NotifyMotionArgs mLastTouchEvent{0 /*id*/,
- 0 /*eventTime*/,
- 0 /*readTime*/,
- 0 /*deviceId*/,
- AINPUT_SOURCE_TOUCHSCREEN,
- 0 /*displayId*/,
- 0 /*policyFlags*/,
- 0 /*action*/,
- 0 /*actionButton*/,
- 0 /*flags*/,
- 0 /*metaState*/,
- 0 /*buttonState*/,
- MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE,
- 0 /*pointerCount*/,
- nullptr /*properties*/,
- nullptr /*coords*/,
- 0. /*xPrecision*/,
- 0. /*yPrecision*/,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
- 0 /*downTime*/,
- {}};
- bool mCurrentTouchIsCanceled = false;
+ // Stores the device id's of styli that are currently down.
+ std::set<int32_t /*deviceId*/> mActiveStyli;
+ // For each device, store the last touch event as long as the touch is down. Upon liftoff,
+ // the entry is erased.
+ std::map<int32_t /*deviceId*/, NotifyMotionArgs> mLastTouchEvents;
+ // Device ids of devices for which the current touch gesture is canceled.
+ std::set<int32_t /*deviceId*/> mCanceledDevices;
+
+ // Device ids of input devices where we encountered simultaneous touch and stylus
+ // events. For these devices, we don't do any event processing (nothing is blocked or altered).
+ std::set<int32_t /*deviceId*/> mDevicesWithMixedToolType;
};
} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
index fb3962e..b69e16a 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.cpp
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -368,6 +368,14 @@
}
void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) {
+ const std::vector<NotifyMotionArgs> processedArgs =
+ mPreferStylusOverTouchBlocker.processMotion(*args);
+ for (const NotifyMotionArgs& loopArgs : processedArgs) {
+ notifyMotionInner(&loopArgs);
+ }
+}
+
+void UnwantedInteractionBlocker::notifyMotionInner(const NotifyMotionArgs* args) {
auto it = mPalmRejectors.find(args->deviceId);
const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args->source);
if (!sendToPalmRejector) {
@@ -401,6 +409,7 @@
mPalmRejectors.emplace(args->deviceId, info);
}
mListener.notifyDeviceReset(args);
+ mPreferStylusOverTouchBlocker.notifyDeviceReset(*args);
}
void UnwantedInteractionBlocker::notifyPointerCaptureChanged(
@@ -437,10 +446,13 @@
auto const& [deviceId, _] = item;
return devicesToKeep.find(deviceId) == devicesToKeep.end();
});
+ mPreferStylusOverTouchBlocker.notifyInputDevicesChanged(inputDevices);
}
void UnwantedInteractionBlocker::dump(std::string& dump) {
dump += "UnwantedInteractionBlocker:\n";
+ dump += " mPreferStylusOverTouchBlocker:\n";
+ dump += addPrefix(mPreferStylusOverTouchBlocker.dump(), " ");
dump += StringPrintf(" mEnablePalmRejection: %s\n", toString(mEnablePalmRejection));
dump += StringPrintf(" isPalmRejectionEnabled (flag value): %s\n",
toString(isPalmRejectionEnabled()));
diff --git a/services/inputflinger/UnwantedInteractionBlocker.h b/services/inputflinger/UnwantedInteractionBlocker.h
index 14068fd..8a1cd72 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.h
+++ b/services/inputflinger/UnwantedInteractionBlocker.h
@@ -23,6 +23,8 @@
#include "ui/events/ozone/evdev/touch_filter/neural_stylus_palm_detection_filter_util.h"
#include "ui/events/ozone/evdev/touch_filter/palm_detection_filter.h"
+#include "PreferStylusOverTouchBlocker.h"
+
namespace android {
// --- Functions for manipulation of event streams
@@ -88,9 +90,14 @@
InputListenerInterface& mListener;
const bool mEnablePalmRejection;
+ // When stylus is down, ignore touch
+ PreferStylusOverTouchBlocker mPreferStylusOverTouchBlocker;
+
// Detect and reject unwanted palms on screen
// Use a separate palm rejector for every touch device.
std::map<int32_t /*deviceId*/, PalmRejector> mPalmRejectors;
+ // TODO(b/210159205): delete this when simultaneous stylus and touch is supported
+ void notifyMotionInner(const NotifyMotionArgs* args);
};
class SlotState {
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 8bd3899..d6a6bd2 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -60,10 +60,11 @@
#define INDENT3 " "
using android::base::StringPrintf;
-using namespace android::flag_operators;
namespace android {
+using namespace ftl::flag_operators;
+
static const char* DEVICE_INPUT_PATH = "/dev/input";
// v4l2 devices go directly into /dev
static const char* DEVICE_PATH = "/dev";
@@ -302,7 +303,8 @@
// --- Global Functions ---
-Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses) {
+ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis,
+ ftl::Flags<InputDeviceClass> deviceClasses) {
// Touch devices get dibs on touch-related axes.
if (deviceClasses.test(InputDeviceClass::TOUCH)) {
switch (axis) {
@@ -765,10 +767,10 @@
return device != nullptr ? device->identifier : InputDeviceIdentifier();
}
-Flags<InputDeviceClass> EventHub::getDeviceClasses(int32_t deviceId) const {
+ftl::Flags<InputDeviceClass> EventHub::getDeviceClasses(int32_t deviceId) const {
std::scoped_lock _l(mLock);
Device* device = getDeviceLocked(deviceId);
- return device != nullptr ? device->classes : Flags<InputDeviceClass>(0);
+ return device != nullptr ? device->classes : ftl::Flags<InputDeviceClass>(0);
}
int32_t EventHub::getDeviceControllerNumber(int32_t deviceId) const {
@@ -1909,7 +1911,7 @@
}
void EventHub::reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier& identifier,
- Flags<InputDeviceClass> classes) {
+ ftl::Flags<InputDeviceClass> classes) {
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, reinterpret_cast<const uint8_t*>(identifier.uniqueId.c_str()),
@@ -2191,7 +2193,7 @@
}
// If the device isn't recognized as something we handle, don't monitor it.
- if (device->classes == Flags<InputDeviceClass>(0)) {
+ if (device->classes == ftl::Flags<InputDeviceClass>(0)) {
ALOGV("Dropping device: id=%d, path='%s', name='%s'", deviceId, devicePath.c_str(),
device->identifier.name.c_str());
return;
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index a050963..ba5083b 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -18,9 +18,10 @@
#include "InputDevice.h"
-#include <ftl/Flags.h>
#include <algorithm>
+#include <ftl/flags.h>
+
#include "CursorInputMapper.h"
#include "ExternalStylusInputMapper.h"
#include "InputReaderContext.h"
@@ -145,7 +146,7 @@
return;
}
std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
- Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses();
+ ftl::Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses();
std::vector<std::unique_ptr<InputMapper>> mappers;
// Check if we should skip population
@@ -236,7 +237,7 @@
void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
uint32_t changes) {
mSources = 0;
- mClasses = Flags<InputDeviceClass>(0);
+ mClasses = ftl::Flags<InputDeviceClass>(0);
mControllerNumber = 0;
for_each_subdevice([this](InputDeviceContext& context) {
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 18e912d..130c556 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -19,13 +19,12 @@
#include <bitset>
#include <climits>
+#include <filesystem>
#include <unordered_map>
#include <vector>
-#include <ftl/Flags.h>
-#include <filesystem>
-
#include <batteryservice/BatteryService.h>
+#include <ftl/flags.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/KeyCharacterMap.h>
@@ -189,7 +188,7 @@
int32_t id;
std::string name;
std::optional<int32_t> maxBrightness;
- Flags<InputLightClass> flags;
+ ftl::Flags<InputLightClass> flags;
std::array<int32_t, COLOR_NUM> rgbIndex;
std::filesystem::path path;
};
@@ -198,7 +197,7 @@
struct RawBatteryInfo {
int32_t id;
std::string name;
- Flags<InputBatteryClass> flags;
+ ftl::Flags<InputBatteryClass> flags;
std::filesystem::path path;
};
@@ -206,7 +205,8 @@
* Gets the class that owns an axis, in cases where multiple classes might claim
* the same axis for different purposes.
*/
-extern Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses);
+extern ftl::Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis,
+ ftl::Flags<InputDeviceClass> deviceClasses);
/*
* Grand Central Station for events.
@@ -239,7 +239,7 @@
FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,
};
- virtual Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const = 0;
+ virtual ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const = 0;
virtual InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const = 0;
@@ -436,7 +436,7 @@
public:
EventHub();
- Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override final;
+ ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override final;
InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override final;
@@ -559,7 +559,7 @@
std::unique_ptr<TouchVideoDevice> videoDevice;
- Flags<InputDeviceClass> classes;
+ ftl::Flags<InputDeviceClass> classes;
BitArray<KEY_MAX> keyBitmask;
BitArray<KEY_MAX> keyState;
@@ -662,7 +662,7 @@
int32_t getNextControllerNumberLocked(const std::string& name) REQUIRES(mLock);
void releaseControllerNumberLocked(int32_t num) REQUIRES(mLock);
void reportDeviceAddedForStatisticsLocked(const InputDeviceIdentifier& identifier,
- Flags<InputDeviceClass> classes) REQUIRES(mLock);
+ ftl::Flags<InputDeviceClass> classes) REQUIRES(mLock);
const std::unordered_map<int32_t, RawBatteryInfo>& getBatteryInfoLocked(int32_t deviceId) const
REQUIRES(mLock);
@@ -725,6 +725,6 @@
bool mPendingINotify;
};
-}; // namespace android
+} // namespace android
#endif // _RUNTIME_EVENT_HUB_H
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 694daa9..728020e 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -17,12 +17,12 @@
#ifndef _UI_INPUTREADER_INPUT_DEVICE_H
#define _UI_INPUTREADER_INPUT_DEVICE_H
-#include <ftl/Flags.h>
+#include <ftl/flags.h>
#include <input/DisplayViewport.h>
#include <input/InputDevice.h>
#include <input/PropertyMap.h>
-#include <stdint.h>
+#include <cstdint>
#include <optional>
#include <unordered_map>
#include <vector>
@@ -53,7 +53,7 @@
inline int32_t getGeneration() const { return mGeneration; }
inline const std::string getName() const { return mIdentifier.name; }
inline const std::string getDescriptor() { return mIdentifier.descriptor; }
- inline Flags<InputDeviceClass> getClasses() const { return mClasses; }
+ inline ftl::Flags<InputDeviceClass> getClasses() const { return mClasses; }
inline uint32_t getSources() const { return mSources; }
inline bool hasEventHubDevices() const { return !mDevices.empty(); }
@@ -160,7 +160,7 @@
int32_t mControllerNumber;
InputDeviceIdentifier mIdentifier;
std::string mAlias;
- Flags<InputDeviceClass> mClasses;
+ ftl::Flags<InputDeviceClass> mClasses;
// map from eventHubId to device context and mappers
using MapperVector = std::vector<std::unique_ptr<InputMapper>>;
@@ -250,7 +250,7 @@
inline int32_t getId() { return mDeviceId; }
inline int32_t getEventHubId() { return mId; }
- inline Flags<InputDeviceClass> getDeviceClasses() const {
+ inline ftl::Flags<InputDeviceClass> getDeviceClasses() const {
return mEventHub->getDeviceClasses(mId);
}
inline InputDeviceIdentifier getDeviceIdentifier() const {
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index bf58705..8641287 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -39,10 +39,11 @@
using android::gui::WindowInfoHandle;
using android::os::InputEventInjectionResult;
using android::os::InputEventInjectionSync;
-using namespace android::flag_operators;
namespace android::inputdispatcher {
+using namespace ftl::flag_operators;
+
// An arbitrary time value.
static const nsecs_t ARBITRARY_TIME = 1234;
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 9f33d23..8ba501c 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -14,6 +14,9 @@
* limitations under the License.
*/
+#include <cinttypes>
+#include <memory>
+
#include <CursorInputMapper.h>
#include <InputDevice.h>
#include <InputMapper.h>
@@ -34,18 +37,15 @@
#include <android-base/thread_annotations.h>
#include <gtest/gtest.h>
#include <gui/constants.h>
-#include <inttypes.h>
-#include <math.h>
-#include <memory>
-#include <regex>
#include "input/DisplayViewport.h"
#include "input/Input.h"
namespace android {
+using namespace ftl::flag_operators;
+
using std::chrono_literals::operator""ms;
-using namespace android::flag_operators;
// Timeout for waiting for an expected event
static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms;
@@ -429,7 +429,7 @@
struct Device {
InputDeviceIdentifier identifier;
- Flags<InputDeviceClass> classes;
+ ftl::Flags<InputDeviceClass> classes;
PropertyMap configuration;
KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
KeyedVector<int, bool> relativeAxes;
@@ -457,7 +457,7 @@
return OK;
}
- explicit Device(Flags<InputDeviceClass> classes) : classes(classes), enabled(true) {}
+ explicit Device(ftl::Flags<InputDeviceClass> classes) : classes(classes), enabled(true) {}
};
std::mutex mLock;
@@ -484,7 +484,8 @@
FakeEventHub() { }
- void addDevice(int32_t deviceId, const std::string& name, Flags<InputDeviceClass> classes) {
+ void addDevice(int32_t deviceId, const std::string& name,
+ ftl::Flags<InputDeviceClass> classes) {
Device* device = new Device(classes);
device->identifier.name = name;
mDevices.add(deviceId, device);
@@ -695,9 +696,9 @@
return index >= 0 ? mDevices.valueAt(index) : nullptr;
}
- Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
+ ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
Device* device = getDevice(deviceId);
- return device ? device->classes : Flags<InputDeviceClass>(0);
+ return device ? device->classes : ftl::Flags<InputDeviceClass>(0);
}
InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
@@ -1572,8 +1573,8 @@
mFakePolicy.clear();
}
- void addDevice(int32_t eventHubId, const std::string& name, Flags<InputDeviceClass> classes,
- const PropertyMap* configuration) {
+ void addDevice(int32_t eventHubId, const std::string& name,
+ ftl::Flags<InputDeviceClass> classes, const PropertyMap* configuration) {
mFakeEventHub->addDevice(eventHubId, name, classes);
if (configuration) {
@@ -1598,7 +1599,8 @@
FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
const std::string& name,
- Flags<InputDeviceClass> classes, uint32_t sources,
+ ftl::Flags<InputDeviceClass> classes,
+ uint32_t sources,
const PropertyMap* configuration) {
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(eventHubId, sources);
@@ -1610,7 +1612,7 @@
TEST_F(InputReaderTest, PolicyGetInputDevices) {
ASSERT_NO_FATAL_FAILURE(addDevice(1, "keyboard", InputDeviceClass::KEYBOARD, nullptr));
- ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", Flags<InputDeviceClass>(0),
+ ASSERT_NO_FATAL_FAILURE(addDevice(2, "ignored", ftl::Flags<InputDeviceClass>(0),
nullptr)); // no classes so device will be ignored
// Should also have received a notification describing the new input devices.
@@ -1672,7 +1674,7 @@
TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
+ constexpr ftl::Flags<InputDeviceClass> deviceClass(InputDeviceClass::KEYBOARD);
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
@@ -1709,7 +1711,7 @@
TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1773,7 +1775,7 @@
TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1806,7 +1808,7 @@
TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1839,7 +1841,7 @@
TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
@@ -1891,7 +1893,7 @@
TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr nsecs_t when = 0;
constexpr int32_t eventHubId = 1;
constexpr nsecs_t readTime = 2;
@@ -1915,7 +1917,7 @@
TEST_F(InputReaderTest, DeviceReset_RandomId) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
@@ -1948,7 +1950,7 @@
TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
constexpr int32_t deviceId = 1;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
@@ -1963,7 +1965,7 @@
TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubId = 1;
const char* DEVICE_LOCATION = "USB1";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
@@ -2008,7 +2010,7 @@
TEST_F(InputReaderTest, WhenEnabledChanges_AllSubdevicesAreUpdated) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
// Must add at least one mapper or the device will be ignored!
@@ -2049,7 +2051,7 @@
TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToSubdeviceMappers) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- constexpr Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
+ constexpr ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD;
constexpr int32_t eventHubIds[2] = {END_RESERVED_ID, END_RESERVED_ID + 1};
// Add two subdevices to device
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
@@ -2106,7 +2108,8 @@
TEST_F(InputReaderTest, VibratorGetVibratorIds) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
+ ftl::Flags<InputDeviceClass> deviceClass =
+ InputDeviceClass::KEYBOARD | InputDeviceClass::VIBRATOR;
constexpr int32_t eventHubId = 1;
const char* DEVICE_LOCATION = "BLUETOOTH";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
@@ -2166,7 +2169,8 @@
TEST_F(InputReaderTest, BatteryGetCapacity) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ ftl::Flags<InputDeviceClass> deviceClass =
+ InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
constexpr int32_t eventHubId = 1;
const char* DEVICE_LOCATION = "BLUETOOTH";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
@@ -2182,7 +2186,8 @@
TEST_F(InputReaderTest, BatteryGetStatus) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ ftl::Flags<InputDeviceClass> deviceClass =
+ InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
constexpr int32_t eventHubId = 1;
const char* DEVICE_LOCATION = "BLUETOOTH";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
@@ -2198,7 +2203,7 @@
TEST_F(InputReaderTest, LightGetColor) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
- Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
+ ftl::Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::LIGHT;
constexpr int32_t eventHubId = 1;
const char* DEVICE_LOCATION = "BLUETOOTH";
std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
@@ -2625,7 +2630,7 @@
static const int32_t DEVICE_ID;
static const int32_t DEVICE_GENERATION;
static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const Flags<InputDeviceClass> DEVICE_CLASSES;
+ static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
static const int32_t EVENTHUB_ID;
std::shared_ptr<FakeEventHub> mFakeEventHub;
@@ -2646,7 +2651,7 @@
mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
identifier);
mReader->pushNextDevice(mDevice);
- mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, Flags<InputDeviceClass>(0));
+ mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, ftl::Flags<InputDeviceClass>(0));
mReader->loopOnce();
}
@@ -2661,14 +2666,14 @@
const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
-const Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
+const ftl::Flags<InputDeviceClass> InputDeviceTest::DEVICE_CLASSES =
InputDeviceClass::KEYBOARD | InputDeviceClass::TOUCH | InputDeviceClass::JOYSTICK;
const int32_t InputDeviceTest::EVENTHUB_ID = 1;
TEST_F(InputDeviceTest, ImmutableProperties) {
ASSERT_EQ(DEVICE_ID, mDevice->getId());
ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
- ASSERT_EQ(Flags<InputDeviceClass>(0), mDevice->getClasses());
+ ASSERT_EQ(ftl::Flags<InputDeviceClass>(0), mDevice->getClasses());
}
TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
@@ -2912,7 +2917,7 @@
static const int32_t DEVICE_ID;
static const int32_t DEVICE_GENERATION;
static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const Flags<InputDeviceClass> DEVICE_CLASSES;
+ static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
static const int32_t EVENTHUB_ID;
std::shared_ptr<FakeEventHub> mFakeEventHub;
@@ -2921,7 +2926,7 @@
std::unique_ptr<InstrumentedInputReader> mReader;
std::shared_ptr<InputDevice> mDevice;
- virtual void SetUp(Flags<InputDeviceClass> classes) {
+ virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = std::make_unique<TestInputListener>();
@@ -2953,7 +2958,7 @@
std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
const std::string& location, int32_t eventHubId,
- Flags<InputDeviceClass> classes) {
+ ftl::Flags<InputDeviceClass> classes) {
InputDeviceIdentifier identifier;
identifier.name = name;
identifier.location = location;
@@ -3045,8 +3050,8 @@
const int32_t InputMapperTest::DEVICE_ID = END_RESERVED_ID + 1000;
const int32_t InputMapperTest::DEVICE_GENERATION = 2;
const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0;
-const Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
- Flags<InputDeviceClass>(0); // not needed for current tests
+const ftl::Flags<InputDeviceClass> InputMapperTest::DEVICE_CLASSES =
+ ftl::Flags<InputDeviceClass>(0); // not needed for current tests
const int32_t InputMapperTest::EVENTHUB_ID = 1;
// --- SwitchInputMapperTest ---
@@ -3842,7 +3847,7 @@
constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
std::shared_ptr<InputDevice> device2 =
newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
- Flags<InputDeviceClass>(0));
+ ftl::Flags<InputDeviceClass>(0));
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
@@ -3954,7 +3959,7 @@
constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
std::shared_ptr<InputDevice> device2 =
newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
- Flags<InputDeviceClass>(0));
+ ftl::Flags<InputDeviceClass>(0));
mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
@@ -8409,7 +8414,7 @@
constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
std::shared_ptr<InputDevice> device2 =
newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
- Flags<InputDeviceClass>(0));
+ ftl::Flags<InputDeviceClass>(0));
mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
0 /*flat*/, 0 /*fuzz*/);
@@ -9350,7 +9355,7 @@
static const int32_t DEVICE_ID;
static const int32_t DEVICE_GENERATION;
static const int32_t DEVICE_CONTROLLER_NUMBER;
- static const Flags<InputDeviceClass> DEVICE_CLASSES;
+ static const ftl::Flags<InputDeviceClass> DEVICE_CLASSES;
static const int32_t EVENTHUB_ID;
std::shared_ptr<FakeEventHub> mFakeEventHub;
@@ -9359,7 +9364,7 @@
std::unique_ptr<InstrumentedInputReader> mReader;
std::shared_ptr<InputDevice> mDevice;
- virtual void SetUp(Flags<InputDeviceClass> classes) {
+ virtual void SetUp(ftl::Flags<InputDeviceClass> classes) {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = std::make_unique<TestInputListener>();
@@ -9385,7 +9390,7 @@
std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
const std::string& location, int32_t eventHubId,
- Flags<InputDeviceClass> classes) {
+ ftl::Flags<InputDeviceClass> classes) {
InputDeviceIdentifier identifier;
identifier.name = name;
identifier.location = location;
@@ -9411,8 +9416,8 @@
const int32_t PeripheralControllerTest::DEVICE_ID = END_RESERVED_ID + 1000;
const int32_t PeripheralControllerTest::DEVICE_GENERATION = 2;
const int32_t PeripheralControllerTest::DEVICE_CONTROLLER_NUMBER = 0;
-const Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
- Flags<InputDeviceClass>(0); // not needed for current tests
+const ftl::Flags<InputDeviceClass> PeripheralControllerTest::DEVICE_CLASSES =
+ ftl::Flags<InputDeviceClass>(0); // not needed for current tests
const int32_t PeripheralControllerTest::EVENTHUB_ID = 1;
// --- BatteryControllerTest ---
diff --git a/services/inputflinger/tests/PreferStylusOverTouch_test.cpp b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp
index 70f40aa..8e2ab88 100644
--- a/services/inputflinger/tests/PreferStylusOverTouch_test.cpp
+++ b/services/inputflinger/tests/PreferStylusOverTouch_test.cpp
@@ -20,12 +20,16 @@
namespace android {
constexpr int32_t TOUCH_DEVICE_ID = 3;
-constexpr int32_t STYLUS_DEVICE_ID = 4;
+constexpr int32_t SECOND_TOUCH_DEVICE_ID = 4;
+constexpr int32_t STYLUS_DEVICE_ID = 5;
+constexpr int32_t SECOND_STYLUS_DEVICE_ID = 6;
constexpr int DOWN = AMOTION_EVENT_ACTION_DOWN;
constexpr int MOVE = AMOTION_EVENT_ACTION_MOVE;
constexpr int UP = AMOTION_EVENT_ACTION_UP;
constexpr int CANCEL = AMOTION_EVENT_ACTION_CANCEL;
+static constexpr int32_t POINTER_1_DOWN =
+ AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
constexpr int32_t TOUCHSCREEN = AINPUT_SOURCE_TOUCHSCREEN;
constexpr int32_t STYLUS = AINPUT_SOURCE_STYLUS;
@@ -78,29 +82,30 @@
class PreferStylusOverTouchTest : public testing::Test {
protected:
- void assertNotBlocked(const NotifyMotionArgs& args) {
- ftl::StaticVector<NotifyMotionArgs, 2> processedArgs = mBlocker.processMotion(args);
- ASSERT_EQ(1u, processedArgs.size());
- ASSERT_EQ(args, processedArgs[0]);
+ void assertNotBlocked(const NotifyMotionArgs& args) { assertResponse(args, {args}); }
+
+ void assertDropped(const NotifyMotionArgs& args) { assertResponse(args, {}); }
+
+ void assertResponse(const NotifyMotionArgs& args,
+ const std::vector<NotifyMotionArgs>& expected) {
+ std::vector<NotifyMotionArgs> receivedArgs = mBlocker.processMotion(args);
+ ASSERT_EQ(expected.size(), receivedArgs.size());
+ for (size_t i = 0; i < expected.size(); i++) {
+ // The 'eventTime' of CANCEL events is dynamically generated. Don't check this field.
+ if (expected[i].action == CANCEL && receivedArgs[i].action == CANCEL) {
+ receivedArgs[i].eventTime = expected[i].eventTime;
+ }
+
+ ASSERT_EQ(expected[i], receivedArgs[i])
+ << expected[i].dump() << " vs " << receivedArgs[i].dump();
+ }
}
- void assertDropped(const NotifyMotionArgs& args) {
- ftl::StaticVector<NotifyMotionArgs, 2> processedArgs = mBlocker.processMotion(args);
- ASSERT_TRUE(processedArgs.empty());
+ void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& devices) {
+ mBlocker.notifyInputDevicesChanged(devices);
}
- void assertCanceled(const NotifyMotionArgs& args,
- std::optional<NotifyMotionArgs> canceledArgs) {
- ftl::StaticVector<NotifyMotionArgs, 2> processedArgs = mBlocker.processMotion(args);
- ASSERT_EQ(2u, processedArgs.size());
- NotifyMotionArgs& cancelEvent = processedArgs[0];
- ASSERT_EQ(CANCEL, cancelEvent.action);
- ASSERT_EQ(AMOTION_EVENT_FLAG_CANCELED, cancelEvent.flags & AMOTION_EVENT_FLAG_CANCELED);
- ASSERT_TRUE(isFromSource(cancelEvent.source, TOUCHSCREEN));
- ASSERT_FALSE(isFromSource(cancelEvent.source, STYLUS));
-
- ASSERT_EQ(args, processedArgs[1]);
- }
+ void dump() const { ALOGI("Blocker: \n%s\n", mBlocker.dump().c_str()); }
private:
PreferStylusOverTouchBlocker mBlocker;
@@ -148,7 +153,8 @@
args = generateMotionArgs(3 /*downTime*/, 3 /*eventTime*/, DOWN, {{10, 30}}, STYLUS);
NotifyMotionArgs cancelArgs =
generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, CANCEL, {{1, 3}}, TOUCHSCREEN);
- assertCanceled(args, cancelArgs);
+ cancelArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
+ assertResponse(args, {cancelArgs, args});
// Both stylus and touch events continue. Stylus should be not blocked, and touch should be
// blocked
@@ -160,6 +166,26 @@
}
/**
+ * Stylus goes down after touch gesture.
+ */
+TEST_F(PreferStylusOverTouchTest, StylusDownAfterTouch) {
+ NotifyMotionArgs args;
+
+ args = generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN);
+ assertNotBlocked(args);
+
+ args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, MOVE, {{1, 3}}, TOUCHSCREEN);
+ assertNotBlocked(args);
+
+ args = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, UP, {{1, 3}}, TOUCHSCREEN);
+ assertNotBlocked(args);
+
+ // Stylus goes down
+ args = generateMotionArgs(3 /*downTime*/, 3 /*eventTime*/, DOWN, {{10, 30}}, STYLUS);
+ assertNotBlocked(args);
+}
+
+/**
* New touch events should be simply blocked (dropped) when stylus is down. No CANCEL event should
* be generated.
*/
@@ -247,4 +273,230 @@
assertNotBlocked(args);
}
+/**
+ * If an event with mixed stylus and touch pointers is encountered, it should be ignored. Touches
+ * from such should pass, even if stylus from the same device goes down.
+ */
+TEST_F(PreferStylusOverTouchTest, MixedStylusAndTouchPointersAreIgnored) {
+ NotifyMotionArgs args;
+
+ // Event from a stylus device, but with finger tool type
+ args = generateMotionArgs(1 /*downTime*/, 1 /*eventTime*/, DOWN, {{1, 2}}, STYLUS);
+ // Keep source stylus, but make the tool type touch
+ args.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ assertNotBlocked(args);
+
+ // Second pointer (stylus pointer) goes down, from the same device
+ args = generateMotionArgs(1 /*downTime*/, 2 /*eventTime*/, POINTER_1_DOWN, {{1, 2}, {10, 20}},
+ STYLUS);
+ // Keep source stylus, but make the tool type touch
+ args.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ assertNotBlocked(args);
+
+ // Second pointer (stylus pointer) goes down, from the same device
+ args = generateMotionArgs(1 /*downTime*/, 3 /*eventTime*/, MOVE, {{2, 3}, {11, 21}}, STYLUS);
+ // Keep source stylus, but make the tool type touch
+ args.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+ assertNotBlocked(args);
+}
+
+/**
+ * When there are two touch devices, stylus down should cancel all current touch streams.
+ */
+TEST_F(PreferStylusOverTouchTest, TouchFromTwoDevicesAndStylus) {
+ NotifyMotionArgs touch1Down =
+ generateMotionArgs(1 /*downTime*/, 1 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN);
+ assertNotBlocked(touch1Down);
+
+ NotifyMotionArgs touch2Down =
+ generateMotionArgs(2 /*downTime*/, 2 /*eventTime*/, DOWN, {{3, 4}}, TOUCHSCREEN);
+ touch2Down.deviceId = SECOND_TOUCH_DEVICE_ID;
+ assertNotBlocked(touch2Down);
+
+ NotifyMotionArgs stylusDown =
+ generateMotionArgs(3 /*downTime*/, 3 /*eventTime*/, DOWN, {{10, 30}}, STYLUS);
+ NotifyMotionArgs cancelArgs1 = touch1Down;
+ cancelArgs1.action = CANCEL;
+ cancelArgs1.flags |= AMOTION_EVENT_FLAG_CANCELED;
+ NotifyMotionArgs cancelArgs2 = touch2Down;
+ cancelArgs2.action = CANCEL;
+ cancelArgs2.flags |= AMOTION_EVENT_FLAG_CANCELED;
+ assertResponse(stylusDown, {cancelArgs1, cancelArgs2, stylusDown});
+}
+
+/**
+ * Touch should be canceled when stylus goes down. After the stylus lifts up, the touch from that
+ * device should continue to be canceled.
+ * If one of the devices is already canceled, it should remain canceled, but new touches from a
+ * different device should go through.
+ */
+TEST_F(PreferStylusOverTouchTest, AllTouchMustLiftAfterCanceledByStylus) {
+ // First device touches down
+ NotifyMotionArgs touch1Down =
+ generateMotionArgs(1 /*downTime*/, 1 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN);
+ assertNotBlocked(touch1Down);
+
+ // Stylus goes down - touch should be canceled
+ NotifyMotionArgs stylusDown =
+ generateMotionArgs(2 /*downTime*/, 2 /*eventTime*/, DOWN, {{10, 30}}, STYLUS);
+ NotifyMotionArgs cancelArgs1 = touch1Down;
+ cancelArgs1.action = CANCEL;
+ cancelArgs1.flags |= AMOTION_EVENT_FLAG_CANCELED;
+ assertResponse(stylusDown, {cancelArgs1, stylusDown});
+
+ // Stylus goes up
+ NotifyMotionArgs stylusUp =
+ generateMotionArgs(2 /*downTime*/, 3 /*eventTime*/, UP, {{10, 30}}, STYLUS);
+ assertNotBlocked(stylusUp);
+
+ // Touch from the first device remains blocked
+ NotifyMotionArgs touch1Move =
+ generateMotionArgs(1 /*downTime*/, 4 /*eventTime*/, MOVE, {{2, 3}}, TOUCHSCREEN);
+ assertDropped(touch1Move);
+
+ // Second touch goes down. It should not be blocked because stylus has already lifted.
+ NotifyMotionArgs touch2Down =
+ generateMotionArgs(5 /*downTime*/, 5 /*eventTime*/, DOWN, {{31, 32}}, TOUCHSCREEN);
+ touch2Down.deviceId = SECOND_TOUCH_DEVICE_ID;
+ assertNotBlocked(touch2Down);
+
+ // First device is lifted up. It's already been canceled, so the UP event should be dropped.
+ NotifyMotionArgs touch1Up =
+ generateMotionArgs(1 /*downTime*/, 6 /*eventTime*/, UP, {{2, 3}}, TOUCHSCREEN);
+ assertDropped(touch1Up);
+
+ // Touch from second device touch should continue to work
+ NotifyMotionArgs touch2Move =
+ generateMotionArgs(5 /*downTime*/, 7 /*eventTime*/, MOVE, {{32, 33}}, TOUCHSCREEN);
+ touch2Move.deviceId = SECOND_TOUCH_DEVICE_ID;
+ assertNotBlocked(touch2Move);
+
+ // Second touch lifts up
+ NotifyMotionArgs touch2Up =
+ generateMotionArgs(5 /*downTime*/, 8 /*eventTime*/, UP, {{32, 33}}, TOUCHSCREEN);
+ touch2Up.deviceId = SECOND_TOUCH_DEVICE_ID;
+ assertNotBlocked(touch2Up);
+
+ // Now that all touch has been lifted, new touch from either first or second device should work
+ NotifyMotionArgs touch3Down =
+ generateMotionArgs(9 /*downTime*/, 9 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN);
+ assertNotBlocked(touch3Down);
+
+ NotifyMotionArgs touch4Down =
+ generateMotionArgs(10 /*downTime*/, 10 /*eventTime*/, DOWN, {{100, 200}}, TOUCHSCREEN);
+ touch4Down.deviceId = SECOND_TOUCH_DEVICE_ID;
+ assertNotBlocked(touch4Down);
+}
+
+/**
+ * When we don't know that a specific device does both stylus and touch, and we only see touch
+ * pointers from it, we should treat it as a touch device. That means, the device events should be
+ * canceled when stylus from another device goes down. When we detect simultaneous touch and stylus
+ * from this device though, we should just pass this device through without canceling anything.
+ *
+ * In this test:
+ * 1. Start by touching down with device 1
+ * 2. Device 2 has stylus going down
+ * 3. Device 1 should be canceled.
+ * 4. When we add stylus pointers to the device 1, they should continue to be canceled.
+ * 5. Device 1 lifts up.
+ * 6. Subsequent events from device 1 should not be canceled even if stylus is down.
+ * 7. If a reset happens, and such device is no longer there, then we should
+ * Therefore, the device 1 is "ignored" and does not participate into "prefer stylus over touch"
+ * behaviour.
+ */
+TEST_F(PreferStylusOverTouchTest, MixedStylusAndTouchDeviceIsCanceledAtFirst) {
+ // Touch from device 1 goes down
+ NotifyMotionArgs touchDown =
+ generateMotionArgs(1 /*downTime*/, 1 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN);
+ touchDown.source = STYLUS;
+ assertNotBlocked(touchDown);
+
+ // Stylus from device 2 goes down. Touch should be canceled.
+ NotifyMotionArgs args =
+ generateMotionArgs(2 /*downTime*/, 2 /*eventTime*/, DOWN, {{10, 20}}, STYLUS);
+ NotifyMotionArgs cancelTouchArgs = touchDown;
+ cancelTouchArgs.action = CANCEL;
+ cancelTouchArgs.flags |= AMOTION_EVENT_FLAG_CANCELED;
+ assertResponse(args, {cancelTouchArgs, args});
+
+ // Introduce a stylus pointer into the device 1 stream. It should be ignored.
+ args = generateMotionArgs(1 /*downTime*/, 3 /*eventTime*/, POINTER_1_DOWN, {{1, 2}, {3, 4}},
+ TOUCHSCREEN);
+ args.pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ args.source = STYLUS;
+ assertDropped(args);
+
+ // Lift up touch from the mixed touch/stylus device
+ args = generateMotionArgs(1 /*downTime*/, 4 /*eventTime*/, CANCEL, {{1, 2}, {3, 4}},
+ TOUCHSCREEN);
+ args.pointerProperties[1].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ args.source = STYLUS;
+ assertDropped(args);
+
+ // Stylus from device 2 is still down. Since the device 1 is now identified as a mixed
+ // touch/stylus device, its events should go through, even if they are touch.
+ args = generateMotionArgs(5 /*downTime*/, 5 /*eventTime*/, DOWN, {{21, 22}}, TOUCHSCREEN);
+ touchDown.source = STYLUS;
+ assertResponse(args, {args});
+
+ // Reconfigure such that only the stylus device remains
+ InputDeviceInfo stylusDevice;
+ stylusDevice.initialize(STYLUS_DEVICE_ID, 1 /*generation*/, 1 /*controllerNumber*/,
+ {} /*identifier*/, "stylus device", false /*external*/,
+ false /*hasMic*/);
+ notifyInputDevicesChanged({stylusDevice});
+ // The touchscreen device was removed, so we no longer remember anything about it. We should
+ // again start blocking touch events from it.
+ args = generateMotionArgs(6 /*downTime*/, 6 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN);
+ args.source = STYLUS;
+ assertDropped(args);
+}
+
+/**
+ * If two styli are active at the same time, touch should be blocked until both of them are lifted.
+ * If one of them lifts, touch should continue to be blocked.
+ */
+TEST_F(PreferStylusOverTouchTest, TouchIsBlockedWhenTwoStyliAreUsed) {
+ NotifyMotionArgs args;
+
+ // First stylus is down
+ assertNotBlocked(generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{10, 30}}, STYLUS));
+
+ // Second stylus is down
+ args = generateMotionArgs(1 /*downTime*/, 1 /*eventTime*/, DOWN, {{20, 40}}, STYLUS);
+ args.deviceId = SECOND_STYLUS_DEVICE_ID;
+ assertNotBlocked(args);
+
+ // Touch goes down. It should be ignored.
+ args = generateMotionArgs(2 /*downTime*/, 2 /*eventTime*/, DOWN, {{1, 2}}, TOUCHSCREEN);
+ assertDropped(args);
+
+ // Lift the first stylus
+ args = generateMotionArgs(0 /*downTime*/, 3 /*eventTime*/, UP, {{10, 30}}, STYLUS);
+ assertNotBlocked(args);
+
+ // Touch should continue to be blocked
+ args = generateMotionArgs(2 /*downTime*/, 4 /*eventTime*/, UP, {{1, 2}}, TOUCHSCREEN);
+ assertDropped(args);
+
+ // New touch should be blocked because second stylus is still down
+ args = generateMotionArgs(5 /*downTime*/, 5 /*eventTime*/, DOWN, {{5, 6}}, TOUCHSCREEN);
+ assertDropped(args);
+
+ // Second stylus goes up
+ args = generateMotionArgs(1 /*downTime*/, 6 /*eventTime*/, UP, {{20, 40}}, STYLUS);
+ args.deviceId = SECOND_STYLUS_DEVICE_ID;
+ assertNotBlocked(args);
+
+ // Current touch gesture should continue to be blocked
+ // Touch should continue to be blocked
+ args = generateMotionArgs(5 /*downTime*/, 7 /*eventTime*/, UP, {{5, 6}}, TOUCHSCREEN);
+ assertDropped(args);
+
+ // Now that all styli were lifted, new touch should go through
+ args = generateMotionArgs(8 /*downTime*/, 8 /*eventTime*/, DOWN, {{7, 8}}, TOUCHSCREEN);
+ assertNotBlocked(args);
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
index b2f8eb3..e378096 100644
--- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
+++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
@@ -519,6 +519,34 @@
&(args = generateMotionArgs(0 /*downTime*/, 4 /*eventTime*/, MOVE, {{7, 8, 9}})));
}
+/**
+ * Send a touch event, and then a stylus event. Make sure that both work.
+ */
+TEST_F(UnwantedInteractionBlockerTest, StylusAfterTouchWorks) {
+ NotifyMotionArgs args;
+ mBlocker->notifyInputDevicesChanged({generateTestDeviceInfo()});
+ args = generateMotionArgs(0 /*downTime*/, 0 /*eventTime*/, DOWN, {{1, 2, 3}});
+ mBlocker->notifyMotion(&args);
+ args = generateMotionArgs(0 /*downTime*/, 1 /*eventTime*/, MOVE, {{4, 5, 6}});
+ mBlocker->notifyMotion(&args);
+ args = generateMotionArgs(0 /*downTime*/, 2 /*eventTime*/, UP, {{4, 5, 6}});
+ mBlocker->notifyMotion(&args);
+
+ // Now touch down stylus
+ args = generateMotionArgs(3 /*downTime*/, 3 /*eventTime*/, DOWN, {{10, 20, 30}});
+ args.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ args.source |= AINPUT_SOURCE_STYLUS;
+ mBlocker->notifyMotion(&args);
+ args = generateMotionArgs(3 /*downTime*/, 4 /*eventTime*/, MOVE, {{40, 50, 60}});
+ args.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ args.source |= AINPUT_SOURCE_STYLUS;
+ mBlocker->notifyMotion(&args);
+ args = generateMotionArgs(3 /*downTime*/, 5 /*eventTime*/, UP, {{40, 50, 60}});
+ args.pointerProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
+ args.source |= AINPUT_SOURCE_STYLUS;
+ mBlocker->notifyMotion(&args);
+}
+
using UnwantedInteractionBlockerTestDeathTest = UnwantedInteractionBlockerTest;
/**
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 7194db3..b18d204 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -257,11 +257,13 @@
bool isUidActive(uid_t uid);
- void onUidGone(uid_t uid, bool disabled);
- void onUidActive(uid_t uid);
- void onUidIdle(uid_t uid, bool disabled);
+ void onUidGone(uid_t uid, bool disabled) override;
+ void onUidActive(uid_t uid) override;
+ void onUidIdle(uid_t uid, bool disabled) override;
void onUidStateChanged(uid_t uid __unused, int32_t procState __unused,
- int64_t procStateSeq __unused, int32_t capability __unused) {}
+ int64_t procStateSeq __unused,
+ int32_t capability __unused) override {}
+ void onUidProcAdjChanged(uid_t uid __unused) override {}
void addOverrideUid(uid_t uid, bool active);
void removeOverrideUid(uid_t uid);
diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp
index 7dd2331..6bad962 100644
--- a/services/sensorservice/SensorServiceUtils.cpp
+++ b/services/sensorservice/SensorServiceUtils.cpp
@@ -39,6 +39,7 @@
return 5;
case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ case SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED:
case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
case SENSOR_TYPE_ACCELEROMETER_LIMITED_AXES:
case SENSOR_TYPE_GYROSCOPE_LIMITED_AXES:
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index bcae8d9..c5d7a60 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -1098,6 +1098,13 @@
}
}
+ if (s.what & layer_state_t::eDimmingEnabledChanged) {
+ if (mDrawingState.dimmingEnabled != s.dimmingEnabled) {
+ ALOGV("%s: false [eDimmingEnabledChanged changed]", __func__);
+ return false;
+ }
+ }
+
ALOGV("%s: true", __func__);
return true;
}
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index aefc014..516c3ef 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -23,6 +23,7 @@
"android.hardware.graphics.composer3-V1-ndk",
"android.hardware.power@1.0",
"android.hardware.power@1.3",
+ "android.hardware.power-V2-cpp",
"libbase",
"libcutils",
"libgui",
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 283fe86..974f7c6 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -207,6 +207,9 @@
// framerate of the layer as measured by LayerHistory
float fps;
+ // The dimming flag
+ bool dimmingEnabled{true};
+
virtual ~LayerFECompositionState();
// Debugging
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
index cb00e71..29d3366 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -16,20 +16,20 @@
#pragma once
+#include <string>
+
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
#include <android-base/strings.h>
+#include <ftl/flags.h>
+#include <math/HashCombine.h>
+
#include <compositionengine/LayerFE.h>
#include <compositionengine/LayerFECompositionState.h>
#include <compositionengine/OutputLayer.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
-#include <ftl/Flags.h>
-
-#include <string>
#include "DisplayHardware/Hal.h"
-#include "math/HashCombine.h"
-
-#include <aidl/android/hardware/graphics/common/BufferUsage.h>
-#include <aidl/android/hardware/graphics/composer3/Composition.h>
namespace std {
template <typename T>
@@ -84,13 +84,13 @@
public:
virtual ~StateInterface() = default;
- virtual Flags<LayerStateField> update(const compositionengine::OutputLayer* layer) = 0;
+ virtual ftl::Flags<LayerStateField> update(const compositionengine::OutputLayer* layer) = 0;
virtual size_t getHash() const = 0;
virtual LayerStateField getField() const = 0;
- virtual Flags<LayerStateField> getFieldIfDifferent(const StateInterface* other) const = 0;
+ virtual ftl::Flags<LayerStateField> getFieldIfDifferent(const StateInterface* other) const = 0;
virtual bool equals(const StateInterface* other) const = 0;
@@ -152,12 +152,12 @@
~OutputLayerState() override = default;
// Returns this member's field flag if it was changed
- Flags<LayerStateField> update(const compositionengine::OutputLayer* layer) override {
+ ftl::Flags<LayerStateField> update(const compositionengine::OutputLayer* layer) override {
T newValue = mReader(layer);
return update(newValue);
}
- Flags<LayerStateField> update(const T& newValue) {
+ ftl::Flags<LayerStateField> update(const T& newValue) {
if (!mEquals(mValue, newValue)) {
mValue = newValue;
mHash = {};
@@ -176,14 +176,14 @@
return *mHash;
}
- Flags<LayerStateField> getFieldIfDifferent(const StateInterface* other) const override {
+ ftl::Flags<LayerStateField> getFieldIfDifferent(const StateInterface* other) const override {
if (other->getField() != FIELD) {
return {};
}
// The early return ensures that this downcast is sound
const OutputLayerState* otherState = static_cast<const OutputLayerState*>(other);
- return *this != *otherState ? FIELD : Flags<LayerStateField>{};
+ return *this != *otherState ? FIELD : ftl::Flags<LayerStateField>{};
}
bool equals(const StateInterface* other) const override {
@@ -215,7 +215,7 @@
LayerState(compositionengine::OutputLayer* layer);
// Returns which fields were updated
- Flags<LayerStateField> update(compositionengine::OutputLayer*);
+ ftl::Flags<LayerStateField> update(compositionengine::OutputLayer*);
// Computes a hash for this LayerState.
// The hash is only computed from NonUniqueFields, and excludes GraphicBuffers since they are
@@ -224,7 +224,7 @@
// Returns the bit-set of differing fields between this LayerState and another LayerState.
// This bit-set is based on NonUniqueFields only, and excludes GraphicBuffers.
- Flags<LayerStateField> getDifferingFields(const LayerState& other) const;
+ ftl::Flags<LayerStateField> getDifferingFields(const LayerState& other) const;
compositionengine::OutputLayer* getOutputLayer() const { return mOutputLayer; }
int32_t getId() const { return mId.get(); }
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
index ef1560e..6be6735 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Predictor.h
@@ -16,6 +16,8 @@
#pragma once
+#include <ftl/flags.h>
+
#include <compositionengine/impl/planner/LayerState.h>
namespace android::compositionengine::impl::planner {
@@ -35,7 +37,7 @@
// This implies that only one layer is allowed to differ in an approximate match.
size_t differingIndex;
// Set of fields that differ for the differing layer in the approximate match.
- Flags<LayerStateField> differingFields;
+ ftl::Flags<LayerStateField> differingFields;
};
// Returns an approximate match when comparing this layer stack with the provided list of
diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
index ff7d430..6631a27 100644
--- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp
@@ -121,6 +121,7 @@
dumpVal(out, "isColorspaceAgnostic", isColorspaceAgnostic);
dumpVal(out, "dataspace", toString(dataspace), dataspace);
dumpVal(out, "hdr metadata types", hdrMetadata.validTypes);
+ dumpVal(out, "dimming enabled", dimmingEnabled);
dumpVal(out, "colorTransform", colorTransform);
out.append("\n");
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 723593d..3289d55 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -324,9 +324,10 @@
// For hdr content, treat the white point as the display brightness - HDR content should not be
// boosted or dimmed.
+ // If the layer explicitly requests to disable dimming, then don't dim either.
if (isHdrDataspace(state.dataspace) ||
getOutput().getState().displayBrightnessNits == getOutput().getState().sdrWhitePointNits ||
- getOutput().getState().displayBrightnessNits == 0.f) {
+ getOutput().getState().displayBrightnessNits == 0.f || !layerFEState->dimmingEnabled) {
state.dimmingRatio = 1.f;
state.whitePointNits = getOutput().getState().displayBrightnessNits;
} else {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
index c79ca0d..f439caf 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/LayerState.cpp
@@ -41,7 +41,7 @@
update(layer);
}
-Flags<LayerStateField> LayerState::update(compositionengine::OutputLayer* layer) {
+ftl::Flags<LayerStateField> LayerState::update(compositionengine::OutputLayer* layer) {
ALOGE_IF(mOutputLayer != layer && layer->getLayerFE().getSequence() != mId.get(),
"[%s] Expected mOutputLayer ID to never change: %d, %d", __func__,
layer->getLayerFE().getSequence(), mId.get());
@@ -50,7 +50,7 @@
// same, i.e., the LayerFE is the same. An example use-case is screen rotation.
mOutputLayer = layer;
- Flags<LayerStateField> differences;
+ ftl::Flags<LayerStateField> differences;
// Update the unique fields as well, since we have to set them at least
// once from the OutputLayer
@@ -76,8 +76,8 @@
return hash;
}
-Flags<LayerStateField> LayerState::getDifferingFields(const LayerState& other) const {
- Flags<LayerStateField> differences;
+ftl::Flags<LayerStateField> LayerState::getDifferingFields(const LayerState& other) const {
+ ftl::Flags<LayerStateField> differences;
auto myFields = getNonUniqueFields();
auto otherFields = other.getNonUniqueFields();
for (size_t i = 0; i < myFields.size(); ++i) {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
index 74d2701..c8413eb 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Planner.cpp
@@ -97,7 +97,7 @@
if (const auto layerEntry = mPreviousLayers.find(id); layerEntry != mPreviousLayers.end()) {
// Track changes from previous info
LayerState& state = layerEntry->second;
- Flags<LayerStateField> differences = state.update(layer);
+ ftl::Flags<LayerStateField> differences = state.update(layer);
if (differences.get() == 0) {
state.incrementFramesSinceBufferUpdate();
} else {
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
index 2d53583..2fc029f 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Predictor.cpp
@@ -57,7 +57,7 @@
return std::nullopt;
}
- Flags<LayerStateField> differingFields = mLayers[i].getDifferingFields(*other[i]);
+ ftl::Flags<LayerStateField> differingFields = mLayers[i].getDifferingFields(*other[i]);
// If we don't find an approximate match on this layer, then the LayerStacks differ
// by too much, so return nothing
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
index 8eb1946..ceee48c 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp
@@ -668,6 +668,13 @@
EXPECT_EQ(mOutputState.sdrWhitePointNits / mOutputState.displayBrightnessNits,
mOutputLayer.getState().dimmingRatio);
+ mLayerFEState.dimmingEnabled = false;
+ mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
+ EXPECT_EQ(mOutputState.displayBrightnessNits, mOutputLayer.getState().whitePointNits);
+ EXPECT_EQ(1.f, mOutputLayer.getState().dimmingRatio);
+
+ // change dimmingEnabled back to true.
+ mLayerFEState.dimmingEnabled = true;
mLayerFEState.dataspace = ui::Dataspace::BT2020_ITU_PQ;
mLayerFEState.isColorspaceAgnostic = false;
mOutputLayer.updateCompositionState(false, false, ui::Transform::RotationFlags::ROT_0);
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
index bd4ff13..5c6e8da 100644
--- a/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/planner/LayerStateTest.cpp
@@ -97,12 +97,12 @@
void verifyUniqueDifferingFields(const LayerState& lhs, const LayerState& rhs) {
EXPECT_EQ(lhs.getHash(), rhs.getHash());
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::None), lhs.getDifferingFields(rhs));
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::None), rhs.getDifferingFields(lhs));
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::None), lhs.getDifferingFields(rhs));
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::None), rhs.getDifferingFields(lhs));
}
void verifyNonUniqueDifferingFields(const LayerState& lhs, const LayerState& rhs,
- Flags<LayerStateField> fields) {
+ ftl::Flags<LayerStateField> fields) {
EXPECT_NE(lhs.getHash(), rhs.getHash());
EXPECT_EQ(fields, lhs.getDifferingFields(rhs));
@@ -159,9 +159,9 @@
sp<mock::LayerFE> newLayerFE = sp<mock::LayerFE>::make();
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionState, sSequenceIdTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
EXPECT_EQ(sSequenceIdTwo, mLayerState->getId());
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Id), updates);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Id), updates);
}
TEST_F(LayerStateTest, compareId) {
@@ -204,9 +204,9 @@
sp<mock::LayerFE> newLayerFE = sp<mock::LayerFE>::make();
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionState, sSequenceId, sDebugNameTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
EXPECT_EQ(sDebugNameTwo, mLayerState->getName());
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Name), updates);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Name), updates);
}
TEST_F(LayerStateTest, compareName) {
@@ -253,9 +253,9 @@
outputLayerCompositionStateTwo.displayFrame = sRectTwo;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo,
layerFECompositionState);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
EXPECT_EQ(sRectTwo, mLayerState->getDisplayFrame());
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::DisplayFrame), updates);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::DisplayFrame), updates);
}
TEST_F(LayerStateTest, compareDisplayFrame) {
@@ -315,9 +315,9 @@
layerFECompositionStateTwo.compositionType = Composition::SOLID_COLOR;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
EXPECT_EQ(Composition::SOLID_COLOR, mLayerState->getCompositionType());
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::CompositionType), updates);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::CompositionType), updates);
}
TEST_F(LayerStateTest, compareCompositionType) {
@@ -357,8 +357,8 @@
layerFECompositionStateTwo.buffer = new GraphicBuffer();
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Buffer), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Buffer), updates);
}
TEST_F(LayerStateTest, updateBufferSingleBufferedLegacy) {
@@ -380,8 +380,8 @@
layerFECompositionStateTwo.frameNumber = i;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Buffer), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Buffer), updates);
}
}
@@ -404,8 +404,8 @@
for (uint64_t i = 0; i < 10; i++) {
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Buffer), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Buffer), updates);
}
}
@@ -446,8 +446,8 @@
outputLayerCompositionStateTwo.sourceCrop = sFloatRectTwo;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo,
layerFECompositionState);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::SourceCrop), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::SourceCrop), updates);
}
TEST_F(LayerStateTest, compareSourceCrop) {
@@ -485,8 +485,8 @@
outputLayerCompositionStateTwo.bufferTransform = Hwc2::Transform::FLIP_V;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo,
layerFECompositionState);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::BufferTransform), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::BufferTransform), updates);
}
TEST_F(LayerStateTest, compareBufferTransform) {
@@ -525,8 +525,8 @@
layerFECompositionStateTwo.blendMode = hal::BlendMode::PREMULTIPLIED;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::BlendMode), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::BlendMode), updates);
}
TEST_F(LayerStateTest, compareBlendMode) {
@@ -564,8 +564,8 @@
layerFECompositionStateTwo.alpha = sAlphaTwo;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Alpha), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Alpha), updates);
}
TEST_F(LayerStateTest, compareAlpha) {
@@ -603,8 +603,8 @@
layerFECompositionStateTwo.metadata[sMetadataKeyTwo] = sMetadataValueTwo;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::LayerMetadata), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::LayerMetadata), updates);
}
TEST_F(LayerStateTest, compareLayerMetadata) {
@@ -652,8 +652,8 @@
outputLayerCompositionStateTwo.visibleRegion = sRegionTwo;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo,
layerFECompositionState);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::VisibleRegion), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::VisibleRegion), updates);
}
TEST_F(LayerStateTest, compareVisibleRegion) {
@@ -691,8 +691,8 @@
outputLayerCompositionStateTwo.dataspace = ui::Dataspace::DISPLAY_P3;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionStateTwo,
layerFECompositionState);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Dataspace), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Dataspace), updates);
}
TEST_F(LayerStateTest, compareDataspace) {
@@ -738,9 +738,9 @@
"buffer2");
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::Buffer) |
- Flags<LayerStateField>(LayerStateField::PixelFormat),
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::Buffer) |
+ ftl::Flags<LayerStateField>(LayerStateField::PixelFormat),
updates);
}
@@ -768,7 +768,7 @@
auto otherLayerState = std::make_unique<LayerState>(&newOutputLayer);
verifyNonUniqueDifferingFields(*mLayerState, *otherLayerState,
- Flags<LayerStateField>(LayerStateField::PixelFormat));
+ ftl::Flags<LayerStateField>(LayerStateField::PixelFormat));
EXPECT_TRUE(mLayerState->compare(*otherLayerState));
EXPECT_TRUE(otherLayerState->compare(*mLayerState));
@@ -790,8 +790,8 @@
layerFECompositionStateTwo.colorTransform = sMat4One;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::ColorTransform), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::ColorTransform), updates);
}
TEST_F(LayerStateTest, compareColorTransform) {
@@ -831,8 +831,8 @@
layerFECompositionStateTwo.sidebandStream = NativeHandle::create(sFakeSidebandStreamTwo, false);
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::SidebandStream), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::SidebandStream), updates);
}
TEST_F(LayerStateTest, compareSidebandStream) {
@@ -870,8 +870,8 @@
layerFECompositionStateTwo.color = sHalf4Two;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::SolidColor), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::SolidColor), updates);
}
TEST_F(LayerStateTest, compareSolidColor) {
@@ -909,8 +909,8 @@
layerFECompositionStateTwo.backgroundBlurRadius = sBgBlurRadiusTwo;
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::BackgroundBlurRadius), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::BackgroundBlurRadius), updates);
}
TEST_F(LayerStateTest, compareBackgroundBlur) {
@@ -949,8 +949,8 @@
layerFECompositionStateTwo.blurRegions.push_back(sBlurRegionTwo);
setupMocksForLayer(newOutputLayer, *newLayerFE, outputLayerCompositionState,
layerFECompositionStateTwo);
- Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
- EXPECT_EQ(Flags<LayerStateField>(LayerStateField::BlurRegions), updates);
+ ftl::Flags<LayerStateField> updates = mLayerState->update(&newOutputLayer);
+ EXPECT_EQ(ftl::Flags<LayerStateField>(LayerStateField::BlurRegions), updates);
}
TEST_F(LayerStateTest, compareBlurRegions) {
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index f5a4b3d..9116fd3 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -471,9 +471,8 @@
return;
}
- const auto [lowFps, highFps] = mRefreshRateConfigs->getSupportedRefreshRateRange();
- mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(*mFlinger, lowFps.getIntValue(),
- highFps.getIntValue(), showSpinnner);
+ const auto fpsRange = mRefreshRateConfigs->getSupportedRefreshRateRange();
+ mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(fpsRange, showSpinnner);
mRefreshRateOverlay->setLayerStack(getLayerStack());
mRefreshRateOverlay->setViewport(getSize());
mRefreshRateOverlay->changeRefreshRate(getActiveMode()->getFps());
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 2c4a300..d5d87b4 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -21,6 +21,7 @@
#include <string>
#include <unordered_map>
+#include <android-base/thread_annotations.h>
#include <android/native_window.h>
#include <binder/IBinder.h>
#include <gui/LayerState.h>
@@ -28,6 +29,7 @@
#include <renderengine/RenderEngine.h>
#include <system/window.h>
#include <ui/DisplayId.h>
+#include <ui/DisplayIdentification.h>
#include <ui/DisplayState.h>
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
@@ -39,15 +41,11 @@
#include <utils/RefBase.h>
#include <utils/Timers.h>
-#include "MainThreadGuard.h"
-
-#include <ui/DisplayIdentification.h>
#include "DisplayHardware/DisplayMode.h"
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/PowerAdvisor.h"
-
#include "Scheduler/RefreshRateConfigs.h"
-
+#include "ThreadContext.h"
#include "TracedOrdinal.h"
namespace android {
@@ -99,9 +97,9 @@
void setLayerStack(ui::LayerStack);
void setDisplaySize(int width, int height);
void setProjection(ui::Rotation orientation, Rect viewport, Rect frame);
- void stageBrightness(float brightness) REQUIRES(SF_MAIN_THREAD);
- void persistBrightness(bool needsComposite) REQUIRES(SF_MAIN_THREAD);
- bool isBrightnessStale() const REQUIRES(SF_MAIN_THREAD);
+ void stageBrightness(float brightness) REQUIRES(kMainThreadContext);
+ void persistBrightness(bool needsComposite) REQUIRES(kMainThreadContext);
+ bool isBrightnessStale() const REQUIRES(kMainThreadContext);
void setFlags(uint32_t flags);
ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; }
@@ -109,7 +107,7 @@
static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags();
- std::optional<float> getStagedBrightness() const REQUIRES(SF_MAIN_THREAD);
+ std::optional<float> getStagedBrightness() const REQUIRES(kMainThreadContext);
ui::Transform::RotationFlags getTransformHint() const;
const ui::Transform& getTransform() const;
const Rect& getLayerStackSpaceRect() const;
@@ -209,15 +207,15 @@
bool setDesiredActiveMode(const ActiveModeInfo&) EXCLUDES(mActiveModeLock);
std::optional<ActiveModeInfo> getDesiredActiveMode() const EXCLUDES(mActiveModeLock);
void clearDesiredActiveModeState() EXCLUDES(mActiveModeLock);
- ActiveModeInfo getUpcomingActiveMode() const REQUIRES(SF_MAIN_THREAD) {
+ ActiveModeInfo getUpcomingActiveMode() const REQUIRES(kMainThreadContext) {
return mUpcomingActiveMode;
}
- void setActiveMode(DisplayModeId) REQUIRES(SF_MAIN_THREAD);
+ void setActiveMode(DisplayModeId) REQUIRES(kMainThreadContext);
status_t initiateModeChange(const ActiveModeInfo&,
const hal::VsyncPeriodChangeConstraints& constraints,
hal::VsyncPeriodChangeTimeline* outTimeline)
- REQUIRES(SF_MAIN_THREAD);
+ REQUIRES(kMainThreadContext);
// Return the immutable list of supported display modes. The HWC may report different modes
// after a hotplug reconnect event, in which case the DisplayDevice object will be recreated.
@@ -304,7 +302,7 @@
ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock);
TracedOrdinal<bool> mDesiredActiveModeChanged
GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false};
- ActiveModeInfo mUpcomingActiveMode GUARDED_BY(SF_MAIN_THREAD);
+ ActiveModeInfo mUpcomingActiveMode GUARDED_BY(kMainThreadContext);
};
struct DisplayDeviceState {
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 44c086d..05f488b 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -32,7 +32,6 @@
#include <utils/Trace.h>
#include <android/hardware/power/1.3/IPower.h>
-#include <android/hardware/power/IPower.h>
#include <android/hardware/power/IPowerHintSession.h>
#include <android/hardware/power/WorkDuration.h>
@@ -62,8 +61,6 @@
using scheduler::OneShotTimer;
-class AidlPowerHalWrapper;
-
PowerAdvisor::~PowerAdvisor() = default;
namespace {
@@ -294,259 +291,232 @@
const sp<V1_3::IPower> mPowerHal = nullptr;
};
-class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
-public:
- AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
- auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
- if (!ret.isOk()) {
- mHasExpensiveRendering = false;
- }
-
- ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT,
- &mHasDisplayUpdateImminent);
- if (!ret.isOk()) {
- mHasDisplayUpdateImminent = false;
- }
-
- mSupportsPowerHint = checkPowerHintSessionSupported();
+AidlPowerHalWrapper::AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
+ auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
+ if (!ret.isOk()) {
+ mHasExpensiveRendering = false;
}
- ~AidlPowerHalWrapper() override {
- if (mPowerHintSession != nullptr) {
- mPowerHintSession->close();
- mPowerHintSession = nullptr;
- }
- };
-
- static std::unique_ptr<HalWrapper> connect() {
- // This only waits if the service is actually declared
- sp<IPower> powerHal = waitForVintfService<IPower>();
- if (powerHal == nullptr) {
- return nullptr;
- }
- ALOGI("Loaded AIDL Power HAL service");
-
- return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
+ ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT, &mHasDisplayUpdateImminent);
+ if (!ret.isOk()) {
+ mHasDisplayUpdateImminent = false;
}
- bool setExpensiveRendering(bool enabled) override {
- ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
- if (!mHasExpensiveRendering) {
- ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
- return true;
- }
+ mSupportsPowerHint = checkPowerHintSessionSupported();
+}
- auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
- if (ret.isOk()) {
- traceExpensiveRendering(enabled);
- }
- return ret.isOk();
+AidlPowerHalWrapper::~AidlPowerHalWrapper() {
+ if (mPowerHintSession != nullptr) {
+ mPowerHintSession->close();
+ mPowerHintSession = nullptr;
}
-
- bool notifyDisplayUpdateImminent() override {
- ALOGV("AIDL notifyDisplayUpdateImminent");
- if (!mHasDisplayUpdateImminent) {
- ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
- return true;
- }
-
- auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
- return ret.isOk();
- }
-
- // only version 2+ of the aidl supports power hint sessions, hidl has no support
- bool supportsPowerHintSession() override { return mSupportsPowerHint; }
-
- bool checkPowerHintSessionSupported() {
- int64_t unused;
- // Try to get preferred rate to determine if hint sessions are supported
- // We check for isOk not EX_UNSUPPORTED_OPERATION to lump other errors
- return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
- }
-
- bool isPowerHintSessionRunning() override { return mPowerHintSession != nullptr; }
-
- void closePowerHintSession() {
- if (mPowerHintSession != nullptr) {
- mPowerHintSession->close();
- mPowerHintSession = nullptr;
- }
- }
-
- void restartPowerHintSession() {
- closePowerHintSession();
- startPowerHintSession();
- }
-
- void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override {
- if (threadIds != mPowerHintThreadIds) {
- mPowerHintThreadIds = threadIds;
- if (isPowerHintSessionRunning()) {
- restartPowerHintSession();
- }
- }
- }
-
- bool startPowerHintSession() override {
- if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
- ALOGV("Cannot start power hint session, skipping");
- return false;
- }
- auto ret = mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
- mPowerHintThreadIds, mTargetDuration,
- &mPowerHintSession);
- if (!ret.isOk()) {
- ALOGW("Failed to start power hint session with error: %s",
- ret.exceptionToString(ret.exceptionCode()).c_str());
- } else {
- mLastTargetDurationSent = mTargetDuration;
- }
- return isPowerHintSessionRunning();
- }
-
- bool shouldSetTargetDuration(int64_t targetDurationNanos) {
- // report if the change in target from our last submission to now exceeds the threshold
- return abs(1.0 -
- static_cast<double>(mLastTargetDurationSent) /
- static_cast<double>(targetDurationNanos)) >=
- kAllowedTargetDeviationPercent;
- }
-
- void setTargetWorkDuration(int64_t targetDurationNanos) override {
- ATRACE_CALL();
- mTargetDuration = targetDurationNanos;
- if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDurationNanos);
- if (!sNormalizeTarget && shouldSetTargetDuration(targetDurationNanos) &&
- isPowerHintSessionRunning()) {
- if (mLastActualDurationSent.has_value()) {
- // update the error term here since we are actually sending an update to powerhal
- if (sTraceHintSessionData)
- ATRACE_INT64("Target error term",
- targetDurationNanos - *mLastActualDurationSent);
- }
- ALOGV("Sending target time: %lld ns", static_cast<long long>(targetDurationNanos));
- mLastTargetDurationSent = targetDurationNanos;
- auto ret = mPowerHintSession->updateTargetWorkDuration(targetDurationNanos);
- if (!ret.isOk()) {
- ALOGW("Failed to set power hint target work duration with error: %s",
- ret.exceptionMessage().c_str());
- mShouldReconnectHal = true;
- }
- }
- }
-
- bool shouldReportActualDurationsNow() {
- // report if we have never reported before or are approaching a stale session
- if (!mLastActualDurationSent.has_value() ||
- (systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) {
- return true;
- }
-
- if (!mActualDuration.has_value()) {
- return false;
- }
-
- // duration of most recent timing
- const double mostRecentActualDuration = static_cast<double>(*mActualDuration);
- // duration of the last timing actually reported to the powerhal
- const double lastReportedActualDuration = static_cast<double>(*mLastActualDurationSent);
-
- // report if the change in duration from then to now exceeds the threshold
- return abs(1.0 - mostRecentActualDuration / lastReportedActualDuration) >=
- kAllowedActualDeviationPercent;
- }
-
- void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) override {
- ATRACE_CALL();
-
- if (actualDurationNanos < 0 || !isPowerHintSessionRunning()) {
- ALOGV("Failed to send actual work duration, skipping");
- return;
- }
-
- WorkDuration duration;
- duration.durationNanos = actualDurationNanos;
- mActualDuration = actualDurationNanos;
-
- // normalize the sent values to a pre-set target
- if (sNormalizeTarget) {
- duration.durationNanos += mLastTargetDurationSent - mTargetDuration;
- }
- duration.timeStampNanos = timeStampNanos;
- mPowerHintQueue.push_back(duration);
-
- long long targetNsec = mTargetDuration;
- long long durationNsec = actualDurationNanos;
-
- if (sTraceHintSessionData) {
- ATRACE_INT64("Measured duration", durationNsec);
- ATRACE_INT64("Target error term", targetNsec - durationNsec);
- }
-
- ALOGV("Sending actual work duration of: %lld on target: %lld with error: %lld",
- durationNsec, targetNsec, targetNsec - durationNsec);
-
- // This rate limiter queues similar duration reports to the powerhal into
- // batches to avoid excessive binder calls. The criteria to send a given batch
- // are outlined in shouldReportActualDurationsNow()
- if (shouldReportActualDurationsNow()) {
- ALOGV("Sending hint update batch");
- mLastActualReportTimestamp = systemTime();
- auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
- if (!ret.isOk()) {
- ALOGW("Failed to report actual work durations with error: %s",
- ret.exceptionMessage().c_str());
- mShouldReconnectHal = true;
- }
- mPowerHintQueue.clear();
- // we save the non-normalized value here to detect % changes
- mLastActualDurationSent = actualDurationNanos;
- }
- }
-
- bool shouldReconnectHAL() override { return mShouldReconnectHal; }
-
- std::vector<int32_t> getPowerHintSessionThreadIds() override { return mPowerHintThreadIds; }
-
- std::optional<int64_t> getTargetWorkDuration() override { return mTargetDuration; }
-
-private:
- const sp<IPower> mPowerHal = nullptr;
- bool mHasExpensiveRendering = false;
- bool mHasDisplayUpdateImminent = false;
- // Used to indicate an error state and need for reconstruction
- bool mShouldReconnectHal = false;
- // This is not thread safe, but is currently protected by mPowerHalMutex so it needs no lock
- sp<IPowerHintSession> mPowerHintSession = nullptr;
- // Queue of actual durations saved to report
- std::vector<WorkDuration> mPowerHintQueue;
- // The latest un-normalized values we have received for target and actual
- int64_t mTargetDuration = kDefaultTarget.count();
- std::optional<int64_t> mActualDuration;
- // The list of thread ids, stored so we can restart the session from this class if needed
- std::vector<int32_t> mPowerHintThreadIds;
- bool mSupportsPowerHint;
- // Keep track of the last messages sent for rate limiter change detection
- std::optional<int64_t> mLastActualDurationSent;
- // timestamp of the last report we sent, used to avoid stale sessions
- int64_t mLastActualReportTimestamp = 0;
- int64_t mLastTargetDurationSent = kDefaultTarget.count();
- // Whether to normalize all the actual values as error terms relative to a constant target
- // This saves a binder call by not setting the target, and should not affect the pid values
- static const bool sNormalizeTarget;
- // Whether we should emit ATRACE_INT data for hint sessions
- static const bool sTraceHintSessionData;
- // Max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
- static constexpr double kAllowedActualDeviationPercent = 0.1;
- // Max percent the target duration can vary without causing a report (eg: 0.05 = 5%)
- static constexpr double kAllowedTargetDeviationPercent = 0.05;
- // Target used for init and normalization, the actual value does not really matter
- static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms;
- // Amount of time after the last message was sent before the session goes stale
- // actually 100ms but we use 80 here to ideally avoid going stale
- static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
};
+std::unique_ptr<PowerAdvisor::HalWrapper> AidlPowerHalWrapper::connect() {
+ // This only waits if the service is actually declared
+ sp<IPower> powerHal = waitForVintfService<IPower>();
+ if (powerHal == nullptr) {
+ return nullptr;
+ }
+ ALOGI("Loaded AIDL Power HAL service");
+
+ return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
+}
+
+bool AidlPowerHalWrapper::setExpensiveRendering(bool enabled) {
+ ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
+ if (!mHasExpensiveRendering) {
+ ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
+ return true;
+ }
+
+ auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
+ if (ret.isOk()) {
+ traceExpensiveRendering(enabled);
+ }
+ return ret.isOk();
+}
+
+bool AidlPowerHalWrapper::notifyDisplayUpdateImminent() {
+ ALOGV("AIDL notifyDisplayUpdateImminent");
+ if (!mHasDisplayUpdateImminent) {
+ ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
+ return true;
+ }
+
+ auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
+ return ret.isOk();
+}
+
+// only version 2+ of the aidl supports power hint sessions, hidl has no support
+bool AidlPowerHalWrapper::supportsPowerHintSession() {
+ return mSupportsPowerHint;
+}
+
+bool AidlPowerHalWrapper::checkPowerHintSessionSupported() {
+ int64_t unused;
+ // Try to get preferred rate to determine if hint sessions are supported
+ // We check for isOk not EX_UNSUPPORTED_OPERATION to lump together errors
+ return mPowerHal->getHintSessionPreferredRate(&unused).isOk();
+}
+
+bool AidlPowerHalWrapper::isPowerHintSessionRunning() {
+ return mPowerHintSession != nullptr;
+}
+
+void AidlPowerHalWrapper::closePowerHintSession() {
+ if (mPowerHintSession != nullptr) {
+ mPowerHintSession->close();
+ mPowerHintSession = nullptr;
+ }
+}
+
+void AidlPowerHalWrapper::restartPowerHintSession() {
+ closePowerHintSession();
+ startPowerHintSession();
+}
+
+void AidlPowerHalWrapper::setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) {
+ if (threadIds != mPowerHintThreadIds) {
+ mPowerHintThreadIds = threadIds;
+ if (isPowerHintSessionRunning()) {
+ restartPowerHintSession();
+ }
+ }
+}
+
+bool AidlPowerHalWrapper::startPowerHintSession() {
+ if (mPowerHintSession != nullptr || mPowerHintThreadIds.empty()) {
+ ALOGV("Cannot start power hint session, skipping");
+ return false;
+ }
+ auto ret =
+ mPowerHal->createHintSession(getpid(), static_cast<int32_t>(getuid()),
+ mPowerHintThreadIds, mTargetDuration, &mPowerHintSession);
+ if (!ret.isOk()) {
+ ALOGW("Failed to start power hint session with error: %s",
+ ret.exceptionToString(ret.exceptionCode()).c_str());
+ } else {
+ mLastTargetDurationSent = mTargetDuration;
+ }
+ return isPowerHintSessionRunning();
+}
+
+bool AidlPowerHalWrapper::shouldSetTargetDuration(int64_t targetDurationNanos) {
+ if (targetDurationNanos <= 0) {
+ return false;
+ }
+ // report if the change in target from our last submission to now exceeds the threshold
+ return abs(1.0 -
+ static_cast<double>(mLastTargetDurationSent) /
+ static_cast<double>(targetDurationNanos)) >= kAllowedTargetDeviationPercent;
+}
+
+void AidlPowerHalWrapper::setTargetWorkDuration(int64_t targetDurationNanos) {
+ ATRACE_CALL();
+ mTargetDuration = targetDurationNanos;
+ if (sTraceHintSessionData) ATRACE_INT64("Time target", targetDurationNanos);
+ if (!sNormalizeTarget && isPowerHintSessionRunning() &&
+ shouldSetTargetDuration(targetDurationNanos)) {
+ if (mLastActualDurationSent.has_value()) {
+ // update the error term here since we are actually sending an update to powerhal
+ if (sTraceHintSessionData)
+ ATRACE_INT64("Target error term", targetDurationNanos - *mLastActualDurationSent);
+ }
+ ALOGV("Sending target time: %" PRId64 "ns", targetDurationNanos);
+ mLastTargetDurationSent = targetDurationNanos;
+ auto ret = mPowerHintSession->updateTargetWorkDuration(targetDurationNanos);
+ if (!ret.isOk()) {
+ ALOGW("Failed to set power hint target work duration with error: %s",
+ ret.exceptionMessage().c_str());
+ mShouldReconnectHal = true;
+ }
+ }
+}
+
+bool AidlPowerHalWrapper::shouldReportActualDurationsNow() {
+ // report if we have never reported before or are approaching a stale session
+ if (!mLastActualDurationSent.has_value() ||
+ (systemTime() - mLastActualReportTimestamp) > kStaleTimeout.count()) {
+ return true;
+ }
+
+ if (!mActualDuration.has_value()) {
+ return false;
+ }
+
+ // duration of most recent timing
+ const double mostRecentActualDuration = static_cast<double>(*mActualDuration);
+ // duration of the last timing actually reported to the powerhal
+ const double lastReportedActualDuration = static_cast<double>(*mLastActualDurationSent);
+
+ // report if the change in duration from then to now exceeds the threshold
+ return abs(1.0 - mostRecentActualDuration / lastReportedActualDuration) >=
+ kAllowedActualDeviationPercent;
+}
+
+void AidlPowerHalWrapper::sendActualWorkDuration(int64_t actualDurationNanos,
+ nsecs_t timeStampNanos) {
+ ATRACE_CALL();
+
+ if (actualDurationNanos < 0 || !isPowerHintSessionRunning()) {
+ ALOGV("Failed to send actual work duration, skipping");
+ return;
+ }
+
+ WorkDuration duration;
+ duration.durationNanos = actualDurationNanos;
+ mActualDuration = actualDurationNanos;
+
+ // normalize the sent values to a pre-set target
+ if (sNormalizeTarget) {
+ duration.durationNanos += mLastTargetDurationSent - mTargetDuration;
+ }
+ duration.timeStampNanos = timeStampNanos;
+ mPowerHintQueue.push_back(duration);
+
+ nsecs_t targetNsec = mTargetDuration;
+ nsecs_t durationNsec = actualDurationNanos;
+
+ if (sTraceHintSessionData) {
+ ATRACE_INT64("Measured duration", durationNsec);
+ ATRACE_INT64("Target error term", targetNsec - durationNsec);
+ }
+
+ ALOGV("Sending actual work duration of: %" PRId64 " on target: %" PRId64
+ " with error: %" PRId64,
+ durationNsec, targetNsec, targetNsec - durationNsec);
+
+ // This rate limiter queues similar duration reports to the powerhal into
+ // batches to avoid excessive binder calls. The criteria to send a given batch
+ // are outlined in shouldReportActualDurationsNow()
+ if (shouldReportActualDurationsNow()) {
+ ALOGV("Sending hint update batch");
+ mLastActualReportTimestamp = systemTime();
+ auto ret = mPowerHintSession->reportActualWorkDuration(mPowerHintQueue);
+ if (!ret.isOk()) {
+ ALOGW("Failed to report actual work durations with error: %s",
+ ret.exceptionMessage().c_str());
+ mShouldReconnectHal = true;
+ }
+ mPowerHintQueue.clear();
+ // we save the non-normalized value here to detect % changes
+ mLastActualDurationSent = actualDurationNanos;
+ }
+}
+
+bool AidlPowerHalWrapper::shouldReconnectHAL() {
+ return mShouldReconnectHal;
+}
+
+std::vector<int32_t> AidlPowerHalWrapper::getPowerHintSessionThreadIds() {
+ return mPowerHintThreadIds;
+}
+
+std::optional<int64_t> AidlPowerHalWrapper::getTargetWorkDuration() {
+ return mTargetDuration;
+}
+
const bool AidlPowerHalWrapper::sTraceHintSessionData =
base::GetBoolProperty(std::string("debug.sf.trace_hint_sessions"), false);
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 0db56aa..3f47ffd 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -22,6 +22,7 @@
#include <utils/Mutex.h>
+#include <android/hardware/power/IPower.h>
#include <ui/DisplayIdentification.h>
#include "../Scheduler/OneShotTimer.h"
@@ -118,6 +119,69 @@
scheduler::OneShotTimer mScreenUpdateTimer;
};
+class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
+public:
+ explicit AidlPowerHalWrapper(sp<hardware::power::IPower> powerHal);
+ ~AidlPowerHalWrapper() override;
+
+ static std::unique_ptr<HalWrapper> connect();
+
+ bool setExpensiveRendering(bool enabled) override;
+ bool notifyDisplayUpdateImminent() override;
+ bool supportsPowerHintSession() override;
+ bool isPowerHintSessionRunning() override;
+ void restartPowerHintSession() override;
+ void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override;
+ bool startPowerHintSession() override;
+ void setTargetWorkDuration(int64_t targetDurationNanos) override;
+ void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) override;
+ bool shouldReconnectHAL() override;
+ std::vector<int32_t> getPowerHintSessionThreadIds() override;
+ std::optional<int64_t> getTargetWorkDuration() override;
+
+private:
+ bool checkPowerHintSessionSupported();
+ void closePowerHintSession();
+ bool shouldReportActualDurationsNow();
+ bool shouldSetTargetDuration(int64_t targetDurationNanos);
+
+ const sp<hardware::power::IPower> mPowerHal = nullptr;
+ bool mHasExpensiveRendering = false;
+ bool mHasDisplayUpdateImminent = false;
+ // Used to indicate an error state and need for reconstruction
+ bool mShouldReconnectHal = false;
+ // This is not thread safe, but is currently protected by mPowerHalMutex so it needs no lock
+ sp<hardware::power::IPowerHintSession> mPowerHintSession = nullptr;
+ // Queue of actual durations saved to report
+ std::vector<hardware::power::WorkDuration> mPowerHintQueue;
+ // The latest un-normalized values we have received for target and actual
+ int64_t mTargetDuration = kDefaultTarget.count();
+ std::optional<int64_t> mActualDuration;
+ // The list of thread ids, stored so we can restart the session from this class if needed
+ std::vector<int32_t> mPowerHintThreadIds;
+ bool mSupportsPowerHint;
+ // Keep track of the last messages sent for rate limiter change detection
+ std::optional<int64_t> mLastActualDurationSent;
+ // timestamp of the last report we sent, used to avoid stale sessions
+ int64_t mLastActualReportTimestamp = 0;
+ int64_t mLastTargetDurationSent = kDefaultTarget.count();
+ // Whether to normalize all the actual values as error terms relative to a constant target
+ // This saves a binder call by not setting the target, and should not affect the pid values
+ static const bool sNormalizeTarget;
+ // Whether we should emit ATRACE_INT data for hint sessions
+ static const bool sTraceHintSessionData;
+
+ // Max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
+ static constexpr double kAllowedActualDeviationPercent = 0.1;
+ // Max percent the target duration can vary without causing a report (eg: 0.05 = 5%)
+ static constexpr double kAllowedTargetDeviationPercent = 0.05;
+ // Target used for init and normalization, the actual value does not really matter
+ static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms;
+ // Amount of time after the last message was sent before the session goes stale
+ // actually 100ms but we use 80 here to ideally avoid going stale
+ static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
+};
+
} // namespace impl
} // namespace Hwc2
} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index b4fb51f..3803a78 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -19,20 +19,20 @@
#pragma clang diagnostic ignored "-Wconversion"
// #define LOG_NDEBUG 0
-#include "VirtualDisplaySurface.h"
#include <cinttypes>
-#include "HWComposer.h"
-#include "SurfaceFlinger.h"
-
-#include <ftl/Flags.h>
#include <ftl/enum.h>
+#include <ftl/flags.h>
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/IProducerListener.h>
#include <system/window.h>
+#include "HWComposer.h"
+#include "SurfaceFlinger.h"
+#include "VirtualDisplaySurface.h"
+
#define VDS_LOGE(msg, ...) ALOGE("[%s] " msg, \
mDisplayName.c_str(), ##__VA_ARGS__)
#define VDS_LOGW_IF(cond, msg, ...) ALOGW_IF(cond, "[%s] " msg, \
@@ -657,7 +657,7 @@
std::string VirtualDisplaySurface::toString(CompositionType type) {
using namespace std::literals;
- return type == CompositionType::Unknown ? "Unknown"s : Flags(type).string();
+ return type == CompositionType::Unknown ? "Unknown"s : ftl::Flags(type).string();
}
} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index fa5a1c8..bd73723 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -37,6 +37,7 @@
#include <cutils/native_handle.h>
#include <cutils/properties.h>
#include <ftl/enum.h>
+#include <ftl/fake_guard.h>
#include <gui/BufferItem.h>
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
@@ -81,11 +82,13 @@
constexpr int kDumpTableRowLength = 159;
} // namespace
+using namespace ftl::flag_operators;
+
using base::StringAppendF;
-using namespace android::flag_operators;
-using PresentState = frametimeline::SurfaceFrame::PresentState;
using gui::WindowInfo;
+using PresentState = frametimeline::SurfaceFrame::PresentState;
+
std::atomic<int32_t> Layer::sSequence{1};
Layer::Layer(const LayerCreationArgs& args)
@@ -139,6 +142,7 @@
mDrawingState.destinationFrame.makeInvalid();
mDrawingState.isTrustedOverlay = false;
mDrawingState.dropInputMode = gui::DropInputMode::NONE;
+ mDrawingState.dimmingEnabled = true;
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
// Set an invalid color so there is no color fill.
@@ -477,6 +481,7 @@
compositionState->colorTransformIsIdentity = !hasColorTransform();
compositionState->surfaceDamage = surfaceDamageRegion;
compositionState->hasProtectedContent = isProtected();
+ compositionState->dimmingEnabled = isDimmingEnabled();
const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
@@ -1038,6 +1043,16 @@
return true;
}
+bool Layer::setDimmingEnabled(const bool dimmingEnabled) {
+ if (mDrawingState.dimmingEnabled == dimmingEnabled) return false;
+
+ mDrawingState.sequence++;
+ mDrawingState.dimmingEnabled = dimmingEnabled;
+ mDrawingState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
bool Layer::setFrameRateSelectionPriority(int32_t priority) {
if (mDrawingState.frameRateSelectionPriority == priority) return false;
mDrawingState.frameRateSelectionPriority = priority;
@@ -1373,10 +1388,10 @@
// ----------------------------------------------------------------------------
// TODO(marissaw): add new layer state info to layer debugging
-LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const {
+gui::LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const {
using namespace std::string_literals;
- LayerDebugInfo info;
+ gui::LayerDebugInfo info;
const State& ds = getDrawingState();
info.mName = getName();
sp<Layer> parent = mDrawingParent.promote();
@@ -2045,10 +2060,10 @@
writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags);
if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
+ ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread.
+
// Only populate for the primary display.
- UnnecessaryLock assumeLocked(mFlinger->mStateLock); // called from the main thread.
- const auto display = mFlinger->getDefaultDisplayDeviceLocked();
- if (display) {
+ if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) {
const auto compositionType = getCompositionType(*display);
layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType));
LayerProtoHelper::writeToProto(getVisibleRegion(display.get()),
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 846460d..455920b 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -69,13 +69,16 @@
class DisplayDevice;
class GraphicBuffer;
class SurfaceFlinger;
-class LayerDebugInfo;
namespace compositionengine {
class OutputLayer;
struct LayerFECompositionState;
}
+namespace gui {
+class LayerDebugInfo;
+}
+
namespace impl {
class SurfaceInterceptor;
}
@@ -281,6 +284,8 @@
gui::DropInputMode dropInputMode;
bool autoRefresh = false;
+
+ bool dimmingEnabled = true;
};
/*
@@ -411,6 +416,7 @@
virtual mat4 getColorTransform() const;
virtual bool hasColorTransform() const;
virtual bool isColorSpaceAgnostic() const { return mDrawingState.colorSpaceAgnostic; }
+ virtual bool isDimmingEnabled() const { return getDrawingState().dimmingEnabled; };
// Used only to set BufferStateLayer state
virtual bool setTransform(uint32_t /*transform*/) { return false; };
@@ -437,6 +443,7 @@
}
virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
virtual bool setColorSpaceAgnostic(const bool agnostic);
+ virtual bool setDimmingEnabled(const bool dimmingEnabled);
virtual bool setFrameRateSelectionPriority(int32_t priority);
virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint);
virtual void setAutoRefresh(bool /* autoRefresh */) {}
@@ -737,7 +744,7 @@
inline const State& getDrawingState() const { return mDrawingState; }
inline State& getDrawingState() { return mDrawingState; }
- LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const;
+ gui::LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const;
void miniDump(std::string& result, const DisplayDevice&) const;
void dumpFrameStats(std::string& result) const;
diff --git a/services/surfaceflinger/MainThreadGuard.h b/services/surfaceflinger/MainThreadGuard.h
deleted file mode 100644
index c1aa118..0000000
--- a/services/surfaceflinger/MainThreadGuard.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <utils/Mutex.h>
-
-namespace android {
-namespace {
-
-// Helps to ensure that some functions runs on SF's main thread by using the
-// clang thread safety annotations.
-class CAPABILITY("mutex") MainThreadGuard {
-} SF_MAIN_THREAD;
-
-struct SCOPED_CAPABILITY MainThreadScopedGuard {
-public:
- explicit MainThreadScopedGuard(MainThreadGuard& mutex) ACQUIRE(mutex) {}
- ~MainThreadScopedGuard() RELEASE() {}
-};
-} // namespace
-} // namespace android
diff --git a/services/surfaceflinger/MutexUtils.h b/services/surfaceflinger/MutexUtils.h
new file mode 100644
index 0000000..f8be6f3
--- /dev/null
+++ b/services/surfaceflinger/MutexUtils.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <log/log.h>
+#include <utils/Mutex.h>
+
+namespace android {
+
+struct SCOPED_CAPABILITY ConditionalLock {
+ ConditionalLock(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) {
+ if (lock) mutex.lock();
+ }
+
+ ~ConditionalLock() RELEASE() {
+ if (lock) mutex.unlock();
+ }
+
+ Mutex& mutex;
+ const bool lock;
+};
+
+struct SCOPED_CAPABILITY TimedLock {
+ TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex)
+ : mutex(mutex), status(mutex.timedLock(timeout)) {
+ ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status);
+ }
+
+ ~TimedLock() RELEASE() {
+ if (locked()) mutex.unlock();
+ }
+
+ bool locked() const { return status == NO_ERROR; }
+
+ Mutex& mutex;
+ const status_t status;
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 81c1566..80aa072 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -14,22 +14,20 @@
* limitations under the License.
*/
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
-
#include <algorithm>
#include "RefreshRateOverlay.h"
#include "Client.h"
#include "Layer.h"
-#include <SkBlendMode.h>
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+#include <SkCanvas.h>
#include <SkPaint.h>
+#pragma clang diagnostic pop
+#include <SkBlendMode.h>
#include <SkRect.h>
#include <SkSurface.h>
-#include <gui/IProducerListener.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
@@ -37,29 +35,40 @@
#define LOG_TAG "RefreshRateOverlay"
namespace android {
+namespace {
-void RefreshRateOverlay::SevenSegmentDrawer::drawSegment(Segment segment, int left, SkColor& color,
+constexpr int kDigitWidth = 64;
+constexpr int kDigitHeight = 100;
+constexpr int kDigitSpace = 16;
+
+// Layout is digit, space, digit, space, digit, space, spinner.
+constexpr int kBufferWidth = 4 * kDigitWidth + 3 * kDigitSpace;
+constexpr int kBufferHeight = kDigitHeight;
+
+} // namespace
+
+void RefreshRateOverlay::SevenSegmentDrawer::drawSegment(Segment segment, int left, SkColor color,
SkCanvas& canvas) {
const SkRect rect = [&]() {
switch (segment) {
case Segment::Upper:
- return SkRect::MakeLTRB(left, 0, left + DIGIT_WIDTH, DIGIT_SPACE);
+ return SkRect::MakeLTRB(left, 0, left + kDigitWidth, kDigitSpace);
case Segment::UpperLeft:
- return SkRect::MakeLTRB(left, 0, left + DIGIT_SPACE, DIGIT_HEIGHT / 2);
+ return SkRect::MakeLTRB(left, 0, left + kDigitSpace, kDigitHeight / 2);
case Segment::UpperRight:
- return SkRect::MakeLTRB(left + DIGIT_WIDTH - DIGIT_SPACE, 0, left + DIGIT_WIDTH,
- DIGIT_HEIGHT / 2);
+ return SkRect::MakeLTRB(left + kDigitWidth - kDigitSpace, 0, left + kDigitWidth,
+ kDigitHeight / 2);
case Segment::Middle:
- return SkRect::MakeLTRB(left, DIGIT_HEIGHT / 2 - DIGIT_SPACE / 2,
- left + DIGIT_WIDTH, DIGIT_HEIGHT / 2 + DIGIT_SPACE / 2);
+ return SkRect::MakeLTRB(left, kDigitHeight / 2 - kDigitSpace / 2,
+ left + kDigitWidth, kDigitHeight / 2 + kDigitSpace / 2);
case Segment::LowerLeft:
- return SkRect::MakeLTRB(left, DIGIT_HEIGHT / 2, left + DIGIT_SPACE, DIGIT_HEIGHT);
+ return SkRect::MakeLTRB(left, kDigitHeight / 2, left + kDigitSpace, kDigitHeight);
case Segment::LowerRight:
- return SkRect::MakeLTRB(left + DIGIT_WIDTH - DIGIT_SPACE, DIGIT_HEIGHT / 2,
- left + DIGIT_WIDTH, DIGIT_HEIGHT);
+ return SkRect::MakeLTRB(left + kDigitWidth - kDigitSpace, kDigitHeight / 2,
+ left + kDigitWidth, kDigitHeight);
case Segment::Bottom:
- return SkRect::MakeLTRB(left, DIGIT_HEIGHT - DIGIT_SPACE, left + DIGIT_WIDTH,
- DIGIT_HEIGHT);
+ return SkRect::MakeLTRB(left, kDigitHeight - kDigitSpace, left + kDigitWidth,
+ kDigitHeight);
}
}();
@@ -69,7 +78,7 @@
canvas.drawRect(rect, paint);
}
-void RefreshRateOverlay::SevenSegmentDrawer::drawDigit(int digit, int left, SkColor& color,
+void RefreshRateOverlay::SevenSegmentDrawer::drawDigit(int digit, int left, SkColor color,
SkCanvas& canvas) {
if (digit < 0 || digit > 9) return;
@@ -94,37 +103,45 @@
drawSegment(Segment::Bottom, left, color, canvas);
}
-std::vector<sp<GraphicBuffer>> RefreshRateOverlay::SevenSegmentDrawer::draw(
- int number, SkColor& color, ui::Transform::RotationFlags rotation, bool showSpinner) {
+auto RefreshRateOverlay::SevenSegmentDrawer::draw(int number, SkColor color,
+ ui::Transform::RotationFlags rotation,
+ bool showSpinner) -> Buffers {
if (number < 0 || number > 1000) return {};
const auto hundreds = number / 100;
const auto tens = (number / 10) % 10;
const auto ones = number % 10;
- std::vector<sp<GraphicBuffer>> buffers;
- const auto loopCount = showSpinner ? 6 : 1;
- for (int i = 0; i < loopCount; i++) {
+ const size_t loopCount = showSpinner ? 6 : 1;
+
+ Buffers buffers;
+ buffers.reserve(loopCount);
+
+ for (size_t i = 0; i < loopCount; i++) {
// Pre-rotate the buffer before it reaches SurfaceFlinger.
SkMatrix canvasTransform = SkMatrix();
- auto [bufferWidth, bufferHeight] = [&] {
+ const auto [bufferWidth, bufferHeight] = [&]() -> std::pair<int, int> {
switch (rotation) {
case ui::Transform::ROT_90:
- canvasTransform.setTranslate(BUFFER_HEIGHT, 0);
- canvasTransform.preRotate(90);
- return std::make_tuple(BUFFER_HEIGHT, BUFFER_WIDTH);
+ canvasTransform.setTranslate(kBufferHeight, 0);
+ canvasTransform.preRotate(90.f);
+ return {kBufferHeight, kBufferWidth};
case ui::Transform::ROT_270:
- canvasTransform.setRotate(270, BUFFER_WIDTH / 2.0, BUFFER_WIDTH / 2.0);
- return std::make_tuple(BUFFER_HEIGHT, BUFFER_WIDTH);
+ canvasTransform.setRotate(270.f, kBufferWidth / 2.f, kBufferWidth / 2.f);
+ return {kBufferHeight, kBufferWidth};
default:
- return std::make_tuple(BUFFER_WIDTH, BUFFER_HEIGHT);
+ return {kBufferWidth, kBufferHeight};
}
}();
+
sp<GraphicBuffer> buffer =
- new GraphicBuffer(bufferWidth, bufferHeight, HAL_PIXEL_FORMAT_RGBA_8888, 1,
+ new GraphicBuffer(static_cast<uint32_t>(bufferWidth),
+ static_cast<uint32_t>(bufferHeight), HAL_PIXEL_FORMAT_RGBA_8888,
+ 1,
GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER |
GRALLOC_USAGE_HW_TEXTURE,
"RefreshRateOverlayBuffer");
+
const status_t bufferStatus = buffer->initCheck();
LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "RefreshRateOverlay: Buffer failed to allocate: %d",
bufferStatus);
@@ -137,15 +154,15 @@
if (hundreds != 0) {
drawDigit(hundreds, left, color, *canvas);
}
- left += DIGIT_WIDTH + DIGIT_SPACE;
+ left += kDigitWidth + kDigitSpace;
if (tens != 0) {
drawDigit(tens, left, color, *canvas);
}
- left += DIGIT_WIDTH + DIGIT_SPACE;
+ left += kDigitWidth + kDigitSpace;
drawDigit(ones, left, color, *canvas);
- left += DIGIT_WIDTH + DIGIT_SPACE;
+ left += kDigitWidth + kDigitSpace;
if (showSpinner) {
switch (i) {
@@ -172,51 +189,48 @@
void* pixels = nullptr;
buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
+
const SkImageInfo& imageInfo = surface->imageInfo();
- size_t dstRowBytes = buffer->getStride() * imageInfo.bytesPerPixel();
+ const size_t dstRowBytes =
+ buffer->getStride() * static_cast<size_t>(imageInfo.bytesPerPixel());
+
canvas->readPixels(imageInfo, pixels, dstRowBytes, 0, 0);
buffer->unlock();
- buffers.emplace_back(buffer);
+ buffers.push_back(std::move(buffer));
}
return buffers;
}
-RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger, uint32_t lowFps, uint32_t highFps,
- bool showSpinner)
- : mFlinger(flinger),
- mClient(new Client(&mFlinger)),
+RefreshRateOverlay::RefreshRateOverlay(FpsRange fpsRange, bool showSpinner)
+ : mFpsRange(fpsRange),
mShowSpinner(showSpinner),
- mLowFps(lowFps),
- mHighFps(highFps) {
- createLayer();
-}
-
-bool RefreshRateOverlay::createLayer() {
- mSurfaceControl =
- SurfaceComposerClient::getDefault()
- ->createSurface(String8("RefreshRateOverlay"), SevenSegmentDrawer::getWidth(),
- SevenSegmentDrawer::getHeight(), PIXEL_FORMAT_RGBA_8888,
- ISurfaceComposerClient::eFXSurfaceBufferState);
-
+ mSurfaceControl(SurfaceComposerClient::getDefault()
+ ->createSurface(String8("RefreshRateOverlay"), kBufferWidth,
+ kBufferHeight, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferState)) {
if (!mSurfaceControl) {
- ALOGE("failed to create buffer state layer");
- return false;
+ ALOGE("%s: Failed to create buffer state layer", __func__);
+ return;
}
+ constexpr float kFrameRate = 0.f;
+ constexpr int8_t kCompatibility = static_cast<int8_t>(Layer::FrameRateCompatibility::NoVote);
+ constexpr int8_t kSeamlessness = ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS;
+
SurfaceComposerClient::Transaction()
- .setFrameRate(mSurfaceControl, 0.0f,
- static_cast<int8_t>(Layer::FrameRateCompatibility::NoVote),
- static_cast<int8_t>(scheduler::Seamlessness::OnlySeamless))
+ .setFrameRate(mSurfaceControl, kFrameRate, kCompatibility, kSeamlessness)
.setLayer(mSurfaceControl, INT32_MAX - 2)
.setTrustedOverlay(mSurfaceControl, true)
.apply();
-
- return true;
}
-const std::vector<sp<GraphicBuffer>>& RefreshRateOverlay::getOrCreateBuffers(uint32_t fps) {
- ui::Transform::RotationFlags transformHint =
+auto RefreshRateOverlay::getOrCreateBuffers(Fps fps) -> const Buffers& {
+ static const Buffers kNoBuffers;
+ if (!mSurfaceControl) return kNoBuffers;
+
+ const auto transformHint =
static_cast<ui::Transform::RotationFlags>(mSurfaceControl->getTransformHint());
+
// Tell SurfaceFlinger about the pre-rotation on the buffer.
const auto transform = [&] {
switch (transformHint) {
@@ -233,40 +247,49 @@
t.setTransform(mSurfaceControl, transform);
t.apply();
- if (mBufferCache.find(transformHint) == mBufferCache.end() ||
- mBufferCache.at(transformHint).find(fps) == mBufferCache.at(transformHint).end()) {
- // Ensure the range is > 0, so we don't divide by 0.
- const auto rangeLength = std::max(1u, mHighFps - mLowFps);
- // Clip values outside the range [mLowFps, mHighFps]. The current fps may be outside
- // of this range if the display has changed its set of supported refresh rates.
- fps = std::max(fps, mLowFps);
- fps = std::min(fps, mHighFps);
- const auto fpsScale = static_cast<float>(fps - mLowFps) / rangeLength;
- SkColor4f colorBase = SkColor4f::FromColor(HIGH_FPS_COLOR) * fpsScale;
- SkColor4f lowFpsColor = SkColor4f::FromColor(LOW_FPS_COLOR) * (1 - fpsScale);
- colorBase.fR = colorBase.fR + lowFpsColor.fR;
- colorBase.fG = colorBase.fG + lowFpsColor.fG;
- colorBase.fB = colorBase.fB + lowFpsColor.fB;
- colorBase.fA = ALPHA;
- SkColor color = colorBase.toSkColor();
- auto buffers = SevenSegmentDrawer::draw(fps, color, transformHint, mShowSpinner);
- mBufferCache[transformHint].emplace(fps, buffers);
+ BufferCache::const_iterator it = mBufferCache.find({fps.getIntValue(), transformHint});
+ if (it == mBufferCache.end()) {
+ const int minFps = mFpsRange.min.getIntValue();
+ const int maxFps = mFpsRange.max.getIntValue();
+
+ // Clamp to the range. The current fps may be outside of this range if the display has
+ // changed its set of supported refresh rates.
+ const int intFps = std::clamp(fps.getIntValue(), minFps, maxFps);
+
+ // Ensure non-zero range to avoid division by zero.
+ const float fpsScale = static_cast<float>(intFps - minFps) / std::max(1, maxFps - minFps);
+
+ constexpr SkColor kMinFpsColor = SK_ColorRED;
+ constexpr SkColor kMaxFpsColor = SK_ColorGREEN;
+ constexpr float kAlpha = 0.8f;
+
+ SkColor4f colorBase = SkColor4f::FromColor(kMaxFpsColor) * fpsScale;
+ const SkColor4f minFpsColor = SkColor4f::FromColor(kMinFpsColor) * (1 - fpsScale);
+
+ colorBase.fR = colorBase.fR + minFpsColor.fR;
+ colorBase.fG = colorBase.fG + minFpsColor.fG;
+ colorBase.fB = colorBase.fB + minFpsColor.fB;
+ colorBase.fA = kAlpha;
+
+ const SkColor color = colorBase.toSkColor();
+
+ auto buffers = SevenSegmentDrawer::draw(intFps, color, transformHint, mShowSpinner);
+ it = mBufferCache.try_emplace({intFps, transformHint}, std::move(buffers)).first;
}
- return mBufferCache[transformHint][fps];
+ return it->second;
}
void RefreshRateOverlay::setViewport(ui::Size viewport) {
constexpr int32_t kMaxWidth = 1000;
- const auto width = std::min(kMaxWidth, std::min(viewport.width, viewport.height));
+ const auto width = std::min({kMaxWidth, viewport.width, viewport.height});
const auto height = 2 * width;
Rect frame((3 * width) >> 4, height >> 5);
frame.offsetBy(width >> 5, height >> 4);
SurfaceComposerClient::Transaction t;
- t.setMatrix(mSurfaceControl,
- frame.getWidth() / static_cast<float>(SevenSegmentDrawer::getWidth()), 0, 0,
- frame.getHeight() / static_cast<float>(SevenSegmentDrawer::getHeight()));
+ t.setMatrix(mSurfaceControl, frame.getWidth() / static_cast<float>(kBufferWidth), 0, 0,
+ frame.getHeight() / static_cast<float>(kBufferHeight));
t.setPosition(mSurfaceControl, frame.left, frame.top);
t.apply();
}
@@ -278,25 +301,22 @@
}
void RefreshRateOverlay::changeRefreshRate(Fps fps) {
- mCurrentFps = fps.getIntValue();
- auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame];
+ mCurrentFps = fps;
+ const auto buffer = getOrCreateBuffers(fps)[mFrame];
SurfaceComposerClient::Transaction t;
t.setBuffer(mSurfaceControl, buffer);
t.apply();
}
void RefreshRateOverlay::animate() {
- if (!mCurrentFps.has_value()) return;
+ if (!mShowSpinner || !mCurrentFps) return;
const auto& buffers = getOrCreateBuffers(*mCurrentFps);
mFrame = (mFrame + 1) % buffers.size();
- auto buffer = buffers[mFrame];
+ const auto buffer = buffers[mFrame];
SurfaceComposerClient::Transaction t;
t.setBuffer(mSurfaceControl, buffer);
t.apply();
}
} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h
index 381df37..a465a36 100644
--- a/services/surfaceflinger/RefreshRateOverlay.h
+++ b/services/surfaceflinger/RefreshRateOverlay.h
@@ -16,32 +16,27 @@
#pragma once
-#include <SkCanvas.h>
#include <SkColor.h>
-#include <unordered_map>
+#include <vector>
-#include <math/vec4.h>
-#include <renderengine/RenderEngine.h>
+#include <ftl/small_map.h>
#include <ui/LayerStack.h>
-#include <ui/Rect.h>
#include <ui/Size.h>
+#include <ui/Transform.h>
#include <utils/StrongPointer.h>
#include <scheduler/Fps.h>
+class SkCanvas;
+
namespace android {
-class Client;
class GraphicBuffer;
-class IBinder;
-class IGraphicBufferProducer;
-class Layer;
-class SurfaceFlinger;
class SurfaceControl;
class RefreshRateOverlay {
public:
- RefreshRateOverlay(SurfaceFlinger&, uint32_t lowFps, uint32_t highFps, bool showSpinner);
+ RefreshRateOverlay(FpsRange, bool showSpinner);
void setLayerStack(ui::LayerStack);
void setViewport(ui::Size);
@@ -49,52 +44,38 @@
void animate();
private:
+ using Buffers = std::vector<sp<GraphicBuffer>>;
+
class SevenSegmentDrawer {
public:
- static std::vector<sp<GraphicBuffer>> draw(int number, SkColor& color,
- ui::Transform::RotationFlags, bool showSpinner);
- static uint32_t getHeight() { return BUFFER_HEIGHT; }
- static uint32_t getWidth() { return BUFFER_WIDTH; }
+ static Buffers draw(int number, SkColor, ui::Transform::RotationFlags, bool showSpinner);
private:
enum class Segment { Upper, UpperLeft, UpperRight, Middle, LowerLeft, LowerRight, Bottom };
- static void drawSegment(Segment segment, int left, SkColor& color, SkCanvas& canvas);
- static void drawDigit(int digit, int left, SkColor& color, SkCanvas& canvas);
-
- static constexpr uint32_t DIGIT_HEIGHT = 100;
- static constexpr uint32_t DIGIT_WIDTH = 64;
- static constexpr uint32_t DIGIT_SPACE = 16;
- static constexpr uint32_t BUFFER_HEIGHT = DIGIT_HEIGHT;
- static constexpr uint32_t BUFFER_WIDTH =
- 4 * DIGIT_WIDTH + 3 * DIGIT_SPACE; // Digit|Space|Digit|Space|Digit|Space|Spinner
+ static void drawSegment(Segment, int left, SkColor, SkCanvas&);
+ static void drawDigit(int digit, int left, SkColor, SkCanvas&);
};
- bool createLayer();
+ const Buffers& getOrCreateBuffers(Fps);
- const std::vector<sp<GraphicBuffer>>& getOrCreateBuffers(uint32_t fps);
+ struct Key {
+ int fps;
+ ui::Transform::RotationFlags flags;
- SurfaceFlinger& mFlinger;
- const sp<Client> mClient;
- sp<IBinder> mIBinder;
- sp<IGraphicBufferProducer> mGbp;
+ bool operator==(Key other) const { return fps == other.fps && flags == other.flags; }
+ };
- std::unordered_map<ui::Transform::RotationFlags,
- std::unordered_map<int, std::vector<sp<GraphicBuffer>>>>
- mBufferCache;
- std::optional<int> mCurrentFps;
- int mFrame = 0;
- static constexpr float ALPHA = 0.8f;
- const SkColor LOW_FPS_COLOR = SK_ColorRED;
- const SkColor HIGH_FPS_COLOR = SK_ColorGREEN;
+ using BufferCache = ftl::SmallMap<Key, Buffers, 9>;
+ BufferCache mBufferCache;
+ std::optional<Fps> mCurrentFps;
+ size_t mFrame = 0;
+
+ const FpsRange mFpsRange; // For color interpolation.
const bool mShowSpinner;
- // Interpolate the colors between these values.
- const uint32_t mLowFps;
- const uint32_t mHighFps;
-
- sp<SurfaceControl> mSurfaceControl;
+ const sp<SurfaceControl> mSurfaceControl;
};
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Features.h b/services/surfaceflinger/Scheduler/include/scheduler/Features.h
index 0e96678..b3a6a60 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/Features.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Features.h
@@ -16,10 +16,10 @@
#pragma once
-#include <ftl/Flags.h>
-
#include <cstdint>
+#include <ftl/flags.h>
+
namespace android::scheduler {
enum class Feature : std::uint8_t {
@@ -29,6 +29,6 @@
kTracePredictedVsync = 0b1000,
};
-using FeatureFlags = Flags<Feature>;
+using FeatureFlags = ftl::Flags<Feature>;
} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f326bfd..d5b7193 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -24,7 +24,10 @@
#include "SurfaceFlinger.h"
+#include <android-base/parseint.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <android/configuration.h>
#include <android/gui/IDisplayEventConnection.h>
#include <android/gui/StaticDisplayInfo.h>
@@ -50,6 +53,7 @@
#include <configstore/Utils.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
+#include <ftl/fake_guard.h>
#include <ftl/future.h>
#include <ftl/small_map.h>
#include <gui/BufferQueue.h>
@@ -124,6 +128,7 @@
#include "LayerRenderArea.h"
#include "LayerVector.h"
#include "MonitoredProducer.h"
+#include "MutexUtils.h"
#include "NativeWindowSurface.h"
#include "RefreshRateOverlay.h"
#include "RegionSamplingThread.h"
@@ -139,49 +144,26 @@
#include "TimeStats/TimeStats.h"
#include "TunnelModeEnabledReporter.h"
#include "WindowInfosListenerInvoker.h"
-#include "android-base/parseint.h"
-#include "android-base/stringprintf.h"
-#include "android-base/strings.h"
#include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
#include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
-#define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock)
-
-// Note: The parentheses around `expr` are needed to deduce an lvalue or rvalue reference.
-#define ON_MAIN_THREAD(expr) \
- [&]() -> decltype(auto) { \
- LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \
- UnnecessaryLock lock(mStateLock); \
- return (expr); \
- }()
-
-#define MAIN_THREAD_GUARD(expr) \
- [&]() -> decltype(auto) { \
- LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \
- MainThreadScopedGuard lock(SF_MAIN_THREAD); \
- return (expr); \
- }()
-
#undef NO_THREAD_SAFETY_ANALYSIS
#define NO_THREAD_SAFETY_ANALYSIS \
- _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"")
-
-using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
-using aidl::android::hardware::graphics::composer3::Capability;
-using aidl::android::hardware::graphics::composer3::DisplayCapability;
-using KernelIdleTimerController =
- ::android::scheduler::RefreshRateConfigs::KernelIdleTimerController;
+ _Pragma("GCC error \"Prefer <ftl/fake_guard.h> or MutexUtils.h helpers.\"")
namespace android {
using namespace std::string_literals;
-using namespace android::hardware::configstore;
-using namespace android::hardware::configstore::V1_0;
-using namespace android::sysprop;
+using namespace hardware::configstore;
+using namespace hardware::configstore::V1_0;
+using namespace sysprop;
-using android::hardware::power::Boost;
+using aidl::android::hardware::graphics::common::DisplayDecorationSupport;
+using aidl::android::hardware::graphics::composer3::Capability;
+using aidl::android::hardware::graphics::composer3::DisplayCapability;
+
using base::StringAppendF;
using gui::DisplayInfo;
using gui::IDisplayEventConnection;
@@ -192,6 +174,8 @@
using ui::DisplayPrimaries;
using ui::RenderIntent;
+using KernelIdleTimerController = scheduler::RefreshRateConfigs::KernelIdleTimerController;
+
namespace hal = android::hardware::graphics::composer::hal;
namespace {
@@ -223,38 +207,6 @@
#pragma clang diagnostic pop
-template <typename Mutex>
-struct SCOPED_CAPABILITY ConditionalLockGuard {
- ConditionalLockGuard(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) {
- if (lock) mutex.lock();
- }
-
- ~ConditionalLockGuard() RELEASE() {
- if (lock) mutex.unlock();
- }
-
- Mutex& mutex;
- const bool lock;
-};
-
-using ConditionalLock = ConditionalLockGuard<Mutex>;
-
-struct SCOPED_CAPABILITY TimedLock {
- TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex)
- : mutex(mutex), status(mutex.timedLock(timeout)) {
- ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status);
- }
-
- ~TimedLock() RELEASE() {
- if (locked()) mutex.unlock();
- }
-
- bool locked() const { return status == NO_ERROR; }
-
- Mutex& mutex;
- const status_t status;
-};
-
// TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity.
constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV;
@@ -730,13 +682,15 @@
if (renderEngineTid.has_value()) {
tidList.emplace_back(*renderEngineTid);
}
- mPowerAdvisor.startPowerHintSession(tidList);
+ if (!mPowerAdvisor.startPowerHintSession(tidList)) {
+ ALOGW("Cannot start power hint session");
+ }
}
mBootStage = BootStage::FINISHED;
if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
- ON_MAIN_THREAD(enableRefreshRateOverlay(true));
+ FTL_FAKE_GUARD(mStateLock, enableRefreshRateOverlay(true));
}
}));
}
@@ -937,8 +891,9 @@
FrameEvent::DEQUEUE_READY,
FrameEvent::RELEASE,
};
- ConditionalLock _l(mStateLock,
- std::this_thread::get_id() != mMainThreadId);
+
+ ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
+
if (!getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
}
@@ -1041,13 +996,8 @@
outMode.resolution = ui::Size(width, height);
- if (mEmulatedDisplayDensity) {
- outMode.xDpi = mEmulatedDisplayDensity;
- outMode.yDpi = mEmulatedDisplayDensity;
- } else {
- outMode.xDpi = xDpi;
- outMode.yDpi = yDpi;
- }
+ outMode.xDpi = xDpi;
+ outMode.yDpi = yDpi;
const nsecs_t period = mode->getVsyncPeriod();
outMode.refreshRate = Fps::fromPeriodNsecs(period).getValue();
@@ -1143,7 +1093,7 @@
}
auto future = mScheduler->schedule([=]() -> status_t {
- const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
+ const auto display = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(displayToken));
if (!display) {
ALOGE("Attempt to set allowed display modes for invalid display token %p",
displayToken.get());
@@ -1184,7 +1134,9 @@
return;
}
- const auto upcomingModeInfo = MAIN_THREAD_GUARD(display->getUpcomingActiveMode());
+ const auto upcomingModeInfo =
+ FTL_FAKE_GUARD(kMainThreadContext, display->getUpcomingActiveMode());
+
if (!upcomingModeInfo.mode) {
// There is no pending mode change. This can happen if the active
// display changed and the mode change happened on a different display.
@@ -1203,9 +1155,8 @@
return;
}
- // We just created this display so we can call even if we are not on
- // the main thread
- MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD);
+ // We just created this display so we can call even if we are not on the main thread.
+ ftl::FakeGuard guard(kMainThreadContext);
display->setActiveMode(upcomingModeInfo.mode->getId());
const Fps refreshRate = upcomingModeInfo.mode->getFps();
@@ -1290,8 +1241,10 @@
constraints.seamlessRequired = false;
hal::VsyncPeriodChangeTimeline outTimeline;
- const auto status = MAIN_THREAD_GUARD(
- display->initiateModeChange(*desiredActiveMode, constraints, &outTimeline));
+ const auto status = FTL_FAKE_GUARD(kMainThreadContext,
+ display->initiateModeChange(*desiredActiveMode,
+ constraints, &outTimeline));
+
if (status != NO_ERROR) {
// initiateModeChange may fail if a hotplug event is just about
// to be sent. We just log the error in this case.
@@ -1324,8 +1277,9 @@
}
void SurfaceFlinger::disableExpensiveRendering() {
- auto future = mScheduler->schedule([=]() MAIN_THREAD {
- ATRACE_CALL();
+ const char* const whence = __func__;
+ auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
+ ATRACE_NAME(whence);
if (mPowerAdvisor.isUsingExpensiveRendering()) {
for (const auto& [_, display] : mDisplays) {
constexpr bool kDisable = false;
@@ -1373,7 +1327,7 @@
return BAD_VALUE;
}
- auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t {
+ auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set active color mode %s (%d) for invalid display token %p",
@@ -1408,17 +1362,17 @@
}
status_t SurfaceFlinger::getBootDisplayModeSupport(bool* outSupport) const {
- auto future = mScheduler->schedule([=]() MAIN_THREAD mutable -> status_t {
- *outSupport = getHwComposer().hasCapability(Capability::BOOT_DISPLAY_CONFIG);
- return NO_ERROR;
- });
- return future.get();
+ auto future = mScheduler->schedule(
+ [this] { return getHwComposer().hasCapability(Capability::BOOT_DISPLAY_CONFIG); });
+
+ *outSupport = future.get();
+ return NO_ERROR;
}
status_t SurfaceFlinger::setBootDisplayMode(const sp<IBinder>& displayToken,
ui::DisplayModeId modeId) {
const char* const whence = __func__;
- auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t {
+ auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("%s: Invalid display token %p", whence, displayToken.get());
@@ -1445,7 +1399,7 @@
status_t SurfaceFlinger::clearBootDisplayMode(const sp<IBinder>& displayToken) {
const char* const whence = __func__;
- auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t {
+ auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
return getHwComposer().clearBootDisplayMode(*displayId);
} else {
@@ -1458,7 +1412,7 @@
void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) {
const char* const whence = __func__;
- static_cast<void>(mScheduler->schedule([=]() MAIN_THREAD {
+ static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
getHwComposer().setAutoLowLatencyMode(*displayId, on);
} else {
@@ -1469,7 +1423,7 @@
void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) {
const char* const whence = __func__;
- static_cast<void>(mScheduler->schedule([=]() MAIN_THREAD {
+ static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE;
getHwComposer().setContentType(*displayId, type);
@@ -1534,7 +1488,7 @@
bool enable, uint8_t componentMask,
uint64_t maxFrames) {
const char* const whence = __func__;
- auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t {
+ auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t {
if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) {
return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable,
componentMask, maxFrames);
@@ -1608,10 +1562,10 @@
: BAD_VALUE;
}
-status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) {
+status_t SurfaceFlinger::getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) {
outLayers->clear();
auto future = mScheduler->schedule([=] {
- const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+ const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
mDrawingState.traverseInZOrder([&](Layer* layer) {
outLayers->push_back(layer->getLayerDebugInfo(display.get()));
});
@@ -1723,7 +1677,7 @@
}
const char* const whence = __func__;
- return ftl::chain(mScheduler->schedule([=]() MAIN_THREAD {
+ return ftl::chain(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
if (const auto display = getDisplayDeviceLocked(displayToken)) {
const bool supportsDisplayBrightnessCommand =
getHwComposer().getComposer()->isSupported(
@@ -1737,7 +1691,9 @@
compositionDisplay->editState().displayBrightnessNits;
compositionDisplay->setDisplayBrightness(brightness.sdrWhitePointNits,
brightness.displayBrightnessNits);
- MAIN_THREAD_GUARD(display->stageBrightness(brightness.displayBrightness));
+ FTL_FAKE_GUARD(kMainThreadContext,
+ display->stageBrightness(brightness.displayBrightness));
+
if (brightness.sdrWhitePointNits / brightness.displayBrightnessNits !=
currentDimmingRatio) {
scheduleComposite(FrameHint::kNone);
@@ -1807,6 +1763,7 @@
}
status_t SurfaceFlinger::notifyPowerBoost(int32_t boostId) {
+ using hardware::power::Boost;
Boost powerBoost = static_cast<Boost>(boostId);
if (powerBoost == Boost::INTERACTION) {
@@ -1967,7 +1924,7 @@
ATRACE_CALL();
// On main thread to avoid race conditions with display power state.
- static_cast<void>(mScheduler->schedule([=]() MAIN_THREAD {
+ static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
if (const auto display = getDefaultDisplayDeviceLocked();
@@ -2015,8 +1972,8 @@
: stats.vsyncTime + stats.vsyncPeriod;
}
-bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) {
- MainThreadScopedGuard mainThreadGuard(SF_MAIN_THREAD);
+bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime)
+ FTL_FAKE_GUARD(kMainThreadContext) {
// we set this once at the beginning of commit to ensure consistency throughout the whole frame
mPowerHintSessionData.sessionEnabled = mPowerAdvisor.usePowerHintSession();
if (mPowerHintSessionData.sessionEnabled) {
@@ -2182,20 +2139,21 @@
mLayerTracing.notify(mVisibleRegionsDirty, frameTime);
}
- MAIN_THREAD_GUARD(persistDisplayBrightness(mustComposite));
+ persistDisplayBrightness(mustComposite);
return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER);
}
-void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId) {
+void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId)
+ FTL_FAKE_GUARD(kMainThreadContext) {
ATRACE_FORMAT("%s %" PRId64, __func__, vsyncId);
- MainThreadScopedGuard mainThreadGuard(SF_MAIN_THREAD);
+
if (mPowerHintSessionData.sessionEnabled) {
mPowerHintSessionData.compositeStart = systemTime();
}
compositionengine::CompositionRefreshArgs refreshArgs;
- const auto& displays = ON_MAIN_THREAD(mDisplays);
+ const auto& displays = FTL_FAKE_GUARD(mStateLock, mDisplays);
refreshArgs.outputs.reserve(displays.size());
for (const auto& [_, display] : displays) {
refreshArgs.outputs.push_back(display->getCompositionDisplay());
@@ -2433,7 +2391,7 @@
ATRACE_CALL();
ALOGV("postComposition");
- const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get();
+ const auto* display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get();
getBE().mGlCompositionDoneTimeline.updateSignalTimes();
std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
@@ -2633,44 +2591,37 @@
}
FloatRect SurfaceFlinger::getMaxDisplayBounds() {
- // Find the largest width and height among all the displays.
- int32_t maxDisplayWidth = 0;
- int32_t maxDisplayHeight = 0;
+ const ui::Size maxSize = [this] {
+ ftl::FakeGuard guard(mStateLock);
- // If there are no displays, set a valid display bounds so we can still compute a valid layer
- // bounds.
- if (ON_MAIN_THREAD(mDisplays.size()) == 0) {
- maxDisplayWidth = maxDisplayHeight = 5000;
- }
+ // The LayerTraceGenerator tool runs without displays.
+ if (mDisplays.empty()) return ui::Size{5000, 5000};
- for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
- const auto& displayDevice = pair.second;
- int32_t width = displayDevice->getWidth();
- int32_t height = displayDevice->getHeight();
- if (width > maxDisplayWidth) {
- maxDisplayWidth = width;
- }
- if (height > maxDisplayHeight) {
- maxDisplayHeight = height;
- }
- }
+ return std::accumulate(mDisplays.begin(), mDisplays.end(), ui::kEmptySize,
+ [](ui::Size size, const auto& pair) -> ui::Size {
+ const auto& display = pair.second;
+ return {std::max(size.getWidth(), display->getWidth()),
+ std::max(size.getHeight(), display->getHeight())};
+ });
+ }();
// Ignore display bounds for now since they will be computed later. Use a large Rect bound
// to ensure it's bigger than an actual display will be.
- FloatRect maxBounds = FloatRect(-maxDisplayWidth * 10, -maxDisplayHeight * 10,
- maxDisplayWidth * 10, maxDisplayHeight * 10);
- return maxBounds;
+ const float xMax = maxSize.getWidth() * 10.f;
+ const float yMax = maxSize.getHeight() * 10.f;
+
+ return {-xMax, -yMax, xMax, yMax};
}
void SurfaceFlinger::computeLayerBounds() {
- FloatRect maxBounds = getMaxDisplayBounds();
+ const FloatRect maxBounds = getMaxDisplayBounds();
for (const auto& layer : mDrawingState.layersSortedByZ) {
layer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */);
}
}
void SurfaceFlinger::postFrame() {
- const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+ const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
if (display && getHwComposer().isConnected(display->getPhysicalId())) {
uint32_t flipCount = display->getPageFlipCount();
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
@@ -2924,7 +2875,8 @@
RenderIntent::COLORIMETRIC,
Dataspace::UNKNOWN});
if (!state.isVirtual()) {
- MAIN_THREAD_GUARD(display->setActiveMode(state.physical->activeMode->getId()));
+ FTL_FAKE_GUARD(kMainThreadContext,
+ display->setActiveMode(state.physical->activeMode->getId()));
display->setDeviceProductInfo(state.physical->deviceProductInfo);
}
@@ -3294,7 +3246,7 @@
return;
}
- for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
+ for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
if (const auto brightness = display->getStagedBrightness(); brightness) {
if (!needsComposite) {
const status_t error =
@@ -3317,7 +3269,7 @@
std::vector<DisplayInfo>& outDisplayInfos) {
ftl::SmallMap<ui::LayerStack, DisplayDevice::InputInfo, 4> displayInputInfos;
- for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
+ for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
const auto layerStack = display->getLayerStack();
const auto info = display->getInputInfo();
@@ -3362,7 +3314,7 @@
void SurfaceFlinger::updateCursorAsync() {
compositionengine::CompositionRefreshArgs refreshArgs;
- for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
+ for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
if (HalDisplayId::tryCast(display->getId())) {
refreshArgs.outputs.push_back(display->getCompositionDisplay());
}
@@ -3547,7 +3499,7 @@
}
void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) {
- for (const auto& [token, displayDevice] : ON_MAIN_THREAD(mDisplays)) {
+ for (const auto& [token, displayDevice] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
auto display = displayDevice->getCompositionDisplay();
if (display->includesLayer(layer->getOutputFilter())) {
display->editState().dirtyRegion.orSelf(dirty);
@@ -4535,6 +4487,9 @@
if (what & layer_state_t::eAutoRefreshChanged) {
layer->setAutoRefresh(s.autoRefresh);
}
+ if (what & layer_state_t::eDimmingEnabledChanged) {
+ if (layer->setDimmingEnabled(s.dimmingEnabled)) flags |= eTraversalNeeded;
+ }
if (what & layer_state_t::eTrustedOverlayChanged) {
if (layer->setTrustedOverlay(s.isTrustedOverlay)) {
flags |= eTraversalNeeded;
@@ -4833,7 +4788,8 @@
void SurfaceFlinger::initializeDisplays() {
// Async since we may be called from the main thread.
- static_cast<void>(mScheduler->schedule([this]() MAIN_THREAD { onInitializeDisplays(); }));
+ static_cast<void>(
+ mScheduler->schedule([this]() FTL_FAKE_GUARD(mStateLock) { onInitializeDisplays(); }));
}
void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) {
@@ -4933,7 +4889,7 @@
}
void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
- auto future = mScheduler->schedule([=]() MAIN_THREAD {
+ auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) {
const auto display = getDisplayDeviceLocked(displayToken);
if (!display) {
ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
@@ -4980,7 +4936,7 @@
bool dumpLayers = true;
{
- TimedLock lock(mStateLock, s2ns(1), __FUNCTION__);
+ TimedLock lock(mStateLock, s2ns(1), __func__);
if (!lock.locked()) {
StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n",
strerror(-lock.status), lock.status);
@@ -5068,8 +5024,6 @@
mFrameTimeline->parseArgs(args, result);
}
-// This should only be called from the main thread. Otherwise it would need
-// the lock and should use mCurrentState rather than mDrawingState.
void SurfaceFlinger::logFrameStats() {
mDrawingState.traverse([&](Layer* layer) {
layer->logFrameStats();
@@ -5227,7 +5181,7 @@
}
void SurfaceFlinger::dumpDisplayProto(LayersTraceProto& layersTraceProto) const {
- for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
+ for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
DisplayProto* displayProto = layersTraceProto.add_displays();
displayProto->set_id(display->getId().value);
displayProto->set_name(display->getDisplayName());
@@ -5506,25 +5460,14 @@
#pragma clang diagnostic push
#pragma clang diagnostic error "-Wswitch-enum"
switch (static_cast<ISurfaceComposerTag>(code)) {
- case ENABLE_VSYNC_INJECTIONS:
- case INJECT_VSYNC:
- if (!hasMockHwc()) return PERMISSION_DENIED;
- [[fallthrough]];
// These methods should at minimum make sure that the client requested
// access to SF.
case BOOT_FINISHED:
- case CLEAR_ANIMATION_FRAME_STATS:
- case GET_ANIMATION_FRAME_STATS:
- case OVERRIDE_HDR_TYPES:
case GET_HDR_CAPABILITIES:
case SET_DESIRED_DISPLAY_MODE_SPECS:
case GET_DESIRED_DISPLAY_MODE_SPECS:
- case SET_ACTIVE_COLOR_MODE:
- case SET_BOOT_DISPLAY_MODE:
case GET_AUTO_LOW_LATENCY_MODE_SUPPORT:
case GET_GAME_CONTENT_TYPE_SUPPORT:
- case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
- case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
case GET_DISPLAYED_CONTENT_SAMPLE:
case ADD_TUNNEL_MODE_ENABLED_LISTENER:
case REMOVE_TUNNEL_MODE_ENABLED_LISTENER:
@@ -5541,16 +5484,6 @@
}
return OK;
}
- case GET_LAYER_DEBUG_INFO: {
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
- ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- return OK;
- }
// Used by apps to hook Choreographer to SurfaceFlinger.
case CREATE_DISPLAY_EVENT_CONNECTION:
// The following calls are currently used by clients that do not
@@ -5560,17 +5493,11 @@
case GET_ACTIVE_COLOR_MODE:
case GET_ACTIVE_DISPLAY_MODE:
case GET_DISPLAY_COLOR_MODES:
- case GET_DISPLAY_NATIVE_PRIMARIES:
- case GET_DYNAMIC_DISPLAY_INFO:
case GET_DISPLAY_MODES:
- case GET_SUPPORTED_FRAME_TIMESTAMPS:
// Calling setTransactionState is safe, because you need to have been
// granted a reference to Client* and Handle* to do anything with it.
case SET_TRANSACTION_STATE:
case CREATE_CONNECTION:
- case GET_COLOR_MANAGEMENT:
- case GET_COMPOSITION_PREFERENCE:
- case GET_PROTECTED_CONTENT_SUPPORT:
// setFrameRate() is deliberately available for apps to call without any
// special permissions.
case SET_FRAME_RATE:
@@ -5611,13 +5538,6 @@
}
return PERMISSION_DENIED;
}
- case ON_PULL_ATOM: {
- const int uid = IPCThreadState::self()->getCallingUid();
- if (uid == AID_SYSTEM) {
- return OK;
- }
- return PERMISSION_DENIED;
- }
case ADD_WINDOW_INFOS_LISTENER:
case REMOVE_WINDOW_INFOS_LISTENER: {
const int uid = IPCThreadState::self()->getCallingUid();
@@ -5632,9 +5552,14 @@
case GET_PHYSICAL_DISPLAY_IDS:
case GET_PHYSICAL_DISPLAY_TOKEN:
case SET_POWER_MODE:
+ case GET_SUPPORTED_FRAME_TIMESTAMPS:
case GET_DISPLAY_STATE:
case GET_DISPLAY_STATS:
case GET_STATIC_DISPLAY_INFO:
+ case GET_DYNAMIC_DISPLAY_INFO:
+ case GET_DISPLAY_NATIVE_PRIMARIES:
+ case SET_ACTIVE_COLOR_MODE:
+ case SET_BOOT_DISPLAY_MODE:
case CLEAR_BOOT_DISPLAY_MODE:
case GET_BOOT_DISPLAY_MODE_SUPPORT:
case SET_AUTO_LOW_LATENCY_MODE:
@@ -5642,6 +5567,18 @@
case CAPTURE_LAYERS:
case CAPTURE_DISPLAY:
case CAPTURE_DISPLAY_BY_ID:
+ case CLEAR_ANIMATION_FRAME_STATS:
+ case GET_ANIMATION_FRAME_STATS:
+ case OVERRIDE_HDR_TYPES:
+ case ON_PULL_ATOM:
+ case ENABLE_VSYNC_INJECTIONS:
+ case INJECT_VSYNC:
+ case GET_LAYER_DEBUG_INFO:
+ case GET_COLOR_MANAGEMENT:
+ case GET_COMPOSITION_PREFERENCE:
+ case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
+ case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
+ case GET_PROTECTED_CONTENT_SUPPORT:
case IS_WIDE_COLOR_DISPLAY:
case GET_DISPLAY_BRIGHTNESS_SUPPORT:
case SET_DISPLAY_BRIGHTNESS:
@@ -5858,7 +5795,7 @@
int64_t startingTime =
(fixedStartingTime) ? fixedStartingTime : systemTime();
mScheduler
- ->schedule([&]() MAIN_THREAD {
+ ->schedule([&]() FTL_FAKE_GUARD(mStateLock) {
mLayerTracing.notify("start", startingTime);
})
.wait();
@@ -5971,10 +5908,12 @@
switch (n = data.readInt32()) {
case 0:
case 1:
- ON_MAIN_THREAD(enableRefreshRateOverlay(static_cast<bool>(n)));
+ FTL_FAKE_GUARD(mStateLock,
+ enableRefreshRateOverlay(static_cast<bool>(n)));
break;
default: {
- reply->writeBool(ON_MAIN_THREAD(isRefreshRateOverlayEnabled()));
+ reply->writeBool(
+ FTL_FAKE_GUARD(mStateLock, isRefreshRateOverlayEnabled()));
}
}
});
@@ -6012,7 +5951,7 @@
return mScheduler
->schedule([this] {
const auto display =
- ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+ FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
// This is a little racy, but not in a way that hurts anything. As
// we grab the defaultMode from the display manager policy, we could
@@ -6034,7 +5973,7 @@
return mScheduler
->schedule([this] {
const auto display =
- ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+ FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
constexpr bool kOverridePolicy = true;
return setDesiredDisplayModeSpecsInternal(display, {},
kOverridePolicy);
@@ -6150,7 +6089,7 @@
// Update the overlay on the main thread to avoid race conditions with
// mRefreshRateConfigs->getActiveMode()
static_cast<void>(mScheduler->schedule([=] {
- const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+ const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
if (!display) {
ALOGW("%s: default display is null", __func__);
return;
@@ -6948,7 +6887,7 @@
}
auto future = mScheduler->schedule([=]() -> status_t {
- const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
+ const auto display = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(displayToken));
if (!display) {
ALOGE("Attempt to set desired display modes for invalid display token %p",
displayToken.get());
@@ -7193,7 +7132,7 @@
if (const auto frameRateOverride = mScheduler->getFrameRateOverride(uid)) {
refreshRate = *frameRateOverride;
} else if (!getHwComposer().isHeadless()) {
- if (const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked())) {
+ if (const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked())) {
refreshRate = display->refreshRateConfigs().getActiveMode()->getFps();
}
}
@@ -7413,6 +7352,18 @@
return binder::Status::ok();
}
+binder::Status SurfaceComposerAIDL::getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) {
+ status_t status;
+ if (!outSupported) {
+ status = UNEXPECTED_NULL;
+ } else {
+ outSupported->clear();
+ status = mFlinger->getSupportedFrameTimestamps(outSupported);
+ }
+ return binder::Status::fromStatusT(status);
+}
+
binder::Status SurfaceComposerAIDL::getDisplayStats(const sp<IBinder>& display,
gui::DisplayStatInfo* outStatInfo) {
DisplayStatInfo statInfo;
@@ -7478,6 +7429,99 @@
return binder::Status::fromStatusT(status);
}
+binder::Status SurfaceComposerAIDL::getDynamicDisplayInfo(const sp<IBinder>& display,
+ gui::DynamicDisplayInfo* outInfo) {
+ ui::DynamicDisplayInfo info;
+ status_t status = mFlinger->getDynamicDisplayInfo(display, &info);
+ if (status == NO_ERROR) {
+ // convert ui::DynamicDisplayInfo to gui::DynamicDisplayInfo
+ outInfo->supportedDisplayModes.clear();
+ outInfo->supportedDisplayModes.reserve(info.supportedDisplayModes.size());
+ for (const auto& mode : info.supportedDisplayModes) {
+ gui::DisplayMode outMode;
+ outMode.id = mode.id;
+ outMode.resolution.width = mode.resolution.width;
+ outMode.resolution.height = mode.resolution.height;
+ outMode.xDpi = mode.xDpi;
+ outMode.yDpi = mode.yDpi;
+ outMode.refreshRate = mode.refreshRate;
+ outMode.appVsyncOffset = mode.appVsyncOffset;
+ outMode.sfVsyncOffset = mode.sfVsyncOffset;
+ outMode.presentationDeadline = mode.presentationDeadline;
+ outMode.group = mode.group;
+ outInfo->supportedDisplayModes.push_back(outMode);
+ }
+
+ outInfo->activeDisplayModeId = info.activeDisplayModeId;
+
+ outInfo->supportedColorModes.clear();
+ outInfo->supportedColorModes.reserve(info.supportedColorModes.size());
+ for (const auto& cmode : info.supportedColorModes) {
+ outInfo->supportedColorModes.push_back(static_cast<int32_t>(cmode));
+ }
+
+ outInfo->activeColorMode = static_cast<int32_t>(info.activeColorMode);
+
+ gui::HdrCapabilities& hdrCapabilities = outInfo->hdrCapabilities;
+ hdrCapabilities.supportedHdrTypes.clear();
+ hdrCapabilities.supportedHdrTypes.reserve(
+ info.hdrCapabilities.getSupportedHdrTypes().size());
+ for (const auto& hdr : info.hdrCapabilities.getSupportedHdrTypes()) {
+ hdrCapabilities.supportedHdrTypes.push_back(static_cast<int32_t>(hdr));
+ }
+ hdrCapabilities.maxLuminance = info.hdrCapabilities.getDesiredMaxLuminance();
+ hdrCapabilities.maxAverageLuminance = info.hdrCapabilities.getDesiredMaxAverageLuminance();
+ hdrCapabilities.minLuminance = info.hdrCapabilities.getDesiredMinLuminance();
+
+ outInfo->autoLowLatencyModeSupported = info.autoLowLatencyModeSupported;
+ outInfo->gameContentTypeSupported = info.gameContentTypeSupported;
+ outInfo->preferredBootDisplayMode = info.preferredBootDisplayMode;
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayNativePrimaries(const sp<IBinder>& display,
+ gui::DisplayPrimaries* outPrimaries) {
+ ui::DisplayPrimaries primaries;
+ status_t status = mFlinger->getDisplayNativePrimaries(display, primaries);
+ if (status == NO_ERROR) {
+ outPrimaries->red.X = primaries.red.X;
+ outPrimaries->red.Y = primaries.red.Y;
+ outPrimaries->red.Z = primaries.red.Z;
+
+ outPrimaries->green.X = primaries.green.X;
+ outPrimaries->green.Y = primaries.green.Y;
+ outPrimaries->green.Z = primaries.green.Z;
+
+ outPrimaries->blue.X = primaries.blue.X;
+ outPrimaries->blue.Y = primaries.blue.Y;
+ outPrimaries->blue.Z = primaries.blue.Z;
+
+ outPrimaries->white.X = primaries.white.X;
+ outPrimaries->white.Y = primaries.white.Y;
+ outPrimaries->white.Z = primaries.white.Z;
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setActiveColorMode(const sp<IBinder>& display, int colorMode) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->setActiveColorMode(display, static_cast<ui::ColorMode>(colorMode));
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setBootDisplayMode(const sp<IBinder>& display,
+ int displayModeId) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->setBootDisplayMode(display,
+ static_cast<ui::DisplayModeId>(displayModeId));
+ }
+ return binder::Status::fromStatusT(status);
+}
+
binder::Status SurfaceComposerAIDL::clearBootDisplayMode(const sp<IBinder>& display) {
status_t status = checkAccessPermission();
if (status == OK) {
@@ -7538,6 +7582,168 @@
return binder::Status::fromStatusT(status);
}
+binder::Status SurfaceComposerAIDL::clearAnimationFrameStats() {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->clearAnimationFrameStats();
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getAnimationFrameStats(gui::FrameStats* outStats) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binder::Status::fromStatusT(status);
+ }
+
+ FrameStats stats;
+ status = mFlinger->getAnimationFrameStats(&stats);
+ if (status == NO_ERROR) {
+ outStats->refreshPeriodNano = stats.refreshPeriodNano;
+ outStats->desiredPresentTimesNano.reserve(stats.desiredPresentTimesNano.size());
+ for (const auto& t : stats.desiredPresentTimesNano) {
+ outStats->desiredPresentTimesNano.push_back(t);
+ }
+ outStats->actualPresentTimesNano.reserve(stats.actualPresentTimesNano.size());
+ for (const auto& t : stats.actualPresentTimesNano) {
+ outStats->actualPresentTimesNano.push_back(t);
+ }
+ outStats->frameReadyTimesNano.reserve(stats.frameReadyTimesNano.size());
+ for (const auto& t : stats.frameReadyTimesNano) {
+ outStats->frameReadyTimesNano.push_back(t);
+ }
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<int32_t>& hdrTypes) {
+ // overrideHdrTypes is used by CTS tests, which acquire the necessary
+ // permission dynamically. Don't use the permission cache for this check.
+ status_t status = checkAccessPermission(false);
+ if (status != OK) {
+ return binder::Status::fromStatusT(status);
+ }
+
+ std::vector<ui::Hdr> hdrTypesVector;
+ for (int32_t i : hdrTypes) {
+ hdrTypesVector.push_back(static_cast<ui::Hdr>(i));
+ }
+ status = mFlinger->overrideHdrTypes(display, hdrTypesVector);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::onPullAtom(int32_t atomId, gui::PullAtomData* outPullData) {
+ status_t status;
+ const int uid = IPCThreadState::self()->getCallingUid();
+ if (uid != AID_SYSTEM) {
+ status = PERMISSION_DENIED;
+ } else {
+ status = mFlinger->onPullAtom(atomId, &outPullData->data, &outPullData->success);
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::enableVSyncInjections(bool enable) {
+ if (!mFlinger->hasMockHwc()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->enableVSyncInjections(enable);
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::injectVSync(int64_t when) {
+ if (!mFlinger->hasMockHwc()) {
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->injectVSync(when);
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) {
+ if (!outLayers) {
+ return binder::Status::fromStatusT(UNEXPECTED_NULL);
+ }
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
+ ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
+ return binder::Status::fromStatusT(PERMISSION_DENIED);
+ }
+ status_t status = mFlinger->getLayerDebugInfo(outLayers);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getColorManagement(bool* outGetColorManagement) {
+ status_t status = mFlinger->getColorManagement(outGetColorManagement);
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getCompositionPreference(gui::CompositionPreference* outPref) {
+ ui::Dataspace dataspace;
+ ui::PixelFormat pixelFormat;
+ ui::Dataspace wideColorGamutDataspace;
+ ui::PixelFormat wideColorGamutPixelFormat;
+ status_t status =
+ mFlinger->getCompositionPreference(&dataspace, &pixelFormat, &wideColorGamutDataspace,
+ &wideColorGamutPixelFormat);
+ if (status == NO_ERROR) {
+ outPref->defaultDataspace = static_cast<int32_t>(dataspace);
+ outPref->defaultPixelFormat = static_cast<int32_t>(pixelFormat);
+ outPref->wideColorGamutDataspace = static_cast<int32_t>(wideColorGamutDataspace);
+ outPref->wideColorGamutPixelFormat = static_cast<int32_t>(wideColorGamutPixelFormat);
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayedContentSamplingAttributes(
+ const sp<IBinder>& display, gui::ContentSamplingAttributes* outAttrs) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binder::Status::fromStatusT(status);
+ }
+
+ ui::PixelFormat format;
+ ui::Dataspace dataspace;
+ uint8_t componentMask;
+ status = mFlinger->getDisplayedContentSamplingAttributes(display, &format, &dataspace,
+ &componentMask);
+ if (status == NO_ERROR) {
+ outAttrs->format = static_cast<int32_t>(format);
+ outAttrs->dataspace = static_cast<int32_t>(dataspace);
+ outAttrs->componentMask = static_cast<int8_t>(componentMask);
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setDisplayContentSamplingEnabled(const sp<IBinder>& display,
+ bool enable,
+ int8_t componentMask,
+ int64_t maxFrames) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->setDisplayContentSamplingEnabled(display, enable,
+ static_cast<uint8_t>(componentMask),
+ static_cast<uint64_t>(maxFrames));
+ }
+ return binder::Status::fromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getProtectedContentSupport(bool* outSupported) {
+ status_t status = mFlinger->getProtectedContentSupport(outSupported);
+ return binder::Status::fromStatusT(status);
+}
+
binder::Status SurfaceComposerAIDL::isWideColorDisplay(const sp<IBinder>& token,
bool* outIsWideColorDisplay) {
status_t status = mFlinger->isWideColorDisplay(token, outIsWideColorDisplay);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index bb0bc3f..b32462d 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -32,6 +32,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/ISurfaceComposerClient.h>
#include <gui/ITransactionCompletedListener.h>
+#include <gui/LayerDebugInfo.h>
#include <gui/LayerState.h>
#include <layerproto/LayerProtoHeader.h>
#include <math/mat4.h>
@@ -65,6 +66,7 @@
#include "Scheduler/Scheduler.h"
#include "Scheduler/VsyncModulator.h"
#include "SurfaceFlingerFactory.h"
+#include "ThreadContext.h"
#include "TracedOrdinal.h"
#include "Tracing/LayerTracing.h"
#include "Tracing/TransactionTracing.h"
@@ -184,11 +186,6 @@
std::atomic<nsecs_t> mLastSwapTime = 0;
};
-struct SCOPED_CAPABILITY UnnecessaryLock {
- explicit UnnecessaryLock(Mutex& mutex) ACQUIRE(mutex) {}
- ~UnnecessaryLock() RELEASE() {}
-};
-
class SurfaceFlinger : public BnSurfaceComposer,
public PriorityDumper,
private IBinder::DeathRecipient,
@@ -559,7 +556,7 @@
void bootFinished() override;
bool authenticateSurfaceTexture(
const sp<IGraphicBufferProducer>& bufferProducer) const override;
- status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
+ virtual status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const;
sp<IDisplayEventConnection> createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp,
ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) override;
@@ -574,38 +571,36 @@
status_t getStaticDisplayInfo(const sp<IBinder>& displayToken, ui::StaticDisplayInfo*)
EXCLUDES(mStateLock);
status_t getDynamicDisplayInfo(const sp<IBinder>& displayToken, ui::DynamicDisplayInfo*)
- EXCLUDES(mStateLock) override;
- status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken,
- ui::DisplayPrimaries&) override;
- status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
+ EXCLUDES(mStateLock);
+ status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken, ui::DisplayPrimaries&);
+ status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
status_t getBootDisplayModeSupport(bool* outSupport) const;
- status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id) override;
+ status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id);
status_t clearBootDisplayMode(const sp<IBinder>& displayToken);
void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on);
void setGameContentType(const sp<IBinder>& displayToken, bool on);
void setPowerMode(const sp<IBinder>& displayToken, int mode);
- status_t clearAnimationFrameStats() override;
- status_t getAnimationFrameStats(FrameStats* outStats) const override;
+ status_t clearAnimationFrameStats();
+ status_t getAnimationFrameStats(FrameStats* outStats) const;
status_t overrideHdrTypes(const sp<IBinder>& displayToken,
- const std::vector<ui::Hdr>& hdrTypes) override;
- status_t onPullAtom(const int32_t atomId, std::string* pulledData, bool* success) override;
- status_t enableVSyncInjections(bool enable) override;
- status_t injectVSync(nsecs_t when) override;
- status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override;
- status_t getColorManagement(bool* outGetColorManagement) const override;
+ const std::vector<ui::Hdr>& hdrTypes);
+ status_t onPullAtom(const int32_t atomId, std::string* pulledData, bool* success);
+ status_t enableVSyncInjections(bool enable);
+ status_t injectVSync(nsecs_t when);
+ status_t getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers);
+ status_t getColorManagement(bool* outGetColorManagement) const;
status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
ui::Dataspace* outWideColorGamutDataspace,
- ui::PixelFormat* outWideColorGamutPixelFormat) const override;
+ ui::PixelFormat* outWideColorGamutPixelFormat) const;
status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& displayToken,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const override;
+ uint8_t* outComponentMask) const;
status_t setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken, bool enable,
- uint8_t componentMask, uint64_t maxFrames) override;
+ uint8_t componentMask, uint64_t maxFrames);
status_t getDisplayedContentSample(const sp<IBinder>& displayToken, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const override;
- status_t getProtectedContentSupport(bool* outSupported) const override;
+ uint64_t timestamp, DisplayedFrameStats* outStats) const;
+ status_t getProtectedContentSupport(bool* outSupported) const;
status_t isWideColorDisplay(const sp<IBinder>& displayToken, bool* outIsWideColorDisplay) const;
status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) override;
@@ -752,7 +747,7 @@
void updateLayerGeometry();
void updateInputFlinger();
- void persistDisplayBrightness(bool needsComposite) REQUIRES(SF_MAIN_THREAD);
+ void persistDisplayBrightness(bool needsComposite) REQUIRES(kMainThreadContext);
void buildWindowInfos(std::vector<gui::WindowInfo>& outWindowInfos,
std::vector<gui::DisplayInfo>& outDisplayInfos);
void commitInputWindowCommands() REQUIRES(mStateLock);
@@ -985,7 +980,7 @@
void setCompositorTimingSnapped(const DisplayStatInfo& stats,
nsecs_t compositeToPresentLatency);
- void postFrame();
+ void postFrame() REQUIRES(kMainThreadContext);
/*
* Display management
@@ -1100,7 +1095,7 @@
void clearStatsLocked(const DumpArgs& args, std::string& result);
void dumpTimeStats(const DumpArgs& args, bool asProto, std::string& result) const;
void dumpFrameTimeline(const DumpArgs& args, std::string& result) const;
- void logFrameStats();
+ void logFrameStats() REQUIRES(kMainThreadContext);
void dumpVSync(std::string& result) const REQUIRES(mStateLock);
void dumpStaticScreenStats(std::string& result) const;
@@ -1443,7 +1438,7 @@
nsecs_t commitStart;
nsecs_t compositeStart;
nsecs_t presentEnd;
- } mPowerHintSessionData GUARDED_BY(SF_MAIN_THREAD);
+ } mPowerHintSessionData GUARDED_BY(kMainThreadContext);
nsecs_t mAnimationTransactionTimeout = s2ns(5);
@@ -1461,12 +1456,19 @@
binder::Status getPrimaryPhysicalDisplayId(int64_t* outDisplayId) override;
binder::Status getPhysicalDisplayToken(int64_t displayId, sp<IBinder>* outDisplay) override;
binder::Status setPowerMode(const sp<IBinder>& display, int mode) override;
+ binder::Status getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) override;
binder::Status getDisplayStats(const sp<IBinder>& display,
gui::DisplayStatInfo* outStatInfo) override;
binder::Status getDisplayState(const sp<IBinder>& display,
gui::DisplayState* outState) override;
binder::Status getStaticDisplayInfo(const sp<IBinder>& display,
gui::StaticDisplayInfo* outInfo) override;
+ binder::Status getDynamicDisplayInfo(const sp<IBinder>& display,
+ gui::DynamicDisplayInfo* outInfo) override;
+ binder::Status getDisplayNativePrimaries(const sp<IBinder>& display,
+ gui::DisplayPrimaries* outPrimaries) override;
+ binder::Status setActiveColorMode(const sp<IBinder>& display, int colorMode) override;
+ binder::Status setBootDisplayMode(const sp<IBinder>& display, int displayModeId) override;
binder::Status clearBootDisplayMode(const sp<IBinder>& display) override;
binder::Status getBootDisplayModeSupport(bool* outMode) override;
binder::Status setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override;
@@ -1476,6 +1478,22 @@
binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override;
binder::Status captureLayers(const LayerCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
+ binder::Status clearAnimationFrameStats() override;
+ binder::Status getAnimationFrameStats(gui::FrameStats* outStats) override;
+ binder::Status overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<int32_t>& hdrTypes) override;
+ binder::Status onPullAtom(int32_t atomId, gui::PullAtomData* outPullData) override;
+ binder::Status enableVSyncInjections(bool enable) override;
+ binder::Status injectVSync(int64_t when) override;
+ binder::Status getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) override;
+ binder::Status getColorManagement(bool* outGetColorManagement) override;
+ binder::Status getCompositionPreference(gui::CompositionPreference* outPref) override;
+ binder::Status getDisplayedContentSamplingAttributes(
+ const sp<IBinder>& display, gui::ContentSamplingAttributes* outAttrs) override;
+ binder::Status setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ int8_t componentMask,
+ int64_t maxFrames) override;
+ binder::Status getProtectedContentSupport(bool* outSupporte) override;
binder::Status isWideColorDisplay(const sp<IBinder>& token,
bool* outIsWideColorDisplay) override;
binder::Status getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/services/surfaceflinger/ThreadContext.h
similarity index 65%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to services/surfaceflinger/ThreadContext.h
index d75777b..85c379d 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/services/surfaceflinger/ThreadContext.h
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-package android.gui;
+#pragma once
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+namespace android {
-/** @hide */
-parcelable DisplayModelId {
- int id;
-}
+// Enforces exclusive access by the main thread.
+constexpr class [[clang::capability("mutex")]] {
+} kMainThreadContext;
+
+} // namespace android
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index a1374e5..e8ecf2f 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -430,7 +430,7 @@
bufferProto.height(), bufferProto.pixel_format(),
bufferProto.usage()));
layer.bufferData->frameNumber = bufferProto.frame_number();
- layer.bufferData->flags = Flags<BufferData::BufferDataChange>(bufferProto.flags());
+ layer.bufferData->flags = ftl::Flags<BufferData::BufferDataChange>(bufferProto.flags());
layer.bufferData->cachedBuffer.id = bufferProto.cached_buffer_id();
layer.bufferData->acquireFence = Fence::NO_FENCE;
}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 1d0f62b..a80aca2 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -22,6 +22,7 @@
#include <compositionengine/impl/CompositionEngine.h>
#include <compositionengine/impl/Display.h>
#include <compositionengine/impl/OutputLayerCompositionState.h>
+#include <ftl/fake_guard.h>
#include <gui/LayerDebugInfo.h>
#include <gui/ScreenCaptureResults.h>
#include <gui/SurfaceComposerClient.h>
@@ -50,6 +51,7 @@
#include "SurfaceFlinger.h"
#include "SurfaceFlingerDefaultFactory.h"
#include "SurfaceInterceptor.h"
+#include "ThreadContext.h"
#include "TimeStats/TimeStats.h"
#include "renderengine/mock/RenderEngine.h"
@@ -445,7 +447,7 @@
mFlinger->clearStatsLocked(dumpArgs, result);
mFlinger->dumpTimeStats(dumpArgs, fdp->ConsumeBool(), result);
- mFlinger->logFrameStats();
+ FTL_FAKE_GUARD(kMainThreadContext, mFlinger->logFrameStats());
result = fdp->ConsumeRandomLengthString().c_str();
mFlinger->dumpFrameTimeline(dumpArgs, result);
@@ -651,7 +653,7 @@
updateCompositorTiming(&mFdp);
mFlinger->setCompositorTimingSnapped({}, mFdp.ConsumeIntegral<nsecs_t>());
- mFlinger->postFrame();
+ FTL_FAKE_GUARD(kMainThreadContext, mFlinger->postFrame());
mFlinger->calculateExpectedPresentTime({});
mFlinger->enableHalVirtualDisplays(mFdp.ConsumeBool());
diff --git a/services/surfaceflinger/tests/BootDisplayMode_test.cpp b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
index d70908e..4cd6ef8 100644
--- a/services/surfaceflinger/tests/BootDisplayMode_test.cpp
+++ b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
@@ -26,14 +26,14 @@
namespace android {
TEST(BootDisplayModeTest, setBootDisplayMode) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<gui::ISurfaceComposer> sf_aidl(ComposerServiceAIDL::getComposerService());
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
bool bootModeSupport = false;
- binder::Status status = sf_aidl->getBootDisplayModeSupport(&bootModeSupport);
+ binder::Status status = sf->getBootDisplayModeSupport(&bootModeSupport);
ASSERT_NO_FATAL_FAILURE(status.transactionError());
if (bootModeSupport) {
- ASSERT_EQ(NO_ERROR, sf->setBootDisplayMode(displayToken, 0));
+ status = sf->setBootDisplayMode(displayToken, 0);
+ ASSERT_EQ(NO_ERROR, status.transactionError());
}
}
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index d33bc10..6549a22 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -18,13 +18,13 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
+#include <android/gui/ISurfaceComposer.h>
#include <gtest/gtest.h>
-#include <gui/ISurfaceComposer.h>
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/android_filesystem_config.h>
-#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
#include <ui/DynamicDisplayInfo.h>
#include <utils/String8.h>
@@ -34,6 +34,7 @@
namespace android {
using Transaction = SurfaceComposerClient::Transaction;
+using gui::LayerDebugInfo;
using ui::ColorMode;
namespace {
@@ -307,23 +308,26 @@
*/
TEST_F(CredentialsTest, GetLayerDebugInfo) {
setupBackgroundSurface();
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
// Historically, only root and shell can access the getLayerDebugInfo which
// is called when we call dumpsys. I don't see a reason why we should change this.
std::vector<LayerDebugInfo> outLayers;
// Check with root.
seteuid(AID_ROOT);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ binder::Status status = sf->getLayerDebugInfo(&outLayers);
+ ASSERT_EQ(NO_ERROR, status.transactionError());
// Check as a shell.
seteuid(AID_SHELL);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ status = sf->getLayerDebugInfo(&outLayers);
+ ASSERT_EQ(NO_ERROR, status.transactionError());
// Check as anyone else.
seteuid(AID_ROOT);
seteuid(AID_BIN);
- ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
+ status = sf->getLayerDebugInfo(&outLayers);
+ ASSERT_EQ(PERMISSION_DENIED, status.transactionError());
}
TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 6bd7920..43386b2 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -26,6 +26,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
#include "BufferGenerator.h"
@@ -44,8 +45,9 @@
ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed));
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ binder::Status status = sf->getColorManagement(&mColorManagementUsed);
+ ASSERT_NO_FATAL_FAILURE(status.transactionError());
mCaptureArgs.displayToken = mDisplay;
}
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 168b576..704815d 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -28,6 +28,7 @@
"android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.mapper@4.0",
"android.hardware.power@1.3",
+ "android.hardware.power-V2-cpp",
"libbase",
"libbinder",
"libbinder_ndk",
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index b3b4ec1..12e5d46 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -43,6 +43,7 @@
#include <hwbinder/ProcessState.h>
#include <log/log.h>
#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
#include <ui/DynamicDisplayInfo.h>
#include <utils/Looper.h>
@@ -992,7 +993,7 @@
// Tests that VSYNC injection can be safely toggled while invalidating.
TEST_F(DisplayTest_2_1, VsyncInjection) {
- const auto flinger = ComposerService::getComposerService();
+ const auto flinger = ComposerServiceAIDL::getComposerService();
bool enable = true;
for (int i = 0; i < 100; i++) {
@@ -1238,9 +1239,10 @@
sFakeComposer->clearFrames();
ASSERT_EQ(0, sFakeComposer->getFrameCount());
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- std::vector<LayerDebugInfo> layers;
- status_t result = sf->getLayerDebugInfo(&layers);
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ std::vector<gui::LayerDebugInfo> layers;
+ binder::Status status = sf->getLayerDebugInfo(&layers);
+ status_t result = status.transactionError();
if (result != NO_ERROR) {
ALOGE("Failed to get layers %s %d", strerror(-result), result);
} else {
diff --git a/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp b/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp
new file mode 100644
index 0000000..e25a0ae
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/AidlPowerHalWrapperTest.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "AidlPowerHalWrapperTest"
+
+#include <android/hardware/power/IPower.h>
+#include <android/hardware/power/IPowerHintSession.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <chrono>
+#include <memory>
+#include "DisplayHardware/PowerAdvisor.h"
+#include "android/hardware/power/WorkDuration.h"
+#include "binder/Status.h"
+#include "log/log_main.h"
+#include "mock/DisplayHardware/MockIPower.h"
+#include "mock/DisplayHardware/MockIPowerHintSession.h"
+#include "utils/Timers.h"
+
+using namespace android;
+using namespace android::Hwc2::mock;
+using namespace android::hardware::power;
+using namespace std::chrono_literals;
+using namespace testing;
+
+namespace android::Hwc2::impl {
+
+class AidlPowerHalWrapperTest : public testing::Test {
+public:
+ void SetUp() override;
+
+protected:
+ std::unique_ptr<AidlPowerHalWrapper> mWrapper = nullptr;
+ sp<NiceMock<MockIPower>> mMockHal = nullptr;
+ sp<NiceMock<MockIPowerHintSession>> mMockSession = nullptr;
+ void verifyAndClearExpectations();
+ void sendActualWorkDurationGroup(std::vector<WorkDuration> durations,
+ std::chrono::nanoseconds sleepBeforeLastSend);
+};
+
+void AidlPowerHalWrapperTest::SetUp() {
+ mMockHal = new NiceMock<MockIPower>();
+ mMockSession = new NiceMock<MockIPowerHintSession>();
+ ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_)).WillByDefault(Return(Status::ok()));
+ mWrapper = std::make_unique<AidlPowerHalWrapper>(mMockHal);
+}
+
+void AidlPowerHalWrapperTest::verifyAndClearExpectations() {
+ Mock::VerifyAndClearExpectations(mMockHal.get());
+ Mock::VerifyAndClearExpectations(mMockSession.get());
+}
+
+void AidlPowerHalWrapperTest::sendActualWorkDurationGroup(
+ std::vector<WorkDuration> durations, std::chrono::nanoseconds sleepBeforeLastSend) {
+ for (size_t i = 0; i < durations.size(); i++) {
+ if (i == durations.size() - 1) {
+ std::this_thread::sleep_for(sleepBeforeLastSend);
+ }
+ auto duration = durations[i];
+ mWrapper->sendActualWorkDuration(duration.durationNanos, duration.timeStampNanos);
+ }
+}
+WorkDuration toWorkDuration(std::chrono::nanoseconds durationNanos, int64_t timeStampNanos) {
+ WorkDuration duration;
+ duration.durationNanos = durationNanos.count();
+ duration.timeStampNanos = timeStampNanos;
+ return duration;
+}
+
+namespace {
+TEST_F(AidlPowerHalWrapperTest, supportsPowerHintSession) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+ Mock::VerifyAndClearExpectations(mMockHal.get());
+ ON_CALL(*mMockHal.get(), getHintSessionPreferredRate(_))
+ .WillByDefault(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
+ auto newWrapper = AidlPowerHalWrapper(mMockHal);
+ EXPECT_FALSE(newWrapper.supportsPowerHintSession());
+}
+
+TEST_F(AidlPowerHalWrapperTest, startPowerHintSession) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+ std::vector<int32_t> threadIds = {1, 2};
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ EXPECT_TRUE(mWrapper->startPowerHintSession());
+ EXPECT_FALSE(mWrapper->startPowerHintSession());
+}
+
+TEST_F(AidlPowerHalWrapperTest, restartNewPoserHintSessionWithNewThreadIds) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+
+ std::vector<int32_t> threadIds = {1, 2};
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_EQ(mWrapper->getPowerHintSessionThreadIds(), threadIds);
+ ASSERT_TRUE(mWrapper->startPowerHintSession());
+ verifyAndClearExpectations();
+
+ threadIds = {2, 3};
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ EXPECT_CALL(*mMockSession.get(), close()).Times(1);
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_EQ(mWrapper->getPowerHintSessionThreadIds(), threadIds);
+ verifyAndClearExpectations();
+
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _)).Times(0);
+ EXPECT_CALL(*mMockSession.get(), close()).Times(0);
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ verifyAndClearExpectations();
+}
+
+TEST_F(AidlPowerHalWrapperTest, setTargetWorkDuration) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+
+ std::vector<int32_t> threadIds = {1, 2};
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ ASSERT_TRUE(mWrapper->startPowerHintSession());
+ verifyAndClearExpectations();
+
+ std::chrono::nanoseconds base = 100ms;
+ // test cases with target work duration and whether it should update hint against baseline 100ms
+ const std::vector<std::pair<std::chrono::nanoseconds, bool>> testCases = {{0ms, false},
+ {-1ms, false},
+ {200ms, true},
+ {2ms, true},
+ {96ms, false},
+ {104ms, false}};
+
+ for (const auto& test : testCases) {
+ // reset to 100ms baseline
+ mWrapper->setTargetWorkDuration(1);
+ mWrapper->setTargetWorkDuration(base.count());
+
+ auto target = test.first;
+ EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(target.count()))
+ .Times(test.second ? 1 : 0);
+ mWrapper->setTargetWorkDuration(target.count());
+ verifyAndClearExpectations();
+ }
+}
+
+TEST_F(AidlPowerHalWrapperTest, setTargetWorkDuration_shouldReconnectOnError) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+
+ std::vector<int32_t> threadIds = {1, 2};
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ ASSERT_TRUE(mWrapper->startPowerHintSession());
+ verifyAndClearExpectations();
+
+ EXPECT_CALL(*mMockSession.get(), updateTargetWorkDuration(1))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
+ mWrapper->setTargetWorkDuration(1);
+ EXPECT_TRUE(mWrapper->shouldReconnectHAL());
+}
+
+TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+
+ std::vector<int32_t> threadIds = {1, 2};
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ ASSERT_TRUE(mWrapper->startPowerHintSession());
+ verifyAndClearExpectations();
+
+ auto base = toWorkDuration(100ms, 0);
+ // test cases with actual work durations and whether it should update hint against baseline
+ // 100ms
+ const std::vector<std::pair<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, bool>>
+ testCases = {{{{-1ms, 100}}, false},
+ {{{91ms, 100}}, false},
+ {{{109ms, 100}}, false},
+ {{{100ms, 100}, {200ms, 200}}, true},
+ {{{100ms, 500}, {100ms, 600}, {3ms, 600}}, true}};
+
+ for (const auto& test : testCases) {
+ // reset actual duration
+ sendActualWorkDurationGroup({base}, 80ms);
+
+ auto raw = test.first;
+ std::vector<WorkDuration> durations(raw.size());
+ std::transform(raw.begin(), raw.end(), durations.begin(),
+ [](std::pair<std::chrono::nanoseconds, nsecs_t> d) {
+ return toWorkDuration(d.first, d.second);
+ });
+ EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations))
+ .Times(test.second ? 1 : 0);
+ sendActualWorkDurationGroup(durations, 0ms);
+ verifyAndClearExpectations();
+ }
+}
+
+TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_exceedsStaleTime) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+
+ std::vector<int32_t> threadIds = {1, 2};
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ ASSERT_TRUE(mWrapper->startPowerHintSession());
+ verifyAndClearExpectations();
+
+ auto base = toWorkDuration(100ms, 0);
+ // test cases with actual work durations and whether it should update hint against baseline
+ // 100ms
+ const std::vector<std::pair<std::vector<std::pair<std::chrono::nanoseconds, nsecs_t>>, bool>>
+ testCases = {{{{91ms, 100}}, true}, {{{109ms, 100}}, true}};
+
+ for (const auto& test : testCases) {
+ // reset actual duration
+ sendActualWorkDurationGroup({base}, 80ms);
+
+ auto raw = test.first;
+ std::vector<WorkDuration> durations(raw.size());
+ std::transform(raw.begin(), raw.end(), durations.begin(),
+ [](std::pair<std::chrono::nanoseconds, nsecs_t> d) {
+ return toWorkDuration(d.first, d.second);
+ });
+ EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(durations))
+ .Times(test.second ? 1 : 0);
+ sendActualWorkDurationGroup(durations, 80ms);
+ verifyAndClearExpectations();
+ }
+}
+
+TEST_F(AidlPowerHalWrapperTest, sendActualWorkDuration_shouldReconnectOnError) {
+ ASSERT_TRUE(mWrapper->supportsPowerHintSession());
+
+ std::vector<int32_t> threadIds = {1, 2};
+ mWrapper->setPowerHintSessionThreadIds(threadIds);
+ EXPECT_CALL(*mMockHal.get(), createHintSession(_, _, threadIds, _, _))
+ .WillOnce(DoAll(SetArgPointee<4>(mMockSession), Return(Status::ok())));
+ ASSERT_TRUE(mWrapper->startPowerHintSession());
+ verifyAndClearExpectations();
+ WorkDuration duration;
+ duration.durationNanos = 1;
+ EXPECT_CALL(*mMockSession.get(), reportActualWorkDuration(_))
+ .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_ILLEGAL_STATE)));
+ sendActualWorkDurationGroup({duration}, 0ms);
+ EXPECT_TRUE(mWrapper->shouldReconnectHAL());
+}
+
+} // namespace
+} // namespace android::Hwc2::impl
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 1eea023..cc9d48c 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -26,6 +26,8 @@
srcs: [
"mock/DisplayHardware/MockComposer.cpp",
"mock/DisplayHardware/MockHWC2.cpp",
+ "mock/DisplayHardware/MockIPower.cpp",
+ "mock/DisplayHardware/MockIPowerHintSession.cpp",
"mock/DisplayHardware/MockPowerAdvisor.cpp",
"mock/MockEventThread.cpp",
"mock/MockFrameTimeline.cpp",
@@ -67,6 +69,7 @@
":libsurfaceflinger_mock_sources",
":libsurfaceflinger_sources",
"libsurfaceflinger_unittest_main.cpp",
+ "AidlPowerHalWrapperTest.cpp",
"CachingTest.cpp",
"CompositionTest.cpp",
"DispSyncSourceTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp
index 73c60e1..225ad16 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp
@@ -19,6 +19,7 @@
#include "DisplayTransactionTestHelpers.h"
+#include <ftl/fake_guard.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -35,7 +36,7 @@
};
TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessNoComposite) {
- MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD);
+ ftl::FakeGuard guard(kMainThreadContext);
sp<DisplayDevice> displayDevice = getDisplayDevice();
EXPECT_EQ(std::nullopt, displayDevice->getStagedBrightness());
@@ -52,7 +53,7 @@
}
TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessWithComposite) {
- MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD);
+ ftl::FakeGuard guard(kMainThreadContext);
sp<DisplayDevice> displayDevice = getDisplayDevice();
EXPECT_EQ(std::nullopt, displayDevice->getStagedBrightness());
@@ -70,7 +71,7 @@
}
TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessWithCompositeShortCircuitsOnNoOp) {
- MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD);
+ ftl::FakeGuard guard(kMainThreadContext);
sp<DisplayDevice> displayDevice = getDisplayDevice();
EXPECT_EQ(std::nullopt, displayDevice->getStagedBrightness());
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 14d8f98..fa36d9c 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -34,12 +34,13 @@
using namespace std::chrono_literals;
using namespace std::placeholders;
-using namespace android::flag_operators;
using testing::_;
using testing::Invoke;
namespace android {
+using namespace ftl::flag_operators;
+
namespace {
constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = PhysicalDisplayId::fromPort(111u);
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.cpp
similarity index 65%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.cpp
index d75777b..2323ebb 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.cpp
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-package android.gui;
+#include "mock/DisplayHardware/MockIPower.h"
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+namespace android::Hwc2::mock {
-/** @hide */
-parcelable DisplayModelId {
- int id;
-}
+// Explicit default instantiation is recommended.
+MockIPower::MockIPower() = default;
+
+} // namespace android::Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.h
new file mode 100644
index 0000000..0ddc90d
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPower.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "binder/Status.h"
+
+#include <android/hardware/power/IPower.h>
+#include <gmock/gmock.h>
+
+using android::binder::Status;
+using android::hardware::power::Boost;
+using android::hardware::power::IPower;
+using android::hardware::power::IPowerHintSession;
+using android::hardware::power::Mode;
+
+namespace android::Hwc2::mock {
+
+class MockIPower : public IPower {
+public:
+ MockIPower();
+
+ MOCK_METHOD(Status, isBoostSupported, (Boost boost, bool* ret), (override));
+ MOCK_METHOD(Status, setBoost, (Boost boost, int32_t durationMs), (override));
+ MOCK_METHOD(Status, isModeSupported, (Mode mode, bool* ret), (override));
+ MOCK_METHOD(Status, setMode, (Mode mode, bool enabled), (override));
+ MOCK_METHOD(Status, createHintSession,
+ (int32_t tgid, int32_t uid, const std::vector<int32_t>& threadIds,
+ int64_t durationNanos, sp<IPowerHintSession>* session),
+ (override));
+ MOCK_METHOD(Status, getHintSessionPreferredRate, (int64_t * rate), (override));
+ MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
+ MOCK_METHOD(std::string, getInterfaceHash, (), (override));
+ MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+};
+
+} // namespace android::Hwc2::mock
diff --git a/libs/gui/aidl/android/gui/DisplayModelId.aidl b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.cpp
similarity index 65%
copy from libs/gui/aidl/android/gui/DisplayModelId.aidl
copy to services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.cpp
index d75777b..770bc15 100644
--- a/libs/gui/aidl/android/gui/DisplayModelId.aidl
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.cpp
@@ -14,13 +14,11 @@
* limitations under the License.
*/
-package android.gui;
+#include "mock/DisplayHardware/MockIPowerHintSession.h"
-// Product-specific information about the display or the directly connected device on the
-// display chain. For example, if the display is transitively connected, this field may contain
-// product information about the intermediate device.
+namespace android::Hwc2::mock {
-/** @hide */
-parcelable DisplayModelId {
- int id;
-}
+// Explicit default instantiation is recommended.
+MockIPowerHintSession::MockIPowerHintSession() = default;
+
+} // namespace android::Hwc2::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h
new file mode 100644
index 0000000..439f6f4
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockIPowerHintSession.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "binder/Status.h"
+
+#include <android/hardware/power/IPower.h>
+#include <gmock/gmock.h>
+
+using android::binder::Status;
+using android::hardware::power::IPowerHintSession;
+
+using namespace android::hardware::power;
+
+namespace android::Hwc2::mock {
+
+class MockIPowerHintSession : public IPowerHintSession {
+public:
+ MockIPowerHintSession();
+
+ MOCK_METHOD(IBinder*, onAsBinder, (), (override));
+ MOCK_METHOD(Status, pause, (), (override));
+ MOCK_METHOD(Status, resume, (), (override));
+ MOCK_METHOD(Status, close, (), (override));
+ MOCK_METHOD(int32_t, getInterfaceVersion, (), (override));
+ MOCK_METHOD(std::string, getInterfaceHash, (), (override));
+ MOCK_METHOD(Status, updateTargetWorkDuration, (int64_t), (override));
+ MOCK_METHOD(Status, reportActualWorkDuration, (const ::std::vector<WorkDuration>&), (override));
+};
+
+} // namespace android::Hwc2::mock