summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PREUPLOAD.cfg1
-rw-r--r--cmds/atrace/atrace.rc27
-rw-r--r--cmds/dumpstate/dumpstate.cpp8
-rw-r--r--include/input/PropertyMap.h7
-rw-r--r--libs/binder/RecordedTransaction.cpp3
-rw-r--r--libs/binder/RpcState.cpp38
-rw-r--r--libs/binder/RpcState.h20
-rw-r--r--libs/binder/TEST_MAPPING5
-rw-r--r--libs/binder/include/binder/RpcSession.h3
-rw-r--r--libs/binder/rust/src/binder.rs9
-rw-r--r--libs/binder/tests/IBinderRpcTest.aidl4
-rw-r--r--libs/binder/tests/binderRpcBenchmark.cpp8
-rw-r--r--libs/binder/tests/binderRpcTest.cpp91
-rw-r--r--libs/binder/tests/binderRpcTestCommon.h12
-rw-r--r--libs/binder/tests/binderRpcTestFixture.h15
-rw-r--r--libs/binder/tests/binderRpcTestService.cpp12
-rw-r--r--libs/binder/tests/binderRpcTestTrusty.cpp4
-rw-r--r--libs/binder/tests/binderRpcUniversalTests.cpp13
-rw-r--r--libs/binderdebug/Android.bp11
-rw-r--r--libs/binderdebug/stats.cpp62
-rw-r--r--libs/ftl/Android.bp3
-rw-r--r--libs/ftl/TEST_MAPPING12
-rw-r--r--libs/input/Android.bp1
-rw-r--r--libs/input/PropertyMap.cpp29
-rw-r--r--libs/input/TfLiteMotionPredictor.cpp18
-rw-r--r--services/gpuservice/tests/unittests/Android.bp3
-rw-r--r--services/inputflinger/reader/InputDevice.cpp11
-rw-r--r--services/inputflinger/reader/mapper/TouchpadInputMapper.cpp6
-rw-r--r--services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp76
-rw-r--r--services/inputflinger/reader/mapper/gestures/PropertyProvider.h6
-rw-r--r--services/inputflinger/tests/InputReader_test.cpp16
-rw-r--r--services/inputflinger/tests/PropertyProvider_test.cpp65
-rw-r--r--services/inputflinger/tests/TestConstants.h4
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp1
-rw-r--r--services/surfaceflinger/FrontEnd/DisplayInfo.h1
-rw-r--r--services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp6
-rw-r--r--services/surfaceflinger/FrontEnd/LayerCreationArgs.h4
-rw-r--r--services/surfaceflinger/FrontEnd/LayerHierarchy.h10
-rw-r--r--services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp6
-rw-r--r--services/surfaceflinger/FrontEnd/LayerLifecycleManager.h5
-rw-r--r--services/surfaceflinger/FrontEnd/LayerSnapshot.cpp11
-rw-r--r--services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h14
-rw-r--r--services/surfaceflinger/FrontEnd/Update.h52
-rw-r--r--services/surfaceflinger/LayerProtoHelper.cpp127
-rw-r--r--services/surfaceflinger/LayerProtoHelper.h44
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp105
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h33
-rw-r--r--services/surfaceflinger/Tracing/LayerTracing.cpp25
-rw-r--r--services/surfaceflinger/Tracing/LayerTracing.h10
-rw-r--r--services/surfaceflinger/Tracing/TransactionProtoParser.cpp256
-rw-r--r--services/surfaceflinger/Tracing/TransactionProtoParser.h51
-rw-r--r--services/surfaceflinger/Tracing/TransactionTracing.cpp302
-rw-r--r--services/surfaceflinger/Tracing/TransactionTracing.h54
-rw-r--r--services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp295
-rw-r--r--services/surfaceflinger/Tracing/tools/main.cpp3
-rw-r--r--services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h3
-rw-r--r--services/surfaceflinger/layerproto/layers.proto2
-rw-r--r--services/surfaceflinger/layerproto/transactions.proto56
-rw-r--r--services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp20
-rw-r--r--services/surfaceflinger/tests/tracing/testdata/layers_trace_boot.winscopebin25386 -> 24186 bytes
-rw-r--r--services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscopebin1047029 -> 24243 bytes
-rw-r--r--services/surfaceflinger/tests/tracing/testdata/transactions_trace_boot.winscopebin25740 -> 354133 bytes
-rw-r--r--services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscopebin554577 -> 383550 bytes
-rw-r--r--services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp24
-rw-r--r--services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp121
65 files changed, 1299 insertions, 945 deletions
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index c71c4a0251..39eb4abb39 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -14,6 +14,7 @@ clang_format = --commit ${PREUPLOAD_COMMIT} --style file --extensions c,h,cc,cpp
include/powermanager/
libs/binder/fuzzer/
libs/binder/
+ libs/binderdebug/
libs/binderthreadstate/
libs/graphicsenv/
libs/gui/
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 95f5c03a37..e66cc412f0 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -501,6 +501,33 @@ on late-init && property:ro.boot.hypervisor.vm.supported=1
chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/hyp_exit/id
chmod 0440 /sys/kernel/tracing/hyp/events/hyp/hyp_exit/id
+# host_hcall event
+ chmod 0660 /sys/kernel/debug/tracing/hyp/events/hyp/host_hcall/enable
+ chmod 0660 /sys/kernel/tracing/hyp/events/hyp/host_hcall/enable
+# TODO(b/249050813): should this be handled in kernel?
+ chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/host_hcall/format
+ chmod 0440 /sys/kernel/tracing/hyp/events/hyp/host_hcall/format
+ chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/host_hcall/id
+ chmod 0440 /sys/kernel/tracing/hyp/events/hyp/host_hcall/id
+
+# host_smc event
+ chmod 0660 /sys/kernel/debug/tracing/hyp/events/hyp/host_smc/enable
+ chmod 0660 /sys/kernel/tracing/hyp/events/hyp/host_smc/enable
+# TODO(b/249050813): should this be handled in kernel?
+ chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/host_smc/format
+ chmod 0440 /sys/kernel/tracing/hyp/events/hyp/host_smc/format
+ chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/host_smc/id
+ chmod 0440 /sys/kernel/tracing/hyp/events/hyp/host_smc/id
+
+# host_mem_abort event
+ chmod 0660 /sys/kernel/debug/tracing/hyp/events/hyp/host_mem_abort/enable
+ chmod 0660 /sys/kernel/tracing/hyp/events/hyp/host_mem_abort/enable
+# TODO(b/249050813): should this be handled in kernel?
+ chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/host_mem_abort/format
+ chmod 0440 /sys/kernel/tracing/hyp/events/hyp/host_mem_abort/format
+ chmod 0440 /sys/kernel/debug/tracing/hyp/events/hyp/host_mem_abort/id
+ chmod 0440 /sys/kernel/tracing/hyp/events/hyp/host_mem_abort/id
+
on property:persist.debug.atrace.boottrace=1
start boottrace
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 23cdd10a25..6f84e7c0ac 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1254,8 +1254,9 @@ static Dumpstate::RunStatus RunDumpsysTextByPriority(const std::string& title, i
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
dumpsys.writeDumpFooter(STDOUT_FILENO, service, std::chrono::milliseconds(1));
} else {
- status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP, service, args);
- if (status == OK) {
+ status_t status = dumpsys.startDumpThread(Dumpsys::TYPE_DUMP | Dumpsys::TYPE_PID,
+ service, args);
+ if (status == OK) {
dumpsys.writeDumpHeader(STDOUT_FILENO, service, priority);
std::chrono::duration<double> elapsed_seconds;
if (priority == IServiceManager::DUMP_FLAG_PRIORITY_HIGH &&
@@ -1902,6 +1903,9 @@ Dumpstate::RunStatus Dumpstate::DumpstateDefaultAfterCritical() {
}
ds.AddDir(PREREBOOT_DATA_DIR, false);
add_mountinfo();
+ for (const char* path : {"/proc/cpuinfo", "/proc/meminfo"}) {
+ ds.AddZipEntry(ZIP_ROOT_DIR + path, path);
+ }
DumpIpTablesAsRoot();
DumpDynamicPartitionInfo();
ds.AddDir(OTA_METADATA_DIR, true);
diff --git a/include/input/PropertyMap.h b/include/input/PropertyMap.h
index 28e4816afe..18ce16df36 100644
--- a/include/input/PropertyMap.h
+++ b/include/input/PropertyMap.h
@@ -18,7 +18,10 @@
#include <android-base/result.h>
#include <utils/Tokenizer.h>
+
+#include <string>
#include <unordered_map>
+#include <unordered_set>
namespace android {
@@ -57,6 +60,9 @@ public:
*/
void addProperty(const std::string& key, const std::string& value);
+ /* Returns a set of all property keys starting with the given prefix. */
+ std::unordered_set<std::string> getKeysWithPrefix(const std::string& prefix) const;
+
/* Gets the value of a property and parses it.
* Returns true and sets outValue if the key was found and its value was parsed successfully.
* Otherwise returns false and does not modify outValue. (Also logs a warning.)
@@ -65,6 +71,7 @@ public:
bool tryGetProperty(const std::string& key, bool& outValue) const;
bool tryGetProperty(const std::string& key, int32_t& outValue) const;
bool tryGetProperty(const std::string& key, float& outValue) const;
+ bool tryGetProperty(const std::string& key, double& outValue) const;
/* Adds all values from the specified property map. */
void addAll(const PropertyMap* map);
diff --git a/libs/binder/RecordedTransaction.cpp b/libs/binder/RecordedTransaction.cpp
index 51b971651d..ef58ed365f 100644
--- a/libs/binder/RecordedTransaction.cpp
+++ b/libs/binder/RecordedTransaction.cpp
@@ -127,8 +127,7 @@ std::optional<RecordedTransaction> RecordedTransaction::fromDetails(
t.mData.mInterfaceName = std::string(String8(interfaceName).string());
if (interfaceName.size() != t.mData.mInterfaceName.size()) {
LOG(ERROR) << "Interface Name is not valid. Contains characters that aren't single byte "
- "utf-8: "
- << interfaceName;
+ "utf-8.";
return std::nullopt;
}
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 38bd081b8b..ed3ce24e46 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -262,8 +262,10 @@ void RpcState::dump() {
}
void RpcState::clear() {
- RpcMutexUniqueLock _l(mNodeMutex);
+ return clear(RpcMutexUniqueLock(mNodeMutex));
+}
+void RpcState::clear(RpcMutexUniqueLock nodeLock) {
if (mTerminated) {
LOG_ALWAYS_FATAL_IF(!mNodeForAddress.empty(),
"New state should be impossible after terminating!");
@@ -292,7 +294,7 @@ void RpcState::clear() {
auto temp = std::move(mNodeForAddress);
mNodeForAddress.clear(); // RpcState isn't reusable, but for future/explicit
- _l.unlock();
+ nodeLock.unlock();
temp.clear(); // explicit
}
@@ -704,7 +706,7 @@ status_t RpcState::sendDecStrongToTarget(const sp<RpcSession::RpcConnection>& co
};
{
- RpcMutexLockGuard _l(mNodeMutex);
+ RpcMutexUniqueLock _l(mNodeMutex);
if (mTerminated) return DEAD_OBJECT; // avoid fatal only, otherwise races
auto it = mNodeForAddress.find(addr);
LOG_ALWAYS_FATAL_IF(it == mNodeForAddress.end(),
@@ -720,8 +722,9 @@ status_t RpcState::sendDecStrongToTarget(const sp<RpcSession::RpcConnection>& co
body.amount = it->second.timesRecd - target;
it->second.timesRecd = target;
- LOG_ALWAYS_FATAL_IF(nullptr != tryEraseNode(it),
+ LOG_ALWAYS_FATAL_IF(nullptr != tryEraseNode(session, std::move(_l), it),
"Bad state. RpcState shouldn't own received binder");
+ // LOCK ALREADY RELEASED
}
RpcWireHeader cmd = {
@@ -1164,8 +1167,8 @@ status_t RpcState::processDecStrong(const sp<RpcSession::RpcConnection>& connect
it->second.timesSent);
it->second.timesSent -= body.amount;
- sp<IBinder> tempHold = tryEraseNode(it);
- _l.unlock();
+ sp<IBinder> tempHold = tryEraseNode(session, std::move(_l), it);
+ // LOCK ALREADY RELEASED
tempHold = nullptr; // destructor may make binder calls on this session
return OK;
@@ -1229,7 +1232,10 @@ status_t RpcState::validateParcel(const sp<RpcSession>& session, const Parcel& p
return OK;
}
-sp<IBinder> RpcState::tryEraseNode(std::map<uint64_t, BinderNode>::iterator& it) {
+sp<IBinder> RpcState::tryEraseNode(const sp<RpcSession>& session, RpcMutexUniqueLock nodeLock,
+ std::map<uint64_t, BinderNode>::iterator& it) {
+ bool shouldShutdown = false;
+
sp<IBinder> ref;
if (it->second.timesSent == 0) {
@@ -1239,9 +1245,27 @@ sp<IBinder> RpcState::tryEraseNode(std::map<uint64_t, BinderNode>::iterator& it)
LOG_ALWAYS_FATAL_IF(!it->second.asyncTodo.empty(),
"Can't delete binder w/ pending async transactions");
mNodeForAddress.erase(it);
+
+ if (mNodeForAddress.size() == 0) {
+ shouldShutdown = true;
+ }
}
}
+ // If we shutdown, prevent RpcState from being re-used. This prevents another
+ // thread from getting the root object again.
+ if (shouldShutdown) {
+ clear(std::move(nodeLock));
+ } else {
+ nodeLock.unlock(); // explicit
+ }
+ // LOCK IS RELEASED
+
+ if (shouldShutdown) {
+ ALOGI("RpcState has no binders left, so triggering shutdown...");
+ (void)session->shutdownAndWait(false);
+ }
+
return ref;
}
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index ac8658540e..0e23ea7515 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -168,6 +168,7 @@ public:
void clear();
private:
+ void clear(RpcMutexUniqueLock nodeLock);
void dumpLocked();
// Alternative to std::vector<uint8_t> that doesn't abort on allocation failure and caps
@@ -268,11 +269,20 @@ private:
std::string toString() const;
};
- // checks if there is any reference left to a node and erases it. If erase
- // happens, and there is a strong reference to the binder kept by
- // binderNode, this returns that strong reference, so that it can be
- // dropped after any locks are removed.
- sp<IBinder> tryEraseNode(std::map<uint64_t, BinderNode>::iterator& it);
+ // Checks if there is any reference left to a node and erases it. If this
+ // is the last node, shuts down the session.
+ //
+ // Node lock is passed here for convenience, so that we can release it
+ // and terminate the session, but we could leave it up to the caller
+ // by returning a continuation if we needed to erase multiple specific
+ // nodes. It may be tempting to allow the client to keep on holding the
+ // lock and instead just return whether or not we should shutdown, but
+ // this introduces the posssibility that another thread calls
+ // getRootBinder and thinks it is valid, rather than immediately getting
+ // an error.
+ sp<IBinder> tryEraseNode(const sp<RpcSession>& session, RpcMutexUniqueLock nodeLock,
+ std::map<uint64_t, BinderNode>::iterator& it);
+
// true - success
// false - session shutdown, halt
[[nodiscard]] bool nodeProgressAsyncNumber(BinderNode* node);
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index 1488400007..07b38d7368 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -119,5 +119,10 @@
{
"name": "memunreachable_binder_test"
}
+ ],
+ "imports": [
+ {
+ "path": "packages/modules/Virtualization"
+ }
]
}
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 0750ccfc3f..a323febbc7 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -51,6 +51,9 @@ constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_RPC_HEADER_FEATURE_EXPLICIT_PARCEL_
* This represents a session (group of connections) between a client
* and a server. Multiple connections are needed for multiple parallel "binder"
* calls which may also have nested calls.
+ *
+ * Once a binder exists in the session, if all references to all binders are dropped,
+ * the session shuts down.
*/
class RpcSession final : public virtual RefBase {
public:
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 976f54d36f..d0e35de3f7 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -100,22 +100,17 @@ where
/// An interface can promise to be a stable vendor interface ([`Vintf`]), or
/// makes no stability guarantees ([`Local`]). [`Local`] is
/// currently the default stability.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum Stability {
/// Default stability, visible to other modules in the same compilation
/// context (e.g. modules on system.img)
+ #[default]
Local,
/// A Vendor Interface Object, which promises to be stable
Vintf,
}
-impl Default for Stability {
- fn default() -> Self {
- Stability::Local
- }
-}
-
impl From<Stability> for i32 {
fn from(stability: Stability) -> i32 {
use Stability::*;
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index a3ed571462..116476765a 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -80,4 +80,8 @@ interface IBinderRpcTest {
// get queued.
oneway void blockingSendFdOneway(in ParcelFileDescriptor fd);
ParcelFileDescriptor blockingRecvFd();
+
+ // Same as blockingSendFdOneway, but with integers.
+ oneway void blockingSendIntOneway(int n);
+ int blockingRecvInt();
}
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 52ba9b00fd..593927306e 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -102,9 +102,11 @@ std::unique_ptr<RpcTransportCtxFactory> makeFactoryTls() {
}
static sp<RpcSession> gSession = RpcSession::make();
+static sp<IBinder> gRpcBinder;
// Certificate validation happens during handshake and does not affect the result of benchmarks.
// Skip certificate validation to simplify the setup process.
static sp<RpcSession> gSessionTls = RpcSession::make(makeFactoryTls());
+static sp<IBinder> gRpcTlsBinder;
#ifdef __BIONIC__
static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control");
static sp<IBinder> gKernelBinder;
@@ -118,9 +120,9 @@ static sp<IBinder> getBinderForOptions(benchmark::State& state) {
return gKernelBinder;
#endif
case RPC:
- return gSession->getRootObject();
+ return gRpcBinder;
case RPC_TLS:
- return gSessionTls->getRootObject();
+ return gRpcTlsBinder;
default:
LOG(FATAL) << "Unknown transport value: " << transport;
return nullptr;
@@ -254,11 +256,13 @@ int main(int argc, char** argv) {
(void)unlink(addr.c_str());
forkRpcServer(addr.c_str(), RpcServer::make(RpcTransportCtxFactoryRaw::make()));
setupClient(gSession, addr.c_str());
+ gRpcBinder = gSession->getRootObject();
std::string tlsAddr = tmp + "/binderRpcTlsBenchmark";
(void)unlink(tlsAddr.c_str());
forkRpcServer(tlsAddr.c_str(), RpcServer::make(makeFactoryTls()));
setupClient(gSessionTls, tlsAddr.c_str());
+ gRpcTlsBinder = gSessionTls->getRootObject();
::benchmark::RunSpecifiedBenchmarks();
return 0;
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 5952c4172e..efc314bdec 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -163,7 +163,8 @@ public:
session.root = nullptr;
}
- for (auto& info : sessions) {
+ for (size_t sessionNum = 0; sessionNum < sessions.size(); sessionNum++) {
+ auto& info = sessions.at(sessionNum);
sp<RpcSession>& session = info.session;
EXPECT_NE(nullptr, session);
@@ -179,6 +180,7 @@ public:
for (size_t i = 0; i < 3; i++) {
sp<RpcSession> strongSession = weakSession.promote();
EXPECT_EQ(nullptr, strongSession)
+ << "For session " << sessionNum << ". "
<< (debugBacktrace(host.getPid()), debugBacktrace(getpid()),
"Leaked sess: ")
<< strongSession->getStrongCount() << " checked time " << i;
@@ -254,6 +256,10 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc(
const BinderRpcOptions& options) {
CHECK_GE(options.numSessions, 1) << "Must have at least one session to a server";
+ if (options.numIncomingConnectionsBySession.size() != 0) {
+ CHECK_EQ(options.numIncomingConnectionsBySession.size(), options.numSessions);
+ }
+
SocketType socketType = std::get<0>(GetParam());
RpcSecurity rpcSecurity = std::get<1>(GetParam());
uint32_t clientVersion = std::get<2>(GetParam());
@@ -351,9 +357,15 @@ std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc(
status_t status;
- for (const auto& session : sessions) {
+ for (size_t i = 0; i < sessions.size(); i++) {
+ const auto& session = sessions.at(i);
+
+ size_t numIncoming = options.numIncomingConnectionsBySession.size() > 0
+ ? options.numIncomingConnectionsBySession.at(i)
+ : 0;
+
CHECK(session->setProtocolVersion(clientVersion));
- session->setMaxIncomingThreads(options.numIncomingConnections);
+ session->setMaxIncomingThreads(numIncoming);
session->setMaxOutgoingConnections(options.numOutgoingConnections);
session->setFileDescriptorTransportMode(options.clientFileDescriptorTransportMode);
@@ -587,30 +599,22 @@ TEST_P(BinderRpc, OnewayCallQueueing) {
GTEST_SKIP() << "This test requires multiple threads";
}
- constexpr size_t kNumSleeps = 10;
+ constexpr size_t kNumQueued = 10;
constexpr size_t kNumExtraServerThreads = 4;
- constexpr size_t kSleepMs = 50;
// make sure calls to the same object happen on the same thread
auto proc = createRpcTestSocketServerProcess({.numThreads = 1 + kNumExtraServerThreads});
- EXPECT_OK(proc.rootIface->lock());
-
- size_t epochMsBefore = epochMillis();
-
- // all these *Async commands should be queued on the server sequentially,
+ // all these *Oneway commands should be queued on the server sequentially,
// even though there are multiple threads.
- for (size_t i = 0; i + 1 < kNumSleeps; i++) {
- proc.rootIface->sleepMsAsync(kSleepMs);
+ for (size_t i = 0; i + 1 < kNumQueued; i++) {
+ proc.rootIface->blockingSendIntOneway(i);
+ }
+ for (size_t i = 0; i + 1 < kNumQueued; i++) {
+ int n;
+ proc.rootIface->blockingRecvInt(&n);
+ EXPECT_EQ(n, i);
}
- EXPECT_OK(proc.rootIface->unlockInMsAsync(kSleepMs));
-
- // this can only return once the final async call has unlocked
- EXPECT_OK(proc.rootIface->lockUnlock());
-
- size_t epochMsAfter = epochMillis();
-
- EXPECT_GE(epochMsAfter, epochMsBefore + kSleepMs * kNumSleeps);
saturateThreadPool(1 + kNumExtraServerThreads, proc.rootIface);
}
@@ -659,6 +663,32 @@ TEST_P(BinderRpc, OnewayCallExhaustion) {
proc.proc->sessions.erase(proc.proc->sessions.begin() + 1);
}
+TEST_P(BinderRpc, SessionWithIncomingThreadpoolDoesntLeak) {
+ if (clientOrServerSingleThreaded()) {
+ GTEST_SKIP() << "This test requires multiple threads";
+ }
+
+ // session 0 - will check for leaks in destrutor of proc
+ // session 1 - we want to make sure it gets deleted when we drop all references to it
+ auto proc = createRpcTestSocketServerProcess(
+ {.numThreads = 1, .numIncomingConnectionsBySession = {0, 1}, .numSessions = 2});
+
+ wp<RpcSession> session = proc.proc->sessions.at(1).session;
+
+ // remove all references to the second session
+ proc.proc->sessions.at(1).root = nullptr;
+ proc.proc->sessions.erase(proc.proc->sessions.begin() + 1);
+
+ // TODO(b/271830568) more efficient way to wait for other incoming threadpool
+ // to drain commands.
+ for (size_t i = 0; i < 100; i++) {
+ usleep(10 * 1000);
+ if (session.promote() == nullptr) break;
+ }
+
+ EXPECT_EQ(nullptr, session.promote());
+}
+
TEST_P(BinderRpc, SingleDeathRecipient) {
if (clientOrServerSingleThreaded()) {
GTEST_SKIP() << "This test requires multiple threads";
@@ -676,7 +706,7 @@ TEST_P(BinderRpc, SingleDeathRecipient) {
// Death recipient needs to have an incoming connection to be called
auto proc = createRpcTestSocketServerProcess(
- {.numThreads = 1, .numSessions = 1, .numIncomingConnections = 1});
+ {.numThreads = 1, .numSessions = 1, .numIncomingConnectionsBySession = {1}});
auto dr = sp<MyDeathRec>::make();
ASSERT_EQ(OK, proc.rootBinder->linkToDeath(dr, (void*)1, 0));
@@ -689,6 +719,10 @@ TEST_P(BinderRpc, SingleDeathRecipient) {
ASSERT_TRUE(dr->mCv.wait_for(lock, 100ms, [&]() { return dr->dead; }));
// need to wait for the session to shutdown so we don't "Leak session"
+ // can't do this before checking the death recipient by calling
+ // forceShutdown earlier, because shutdownAndWait will also trigger
+ // a death recipient, but if we had a way to wait for the service
+ // to gracefully shutdown, we could use that here.
EXPECT_TRUE(proc.proc->sessions.at(0).session->shutdownAndWait(true));
proc.expectAlreadyShutdown = true;
}
@@ -710,7 +744,7 @@ TEST_P(BinderRpc, SingleDeathRecipientOnShutdown) {
// Death recipient needs to have an incoming connection to be called
auto proc = createRpcTestSocketServerProcess(
- {.numThreads = 1, .numSessions = 1, .numIncomingConnections = 1});
+ {.numThreads = 1, .numSessions = 1, .numIncomingConnectionsBySession = {1}});
auto dr = sp<MyDeathRec>::make();
EXPECT_EQ(OK, proc.rootBinder->linkToDeath(dr, (void*)1, 0));
@@ -743,8 +777,7 @@ TEST_P(BinderRpc, DeathRecipientFailsWithoutIncoming) {
void binderDied(const wp<IBinder>& /* who */) override {}
};
- auto proc = createRpcTestSocketServerProcess(
- {.numThreads = 1, .numSessions = 1, .numIncomingConnections = 0});
+ auto proc = createRpcTestSocketServerProcess({.numThreads = 1, .numSessions = 1});
auto dr = sp<MyDeathRec>::make();
EXPECT_EQ(INVALID_OPERATION, proc.rootBinder->linkToDeath(dr, (void*)1, 0));
@@ -763,19 +796,13 @@ TEST_P(BinderRpc, UnlinkDeathRecipient) {
// Death recipient needs to have an incoming connection to be called
auto proc = createRpcTestSocketServerProcess(
- {.numThreads = 1, .numSessions = 1, .numIncomingConnections = 1});
+ {.numThreads = 1, .numSessions = 1, .numIncomingConnectionsBySession = {1}});
auto dr = sp<MyDeathRec>::make();
ASSERT_EQ(OK, proc.rootBinder->linkToDeath(dr, (void*)1, 0));
ASSERT_EQ(OK, proc.rootBinder->unlinkToDeath(dr, (void*)1, 0, nullptr));
- if (auto status = proc.rootIface->scheduleShutdown(); !status.isOk()) {
- EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status;
- }
-
- // need to wait for the session to shutdown so we don't "Leak session"
- EXPECT_TRUE(proc.proc->sessions.at(0).session->shutdownAndWait(true));
- proc.expectAlreadyShutdown = true;
+ proc.forceShutdown();
}
TEST_P(BinderRpc, Die) {
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index a467ee389b..a9f0df3c0f 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -126,7 +126,11 @@ static inline size_t epochMillis() {
struct BinderRpcOptions {
size_t numThreads = 1;
size_t numSessions = 1;
- size_t numIncomingConnections = 0;
+ // right now, this can be empty, or length numSessions, where each value
+ // represents the info for the corresponding session, but we should
+ // probably switch this to be a list of sessions options so that other
+ // options can all be specified per session
+ std::vector<size_t> numIncomingConnectionsBySession = {};
size_t numOutgoingConnections = SIZE_MAX;
RpcSession::FileDescriptorTransportMode clientFileDescriptorTransportMode =
RpcSession::FileDescriptorTransportMode::NONE;
@@ -445,6 +449,12 @@ public:
Status blockingRecvFd(android::os::ParcelFileDescriptor* /*fd*/) override {
return Status::fromStatusT(UNKNOWN_TRANSACTION);
}
+
+ Status blockingSendIntOneway(int /*n*/) override {
+ return Status::fromStatusT(UNKNOWN_TRANSACTION);
+ }
+
+ Status blockingRecvInt(int* /*n*/) override { return Status::fromStatusT(UNKNOWN_TRANSACTION); }
};
} // namespace android
diff --git a/libs/binder/tests/binderRpcTestFixture.h b/libs/binder/tests/binderRpcTestFixture.h
index c99d68aacf..20fb6bf3ce 100644
--- a/libs/binder/tests/binderRpcTestFixture.h
+++ b/libs/binder/tests/binderRpcTestFixture.h
@@ -64,6 +64,21 @@ struct BinderRpcTestProcessSession {
// whether session should be invalidated by end of run
bool expectAlreadyShutdown = false;
+ // TODO(b/271830568): fix this in binderRpcTest, we always use the first session to cause the
+ // remote process to shutdown. Normally, when we shutdown, the default in the destructor is to
+ // check that there are no leaks and shutdown. However, when there are incoming threadpools,
+ // there will be a few extra binder threads there, so we can't shutdown the server. We should
+ // consider an alternative way of doing the test so that we don't need this, some ideas, such as
+ // program in understanding of incoming threadpool into the destructor so that (e.g.
+ // intelligently wait for sessions to shutdown now that they will do this)
+ void forceShutdown() {
+ if (auto status = rootIface->scheduleShutdown(); !status.isOk()) {
+ EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status;
+ }
+ EXPECT_TRUE(proc->sessions.at(0).session->shutdownAndWait(true));
+ expectAlreadyShutdown = true;
+ }
+
BinderRpcTestProcessSession(BinderRpcTestProcessSession&&) = default;
~BinderRpcTestProcessSession() {
if (!expectAlreadyShutdown) {
diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp
index a27bd2f2e6..ca5a117f00 100644
--- a/libs/binder/tests/binderRpcTestService.cpp
+++ b/libs/binder/tests/binderRpcTestService.cpp
@@ -83,6 +83,18 @@ public:
fd->reset(mFdChannel.read());
return Status::ok();
}
+
+ HandoffChannel<int> mIntChannel;
+
+ Status blockingSendIntOneway(int n) override {
+ mIntChannel.write(n);
+ return Status::ok();
+ }
+
+ Status blockingRecvInt(int* n) override {
+ *n = mIntChannel.read();
+ return Status::ok();
+ }
};
int main(int argc, char* argv[]) {
diff --git a/libs/binder/tests/binderRpcTestTrusty.cpp b/libs/binder/tests/binderRpcTestTrusty.cpp
index 63b56a3a64..85794bdf14 100644
--- a/libs/binder/tests/binderRpcTestTrusty.cpp
+++ b/libs/binder/tests/binderRpcTestTrusty.cpp
@@ -60,9 +60,9 @@ std::string BinderRpc::PrintParamInfo(const testing::TestParamInfo<ParamType>& i
// threads.
std::unique_ptr<ProcessSession> BinderRpc::createRpcTestSocketServerProcessEtc(
const BinderRpcOptions& options) {
- LOG_ALWAYS_FATAL_IF(options.numIncomingConnections != 0,
+ LOG_ALWAYS_FATAL_IF(options.numIncomingConnectionsBySession.size() != 0,
"Non-zero incoming connections %zu on Trusty",
- options.numIncomingConnections);
+ options.numIncomingConnectionsBySession.size());
uint32_t clientVersion = std::get<2>(GetParam());
uint32_t serverVersion = std::get<3>(GetParam());
diff --git a/libs/binder/tests/binderRpcUniversalTests.cpp b/libs/binder/tests/binderRpcUniversalTests.cpp
index 11a22b0fb6..1f4601010c 100644
--- a/libs/binder/tests/binderRpcUniversalTests.cpp
+++ b/libs/binder/tests/binderRpcUniversalTests.cpp
@@ -463,7 +463,7 @@ TEST_P(BinderRpc, Callbacks) {
auto proc = createRpcTestSocketServerProcess(
{.numThreads = 1,
.numSessions = 1,
- .numIncomingConnections = numIncomingConnections});
+ .numIncomingConnectionsBySession = {numIncomingConnections}});
auto cb = sp<MyBinderRpcCallback>::make();
if (callIsOneway) {
@@ -491,16 +491,7 @@ TEST_P(BinderRpc, Callbacks) {
<< "callIsOneway: " << callIsOneway
<< " callbackIsOneway: " << callbackIsOneway << " delayed: " << delayed;
- // since we are severing the connection, we need to go ahead and
- // tell the server to shutdown and exit so that waitpid won't hang
- if (auto status = proc.rootIface->scheduleShutdown(); !status.isOk()) {
- EXPECT_EQ(DEAD_OBJECT, status.transactionError()) << status;
- }
-
- // since this session has an incoming connection w/ a threadpool, we
- // need to manually shut it down
- EXPECT_TRUE(proc.proc->sessions.at(0).session->shutdownAndWait(true));
- proc.expectAlreadyShutdown = true;
+ proc.forceShutdown();
}
}
}
diff --git a/libs/binderdebug/Android.bp b/libs/binderdebug/Android.bp
index 3eeaf3e4f1..1454727114 100644
--- a/libs/binderdebug/Android.bp
+++ b/libs/binderdebug/Android.bp
@@ -21,6 +21,17 @@ package {
default_applicable_licenses: ["frameworks_native_license"],
}
+cc_benchmark {
+ name: "binder_thread_stats",
+ shared_libs: [
+ "libutils",
+ "libbinder",
+ "libbase",
+ ],
+ static_libs: ["libbinderdebug"],
+ srcs: ["stats.cpp"],
+}
+
cc_library {
name: "libbinderdebug",
vendor_available: true,
diff --git a/libs/binderdebug/stats.cpp b/libs/binderdebug/stats.cpp
new file mode 100644
index 0000000000..9c26afaa97
--- /dev/null
+++ b/libs/binderdebug/stats.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 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 <android-base/logging.h>
+#include <binder/BpBinder.h>
+#include <binder/IServiceManager.h>
+#include <binderdebug/BinderDebug.h>
+#include <utils/Errors.h>
+
+#include <inttypes.h>
+
+namespace android {
+
+extern "C" int main() {
+ // ignore args - we only print csv
+
+ // we should use a csv library here for escaping, because
+ // the name is coming from another process
+ printf("name,binder_threads_in_use,binder_threads_started,client_count\n");
+
+ for (const String16& name : defaultServiceManager()->listServices()) {
+ sp<IBinder> binder = defaultServiceManager()->checkService(name);
+ if (binder == nullptr) {
+ fprintf(stderr, "%s is null", String8(name).c_str());
+ continue;
+ }
+
+ BpBinder* remote = binder->remoteBinder();
+ const auto handle = remote->getDebugBinderHandle();
+ CHECK(handle != std::nullopt);
+
+ pid_t pid;
+ CHECK_EQ(OK, binder->getDebugPid(&pid));
+
+ BinderPidInfo info;
+ CHECK_EQ(OK, getBinderPidInfo(BinderDebugContext::BINDER, pid, &info));
+
+ std::vector<pid_t> clientPids;
+ CHECK_EQ(OK,
+ getBinderClientPids(BinderDebugContext::BINDER, getpid(), pid, *handle,
+ &clientPids));
+
+ printf("%s,%" PRIu32 ",%" PRIu32 ",%zu\n", String8(name).c_str(), info.threadUsage,
+ info.threadCount, clientPids.size());
+ }
+ return 0;
+}
+
+} // namespace android
diff --git a/libs/ftl/Android.bp b/libs/ftl/Android.bp
index 8e57152b49..ea1b5e4998 100644
--- a/libs/ftl/Android.bp
+++ b/libs/ftl/Android.bp
@@ -10,9 +10,6 @@ package {
cc_test {
name: "ftl_test",
test_suites: ["device-tests"],
- sanitize: {
- address: true,
- },
srcs: [
"algorithm_test.cpp",
"cast_test.cpp",
diff --git a/libs/ftl/TEST_MAPPING b/libs/ftl/TEST_MAPPING
new file mode 100644
index 0000000000..ec0c671213
--- /dev/null
+++ b/libs/ftl/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+ "presubmit": [
+ {
+ "name": "ftl_test"
+ }
+ ],
+ "hwasan-presubmit": [
+ {
+ "name": "ftl_test"
+ }
+ ]
+}
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index f38dd98428..869458c407 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -167,6 +167,7 @@ cc_library {
cc_defaults {
name: "libinput_fuzz_defaults",
+ cpp_std: "c++20",
host_supported: true,
shared_libs: [
"libutils",
diff --git a/libs/input/PropertyMap.cpp b/libs/input/PropertyMap.cpp
index ed9ac9fc72..9a4f10b21d 100644
--- a/libs/input/PropertyMap.cpp
+++ b/libs/input/PropertyMap.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "PropertyMap"
+#include <cstdlib>
+
#include <input/PropertyMap.h>
#include <log/log.h>
@@ -44,6 +46,16 @@ void PropertyMap::addProperty(const std::string& key, const std::string& value)
mProperties.emplace(key, value);
}
+std::unordered_set<std::string> PropertyMap::getKeysWithPrefix(const std::string& prefix) const {
+ std::unordered_set<std::string> keys;
+ for (const auto& [key, _] : mProperties) {
+ if (key.starts_with(prefix)) {
+ keys.insert(key);
+ }
+ }
+ return keys;
+}
+
bool PropertyMap::hasProperty(const std::string& key) const {
return mProperties.find(key) != mProperties.end();
}
@@ -102,6 +114,23 @@ bool PropertyMap::tryGetProperty(const std::string& key, float& outValue) const
return true;
}
+bool PropertyMap::tryGetProperty(const std::string& key, double& outValue) const {
+ std::string stringValue;
+ if (!tryGetProperty(key, stringValue) || stringValue.length() == 0) {
+ return false;
+ }
+
+ char* end;
+ double value = strtod(stringValue.c_str(), &end);
+ if (*end != '\0') {
+ ALOGW("Property key '%s' has invalid value '%s'. Expected a double.", key.c_str(),
+ stringValue.c_str());
+ return false;
+ }
+ outValue = value;
+ return true;
+}
+
void PropertyMap::addAll(const PropertyMap* map) {
for (const auto& [key, value] : map->mProperties) {
mProperties.emplace(key, value);
diff --git a/libs/input/TfLiteMotionPredictor.cpp b/libs/input/TfLiteMotionPredictor.cpp
index 691e87c366..3b061d1cf1 100644
--- a/libs/input/TfLiteMotionPredictor.cpp
+++ b/libs/input/TfLiteMotionPredictor.cpp
@@ -61,8 +61,21 @@ constexpr char OUTPUT_R[] = "r";
constexpr char OUTPUT_PHI[] = "phi";
constexpr char OUTPUT_PRESSURE[] = "pressure";
+// Ideally, we would just use std::filesystem::exists here, but it requires libc++fs, which causes
+// build issues in other parts of the system.
+#if defined(__ANDROID__)
+bool fileExists(const char* filename) {
+ struct stat buffer;
+ return stat(filename, &buffer) == 0;
+}
+#endif
+
std::string getModelPath() {
#if defined(__ANDROID__)
+ static const char* oemModel = "/vendor/etc/motion_predictor_model.fb";
+ if (fileExists(oemModel)) {
+ return oemModel;
+ }
return "/system/etc/motion_predictor_model.fb";
#else
return base::GetExecutableDirectory() + "/motion_predictor_model.fb";
@@ -217,7 +230,7 @@ void TfLiteMotionPredictorBuffers::pushSample(int64_t timestamp,
std::unique_ptr<TfLiteMotionPredictorModel> TfLiteMotionPredictorModel::create() {
const std::string modelPath = getModelPath();
- const int fd = open(modelPath.c_str(), O_RDONLY);
+ android::base::unique_fd fd(open(modelPath.c_str(), O_RDONLY));
if (fd == -1) {
PLOG(FATAL) << "Could not read model from " << modelPath;
}
@@ -232,9 +245,6 @@ std::unique_ptr<TfLiteMotionPredictorModel> TfLiteMotionPredictorModel::create()
if (!modelBuffer) {
PLOG(FATAL) << "Failed to mmap model";
}
- if (close(fd) == -1) {
- PLOG(FATAL) << "Failed to close model fd";
- }
return std::unique_ptr<TfLiteMotionPredictorModel>(
new TfLiteMotionPredictorModel(std::move(modelBuffer)));
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 86f6c7febb..51642f9472 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -24,9 +24,6 @@ package {
cc_test {
name: "gpuservice_unittest",
test_suites: ["device-tests"],
- sanitize: {
- address: true,
- },
srcs: [
"GpuMemTest.cpp",
"GpuMemTracerTest.cpp",
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 0d2030e0c4..69363b6e10 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -210,14 +210,13 @@ void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
// Touchscreens and touchpad devices.
static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY =
sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true);
- // TODO(b/246587538): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) and DualSense
- // (ce6) touchpads, or at least load this setting from the IDC file.
+ // TODO(b/272518665): Fix the new touchpad stack for Sony DualShock 4 (5c4, 9cc) touchpads, or
+ // at least load this setting from the IDC file.
const InputDeviceIdentifier identifier = contextPtr->getDeviceIdentifier();
- const bool isSonyGamepadTouchpad = identifier.vendor == 0x054c &&
- (identifier.product == 0x05c4 || identifier.product == 0x09cc ||
- identifier.product == 0x0ce6);
+ const bool isSonyDualShock4Touchpad = identifier.vendor == 0x054c &&
+ (identifier.product == 0x05c4 || identifier.product == 0x09cc);
if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
- classes.test(InputDeviceClass::TOUCH_MT) && !isSonyGamepadTouchpad) {
+ classes.test(InputDeviceClass::TOUCH_MT) && !isSonyDualShock4Touchpad) {
mappers.push_back(std::make_unique<TouchpadInputMapper>(*contextPtr));
} else if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index d3af402153..330976719d 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -20,6 +20,7 @@
#include <optional>
#include <android/input.h>
+#include <ftl/enum.h>
#include <input/PrintTools.h>
#include <linux/input-event-codes.h>
#include <log/log_main.h>
@@ -216,6 +217,11 @@ void TouchpadInputMapper::dump(std::string& dump) {
std::list<NotifyArgs> TouchpadInputMapper::configure(nsecs_t when,
const InputReaderConfiguration* config,
uint32_t changes) {
+ if (!changes) {
+ // First time configuration
+ mPropertyProvider.loadPropertiesFromIdcFile(getDeviceContext().getConfiguration());
+ }
+
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
std::optional<int32_t> displayId = mPointerController->getDisplayId();
ui::Rotation orientation = ui::ROTATION_0;
diff --git a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
index 089f45a4e6..3d883389c9 100644
--- a/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
+++ b/services/inputflinger/reader/mapper/gestures/PropertyProvider.cpp
@@ -84,6 +84,29 @@ std::string PropertyProvider::dump() const {
return dump;
}
+void PropertyProvider::loadPropertiesFromIdcFile(const PropertyMap& idcProperties) {
+ // For compatibility with the configuration file syntax, gesture property names in IDC files are
+ // prefixed with "gestureProp." and have spaces replaced by underscores. So, for example, the
+ // configuration key "gestureProp.Palm_Width" refers to the "Palm Width" property.
+ const std::string gesturePropPrefix = "gestureProp.";
+ for (const std::string key : idcProperties.getKeysWithPrefix(gesturePropPrefix)) {
+ std::string propertyName = key.substr(gesturePropPrefix.length());
+ for (size_t i = 0; i < propertyName.length(); i++) {
+ if (propertyName[i] == '_') {
+ propertyName[i] = ' ';
+ }
+ }
+
+ auto it = mProperties.find(propertyName);
+ if (it != mProperties.end()) {
+ it->second.trySetFromIdcProperty(idcProperties, key);
+ } else {
+ ALOGE("Gesture property \"%s\" specified in IDC file does not exist for this device.",
+ propertyName.c_str());
+ }
+ }
+}
+
GesturesProp* PropertyProvider::createIntArrayProperty(const std::string& name, int* loc,
size_t count, const int* init) {
const auto [it, inserted] =
@@ -211,6 +234,59 @@ void GesturesProp::setRealValues(const std::vector<double>& values) {
setValues(std::get<double*>(mDataPointer), values);
}
+namespace {
+
+// Helper to std::visit with lambdas.
+template <typename... V>
+struct Visitor : V... {};
+// explicit deduction guide (not needed as of C++20)
+template <typename... V>
+Visitor(V...) -> Visitor<V...>;
+
+} // namespace
+
+void GesturesProp::trySetFromIdcProperty(const android::PropertyMap& idcProperties,
+ const std::string& propertyName) {
+ if (mCount != 1) {
+ ALOGE("Gesture property \"%s\" is an array, and so cannot be set in an IDC file.",
+ mName.c_str());
+ return;
+ }
+ bool parsedSuccessfully = false;
+ Visitor setVisitor{
+ [&](int*) {
+ int32_t value;
+ parsedSuccessfully = idcProperties.tryGetProperty(propertyName, value);
+ if (parsedSuccessfully) {
+ setIntValues({value});
+ }
+ },
+ [&](GesturesPropBool*) {
+ bool value;
+ parsedSuccessfully = idcProperties.tryGetProperty(propertyName, value);
+ if (parsedSuccessfully) {
+ setBoolValues({value});
+ }
+ },
+ [&](double*) {
+ double value;
+ parsedSuccessfully = idcProperties.tryGetProperty(propertyName, value);
+ if (parsedSuccessfully) {
+ setRealValues({value});
+ }
+ },
+ [&](const char**) {
+ ALOGE("Gesture property \"%s\" is a string, and so cannot be set in an IDC file.",
+ mName.c_str());
+ },
+ };
+ std::visit(setVisitor, mDataPointer);
+
+ ALOGE_IF(!parsedSuccessfully, "Gesture property \"%s\" could set due to a type mismatch.",
+ mName.c_str());
+ return;
+}
+
template <typename T, typename U>
const std::vector<T> GesturesProp::getValues(U* dataPointer) const {
if (mGetter != nullptr) {
diff --git a/services/inputflinger/reader/mapper/gestures/PropertyProvider.h b/services/inputflinger/reader/mapper/gestures/PropertyProvider.h
index 50451a3929..c7e0858c6d 100644
--- a/services/inputflinger/reader/mapper/gestures/PropertyProvider.h
+++ b/services/inputflinger/reader/mapper/gestures/PropertyProvider.h
@@ -22,6 +22,7 @@
#include <vector>
#include "include/gestures.h"
+#include "input/PropertyMap.h"
namespace android {
@@ -35,6 +36,8 @@ public:
GesturesProp& getProperty(const std::string& name);
std::string dump() const;
+ void loadPropertiesFromIdcFile(const PropertyMap& idcProperties);
+
// Methods to be called by the gestures library:
GesturesProp* createIntArrayProperty(const std::string& name, int* loc, size_t count,
const int* init);
@@ -83,6 +86,9 @@ public:
// Setting string values isn't supported since we don't have a use case yet and the memory
// management adds additional complexity.
+ void trySetFromIdcProperty(const android::PropertyMap& idcProperties,
+ const std::string& propertyName);
+
private:
// Two type parameters are required for these methods, rather than one, due to the gestures
// library using its own bool type.
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 711cfbf922..eb58d0bd95 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1830,7 +1830,7 @@ using StylusButtonIntegrationTestTypes =
::testing::Types<UinputTouchScreen, UinputExternalStylus, UinputExternalStylusWithPressure>;
TYPED_TEST_SUITE(StylusButtonIntegrationTest, StylusButtonIntegrationTestTypes);
-TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
+TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsGenerateKeyEvents) {
const auto stylusId = TestFixture::mStylusInfo.getId();
TestFixture::mStylus->pressKey(BTN_STYLUS);
@@ -1844,7 +1844,7 @@ TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsGenerateKeyEvents) {
WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
+TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsSurroundingTouchGesture) {
const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
const auto stylusId = TestFixture::mStylusInfo.getId();
@@ -1890,7 +1890,7 @@ TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingTouchGesture) {
WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGesture) {
+TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsSurroundingHoveringTouchGesture) {
const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
const auto stylusId = TestFixture::mStylusInfo.getId();
@@ -1966,7 +1966,7 @@ TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsSurroundingHoveringTouchGes
WithKeyCode(AKEYCODE_STYLUS_BUTTON_PRIMARY), WithDeviceId(stylusId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
+TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonsWithinTouchGesture) {
const Point centerPoint = TestFixture::mTouchscreen->getCenterPoint();
const auto touchscreenId = TestFixture::mTouchscreenInfo.getId();
const auto stylusId = TestFixture::mStylusInfo.getId();
@@ -2020,7 +2020,7 @@ TYPED_TEST(StylusButtonIntegrationTest, StylusButtonsWithinTouchGesture) {
WithDeviceId(touchscreenId))));
}
-TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
+TYPED_TEST(StylusButtonIntegrationTest, DISABLED_StylusButtonMotionEventsDisabled) {
TestFixture::mFakePolicy->setStylusButtonMotionEventsEnabled(false);
TestFixture::mReader->requestRefreshConfiguration(
InputReaderConfiguration::CHANGE_STYLUS_BUTTON_REPORTING);
@@ -2077,7 +2077,7 @@ TYPED_TEST(StylusButtonIntegrationTest, StylusButtonMotionEventsDisabled) {
// ongoing stylus gesture that is being emitted by the touchscreen.
using ExternalStylusIntegrationTest = TouchIntegrationTest;
-TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
+TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureReported) {
const Point centerPoint = mDevice->getCenterPoint();
// Create an external stylus capable of reporting pressure data that
@@ -2123,7 +2123,7 @@ TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureReported) {
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
}
-TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
+TEST_F(ExternalStylusIntegrationTest, DISABLED_FusedExternalStylusPressureNotReported) {
const Point centerPoint = mDevice->getCenterPoint();
// Create an external stylus capable of reporting pressure data that
@@ -2191,7 +2191,7 @@ TEST_F(ExternalStylusIntegrationTest, FusedExternalStylusPressureNotReported) {
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasNotCalled());
}
-TEST_F(ExternalStylusIntegrationTest, UnfusedExternalStylus) {
+TEST_F(ExternalStylusIntegrationTest, DISABLED_UnfusedExternalStylus) {
const Point centerPoint = mDevice->getCenterPoint();
// Create an external stylus device that does not support pressure. It should not affect any
diff --git a/services/inputflinger/tests/PropertyProvider_test.cpp b/services/inputflinger/tests/PropertyProvider_test.cpp
index 42a6a9f4b9..8a40e78b89 100644
--- a/services/inputflinger/tests/PropertyProvider_test.cpp
+++ b/services/inputflinger/tests/PropertyProvider_test.cpp
@@ -18,6 +18,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include "TestConstants.h"
#include "include/gestures.h"
namespace android {
@@ -283,4 +284,68 @@ TEST_F(PropertyProviderTest, Free) {
EXPECT_FALSE(mProvider.hasProperty("Foo"));
}
+class PropertyProviderIdcLoadingTest : public testing::Test {
+protected:
+ void SetUp() override {
+ int initialInt = 0;
+ GesturesPropBool initialBool = false;
+ double initialReal = 0.0;
+ gesturePropProvider.create_int_fn(&mProvider, "An Integer", &mIntData, 1, &initialInt);
+ gesturePropProvider.create_bool_fn(&mProvider, "A Boolean", &mBoolData, 1, &initialBool);
+ gesturePropProvider.create_real_fn(&mProvider, "A Real", &mRealData, 1, &initialReal);
+ }
+
+ PropertyProvider mProvider;
+
+ int mIntData;
+ GesturesPropBool mBoolData;
+ double mRealData;
+};
+
+TEST_F(PropertyProviderIdcLoadingTest, AllCorrect) {
+ PropertyMap idcProps;
+ idcProps.addProperty("gestureProp.An_Integer", "42");
+ idcProps.addProperty("gestureProp.A_Boolean", "1");
+ idcProps.addProperty("gestureProp.A_Real", "3.14159");
+
+ mProvider.loadPropertiesFromIdcFile(idcProps);
+ EXPECT_THAT(mProvider.getProperty("An Integer").getIntValues(), ElementsAre(42));
+ EXPECT_THAT(mProvider.getProperty("A Boolean").getBoolValues(), ElementsAre(true));
+ EXPECT_NEAR(mProvider.getProperty("A Real").getRealValues()[0], 3.14159, EPSILON);
+}
+
+TEST_F(PropertyProviderIdcLoadingTest, InvalidPropsIgnored) {
+ int intArrayData[2];
+ int initialInts[2] = {0, 1};
+ gesturePropProvider.create_int_fn(&mProvider, "Two Integers", intArrayData, 2, initialInts);
+
+ PropertyMap idcProps;
+ // Wrong type
+ idcProps.addProperty("gestureProp.An_Integer", "37.25");
+ // Wrong size
+ idcProps.addProperty("gestureProp.Two_Integers", "42");
+ // Doesn't exist
+ idcProps.addProperty("gestureProp.Some_Nonexistent_Property", "1");
+ // A valid assignment that should still be applied despite the others being invalid
+ idcProps.addProperty("gestureProp.A_Real", "3.14159");
+
+ mProvider.loadPropertiesFromIdcFile(idcProps);
+ EXPECT_THAT(mProvider.getProperty("An Integer").getIntValues(), ElementsAre(0));
+ EXPECT_THAT(mProvider.getProperty("Two Integers").getIntValues(), ElementsAre(0, 1));
+ EXPECT_FALSE(mProvider.hasProperty("Some Nonexistent Property"));
+ EXPECT_NEAR(mProvider.getProperty("A Real").getRealValues()[0], 3.14159, EPSILON);
+}
+
+TEST_F(PropertyProviderIdcLoadingTest, FunkyName) {
+ int data;
+ int initialData = 0;
+ gesturePropProvider.create_int_fn(&mProvider, " I lOvE sNAKes ", &data, 1, &initialData);
+
+ PropertyMap idcProps;
+ idcProps.addProperty("gestureProp.__I_lOvE_sNAKes_", "42");
+
+ mProvider.loadPropertiesFromIdcFile(idcProps);
+ EXPECT_THAT(mProvider.getProperty(" I lOvE sNAKes ").getIntValues(), ElementsAre(42));
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/TestConstants.h b/services/inputflinger/tests/TestConstants.h
index 27881f6f49..ad48b0fbe0 100644
--- a/services/inputflinger/tests/TestConstants.h
+++ b/services/inputflinger/tests/TestConstants.h
@@ -16,6 +16,10 @@
#pragma once
+#include <chrono>
+
+#include <utils/Timers.h>
+
namespace android {
using std::chrono_literals::operator""ms;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 3cdb3d5c76..064bbd246e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -167,6 +167,7 @@ auto DisplayDevice::getFrontEndInfo() const -> frontend::DisplayInfo {
.receivesInput = receivesInput(),
.isSecure = isSecure(),
.isPrimary = isPrimary(),
+ .isVirtual = isVirtual(),
.rotationFlags = ui::Transform::toRotationFlags(mOrientation),
.transformHint = getTransformHint()};
}
diff --git a/services/surfaceflinger/FrontEnd/DisplayInfo.h b/services/surfaceflinger/FrontEnd/DisplayInfo.h
index 6b9d7a2f5c..76b36fe0f2 100644
--- a/services/surfaceflinger/FrontEnd/DisplayInfo.h
+++ b/services/surfaceflinger/FrontEnd/DisplayInfo.h
@@ -30,6 +30,7 @@ struct DisplayInfo {
bool isSecure;
// TODO(b/238781169) can eliminate once sPrimaryDisplayRotationFlags is removed.
bool isPrimary;
+ bool isVirtual;
ui::Transform::RotationFlags rotationFlags;
ui::Transform::RotationFlags transformHint;
std::string getDebugString() const {
diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
index 5efa3944dd..ce21233424 100644
--- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.cpp
@@ -69,7 +69,9 @@ LayerCreationArgs::LayerCreationArgs(std::optional<uint32_t> id, bool internalLa
: LayerCreationArgs(nullptr, nullptr, /*name=*/"", /*flags=*/0, /*metadata=*/{}, id,
internalLayer) {}
-LayerCreationArgs::LayerCreationArgs(const LayerCreationArgs& args)
- : LayerCreationArgs(args.flinger, args.client, args.name, args.flags, args.metadata) {}
+LayerCreationArgs LayerCreationArgs::fromOtherArgs(const LayerCreationArgs& other) {
+ // returns a new instance of LayerCreationArgs with a unique id.
+ return LayerCreationArgs(other.flinger, other.client, other.name, other.flags, other.metadata);
+}
} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
index 8341e1dfc5..011250c52d 100644
--- a/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
+++ b/services/surfaceflinger/FrontEnd/LayerCreationArgs.h
@@ -37,13 +37,13 @@ namespace android::surfaceflinger {
struct LayerCreationArgs {
static std::atomic<uint32_t> sSequence;
static uint32_t getInternalLayerId(uint32_t id);
+ static LayerCreationArgs fromOtherArgs(const LayerCreationArgs& other);
LayerCreationArgs(android::SurfaceFlinger*, sp<android::Client>, std::string name,
uint32_t flags, gui::LayerMetadata, std::optional<uint32_t> id = std::nullopt,
bool internalLayer = false);
LayerCreationArgs(std::optional<uint32_t> id, bool internalLayer = false);
-
- LayerCreationArgs(const LayerCreationArgs&);
+ LayerCreationArgs() = default; // for tracing
android::SurfaceFlinger* flinger;
sp<android::Client> client;
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
index 3dd89badff..b25b731356 100644
--- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h
+++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h
@@ -104,6 +104,16 @@ public:
static const TraversalPath ROOT;
};
+ struct TraversalPathHash {
+ std::size_t operator()(const LayerHierarchy::TraversalPath& key) const {
+ uint32_t hashCode = key.id * 31;
+ if (key.mirrorRootId != UNASSIGNED_LAYER_ID) {
+ hashCode += key.mirrorRootId * 31;
+ }
+ return std::hash<size_t>{}(hashCode);
+ }
+ };
+
// Helper class to add nodes to an existing traversal id and removes the
// node when it goes out of scope.
class ScopedAddToTraversalPath {
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
index fe42422f6f..3706225228 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.cpp
@@ -71,12 +71,14 @@ void LayerLifecycleManager::addLayers(std::vector<std::unique_ptr<RequestedLayer
}
}
-void LayerLifecycleManager::onHandlesDestroyed(const std::vector<uint32_t>& destroyedHandles) {
+void LayerLifecycleManager::onHandlesDestroyed(const std::vector<uint32_t>& destroyedHandles,
+ bool ignoreUnknownHandles) {
std::vector<uint32_t> layersToBeDestroyed;
for (const auto& layerId : destroyedHandles) {
auto it = mIdToLayer.find(layerId);
if (it == mIdToLayer.end()) {
- LOG_ALWAYS_FATAL("%s Layerid not found %d", __func__, layerId);
+ LOG_ALWAYS_FATAL_IF(!ignoreUnknownHandles, "%s Layerid not found %d", __func__,
+ layerId);
continue;
}
RequestedLayerState& layer = it->second.owner;
diff --git a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
index 25d27ee373..3d9a74c843 100644
--- a/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
+++ b/services/surfaceflinger/FrontEnd/LayerLifecycleManager.h
@@ -40,7 +40,10 @@ public:
// External state changes should be updated in the following order:
void addLayers(std::vector<std::unique_ptr<RequestedLayerState>>);
void applyTransactions(const std::vector<TransactionState>&);
- void onHandlesDestroyed(const std::vector<uint32_t>&);
+ // Ignore unknown handles when iteroping with legacy front end. In the old world, we
+ // would create child layers which are not necessary with the new front end. This means
+ // we will get notified for handle changes that don't exist in the new front end.
+ void onHandlesDestroyed(const std::vector<uint32_t>&, bool ignoreUnknownHandles = false);
// Detaches the layer from its relative parent to prevent a loop in the
// layer hierarchy. This overrides the RequestedLayerState and leaves
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
index 8a450933f0..5e7c25946b 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshot.cpp
@@ -28,9 +28,14 @@ LayerSnapshot::LayerSnapshot(const RequestedLayerState& state,
const LayerHierarchy::TraversalPath& path)
: path(path) {
static uint32_t sUniqueSequenceId = 0;
- // Provide a unique id for clones otherwise keeping using the sequence id.
- // The seq id can still be useful for debugging if its available.
- uniqueSequence = (path.isClone()) ? sUniqueSequenceId++ : state.id;
+ // Provide a unique id for all snapshots.
+ // A front end layer can generate multiple snapshots if its mirrored.
+ // Additionally, if the layer is not reachable, we may choose to destroy
+ // and recreate the snapshot in which case the unique sequence id will
+ // change. The consumer shouldn't tie any lifetimes to this unique id but
+ // register a LayerLifecycleManager::ILifecycleListener or get a list of
+ // destroyed layers from LayerLifecycleManager.
+ uniqueSequence = sUniqueSequenceId++;
sequence = static_cast<int32_t>(state.id);
name = state.name;
textureName = state.textureName;
diff --git a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
index 3997a0ad83..7b1ff2710b 100644
--- a/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
+++ b/services/surfaceflinger/FrontEnd/LayerSnapshotBuilder.h
@@ -68,6 +68,7 @@ public:
void update(const Args&);
std::vector<std::unique_ptr<LayerSnapshot>>& getSnapshots();
LayerSnapshot* getSnapshot(uint32_t layerId) const;
+ LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath& id) const;
typedef std::function<void(const LayerSnapshot& snapshot)> ConstVisitor;
@@ -86,7 +87,6 @@ public:
private:
friend class LayerSnapshotTest;
- LayerSnapshot* getSnapshot(const LayerHierarchy::TraversalPath& id) const;
static LayerSnapshot getRootSnapshot();
// return true if we were able to successfully update the snapshots via
@@ -120,16 +120,8 @@ private:
void updateChildState(LayerSnapshot& snapshot, const LayerSnapshot& childSnapshot,
const Args& args);
- struct TraversalPathHash {
- std::size_t operator()(const LayerHierarchy::TraversalPath& key) const {
- uint32_t hashCode = key.id * 31;
- if (key.mirrorRootId != UNASSIGNED_LAYER_ID) {
- hashCode += key.mirrorRootId * 31;
- }
- return std::hash<size_t>{}(hashCode);
- }
- };
- std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*, TraversalPathHash>
+ std::unordered_map<LayerHierarchy::TraversalPath, LayerSnapshot*,
+ LayerHierarchy::TraversalPathHash>
mIdToSnapshot;
std::vector<std::unique_ptr<LayerSnapshot>> mSnapshots;
LayerSnapshot mRootSnapshot;
diff --git a/services/surfaceflinger/FrontEnd/Update.h b/services/surfaceflinger/FrontEnd/Update.h
new file mode 100644
index 0000000000..e1449b6e1b
--- /dev/null
+++ b/services/surfaceflinger/FrontEnd/Update.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2023 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 <gui/DisplayInfo.h>
+
+#include "FrontEnd/LayerCreationArgs.h"
+#include "RequestedLayerState.h"
+#include "TransactionState.h"
+
+namespace android {
+struct LayerCreatedState {
+ LayerCreatedState(const wp<Layer>& layer, const wp<Layer>& parent, bool addToRoot)
+ : layer(layer), initialParent(parent), addToRoot(addToRoot) {}
+ wp<Layer> layer;
+ // Indicates the initial parent of the created layer, only used for creating layer in
+ // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers.
+ wp<Layer> initialParent;
+ // Indicates whether the layer getting created should be added at root if there's no parent
+ // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will
+ // be added offscreen.
+ bool addToRoot;
+};
+} // namespace android
+
+namespace android::surfaceflinger::frontend {
+
+// Atomic set of changes affecting layer state. These changes are queued in binder threads and
+// applied every vsync.
+struct Update {
+ std::vector<TransactionState> transactions;
+ std::vector<LayerCreatedState> layerCreatedStates;
+ std::vector<std::unique_ptr<frontend::RequestedLayerState>> newLayers;
+ std::vector<LayerCreationArgs> layerCreationArgs;
+ std::vector<uint32_t> destroyedHandles;
+};
+
+} // namespace android::surfaceflinger::frontend
diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp
index 55281fa962..b5ae1a7f5a 100644
--- a/services/surfaceflinger/LayerProtoHelper.cpp
+++ b/services/surfaceflinger/LayerProtoHelper.cpp
@@ -15,6 +15,8 @@
*/
// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#include "FrontEnd/LayerCreationArgs.h"
+#include "FrontEnd/LayerSnapshot.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wextra"
@@ -248,47 +250,88 @@ void LayerProtoHelper::readFromProto(const BlurRegion& proto, android::BlurRegio
outRegion.bottom = proto.bottom();
}
-void LayerProtoHelper::writeHierarchyToProto(
- LayersProto& outLayersProto, const frontend::LayerHierarchy& root,
- const frontend::LayerSnapshotBuilder& snapshotBuilder,
- const std::unordered_map<uint32_t, sp<Layer>>& legacyLayers, uint32_t traceFlags) {
- using Variant = frontend::LayerHierarchy::Variant;
- frontend::LayerSnapshot defaultSnapshot;
-
- LayerProto* layerProto = outLayersProto.add_layers();
- const frontend::RequestedLayerState& layer = *root.getLayer();
- frontend::LayerSnapshot* snapshot = snapshotBuilder.getSnapshot(layer.id);
+LayersProto LayerProtoFromSnapshotGenerator::generate(const frontend::LayerHierarchy& root) {
+ mLayersProto.clear_layers();
+ std::unordered_set<uint64_t> stackIdsToSkip;
+ if ((mTraceFlags & LayerTracing::TRACE_VIRTUAL_DISPLAYS) == 0) {
+ for (const auto& [layerStack, displayInfo] : mDisplayInfos) {
+ if (displayInfo.isVirtual) {
+ stackIdsToSkip.insert(layerStack.id);
+ }
+ }
+ }
- if (!snapshot) {
- defaultSnapshot.uniqueSequence = layer.id;
- snapshot = &defaultSnapshot;
+ frontend::LayerHierarchy::TraversalPath path = frontend::LayerHierarchy::TraversalPath::ROOT;
+ for (auto& [child, variant] : root.mChildren) {
+ if (variant != frontend::LayerHierarchy::Variant::Attached ||
+ stackIdsToSkip.find(child->getLayer()->layerStack.id) != stackIdsToSkip.end()) {
+ continue;
+ }
+ frontend::LayerHierarchy::ScopedAddToTraversalPath addChildToPath(path,
+ child->getLayer()->id,
+ variant);
+ LayerProtoFromSnapshotGenerator::writeHierarchyToProto(*child, path);
}
- writeSnapshotToProto(layerProto, layer, *snapshot, traceFlags);
- for (const auto& [child, variant] : root.mChildren) {
- if (variant == Variant::Attached || variant == Variant::Detached) {
- layerProto->add_children(child->getLayer()->id);
- } else if (variant == Variant::Relative) {
- layerProto->add_relatives(child->getLayer()->id);
+
+ // fill in relative and parent info
+ for (int i = 0; i < mLayersProto.layers_size(); i++) {
+ auto layerProto = mLayersProto.mutable_layers()->Mutable(i);
+ auto it = mChildToRelativeParent.find(layerProto->id());
+ if (it == mChildToRelativeParent.end()) {
+ layerProto->set_z_order_relative_of(-1);
+ } else {
+ layerProto->set_z_order_relative_of(it->second);
+ }
+ it = mChildToParent.find(layerProto->id());
+ if (it == mChildToParent.end()) {
+ layerProto->set_parent(-1);
+ } else {
+ layerProto->set_parent(it->second);
}
}
- auto parent = root.getParent();
- if (parent && parent->getLayer()) {
- layerProto->set_parent(parent->getLayer()->id);
+ mDefaultSnapshots.clear();
+ mChildToRelativeParent.clear();
+ return std::move(mLayersProto);
+}
+
+frontend::LayerSnapshot* LayerProtoFromSnapshotGenerator::getSnapshot(
+ frontend::LayerHierarchy::TraversalPath& path, const frontend::RequestedLayerState& layer) {
+ frontend::LayerSnapshot* snapshot = mSnapshotBuilder.getSnapshot(path);
+ if (snapshot) {
+ return snapshot;
} else {
- layerProto->set_parent(-1);
+ mDefaultSnapshots[path] = frontend::LayerSnapshot(layer, path);
+ return &mDefaultSnapshots[path];
}
+}
- auto relativeParent = root.getRelativeParent();
- if (relativeParent && relativeParent->getLayer()) {
- layerProto->set_z_order_relative_of(relativeParent->getLayer()->id);
- } else {
- layerProto->set_z_order_relative_of(-1);
+void LayerProtoFromSnapshotGenerator::writeHierarchyToProto(
+ const frontend::LayerHierarchy& root, frontend::LayerHierarchy::TraversalPath& path) {
+ using Variant = frontend::LayerHierarchy::Variant;
+ LayerProto* layerProto = mLayersProto.add_layers();
+ const frontend::RequestedLayerState& layer = *root.getLayer();
+ frontend::LayerSnapshot* snapshot = getSnapshot(path, layer);
+ LayerProtoHelper::writeSnapshotToProto(layerProto, layer, *snapshot, mTraceFlags);
+
+ for (const auto& [child, variant] : root.mChildren) {
+ frontend::LayerHierarchy::ScopedAddToTraversalPath addChildToPath(path,
+ child->getLayer()->id,
+ variant);
+ frontend::LayerSnapshot* childSnapshot = getSnapshot(path, layer);
+ if (variant == Variant::Attached || variant == Variant::Detached ||
+ variant == Variant::Mirror) {
+ mChildToParent[childSnapshot->uniqueSequence] = snapshot->uniqueSequence;
+ layerProto->add_children(childSnapshot->uniqueSequence);
+ } else if (variant == Variant::Relative) {
+ mChildToRelativeParent[childSnapshot->uniqueSequence] = snapshot->uniqueSequence;
+ layerProto->add_relatives(childSnapshot->uniqueSequence);
+ }
}
- if (traceFlags & LayerTracing::TRACE_COMPOSITION) {
- auto it = legacyLayers.find(layer.id);
- if (it != legacyLayers.end()) {
+ if (mTraceFlags & LayerTracing::TRACE_COMPOSITION) {
+ auto it = mLegacyLayers.find(layer.id);
+ if (it != mLegacyLayers.end()) {
it->second->writeCompositionStateToProto(layerProto);
}
}
@@ -298,7 +341,10 @@ void LayerProtoHelper::writeHierarchyToProto(
if (variant == Variant::Detached) {
continue;
}
- writeHierarchyToProto(outLayersProto, *child, snapshotBuilder, legacyLayers, traceFlags);
+ frontend::LayerHierarchy::ScopedAddToTraversalPath addChildToPath(path,
+ child->getLayer()->id,
+ variant);
+ writeHierarchyToProto(*child, path);
}
}
@@ -345,6 +391,7 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo,
layerInfo->set_shadow_radius(snapshot.shadowRadius);
layerInfo->set_id(snapshot.uniqueSequence);
+ layerInfo->set_original_id(snapshot.sequence);
layerInfo->set_name(requestedState.name);
layerInfo->set_type("Layer");
@@ -394,6 +441,22 @@ void LayerProtoHelper::writeSnapshotToProto(LayerProto* layerInfo,
[&]() { return layerInfo->mutable_destination_frame(); });
}
+google::protobuf::RepeatedPtrField<DisplayProto> LayerProtoHelper::writeDisplayInfoToProto(
+ const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displayInfos) {
+ google::protobuf::RepeatedPtrField<DisplayProto> displays;
+ displays.Reserve(displayInfos.size());
+ for (const auto& [layerStack, displayInfo] : displayInfos) {
+ auto displayProto = displays.Add();
+ displayProto->set_id(displayInfo.info.displayId);
+ displayProto->set_layer_stack(layerStack.id);
+ displayProto->mutable_size()->set_w(displayInfo.info.logicalWidth);
+ displayProto->mutable_size()->set_h(displayInfo.info.logicalHeight);
+ writeTransformToProto(displayInfo.transform, displayProto->mutable_transform());
+ displayProto->set_is_virtual(displayInfo.isVirtual);
+ }
+ return displays;
+}
+
} // namespace surfaceflinger
} // namespace android
diff --git a/services/surfaceflinger/LayerProtoHelper.h b/services/surfaceflinger/LayerProtoHelper.h
index de4bd01f1a..b84a49b27c 100644
--- a/services/surfaceflinger/LayerProtoHelper.h
+++ b/services/surfaceflinger/LayerProtoHelper.h
@@ -25,6 +25,9 @@
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Transform.h>
+#include <cstdint>
+#include "FrontEnd/LayerHierarchy.h"
+#include "FrontEnd/LayerSnapshot.h"
namespace android {
namespace surfaceflinger {
@@ -58,15 +61,44 @@ public:
static void readFromProto(const ColorTransformProto& colorTransformProto, mat4& matrix);
static void writeToProto(const android::BlurRegion region, BlurRegion*);
static void readFromProto(const BlurRegion& proto, android::BlurRegion& outRegion);
- static void writeHierarchyToProto(LayersProto& layersProto,
- const frontend::LayerHierarchy& root,
- const frontend::LayerSnapshotBuilder& snapshotBuilder,
- const std::unordered_map<uint32_t, sp<Layer>>& mLegacyLayers,
- uint32_t traceFlags);
-
static void writeSnapshotToProto(LayerProto* outProto,
const frontend::RequestedLayerState& requestedState,
const frontend::LayerSnapshot& snapshot, uint32_t traceFlags);
+ static google::protobuf::RepeatedPtrField<DisplayProto> writeDisplayInfoToProto(
+ const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displayInfos);
+};
+
+class LayerProtoFromSnapshotGenerator {
+public:
+ LayerProtoFromSnapshotGenerator(
+ const frontend::LayerSnapshotBuilder& snapshotBuilder,
+ const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displayInfos,
+ const std::unordered_map<uint32_t, sp<Layer>>& legacyLayers, uint32_t traceFlags)
+ : mSnapshotBuilder(snapshotBuilder),
+ mLegacyLayers(legacyLayers),
+ mDisplayInfos(displayInfos),
+ mTraceFlags(traceFlags) {}
+ LayersProto generate(const frontend::LayerHierarchy& root);
+
+private:
+ void writeHierarchyToProto(const frontend::LayerHierarchy& root,
+ frontend::LayerHierarchy::TraversalPath& path);
+ frontend::LayerSnapshot* getSnapshot(frontend::LayerHierarchy::TraversalPath& path,
+ const frontend::RequestedLayerState& layer);
+
+ const frontend::LayerSnapshotBuilder& mSnapshotBuilder;
+ const std::unordered_map<uint32_t, sp<Layer>>& mLegacyLayers;
+ const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& mDisplayInfos;
+ uint32_t mTraceFlags;
+ LayersProto mLayersProto;
+ // winscope expects all the layers, so provide a snapshot even if it not currently drawing
+ std::unordered_map<frontend::LayerHierarchy::TraversalPath, frontend::LayerSnapshot,
+ frontend::LayerHierarchy::TraversalPathHash>
+ mDefaultSnapshots;
+ std::unordered_map<uint32_t /* child unique seq*/, uint32_t /* relative parent unique seq*/>
+ mChildToRelativeParent;
+ std::unordered_map<uint32_t /* child unique seq*/, uint32_t /* parent unique seq*/>
+ mChildToParent;
};
} // namespace surfaceflinger
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 63b7f75c84..8ce479a213 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -105,6 +105,7 @@
#include <memory>
#include <mutex>
#include <optional>
+#include <string>
#include <type_traits>
#include <unordered_map>
#include <vector>
@@ -130,6 +131,7 @@
#include "FrameTracer/FrameTracer.h"
#include "FrontEnd/LayerCreationArgs.h"
#include "FrontEnd/LayerHandle.h"
+#include "FrontEnd/LayerLifecycleManager.h"
#include "FrontEnd/LayerSnapshot.h"
#include "HdrLayerInfoReporter.h"
#include "Layer.h"
@@ -2183,7 +2185,7 @@ void SurfaceFlinger::configure() FTL_FAKE_GUARD(kMainThreadContext) {
}
}
-bool SurfaceFlinger::updateLayerSnapshotsLegacy(VsyncId vsyncId, LifecycleUpdate& update,
+bool SurfaceFlinger::updateLayerSnapshotsLegacy(VsyncId vsyncId, frontend::Update& update,
bool transactionsFlushed,
bool& outTransactionsAreEmpty) {
bool needsTraversal = false;
@@ -2235,7 +2237,7 @@ void SurfaceFlinger::updateLayerHistory(const frontend::LayerSnapshot& snapshot)
}
}
-bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, LifecycleUpdate& update,
+bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, frontend::Update& update,
bool transactionsFlushed, bool& outTransactionsAreEmpty) {
using Changes = frontend::RequestedLayerState::Changes;
ATRACE_NAME("updateLayerSnapshots");
@@ -2485,9 +2487,14 @@ bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expe
Fps::fromPeriodNsecs(vsyncPeriod.ns()));
const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded);
- LifecycleUpdate updates;
+ frontend::Update updates;
if (flushTransactions) {
updates = flushLifecycleUpdates();
+ if (mTransactionTracing) {
+ mTransactionTracing->addCommittedTransactions(vsyncId.value, frameTime.ns(),
+ updates, mFrontEndDisplayInfos,
+ mFrontEndDisplayInfosChanged);
+ }
}
bool transactionsAreEmpty;
if (mLegacyFrontEndEnabled) {
@@ -2529,7 +2536,7 @@ bool SurfaceFlinger::commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expe
if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and tracing should only be enabled for debugging.
- mLayerTracing.notify(mVisibleRegionsDirty, frameTime.ns(), vsyncId.value);
+ addToLayerTracing(mVisibleRegionsDirty, frameTime.ns(), vsyncId.value);
}
mLastCommittedVsyncId = vsyncId;
@@ -2700,7 +2707,7 @@ void SurfaceFlinger::composite(TimePoint frameTime, VsyncId vsyncId)
mLayersWithQueuedFrames.clear();
if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and should only be used for debugging.
- mLayerTracing.notify(mVisibleRegionsDirty, frameTime.ns(), vsyncId.value);
+ addToLayerTracing(mVisibleRegionsDirty, frameTime.ns(), vsyncId.value);
}
if (mVisibleRegionsDirty) mHdrLayerInfoChanged = true;
@@ -4112,6 +4119,9 @@ status_t SurfaceFlinger::addClientLayer(LayerCreationArgs& args, const sp<IBinde
std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
mCreatedLayers.emplace_back(layer, parent, args.addToRoot);
mNewLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args));
+ args.mirrorLayerHandle.clear();
+ args.parentHandle.clear();
+ mNewLayerArgs.emplace_back(std::move(args));
}
setTransactionFlags(eTransactionNeeded);
@@ -4297,10 +4307,6 @@ bool SurfaceFlinger::applyTransactionsLocked(std::vector<TransactionState>& tran
transaction.listenerCallbacks, transaction.originPid,
transaction.originUid, transaction.id);
}
-
- if (mTransactionTracing) {
- mTransactionTracing->addCommittedTransactions(transactions, vsyncId.value);
- }
return needsTraversal;
}
@@ -5142,7 +5148,7 @@ status_t SurfaceFlinger::mirrorLayer(const LayerCreationArgs& args,
sp<Layer> mirrorLayer;
sp<Layer> mirrorFrom;
- LayerCreationArgs mirrorArgs(args);
+ LayerCreationArgs mirrorArgs = LayerCreationArgs::fromOtherArgs(args);
{
Mutex::Autolock _l(mStateLock);
mirrorFrom = LayerHandle::getLayer(mirrorFromHandle);
@@ -5162,11 +5168,6 @@ status_t SurfaceFlinger::mirrorLayer(const LayerCreationArgs& args,
outResult.layerId = mirrorLayer->sequence;
outResult.layerName = String16(mirrorLayer->getDebugName());
- if (mTransactionTracing) {
- mTransactionTracing->onMirrorLayerAdded(outResult.handle->localBinder(),
- mirrorLayer->sequence, args.name,
- mirrorFrom->sequence);
- }
return addClientLayer(mirrorArgs, outResult.handle, mirrorLayer /* layer */,
nullptr /* parent */, nullptr /* outTransformHint */);
}
@@ -5193,7 +5194,7 @@ status_t SurfaceFlinger::mirrorDisplay(DisplayId displayId, const LayerCreationA
}
layerStack = display->getLayerStack();
- LayerCreationArgs mirrorArgs(args);
+ LayerCreationArgs mirrorArgs = LayerCreationArgs::fromOtherArgs(args);
mirrorArgs.flags |= ISurfaceComposerClient::eNoColorFill;
mirrorArgs.addToRoot = true;
mirrorArgs.layerStackToMirror = layerStack;
@@ -5208,11 +5209,6 @@ status_t SurfaceFlinger::mirrorDisplay(DisplayId displayId, const LayerCreationA
return result;
}
- if (mTransactionTracing) {
- mTransactionTracing->onLayerAdded(outResult.handle->localBinder(), outResult.layerId,
- args.name, args.flags, -1 /* parentId */);
- }
-
if (mLegacyFrontEndEnabled) {
std::scoped_lock<std::mutex> lock(mMirrorDisplayLock);
mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client);
@@ -5260,12 +5256,6 @@ status_t SurfaceFlinger::createLayer(LayerCreationArgs& args, gui::CreateSurface
args.addToRoot = false;
}
- const int parentId = parent ? parent->getSequence() : -1;
- if (mTransactionTracing) {
- mTransactionTracing->onLayerAdded(outResult.handle->localBinder(), layer->sequence,
- args.name, args.flags, parentId);
- }
-
uint32_t outTransformHint;
result = addClientLayer(args, outResult.handle, layer, parent, &outTransformHint);
if (result != NO_ERROR) {
@@ -5309,9 +5299,6 @@ void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32
markLayerPendingRemovalLocked(layer);
mBufferCountTracker.remove(handle);
layer.clear();
- if (mTransactionTracing) {
- mTransactionTracing->onHandleRemoved(handle);
- }
setTransactionFlags(eTransactionFlushNeeded);
}
@@ -5562,7 +5549,8 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
LayersTraceProto* layersTrace = traceFileProto.add_entry();
LayersProto layersProto = dumpProtoFromMainThread();
layersTrace->mutable_layers()->Swap(&layersProto);
- dumpDisplayProto(*layersTrace);
+ auto displayProtos = dumpDisplayProto();
+ layersTrace->mutable_displays()->Swap(&displayProtos);
if (asProto) {
result.append(traceFileProto.SerializeAsString());
@@ -5801,22 +5789,15 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const {
return layersProto;
}
- const frontend::LayerHierarchy& root = mLayerHierarchyBuilder.getHierarchy();
- LayersProto layersProto;
- for (auto& [child, variant] : root.mChildren) {
- if (variant != frontend::LayerHierarchy::Variant::Attached ||
- stackIdsToSkip.find(child->getLayer()->layerStack.id) != stackIdsToSkip.end()) {
- continue;
- }
- LayerProtoHelper::writeHierarchyToProto(layersProto, *child, mLayerSnapshotBuilder,
- mLegacyLayers, traceFlags);
- }
- return layersProto;
+ return LayerProtoFromSnapshotGenerator(mLayerSnapshotBuilder, mFrontEndDisplayInfos, {},
+ traceFlags)
+ .generate(mLayerHierarchyBuilder.getHierarchy());
}
-void SurfaceFlinger::dumpDisplayProto(LayersTraceProto& layersTraceProto) const {
+google::protobuf::RepeatedPtrField<DisplayProto> SurfaceFlinger::dumpDisplayProto() const {
+ google::protobuf::RepeatedPtrField<DisplayProto> displays;
for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) {
- DisplayProto* displayProto = layersTraceProto.add_displays();
+ DisplayProto* displayProto = displays.Add();
displayProto->set_id(display->getId().value);
displayProto->set_name(display->getDisplayName());
displayProto->set_layer_stack(display->getLayerStack().id);
@@ -5829,6 +5810,7 @@ void SurfaceFlinger::dumpDisplayProto(LayersTraceProto& layersTraceProto) const
displayProto->mutable_transform());
displayProto->set_is_virtual(display->isVirtual());
}
+ return displays;
}
void SurfaceFlinger::dumpHwc(std::string& result) const {
@@ -6359,9 +6341,10 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r
int64_t startingTime =
(fixedStartingTime) ? fixedStartingTime : systemTime();
mScheduler
- ->schedule([&]() FTL_FAKE_GUARD(mStateLock) {
- mLayerTracing.notify(true /* visibleRegionDirty */,
- startingTime, mLastCommittedVsyncId.value);
+ ->schedule([&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(
+ kMainThreadContext) {
+ addToLayerTracing(true /* visibleRegionDirty */, startingTime,
+ mLastCommittedVsyncId.value);
})
.wait();
}
@@ -7724,10 +7707,6 @@ void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state, Vs
if (hintDisplay) {
layer->updateTransformHint(hintDisplay->getTransformHint());
}
-
- if (mTransactionTracing) {
- mTransactionTracing->onLayerAddedToDrawingState(layer->getSequence(), vsyncId.value);
- }
}
void SurfaceFlinger::sample() {
@@ -7868,10 +7847,6 @@ bool SurfaceFlinger::commitMirrorDisplays(VsyncId vsyncId) {
sp<Layer> childMirror;
createEffectLayer(mirrorArgs, &unused, &childMirror);
childMirror->setClonedChild(layer->createClone());
- if (mTransactionTracing) {
- mTransactionTracing->onLayerAddedToDrawingState(childMirror->getSequence(),
- vsyncId.value);
- }
childMirror->reparent(mirrorDisplay.rootHandle);
}
}
@@ -8056,8 +8031,8 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(uint32_t rootLayerId, uint32_t u
};
}
-SurfaceFlinger::LifecycleUpdate SurfaceFlinger::flushLifecycleUpdates() {
- LifecycleUpdate update;
+frontend::Update SurfaceFlinger::flushLifecycleUpdates() {
+ frontend::Update update;
ATRACE_NAME("TransactionHandler:flushTransactions");
// Locking:
// 1. to prevent onHandleDestroyed from being called while the state lock is held,
@@ -8074,12 +8049,28 @@ SurfaceFlinger::LifecycleUpdate SurfaceFlinger::flushLifecycleUpdates() {
mCreatedLayers.clear();
update.newLayers = std::move(mNewLayers);
mNewLayers.clear();
+ update.layerCreationArgs = std::move(mNewLayerArgs);
+ mNewLayerArgs.clear();
update.destroyedHandles = std::move(mDestroyedHandles);
mDestroyedHandles.clear();
}
return update;
}
+void SurfaceFlinger::addToLayerTracing(bool visibleRegionDirty, int64_t time, int64_t vsyncId) {
+ const uint32_t tracingFlags = mLayerTracing.getFlags();
+ LayersProto layers(dumpDrawingStateProto(tracingFlags));
+ if (tracingFlags & LayerTracing::TRACE_EXTRA) {
+ dumpOffscreenLayersProto(layers);
+ }
+ std::string hwcDump;
+ if (tracingFlags & LayerTracing::TRACE_HWC) {
+ dumpHwc(hwcDump);
+ }
+ auto displays = dumpDisplayProto();
+ mLayerTracing.notify(visibleRegionDirty, time, vsyncId, &layers, std::move(hwcDump), &displays);
+}
+
// gui::ISurfaceComposer
binder::Status SurfaceComposerAIDL::bootFinished() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 63d54bc24d..42d5db7cc9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -455,26 +455,6 @@ private:
FINISHED,
};
- struct LayerCreatedState {
- LayerCreatedState(const wp<Layer>& layer, const wp<Layer>& parent, bool addToRoot)
- : layer(layer), initialParent(parent), addToRoot(addToRoot) {}
- wp<Layer> layer;
- // Indicates the initial parent of the created layer, only used for creating layer in
- // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers.
- wp<Layer> initialParent;
- // Indicates whether the layer getting created should be added at root if there's no parent
- // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will
- // be added offscreen.
- bool addToRoot;
- };
-
- struct LifecycleUpdate {
- std::vector<TransactionState> transactions;
- std::vector<LayerCreatedState> layerCreatedStates;
- std::vector<std::unique_ptr<frontend::RequestedLayerState>> newLayers;
- std::vector<uint32_t> destroyedHandles;
- };
-
template <typename F, std::enable_if_t<!std::is_member_function_pointer_v<F>>* = nullptr>
static Dumper dumper(F&& dump) {
using namespace std::placeholders;
@@ -721,13 +701,13 @@ private:
int64_t vsyncId);
void moveSnapshotsFromCompositionArgs(compositionengine::CompositionRefreshArgs& refreshArgs,
std::vector<std::pair<Layer*, LayerFE*>>& layers);
- bool updateLayerSnapshotsLegacy(VsyncId vsyncId, LifecycleUpdate& update,
+ bool updateLayerSnapshotsLegacy(VsyncId vsyncId, frontend::Update& update,
bool transactionsFlushed, bool& out)
REQUIRES(kMainThreadContext);
- bool updateLayerSnapshots(VsyncId vsyncId, LifecycleUpdate& update, bool transactionsFlushed,
+ bool updateLayerSnapshots(VsyncId vsyncId, frontend::Update& update, bool transactionsFlushed,
bool& out) REQUIRES(kMainThreadContext);
void updateLayerHistory(const frontend::LayerSnapshot& snapshot);
- LifecycleUpdate flushLifecycleUpdates() REQUIRES(kMainThreadContext);
+ frontend::Update flushLifecycleUpdates() REQUIRES(kMainThreadContext);
void updateInputFlinger();
void persistDisplayBrightness(bool needsComposite) REQUIRES(kMainThreadContext);
@@ -1086,7 +1066,9 @@ private:
LayersProto dumpDrawingStateProto(uint32_t traceFlags) const;
void dumpOffscreenLayersProto(LayersProto& layersProto,
uint32_t traceFlags = LayerTracing::TRACE_ALL) const;
- void dumpDisplayProto(LayersTraceProto& layersTraceProto) const;
+ google::protobuf::RepeatedPtrField<DisplayProto> dumpDisplayProto() const;
+ void addToLayerTracing(bool visibleRegionDirty, int64_t time, int64_t vsyncId)
+ REQUIRES(kMainThreadContext);
// Dumps state from HW Composer
void dumpHwc(std::string& result) const;
@@ -1240,7 +1222,7 @@ private:
bool mLayerCachingEnabled = false;
bool mBackpressureGpuComposition = false;
- LayerTracing mLayerTracing{*this};
+ LayerTracing mLayerTracing;
bool mLayerTracingEnabled = false;
std::optional<TransactionTracing> mTransactionTracing;
@@ -1422,6 +1404,7 @@ private:
std::vector<uint32_t> mDestroyedHandles;
std::vector<std::unique_ptr<frontend::RequestedLayerState>> mNewLayers;
+ std::vector<LayerCreationArgs> mNewLayerArgs;
// These classes do not store any client state but help with managing transaction callbacks
// and stats.
std::unordered_map<uint32_t, sp<Layer>> mLegacyLayers;
diff --git a/services/surfaceflinger/Tracing/LayerTracing.cpp b/services/surfaceflinger/Tracing/LayerTracing.cpp
index 566d55353f..2918f7cd37 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.cpp
+++ b/services/surfaceflinger/Tracing/LayerTracing.cpp
@@ -29,9 +29,8 @@
namespace android {
-LayerTracing::LayerTracing(SurfaceFlinger& flinger) : mFlinger(flinger) {
- mBuffer = std::make_unique<RingBuffer<LayersTraceFileProto, LayersTraceProto>>();
-}
+LayerTracing::LayerTracing()
+ : mBuffer(std::make_unique<RingBuffer<LayersTraceFileProto, LayersTraceProto>>()) {}
LayerTracing::~LayerTracing() = default;
@@ -84,8 +83,11 @@ void LayerTracing::setBufferSize(size_t bufferSizeInBytes) {
bool LayerTracing::flagIsSet(uint32_t flags) const {
return (mFlags & flags) == flags;
}
+uint32_t LayerTracing::getFlags() const {
+ return mFlags;
+}
-LayersTraceFileProto LayerTracing::createTraceFileProto() const {
+LayersTraceFileProto LayerTracing::createTraceFileProto() {
LayersTraceFileProto fileProto;
fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 |
LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L);
@@ -101,7 +103,9 @@ void LayerTracing::dump(std::string& result) const {
mBuffer->dump(result);
}
-void LayerTracing::notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId) {
+void LayerTracing::notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId,
+ LayersProto* layers, std::string hwcDump,
+ google::protobuf::RepeatedPtrField<DisplayProto>* displays) {
std::scoped_lock lock(mTraceLock);
if (!mEnabled) {
return;
@@ -116,22 +120,15 @@ void LayerTracing::notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId
entry.set_elapsed_realtime_nanos(time);
const char* where = visibleRegionDirty ? "visibleRegionsDirty" : "bufferLatched";
entry.set_where(where);
- LayersProto layers(mFlinger.dumpDrawingStateProto(mFlags));
-
- if (flagIsSet(LayerTracing::TRACE_EXTRA)) {
- mFlinger.dumpOffscreenLayersProto(layers);
- }
- entry.mutable_layers()->Swap(&layers);
+ entry.mutable_layers()->Swap(layers);
if (flagIsSet(LayerTracing::TRACE_HWC)) {
- std::string hwcDump;
- mFlinger.dumpHwc(hwcDump);
entry.set_hwc_blob(hwcDump);
}
if (!flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
entry.set_excludes_composition_state(true);
}
- mFlinger.dumpDisplayProto(entry);
+ entry.mutable_displays()->Swap(displays);
entry.set_vsync_id(vsyncId);
mBuffer->emplace(std::move(entry));
}
diff --git a/services/surfaceflinger/Tracing/LayerTracing.h b/services/surfaceflinger/Tracing/LayerTracing.h
index b32001cc63..11bb9f45df 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.h
+++ b/services/surfaceflinger/Tracing/LayerTracing.h
@@ -40,14 +40,15 @@ class SurfaceFlinger;
*/
class LayerTracing {
public:
- LayerTracing(SurfaceFlinger& flinger);
+ LayerTracing();
~LayerTracing();
bool enable();
bool disable(std::string filename = FILE_NAME);
bool isEnabled() const;
status_t writeToFile();
- LayersTraceFileProto createTraceFileProto() const;
- void notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId);
+ static LayersTraceFileProto createTraceFileProto();
+ void notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId, LayersProto* layers,
+ std::string hwcDump, google::protobuf::RepeatedPtrField<DisplayProto>* displays);
enum : uint32_t {
TRACE_INPUT = 1 << 1,
@@ -60,13 +61,12 @@ public:
};
void setTraceFlags(uint32_t flags);
bool flagIsSet(uint32_t flags) const;
+ uint32_t getFlags() const;
void setBufferSize(size_t bufferSizeInBytes);
void dump(std::string&) const;
private:
static constexpr auto FILE_NAME = "/data/misc/wmtrace/layers_trace.winscope";
-
- SurfaceFlinger& mFlinger;
uint32_t mFlags = TRACE_INPUT;
mutable std::mutex mTraceLock;
bool mEnabled GUARDED_BY(mTraceLock) = false;
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index ba08ceebc7..8fd653880c 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -15,15 +15,43 @@
*/
#include <gui/SurfaceComposerClient.h>
-#include <renderengine/mock/FakeExternalTexture.h>
#include <ui/Fence.h>
#include <ui/Rect.h>
+#include "FrontEnd/LayerCreationArgs.h"
#include "LayerProtoHelper.h"
#include "TransactionProtoParser.h"
+#include "TransactionState.h"
+#include "gui/LayerState.h"
namespace android::surfaceflinger {
+class FakeExternalTexture : public renderengine::ExternalTexture {
+ const sp<GraphicBuffer> mEmptyBuffer =
+ sp<GraphicBuffer>::make(1u, 1u, PIXEL_FORMAT_RGBA_8888,
+ GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_SW_READ_OFTEN);
+ uint32_t mWidth;
+ uint32_t mHeight;
+ uint64_t mId;
+ PixelFormat mPixelFormat;
+ uint64_t mUsage;
+
+public:
+ FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat,
+ uint64_t usage)
+ : mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {}
+ const sp<GraphicBuffer>& getBuffer() const { return mEmptyBuffer; }
+ bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
+ return getId() == other.getId();
+ }
+ uint32_t getWidth() const override { return mWidth; }
+ uint32_t getHeight() const override { return mHeight; }
+ uint64_t getId() const override { return mId; }
+ PixelFormat getPixelFormat() const override { return mPixelFormat; }
+ uint64_t getUsage() const override { return mUsage; }
+ ~FakeExternalTexture() = default;
+};
+
proto::TransactionState TransactionProtoParser::toProto(const TransactionState& t) {
proto::TransactionState proto;
proto.set_pid(t.originPid);
@@ -35,7 +63,7 @@ proto::TransactionState TransactionProtoParser::toProto(const TransactionState&
proto.mutable_layer_changes()->Reserve(static_cast<int32_t>(t.states.size()));
for (auto& layerState : t.states) {
- proto.mutable_layer_changes()->Add(std::move(toProto(layerState.state)));
+ proto.mutable_layer_changes()->Add(std::move(toProto(layerState)));
}
proto.mutable_display_changes()->Reserve(static_cast<int32_t>(t.displays.size()));
@@ -46,40 +74,22 @@ proto::TransactionState TransactionProtoParser::toProto(const TransactionState&
}
proto::TransactionState TransactionProtoParser::toProto(
- const std::map<int32_t /* layerId */, TracingLayerState>& states) {
+ const std::map<uint32_t /* layerId */, TracingLayerState>& states) {
proto::TransactionState proto;
proto.mutable_layer_changes()->Reserve(static_cast<int32_t>(states.size()));
for (auto& [layerId, state] : states) {
proto::LayerState layerProto = toProto(state);
- if (layerProto.has_buffer_data()) {
- proto::LayerState_BufferData* bufferProto = layerProto.mutable_buffer_data();
- bufferProto->set_buffer_id(state.bufferId);
- bufferProto->set_width(state.bufferWidth);
- bufferProto->set_height(state.bufferHeight);
- bufferProto->set_pixel_format(
- static_cast<proto::LayerState_BufferData_PixelFormat>(state.pixelFormat));
- bufferProto->set_usage(state.bufferUsage);
- }
layerProto.set_has_sideband_stream(state.hasSidebandStream);
- layerProto.set_layer_id(state.layerId);
- layerProto.set_parent_id(state.parentId);
- layerProto.set_relative_parent_id(state.relativeParentId);
- if (layerProto.has_window_info_handle()) {
- layerProto.mutable_window_info_handle()->set_crop_layer_id(state.inputCropId);
- }
proto.mutable_layer_changes()->Add(std::move(layerProto));
}
return proto;
}
-proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer) {
+proto::LayerState TransactionProtoParser::toProto(
+ const ResolvedComposerState& resolvedComposerState) {
proto::LayerState proto;
- if (layer.surface) {
- proto.set_layer_id(mMapper->getLayerId(layer.surface));
- } else {
- proto.set_layer_id(layer.layerId);
- }
-
+ auto& layer = resolvedComposerState.state;
+ proto.set_layer_id(resolvedComposerState.layerId);
proto.set_what(layer.what);
if (layer.what & layer_state_t::ePositionChanged) {
@@ -135,27 +145,13 @@ proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer) {
}
if (layer.what & layer_state_t::eBufferChanged) {
proto::LayerState_BufferData* bufferProto = proto.mutable_buffer_data();
- if (layer.bufferData->hasBuffer()) {
- bufferProto->set_buffer_id(layer.bufferData->getId());
- bufferProto->set_width(layer.bufferData->getWidth());
- bufferProto->set_height(layer.bufferData->getHeight());
+ if (resolvedComposerState.externalTexture) {
+ bufferProto->set_buffer_id(resolvedComposerState.externalTexture->getId());
+ bufferProto->set_width(resolvedComposerState.externalTexture->getWidth());
+ bufferProto->set_height(resolvedComposerState.externalTexture->getHeight());
bufferProto->set_pixel_format(static_cast<proto::LayerState_BufferData_PixelFormat>(
- layer.bufferData->getPixelFormat()));
- bufferProto->set_usage(layer.bufferData->getUsage());
- } else {
- uint64_t bufferId;
- uint32_t width;
- uint32_t height;
- int32_t pixelFormat;
- uint64_t usage;
- mMapper->getGraphicBufferPropertiesFromCache(layer.bufferData->cachedBuffer, &bufferId,
- &width, &height, &pixelFormat, &usage);
- bufferProto->set_buffer_id(bufferId);
- bufferProto->set_width(width);
- bufferProto->set_height(height);
- bufferProto->set_pixel_format(
- static_cast<proto::LayerState_BufferData_PixelFormat>(pixelFormat));
- bufferProto->set_usage(usage);
+ resolvedComposerState.externalTexture->getPixelFormat()));
+ bufferProto->set_usage(resolvedComposerState.externalTexture->getUsage());
}
bufferProto->set_frame_number(layer.bufferData->frameNumber);
bufferProto->set_flags(layer.bufferData->flags.get());
@@ -179,16 +175,10 @@ proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer) {
}
if (layer.what & layer_state_t::eReparent) {
- int64_t layerId = layer.parentSurfaceControlForChild
- ? mMapper->getLayerId(layer.parentSurfaceControlForChild->getHandle())
- : -1;
- proto.set_parent_id(layerId);
+ proto.set_parent_id(resolvedComposerState.parentId);
}
if (layer.what & layer_state_t::eRelativeLayerChanged) {
- int64_t layerId = layer.relativeLayerSurfaceControl
- ? mMapper->getLayerId(layer.relativeLayerSurfaceControl->getHandle())
- : -1;
- proto.set_relative_parent_id(layerId);
+ proto.set_relative_parent_id(resolvedComposerState.relativeParentId);
proto.set_z(layer.z);
}
@@ -207,7 +197,7 @@ proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer) {
windowInfoProto->set_has_wallpaper(inputInfo->inputConfig.test(
gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER));
windowInfoProto->set_global_scale_factor(inputInfo->globalScaleFactor);
- proto::LayerState_Transform* transformProto = windowInfoProto->mutable_transform();
+ proto::Transform* transformProto = windowInfoProto->mutable_transform();
transformProto->set_dsdx(inputInfo->transform.dsdx());
transformProto->set_dtdx(inputInfo->transform.dtdx());
transformProto->set_dtdy(inputInfo->transform.dtdy());
@@ -216,8 +206,7 @@ proto::LayerState TransactionProtoParser::toProto(const layer_state_t& layer) {
transformProto->set_ty(inputInfo->transform.ty());
windowInfoProto->set_replace_touchable_region_with_crop(
inputInfo->replaceTouchableRegionWithCrop);
- windowInfoProto->set_crop_layer_id(
- mMapper->getLayerId(inputInfo->touchableRegionCropHandle.promote()));
+ windowInfoProto->set_crop_layer_id(resolvedComposerState.touchCropId);
}
}
if (layer.what & layer_state_t::eBackgroundColorChanged) {
@@ -289,13 +278,15 @@ proto::DisplayState TransactionProtoParser::toProto(const DisplayState& display)
return proto;
}
-proto::LayerCreationArgs TransactionProtoParser::toProto(const TracingLayerCreationArgs& args) {
+proto::LayerCreationArgs TransactionProtoParser::toProto(const LayerCreationArgs& args) {
proto::LayerCreationArgs proto;
- proto.set_layer_id(args.layerId);
+ proto.set_layer_id(args.sequence);
proto.set_name(args.name);
proto.set_flags(args.flags);
proto.set_parent_id(args.parentId);
- proto.set_mirror_from_id(args.mirrorFromId);
+ proto.set_mirror_from_id(args.layerIdToMirror);
+ proto.set_add_to_root(args.addToRoot);
+ proto.set_layer_stack_to_mirror(args.layerStackToMirror.id);
return proto;
}
@@ -313,15 +304,7 @@ TransactionState TransactionProtoParser::fromProto(const proto::TransactionState
for (int i = 0; i < layerCount; i++) {
ResolvedComposerState s;
s.state.what = 0;
- fromProto(proto.layer_changes(i), s.state);
- if (s.state.bufferData) {
- s.externalTexture = std::make_shared<
- renderengine::mock::FakeExternalTexture>(s.state.bufferData->getWidth(),
- s.state.bufferData->getHeight(),
- s.state.bufferData->getId(),
- s.state.bufferData->getPixelFormat(),
- s.state.bufferData->getUsage());
- }
+ fromProto(proto.layer_changes(i), s);
t.states.emplace_back(s);
}
@@ -334,46 +317,47 @@ TransactionState TransactionProtoParser::fromProto(const proto::TransactionState
}
void TransactionProtoParser::fromProto(const proto::LayerCreationArgs& proto,
- TracingLayerCreationArgs& outArgs) {
- outArgs.layerId = proto.layer_id();
+ LayerCreationArgs& outArgs) {
+ outArgs.sequence = proto.layer_id();
+
outArgs.name = proto.name();
outArgs.flags = proto.flags();
outArgs.parentId = proto.parent_id();
- outArgs.mirrorFromId = proto.mirror_from_id();
+ outArgs.layerIdToMirror = proto.mirror_from_id();
+ outArgs.addToRoot = proto.add_to_root();
+ outArgs.layerStackToMirror.id = proto.layer_stack_to_mirror();
}
void TransactionProtoParser::mergeFromProto(const proto::LayerState& proto,
TracingLayerState& outState) {
- layer_state_t state;
- fromProto(proto, state);
- outState.merge(state);
+ ResolvedComposerState resolvedComposerState;
+ fromProto(proto, resolvedComposerState);
+ layer_state_t& state = resolvedComposerState.state;
+ outState.state.merge(state);
+ outState.layerId = resolvedComposerState.layerId;
if (state.what & layer_state_t::eReparent) {
- outState.parentId = static_cast<int32_t>(proto.parent_id());
+ outState.parentId = resolvedComposerState.parentId;
}
if (state.what & layer_state_t::eRelativeLayerChanged) {
- outState.relativeParentId = static_cast<int32_t>(proto.relative_parent_id());
+ outState.relativeParentId = resolvedComposerState.relativeParentId;
}
if (state.what & layer_state_t::eInputInfoChanged) {
- outState.inputCropId = static_cast<int32_t>(proto.window_info_handle().crop_layer_id());
+ outState.touchCropId = resolvedComposerState.touchCropId;
}
if (state.what & layer_state_t::eBufferChanged) {
- const proto::LayerState_BufferData& bufferProto = proto.buffer_data();
- outState.bufferId = bufferProto.buffer_id();
- outState.bufferWidth = bufferProto.width();
- outState.bufferHeight = bufferProto.height();
- outState.pixelFormat = bufferProto.pixel_format();
- outState.bufferUsage = bufferProto.usage();
+ outState.externalTexture = resolvedComposerState.externalTexture;
}
if (state.what & layer_state_t::eSidebandStreamChanged) {
outState.hasSidebandStream = proto.has_sideband_stream();
}
}
-void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer_state_t& layer) {
- layer.layerId = (int32_t)proto.layer_id();
+void TransactionProtoParser::fromProto(const proto::LayerState& proto,
+ ResolvedComposerState& resolvedComposerState) {
+ auto& layer = resolvedComposerState.state;
+ resolvedComposerState.layerId = proto.layer_id();
layer.what |= proto.what();
- layer.surface = mMapper->getLayerHandle(layer.layerId);
if (proto.what() & layer_state_t::ePositionChanged) {
layer.x = proto.x();
@@ -428,9 +412,15 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer_sta
if (proto.what() & layer_state_t::eBufferChanged) {
const proto::LayerState_BufferData& bufferProto = proto.buffer_data();
layer.bufferData =
- std::move(mMapper->getGraphicData(bufferProto.buffer_id(), bufferProto.width(),
- bufferProto.height(), bufferProto.pixel_format(),
- bufferProto.usage()));
+ std::make_shared<fake::BufferData>(bufferProto.buffer_id(), bufferProto.width(),
+ bufferProto.height(), bufferProto.pixel_format(),
+ bufferProto.usage());
+ resolvedComposerState.externalTexture =
+ std::make_shared<FakeExternalTexture>(layer.bufferData->getWidth(),
+ layer.bufferData->getHeight(),
+ layer.bufferData->getId(),
+ layer.bufferData->getPixelFormat(),
+ layer.bufferData->getUsage());
layer.bufferData->frameNumber = bufferProto.frame_number();
layer.bufferData->flags = ftl::Flags<BufferData::BufferDataChange>(bufferProto.flags());
layer.bufferData->cachedBuffer.id = bufferProto.cached_buffer_id();
@@ -454,26 +444,10 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer_sta
}
if (proto.what() & layer_state_t::eReparent) {
- int64_t layerId = proto.parent_id();
- if (layerId == -1) {
- layer.parentSurfaceControlForChild = nullptr;
- } else {
- layer.parentSurfaceControlForChild =
- sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(),
- mMapper->getLayerHandle(static_cast<int32_t>(layerId)),
- static_cast<int32_t>(layerId), "");
- }
+ resolvedComposerState.parentId = proto.parent_id();
}
if (proto.what() & layer_state_t::eRelativeLayerChanged) {
- int64_t layerId = proto.relative_parent_id();
- if (layerId == -1) {
- layer.relativeLayerSurfaceControl = nullptr;
- } else {
- layer.relativeLayerSurfaceControl =
- sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(),
- mMapper->getLayerHandle(static_cast<int32_t>(layerId)),
- static_cast<int32_t>(layerId), "");
- }
+ resolvedComposerState.relativeParentId = proto.relative_parent_id();
layer.z = proto.z();
}
@@ -493,19 +467,13 @@ void TransactionProtoParser::fromProto(const proto::LayerState& proto, layer_sta
inputInfo.setInputConfig(gui::WindowInfo::InputConfig::DUPLICATE_TOUCH_TO_WALLPAPER,
windowInfoProto.has_wallpaper());
inputInfo.globalScaleFactor = windowInfoProto.global_scale_factor();
- const proto::LayerState_Transform& transformProto = windowInfoProto.transform();
+ const proto::Transform& transformProto = windowInfoProto.transform();
inputInfo.transform.set(transformProto.dsdx(), transformProto.dtdx(), transformProto.dtdy(),
transformProto.dsdy());
inputInfo.transform.set(transformProto.tx(), transformProto.ty());
inputInfo.replaceTouchableRegionWithCrop =
windowInfoProto.replace_touchable_region_with_crop();
- int64_t layerId = windowInfoProto.crop_layer_id();
- if (layerId != -1) {
- inputInfo.touchableRegionCropHandle =
- mMapper->getLayerHandle(static_cast<int32_t>(layerId));
- } else {
- inputInfo.touchableRegionCropHandle = wp<IBinder>();
- }
+ resolvedComposerState.touchCropId = windowInfoProto.crop_layer_id();
layer.windowInfoHandle = sp<gui::WindowInfoHandle>::make(inputInfo);
}
@@ -577,4 +545,62 @@ DisplayState TransactionProtoParser::fromProto(const proto::DisplayState& proto)
return display;
}
+void asProto(proto::Transform* proto, const ui::Transform& transform) {
+ proto->set_dsdx(transform.dsdx());
+ proto->set_dtdx(transform.dtdx());
+ proto->set_dtdy(transform.dtdy());
+ proto->set_dsdy(transform.dsdy());
+ proto->set_tx(transform.tx());
+ proto->set_ty(transform.ty());
+}
+
+proto::DisplayInfo TransactionProtoParser::toProto(const frontend::DisplayInfo& displayInfo,
+ uint32_t layerStack) {
+ proto::DisplayInfo proto;
+ proto.set_layer_stack(layerStack);
+ proto.set_display_id(displayInfo.info.displayId);
+ proto.set_logical_width(displayInfo.info.logicalWidth);
+ proto.set_logical_height(displayInfo.info.logicalHeight);
+ asProto(proto.mutable_transform_inverse(), displayInfo.info.transform);
+ asProto(proto.mutable_transform(), displayInfo.transform);
+ proto.set_receives_input(displayInfo.receivesInput);
+ proto.set_is_secure(displayInfo.isSecure);
+ proto.set_is_primary(displayInfo.isPrimary);
+ proto.set_is_virtual(displayInfo.isVirtual);
+ proto.set_rotation_flags((int)displayInfo.rotationFlags);
+ proto.set_transform_hint((int)displayInfo.transformHint);
+ return proto;
+}
+
+void fromProto2(ui::Transform& outTransform, const proto::Transform& proto) {
+ outTransform.set(proto.dsdx(), proto.dtdx(), proto.dtdy(), proto.dsdy());
+ outTransform.set(proto.tx(), proto.ty());
+}
+
+frontend::DisplayInfo TransactionProtoParser::fromProto(const proto::DisplayInfo& proto) {
+ frontend::DisplayInfo displayInfo;
+ displayInfo.info.displayId = proto.display_id();
+ displayInfo.info.logicalWidth = proto.logical_width();
+ displayInfo.info.logicalHeight = proto.logical_height();
+ fromProto2(displayInfo.info.transform, proto.transform_inverse());
+ fromProto2(displayInfo.transform, proto.transform());
+ displayInfo.receivesInput = proto.receives_input();
+ displayInfo.isSecure = proto.is_secure();
+ displayInfo.isPrimary = proto.is_primary();
+ displayInfo.isPrimary = proto.is_virtual();
+ displayInfo.rotationFlags = (ui::Transform::RotationFlags)proto.rotation_flags();
+ displayInfo.transformHint = (ui::Transform::RotationFlags)proto.transform_hint();
+ return displayInfo;
+}
+
+void TransactionProtoParser::fromProto(
+ const google::protobuf::RepeatedPtrField<proto::DisplayInfo>& proto,
+ display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> outDisplayInfos) {
+ outDisplayInfos.clear();
+ for (const proto::DisplayInfo& displayInfo : proto) {
+ outDisplayInfos.emplace_or_replace(ui::LayerStack::fromValue(displayInfo.layer_stack()),
+ fromProto(displayInfo));
+ }
+}
+
} // namespace android::surfaceflinger
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.h b/services/surfaceflinger/Tracing/TransactionProtoParser.h
index 2232bb9cb1..50944fce0f 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.h
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.h
@@ -18,30 +18,17 @@
#include <gui/fake/BufferData.h>
#include <layerproto/TransactionProto.h>
#include <utils/RefBase.h>
+#include "Display/DisplayMap.h"
+#include "FrontEnd/DisplayInfo.h"
+#include "FrontEnd/LayerCreationArgs.h"
#include "TransactionState.h"
namespace android::surfaceflinger {
-struct TracingLayerCreationArgs {
- int32_t layerId;
- std::string name;
- uint32_t flags = 0;
- int32_t parentId = -1;
- int32_t mirrorFromId = -1;
-};
-
-struct TracingLayerState : layer_state_t {
- uint64_t bufferId;
- uint32_t bufferHeight;
- uint32_t bufferWidth;
- int32_t pixelFormat;
- uint64_t bufferUsage;
+struct TracingLayerState : ResolvedComposerState {
bool hasSidebandStream;
- int32_t parentId;
- int32_t relativeParentId;
- int32_t inputCropId;
- TracingLayerCreationArgs args;
+ LayerCreationArgs args;
};
class TransactionProtoParser {
@@ -51,40 +38,30 @@ public:
class FlingerDataMapper {
public:
virtual ~FlingerDataMapper() = default;
- virtual sp<IBinder> getLayerHandle(int32_t /* layerId */) const { return nullptr; }
- virtual int64_t getLayerId(const sp<IBinder>& /* layerHandle */) const { return -1; }
- virtual int64_t getLayerId(BBinder* /* layerHandle */) const { return -1; }
virtual sp<IBinder> getDisplayHandle(int32_t /* displayId */) const { return nullptr; }
virtual int32_t getDisplayId(const sp<IBinder>& /* displayHandle */) const { return -1; }
- virtual std::shared_ptr<BufferData> getGraphicData(uint64_t bufferId, uint32_t width,
- uint32_t height, int32_t pixelFormat,
- uint64_t usage) const {
- return std::make_shared<fake::BufferData>(bufferId, width, height, pixelFormat, usage);
- }
- virtual void getGraphicBufferPropertiesFromCache(client_cache_t /* cachedBuffer */,
- uint64_t* /* outBufferId */,
- uint32_t* /* outWidth */,
- uint32_t* /* outHeight */,
- int32_t* /* outPixelFormat */,
- uint64_t* /* outUsage */) const {}
};
TransactionProtoParser(std::unique_ptr<FlingerDataMapper> provider)
: mMapper(std::move(provider)) {}
proto::TransactionState toProto(const TransactionState&);
- proto::TransactionState toProto(const std::map<int32_t /* layerId */, TracingLayerState>&);
- proto::LayerCreationArgs toProto(const TracingLayerCreationArgs& args);
+ proto::TransactionState toProto(const std::map<uint32_t /* layerId */, TracingLayerState>&);
+ proto::LayerCreationArgs toProto(const LayerCreationArgs& args);
+ proto::LayerState toProto(const ResolvedComposerState&);
+ proto::DisplayInfo toProto(const frontend::DisplayInfo&, uint32_t layerStack);
TransactionState fromProto(const proto::TransactionState&);
void mergeFromProto(const proto::LayerState&, TracingLayerState& outState);
- void fromProto(const proto::LayerCreationArgs&, TracingLayerCreationArgs& outArgs);
+ void fromProto(const proto::LayerCreationArgs&, LayerCreationArgs& outArgs);
std::unique_ptr<FlingerDataMapper> mMapper;
+ frontend::DisplayInfo fromProto(const proto::DisplayInfo&);
+ void fromProto(const google::protobuf::RepeatedPtrField<proto::DisplayInfo>&,
+ display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> outDisplayInfos);
private:
- proto::LayerState toProto(const layer_state_t&);
proto::DisplayState toProto(const DisplayState&);
- void fromProto(const proto::LayerState&, layer_state_t& out);
+ void fromProto(const proto::LayerState&, ResolvedComposerState& out);
DisplayState fromProto(const proto::DisplayState&);
};
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index cb5320b88c..26ed878396 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -23,75 +23,14 @@
#include <utils/SystemClock.h>
#include <utils/Trace.h>
-#include "ClientCache.h"
+#include "Client.h"
+#include "FrontEnd/LayerCreationArgs.h"
#include "TransactionTracing.h"
-#include "renderengine/ExternalTexture.h"
namespace android {
-// Keeps the binder address as the layer id so we can avoid holding the tracing lock in the
-// binder thread.
-class FlatDataMapper : public TransactionProtoParser::FlingerDataMapper {
-public:
- virtual int64_t getLayerId(const sp<IBinder>& layerHandle) const {
- if (layerHandle == nullptr) {
- return -1;
- }
-
- return reinterpret_cast<int64_t>(layerHandle->localBinder());
- }
-
- void getGraphicBufferPropertiesFromCache(client_cache_t cachedBuffer, uint64_t* outBufferId,
- uint32_t* outWidth, uint32_t* outHeight,
- int32_t* outPixelFormat,
- uint64_t* outUsage) const override {
- std::shared_ptr<renderengine::ExternalTexture> buffer =
- ClientCache::getInstance().get(cachedBuffer);
- if (!buffer || !buffer->getBuffer()) {
- *outBufferId = 0;
- *outWidth = 0;
- *outHeight = 0;
- *outPixelFormat = 0;
- *outUsage = 0;
- return;
- }
-
- *outBufferId = buffer->getId();
- *outWidth = buffer->getWidth();
- *outHeight = buffer->getHeight();
- *outPixelFormat = buffer->getPixelFormat();
- *outUsage = buffer->getUsage();
- return;
- }
-};
-
-class FlingerDataMapper : public FlatDataMapper {
- std::unordered_map<BBinder* /* layerHandle */, int32_t /* layerId */>& mLayerHandles;
-
-public:
- FlingerDataMapper(std::unordered_map<BBinder* /* handle */, int32_t /* id */>& layerHandles)
- : mLayerHandles(layerHandles) {}
-
- int64_t getLayerId(const sp<IBinder>& layerHandle) const override {
- if (layerHandle == nullptr) {
- return -1;
- }
- return getLayerId(layerHandle->localBinder());
- }
-
- int64_t getLayerId(BBinder* localBinder) const {
- auto it = mLayerHandles.find(localBinder);
- if (it == mLayerHandles.end()) {
- ALOGW("Could not find layer handle %p", localBinder);
- return -1;
- }
- return it->second;
- }
-};
-
TransactionTracing::TransactionTracing()
- : mProtoParser(std::make_unique<FlingerDataMapper>(mLayerHandles)),
- mLockfreeProtoParser(std::make_unique<FlatDataMapper>()) {
+ : mProtoParser(std::make_unique<TransactionProtoParser::FlingerDataMapper>()) {
std::scoped_lock lock(mTraceLock);
mBuffer.setSize(mBufferSizeInBytes);
@@ -137,84 +76,77 @@ proto::TransactionTraceFile TransactionTracing::createTraceFileProto() const {
auto timeOffsetNs = static_cast<std::uint64_t>(systemTime(SYSTEM_TIME_REALTIME) -
systemTime(SYSTEM_TIME_MONOTONIC));
proto.set_real_to_elapsed_time_offset_nanos(timeOffsetNs);
+ proto.set_version(TRACING_VERSION);
return proto;
}
void TransactionTracing::dump(std::string& result) const {
std::scoped_lock lock(mTraceLock);
- base::StringAppendF(&result,
- " queued transactions=%zu created layers=%zu handles=%zu states=%zu\n",
- mQueuedTransactions.size(), mCreatedLayers.size(), mLayerHandles.size(),
- mStartingStates.size());
+ base::StringAppendF(&result, " queued transactions=%zu created layers=%zu states=%zu\n",
+ mQueuedTransactions.size(), mCreatedLayers.size(), mStartingStates.size());
mBuffer.dump(result);
}
void TransactionTracing::addQueuedTransaction(const TransactionState& transaction) {
- proto::TransactionState* state =
- new proto::TransactionState(mLockfreeProtoParser.toProto(transaction));
+ proto::TransactionState* state = new proto::TransactionState(mProtoParser.toProto(transaction));
mTransactionQueue.push(state);
}
-TransactionTracing::CommittedTransactions&
-TransactionTracing::findOrCreateCommittedTransactionRecord(int64_t vsyncId) {
- for (auto& pendingTransaction : mPendingTransactions) {
- if (pendingTransaction.vsyncId == vsyncId) {
- return pendingTransaction;
- }
+void TransactionTracing::addCommittedTransactions(
+ int64_t vsyncId, nsecs_t commitTime, frontend::Update& newUpdate,
+ const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displayInfos,
+ bool displayInfoChanged) {
+ CommittedUpdates update;
+ update.vsyncId = vsyncId;
+ update.timestamp = commitTime;
+ update.transactionIds.reserve(newUpdate.transactions.size());
+ for (const auto& transaction : newUpdate.transactions) {
+ update.transactionIds.emplace_back(transaction.id);
}
-
- CommittedTransactions committedTransactions;
- committedTransactions.vsyncId = vsyncId;
- committedTransactions.timestamp = systemTime();
- mPendingTransactions.emplace_back(committedTransactions);
- return mPendingTransactions.back();
-}
-
-void TransactionTracing::onLayerAddedToDrawingState(int layerId, int64_t vsyncId) {
- CommittedTransactions& committedTransactions = findOrCreateCommittedTransactionRecord(vsyncId);
- committedTransactions.createdLayerIds.emplace_back(layerId);
-}
-
-void TransactionTracing::addCommittedTransactions(std::vector<TransactionState>& transactions,
- int64_t vsyncId) {
- CommittedTransactions& committedTransactions = findOrCreateCommittedTransactionRecord(vsyncId);
- committedTransactions.transactionIds.reserve(transactions.size());
- for (const auto& transaction : transactions) {
- committedTransactions.transactionIds.emplace_back(transaction.id);
+ update.displayInfoChanged = displayInfoChanged;
+ if (displayInfoChanged) {
+ update.displayInfos = displayInfos;
}
+ update.createdLayers = std::move(newUpdate.layerCreationArgs);
+ newUpdate.layerCreationArgs.clear();
+ update.destroyedLayerHandles.reserve(newUpdate.destroyedHandles.size());
+ for (uint32_t handle : newUpdate.destroyedHandles) {
+ update.destroyedLayerHandles.push_back(handle);
+ }
+ mPendingUpdates.emplace_back(update);
tryPushToTracingThread();
}
void TransactionTracing::loop() {
while (true) {
- std::vector<CommittedTransactions> committedTransactions;
- std::vector<int32_t> removedLayers;
+ std::vector<CommittedUpdates> committedUpdates;
+ std::vector<uint32_t> destroyedLayers;
{
std::unique_lock<std::mutex> lock(mMainThreadLock);
base::ScopedLockAssertion assumeLocked(mMainThreadLock);
mTransactionsAvailableCv.wait(lock, [&]() REQUIRES(mMainThreadLock) {
- return mDone || !mCommittedTransactions.empty();
+ return mDone || !mUpdates.empty();
});
if (mDone) {
- mCommittedTransactions.clear();
- mRemovedLayers.clear();
+ mUpdates.clear();
+ mDestroyedLayers.clear();
break;
}
- removedLayers = std::move(mRemovedLayers);
- mRemovedLayers.clear();
- committedTransactions = std::move(mCommittedTransactions);
- mCommittedTransactions.clear();
+ destroyedLayers = std::move(mDestroyedLayers);
+ mDestroyedLayers.clear();
+ committedUpdates = std::move(mUpdates);
+ mUpdates.clear();
} // unlock mMainThreadLock
- if (!committedTransactions.empty() || !removedLayers.empty()) {
- addEntry(committedTransactions, removedLayers);
+ if (!committedUpdates.empty() || !destroyedLayers.empty()) {
+ addEntry(committedUpdates, destroyedLayers);
}
}
}
-void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& committedTransactions,
- const std::vector<int32_t>& removedLayers) {
+void TransactionTracing::addEntry(const std::vector<CommittedUpdates>& committedUpdates,
+ const std::vector<uint32_t>& destroyedLayers) {
ATRACE_CALL();
std::scoped_lock lock(mTraceLock);
std::vector<std::string> removedEntries;
@@ -222,59 +154,27 @@ void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& comm
while (auto incomingTransaction = mTransactionQueue.pop()) {
auto transaction = *incomingTransaction;
- int32_t layerCount = transaction.layer_changes_size();
- for (int i = 0; i < layerCount; i++) {
- auto layer = transaction.mutable_layer_changes(i);
- layer->set_layer_id(
- mProtoParser.mMapper->getLayerId(reinterpret_cast<BBinder*>(layer->layer_id())));
- if ((layer->what() & layer_state_t::eReparent) && layer->parent_id() != -1) {
- layer->set_parent_id(
- mProtoParser.mMapper->getLayerId(reinterpret_cast<BBinder*>(
- layer->parent_id())));
- }
-
- if ((layer->what() & layer_state_t::eRelativeLayerChanged) &&
- layer->relative_parent_id() != -1) {
- layer->set_relative_parent_id(
- mProtoParser.mMapper->getLayerId(reinterpret_cast<BBinder*>(
- layer->relative_parent_id())));
- }
-
- if (layer->has_window_info_handle() &&
- layer->window_info_handle().crop_layer_id() != -1) {
- auto input = layer->mutable_window_info_handle();
- input->set_crop_layer_id(
- mProtoParser.mMapper->getLayerId(reinterpret_cast<BBinder*>(
- input->crop_layer_id())));
- }
- }
mQueuedTransactions[incomingTransaction->transaction_id()] = transaction;
delete incomingTransaction;
}
- for (const CommittedTransactions& entry : committedTransactions) {
- entryProto.set_elapsed_realtime_nanos(entry.timestamp);
- entryProto.set_vsync_id(entry.vsyncId);
+ for (const CommittedUpdates& update : committedUpdates) {
+ entryProto.set_elapsed_realtime_nanos(update.timestamp);
+ entryProto.set_vsync_id(update.vsyncId);
entryProto.mutable_added_layers()->Reserve(
- static_cast<int32_t>(entry.createdLayerIds.size()));
+ static_cast<int32_t>(update.createdLayers.size()));
- for (const int32_t& id : entry.createdLayerIds) {
- auto it = mCreatedLayers.find(id);
- if (it != mCreatedLayers.end()) {
- entryProto.mutable_added_layers()->Add(std::move(it->second));
- mCreatedLayers.erase(it);
- } else {
- ALOGW("Could not created layer with id %d", id);
- }
+ for (const auto& args : update.createdLayers) {
+ entryProto.mutable_added_layers()->Add(std::move(mProtoParser.toProto(args)));
}
- entryProto.mutable_removed_layers()->Reserve(static_cast<int32_t>(removedLayers.size()));
- for (auto& removedLayer : removedLayers) {
- entryProto.mutable_removed_layers()->Add(removedLayer);
- mCreatedLayers.erase(removedLayer);
+ entryProto.mutable_destroyed_layers()->Reserve(
+ static_cast<int32_t>(destroyedLayers.size()));
+ for (auto& destroyedLayer : destroyedLayers) {
+ entryProto.mutable_destroyed_layers()->Add(destroyedLayer);
}
entryProto.mutable_transactions()->Reserve(
- static_cast<int32_t>(entry.transactionIds.size()));
- for (const uint64_t& id : entry.transactionIds) {
+ static_cast<int32_t>(update.transactionIds.size()));
+ for (const uint64_t& id : update.transactionIds) {
auto it = mQueuedTransactions.find(id);
if (it != mQueuedTransactions.end()) {
entryProto.mutable_transactions()->Add(std::move(it->second));
@@ -284,13 +184,21 @@ void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& comm
}
}
- entryProto.mutable_removed_layer_handles()->Reserve(
- static_cast<int32_t>(mRemovedLayerHandles.size()));
- for (auto& [handle, layerId] : mRemovedLayerHandles) {
- entryProto.mutable_removed_layer_handles()->Add(layerId);
- mLayerHandles.erase(handle);
+ entryProto.mutable_destroyed_layer_handles()->Reserve(
+ static_cast<int32_t>(update.destroyedLayerHandles.size()));
+ for (auto layerId : update.destroyedLayerHandles) {
+ entryProto.mutable_destroyed_layer_handles()->Add(layerId);
+ }
+
+ entryProto.set_displays_changed(update.displayInfoChanged);
+ if (update.displayInfoChanged) {
+ entryProto.mutable_displays()->Reserve(
+ static_cast<int32_t>(update.displayInfos.size()));
+ for (auto& [layerStack, displayInfo] : update.displayInfos) {
+ entryProto.mutable_displays()->Add(
+ std::move(mProtoParser.toProto(displayInfo, layerStack.id)));
+ }
}
- mRemovedLayerHandles.clear();
std::string serializedProto;
entryProto.SerializeToString(&serializedProto);
@@ -311,7 +219,7 @@ void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& comm
}
void TransactionTracing::flush(int64_t vsyncId) {
- while (!mPendingTransactions.empty() || !mPendingRemovedLayers.empty()) {
+ while (!mPendingUpdates.empty() || !mPendingDestroyedLayers.empty()) {
tryPushToTracingThread();
}
std::unique_lock<std::mutex> lock(mTraceLock);
@@ -325,54 +233,21 @@ void TransactionTracing::flush(int64_t vsyncId) {
});
}
-void TransactionTracing::onLayerAdded(BBinder* layerHandle, int layerId, const std::string& name,
- uint32_t flags, int parentId) {
- std::scoped_lock lock(mTraceLock);
- TracingLayerCreationArgs args{layerId, name, flags, parentId, -1 /* mirrorFromId */};
- if (mLayerHandles.find(layerHandle) != mLayerHandles.end()) {
- ALOGW("Duplicate handles found. %p", layerHandle);
- }
- mLayerHandles[layerHandle] = layerId;
- mCreatedLayers[layerId] = mProtoParser.toProto(args);
-}
-
-void TransactionTracing::onMirrorLayerAdded(BBinder* layerHandle, int layerId,
- const std::string& name, int mirrorFromId) {
- std::scoped_lock lock(mTraceLock);
- TracingLayerCreationArgs args{layerId, name, 0 /* flags */, -1 /* parentId */, mirrorFromId};
- if (mLayerHandles.find(layerHandle) != mLayerHandles.end()) {
- ALOGW("Duplicate handles found. %p", layerHandle);
- }
- mLayerHandles[layerHandle] = layerId;
- mCreatedLayers[layerId] = mProtoParser.toProto(args);
-}
-
void TransactionTracing::onLayerRemoved(int32_t layerId) {
- mPendingRemovedLayers.emplace_back(layerId);
+ mPendingDestroyedLayers.emplace_back(layerId);
tryPushToTracingThread();
}
-void TransactionTracing::onHandleRemoved(BBinder* layerHandle) {
- std::scoped_lock lock(mTraceLock);
- auto it = mLayerHandles.find(layerHandle);
- if (it == mLayerHandles.end()) {
- ALOGW("handle not found. %p", layerHandle);
- return;
- }
- mRemovedLayerHandles.emplace_back(layerHandle, it->second);
-}
-
void TransactionTracing::tryPushToTracingThread() {
// Try to acquire the lock from main thread.
if (mMainThreadLock.try_lock()) {
// We got the lock! Collect any pending transactions and continue.
- mCommittedTransactions.insert(mCommittedTransactions.end(),
- std::make_move_iterator(mPendingTransactions.begin()),
- std::make_move_iterator(mPendingTransactions.end()));
- mPendingTransactions.clear();
- mRemovedLayers.insert(mRemovedLayers.end(), mPendingRemovedLayers.begin(),
- mPendingRemovedLayers.end());
- mPendingRemovedLayers.clear();
+ mUpdates.insert(mUpdates.end(), std::make_move_iterator(mPendingUpdates.begin()),
+ std::make_move_iterator(mPendingUpdates.end()));
+ mPendingUpdates.clear();
+ mDestroyedLayers.insert(mDestroyedLayers.end(), mPendingDestroyedLayers.begin(),
+ mPendingDestroyedLayers.end());
+ mPendingDestroyedLayers.clear();
mTransactionsAvailableCv.notify_one();
mMainThreadLock.unlock();
} else {
@@ -394,24 +269,28 @@ void TransactionTracing::updateStartingStateLocked(
// Merge layer states to starting transaction state.
for (const proto::TransactionState& transaction : removedEntry.transactions()) {
for (const proto::LayerState& layerState : transaction.layer_changes()) {
- auto it = mStartingStates.find((int32_t)layerState.layer_id());
+ auto it = mStartingStates.find(layerState.layer_id());
if (it == mStartingStates.end()) {
- ALOGW("Could not find layer id %d", (int32_t)layerState.layer_id());
+ ALOGW("Could not find layer id %d", layerState.layer_id());
continue;
}
mProtoParser.mergeFromProto(layerState, it->second);
}
}
- for (const int32_t removedLayerHandleId : removedEntry.removed_layer_handles()) {
- mRemovedLayerHandlesAtStart.insert(removedLayerHandleId);
+ for (const uint32_t destroyedLayerHandleId : removedEntry.destroyed_layer_handles()) {
+ mRemovedLayerHandlesAtStart.insert(destroyedLayerHandleId);
}
// Clean up stale starting states since the layer has been removed and the buffer does not
// contain any references to the layer.
- for (const int32_t removedLayerId : removedEntry.removed_layers()) {
- mStartingStates.erase(removedLayerId);
- mRemovedLayerHandlesAtStart.erase(removedLayerId);
+ for (const uint32_t destroyedLayerId : removedEntry.destroyed_layers()) {
+ mStartingStates.erase(destroyedLayerId);
+ mRemovedLayerHandlesAtStart.erase(destroyedLayerId);
+ }
+
+ if (removedEntry.displays_changed()) {
+ mProtoParser.fromProto(removedEntry.displays(), mStartingDisplayInfos);
}
}
@@ -434,10 +313,15 @@ void TransactionTracing::addStartingStateToProtoLocked(proto::TransactionTraceFi
transactionProto.set_post_time(mStartingTimestamp);
entryProto->mutable_transactions()->Add(std::move(transactionProto));
- entryProto->mutable_removed_layer_handles()->Reserve(
+ entryProto->mutable_destroyed_layer_handles()->Reserve(
static_cast<int32_t>(mRemovedLayerHandlesAtStart.size()));
- for (const int32_t removedLayerHandleId : mRemovedLayerHandlesAtStart) {
- entryProto->mutable_removed_layer_handles()->Add(removedLayerHandleId);
+ for (const uint32_t destroyedLayerHandleId : mRemovedLayerHandlesAtStart) {
+ entryProto->mutable_destroyed_layer_handles()->Add(destroyedLayerHandleId);
+ }
+
+ entryProto->mutable_displays()->Reserve(static_cast<int32_t>(mStartingDisplayInfos.size()));
+ for (auto& [layerStack, displayInfo] : mStartingDisplayInfos) {
+ entryProto->mutable_displays()->Add(mProtoParser.toProto(displayInfo, layerStack.id));
}
}
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h
index ae01d3c0cc..f27e7a9663 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.h
+++ b/services/surfaceflinger/Tracing/TransactionTracing.h
@@ -25,8 +25,12 @@
#include <mutex>
#include <thread>
-#include "RingBuffer.h"
+#include "Display/DisplayMap.h"
+#include "FrontEnd/DisplayInfo.h"
+#include "FrontEnd/LayerCreationArgs.h"
+#include "FrontEnd/Update.h"
#include "LocklessStack.h"
+#include "RingBuffer.h"
#include "TransactionProtoParser.h"
using namespace android::surfaceflinger;
@@ -55,22 +59,22 @@ public:
~TransactionTracing();
void addQueuedTransaction(const TransactionState&);
- void addCommittedTransactions(std::vector<TransactionState>& transactions, int64_t vsyncId);
+ void addCommittedTransactions(
+ int64_t vsyncId, nsecs_t commitTime, frontend::Update& update,
+ const display::DisplayMap<ui::LayerStack, frontend::DisplayInfo>& displayInfos,
+ bool displayInfoChanged);
status_t writeToFile(std::string filename = FILE_NAME);
void setBufferSize(size_t bufferSizeInBytes);
- void onLayerAdded(BBinder* layerHandle, int layerId, const std::string& name, uint32_t flags,
- int parentId);
- void onMirrorLayerAdded(BBinder* layerHandle, int layerId, const std::string& name,
- int mirrorFromId);
void onLayerRemoved(int layerId);
- void onHandleRemoved(BBinder* layerHandle);
- void onLayerAddedToDrawingState(int layerId, int64_t vsyncId);
void dump(std::string&) const;
static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
static constexpr auto ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
+ // version 1 - switching to support new frontend
+ static constexpr auto TRACING_VERSION = 1;
private:
friend class TransactionTracingTest;
+ friend class SurfaceFlinger;
static constexpr auto FILE_NAME = "/data/misc/wmtrace/transactions_trace.winscope";
@@ -83,16 +87,12 @@ private:
LocklessStack<proto::TransactionState> mTransactionQueue;
nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock);
std::unordered_map<int, proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
- std::unordered_map<BBinder* /* layerHandle */, int32_t /* layerId */> mLayerHandles
+ std::map<uint32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
+ display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> mStartingDisplayInfos
GUARDED_BY(mTraceLock);
- std::vector<std::pair<BBinder* /* layerHandle */, int32_t /* layerId */>> mRemovedLayerHandles
- GUARDED_BY(mTraceLock);
- std::map<int32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
- std::set<int32_t /* layerId */> mRemovedLayerHandlesAtStart GUARDED_BY(mTraceLock);
- TransactionProtoParser mProtoParser GUARDED_BY(mTraceLock);
- // Parses the transaction to proto without holding any tracing locks so we can generate proto
- // in the binder thread without any contention.
- TransactionProtoParser mLockfreeProtoParser;
+
+ std::set<uint32_t /* layerId */> mRemovedLayerHandlesAtStart GUARDED_BY(mTraceLock);
+ TransactionProtoParser mProtoParser;
// We do not want main thread to block so main thread will try to acquire mMainThreadLock,
// otherwise will push data to temporary container.
@@ -101,27 +101,29 @@ private:
bool mDone GUARDED_BY(mMainThreadLock) = false;
std::condition_variable mTransactionsAvailableCv;
std::condition_variable mTransactionsAddedToBufferCv;
- struct CommittedTransactions {
+ struct CommittedUpdates {
std::vector<uint64_t> transactionIds;
- std::vector<int32_t> createdLayerIds;
+ std::vector<LayerCreationArgs> createdLayers;
+ std::vector<uint32_t> destroyedLayerHandles;
+ bool displayInfoChanged;
+ display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> displayInfos;
int64_t vsyncId;
int64_t timestamp;
};
- std::vector<CommittedTransactions> mCommittedTransactions GUARDED_BY(mMainThreadLock);
- std::vector<CommittedTransactions> mPendingTransactions; // only accessed by main thread
+ std::vector<CommittedUpdates> mUpdates GUARDED_BY(mMainThreadLock);
+ std::vector<CommittedUpdates> mPendingUpdates; // only accessed by main thread
- std::vector<int32_t /* layerId */> mRemovedLayers GUARDED_BY(mMainThreadLock);
- std::vector<int32_t /* layerId */> mPendingRemovedLayers; // only accessed by main thread
+ std::vector<uint32_t /* layerId */> mDestroyedLayers GUARDED_BY(mMainThreadLock);
+ std::vector<uint32_t /* layerId */> mPendingDestroyedLayers; // only accessed by main thread
proto::TransactionTraceFile createTraceFileProto() const;
void loop();
- void addEntry(const std::vector<CommittedTransactions>& committedTransactions,
- const std::vector<int32_t>& removedLayers) EXCLUDES(mTraceLock);
+ void addEntry(const std::vector<CommittedUpdates>& committedTransactions,
+ const std::vector<uint32_t>& removedLayers) EXCLUDES(mTraceLock);
int32_t getLayerIdLocked(const sp<IBinder>& layerHandle) REQUIRES(mTraceLock);
void tryPushToTracingThread() EXCLUDES(mMainThreadLock);
void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock);
void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock);
- CommittedTransactions& findOrCreateCommittedTransactionRecord(int64_t vsyncId);
// TEST
// Wait until all the committed transactions for the specified vsync id are added to the buffer.
void flush(int64_t vsyncId) EXCLUDES(mMainThreadLock);
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index 31f4723915..2418cf22e5 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -14,175 +14,31 @@
* limitations under the License.
*/
+#include <memory>
+#include <vector>
+#include "FrontEnd/LayerCreationArgs.h"
+#include "FrontEnd/RequestedLayerState.h"
+#include "Tracing/LayerTracing.h"
+#include "TransactionState.h"
+#include "cutils/properties.h"
#undef LOG_TAG
#define LOG_TAG "LayerTraceGenerator"
//#define LOG_NDEBUG 0
-#include <TestableSurfaceFlinger.h>
#include <Tracing/TransactionProtoParser.h>
-#include <binder/IPCThreadState.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
#include <gui/LayerState.h>
#include <log/log.h>
-#include <mock/MockEventThread.h>
#include <renderengine/ExternalTexture.h>
-#include <renderengine/mock/RenderEngine.h>
#include <utils/String16.h>
+#include <filesystem>
+#include <fstream>
#include <string>
+#include "LayerProtoHelper.h"
#include "LayerTraceGenerator.h"
namespace android {
-
-class Factory final : public surfaceflinger::Factory {
-public:
- ~Factory() = default;
-
- std::unique_ptr<HWComposer> createHWComposer(const std::string&) override { return nullptr; }
-
- std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(
- Fps /*currentRefreshRate*/) override {
- return std::make_unique<scheduler::FakePhaseOffsets>();
- }
-
- sp<StartPropertySetThread> createStartPropertySetThread(
- bool /* timestampPropertyValue */) override {
- return sp<StartPropertySetThread>();
- }
-
- sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs& /* creationArgs */) override {
- return sp<DisplayDevice>();
- }
-
- sp<GraphicBuffer> createGraphicBuffer(uint32_t /* width */, uint32_t /* height */,
- PixelFormat /* format */, uint32_t /* layerCount */,
- uint64_t /* usage */,
- std::string /* requestorName */) override {
- return sp<GraphicBuffer>();
- }
-
- void createBufferQueue(sp<IGraphicBufferProducer>* /* outProducer */,
- sp<IGraphicBufferConsumer>* /* outConsumer */,
- bool /* consumerIsSurfaceFlinger */) override {}
-
- std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
- const sp<IGraphicBufferProducer>& /* producer */) override {
- return nullptr;
- }
-
- std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override {
- return compositionengine::impl::createCompositionEngine();
- }
-
- sp<Layer> createBufferStateLayer(const LayerCreationArgs& args) {
- return sp<Layer>::make(args);
- }
-
- sp<Layer> createEffectLayer(const LayerCreationArgs& args) { return sp<Layer>::make(args); }
-
- sp<LayerFE> createLayerFE(const std::string& layerName) { return sp<LayerFE>::make(layerName); }
-
- std::unique_ptr<FrameTracer> createFrameTracer() override {
- return std::make_unique<testing::NiceMock<mock::FrameTracer>>();
- }
-
- std::unique_ptr<frametimeline::FrameTimeline> createFrameTimeline(
- std::shared_ptr<TimeStats> timeStats, pid_t surfaceFlingerPid = 0) override {
- return std::make_unique<testing::NiceMock<mock::FrameTimeline>>(timeStats,
- surfaceFlingerPid);
- }
-};
-
-class FakeExternalTexture : public renderengine::ExternalTexture {
- const sp<GraphicBuffer> mNullBuffer = nullptr;
- uint32_t mWidth;
- uint32_t mHeight;
- uint64_t mId;
- PixelFormat mPixelFormat;
- uint64_t mUsage;
-
-public:
- FakeExternalTexture(uint32_t width, uint32_t height, uint64_t id, PixelFormat pixelFormat,
- uint64_t usage)
- : mWidth(width), mHeight(height), mId(id), mPixelFormat(pixelFormat), mUsage(usage) {}
- const sp<GraphicBuffer>& getBuffer() const { return mNullBuffer; }
- bool hasSameBuffer(const renderengine::ExternalTexture& other) const override {
- return getId() == other.getId();
- }
- uint32_t getWidth() const override { return mWidth; }
- uint32_t getHeight() const override { return mHeight; }
- uint64_t getId() const override { return mId; }
- PixelFormat getPixelFormat() const override { return mPixelFormat; }
- uint64_t getUsage() const override { return mUsage; }
- ~FakeExternalTexture() = default;
-};
-
-class MockSurfaceFlinger : public SurfaceFlinger {
-public:
- MockSurfaceFlinger(Factory& factory)
- : SurfaceFlinger(factory, SurfaceFlinger::SkipInitialization) {}
- std::shared_ptr<renderengine::ExternalTexture> getExternalTextureFromBufferData(
- BufferData& bufferData, const char* /* layerName */,
- uint64_t /* transactionId */) override {
- return std::make_shared<FakeExternalTexture>(bufferData.getWidth(), bufferData.getHeight(),
- bufferData.getId(),
- bufferData.getPixelFormat(),
- bufferData.getUsage());
- };
-
- // b/220017192 migrate from transact codes to ISurfaceComposer apis
- void setLayerTracingFlags(int32_t flags) {
- Parcel data;
- Parcel reply;
- data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
- data.writeInt32(flags);
- transact(1033, data, &reply, 0 /* flags */);
- }
-
- void setLayerTraceSize(int32_t sizeInKb) {
- Parcel data;
- Parcel reply;
- data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
- data.writeInt32(sizeInKb);
- transact(1029, data, &reply, 0 /* flags */);
- }
-
- void startLayerTracing(int64_t traceStartTime) {
- Parcel data;
- Parcel reply;
- data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
- data.writeInt32(1);
- data.writeInt64(traceStartTime);
- transact(1025, data, &reply, 0 /* flags */);
- }
-
- void stopLayerTracing(const char* tracePath) {
- Parcel data;
- Parcel reply;
- data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
- data.writeInt32(2);
- data.writeCString(tracePath);
- transact(1025, data, &reply, 0 /* flags */);
- }
-};
-
-class TraceGenFlingerDataMapper : public TransactionProtoParser::FlingerDataMapper {
-public:
- std::unordered_map<int32_t /*layerId*/, sp<IBinder> /* handle */> mLayerHandles;
- sp<IBinder> getLayerHandle(int32_t layerId) const override {
- if (layerId == -1) {
- ALOGE("Error: Called with layer=%d", layerId);
- return nullptr;
- }
- auto it = mLayerHandles.find(layerId);
- if (it == mLayerHandles.end()) {
- ALOGE("Error: Could not find handle for layer=%d", layerId);
- return nullptr;
- }
- return it->second;
- }
-};
+using namespace ftl::flag_operators;
bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile,
const char* outputLayersTracePath) {
@@ -191,82 +47,103 @@ bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile,
return false;
}
- Factory factory;
- sp<MockSurfaceFlinger> flingerPtr = sp<MockSurfaceFlinger>::make(factory);
- TestableSurfaceFlinger flinger(flingerPtr);
- flinger.setupRenderEngine(
- std::make_unique<testing::NiceMock<renderengine::mock::RenderEngine>>());
- flinger.setupMockScheduler({.useNiceMock = true});
+ TransactionProtoParser parser(std::make_unique<TransactionProtoParser::FlingerDataMapper>());
- Hwc2::mock::Composer* composerPtr = new testing::NiceMock<Hwc2::mock::Composer>();
- flinger.setupComposer(std::unique_ptr<Hwc2::Composer>(composerPtr));
- flinger.mutableMaxRenderTargetSize() = 16384;
+ // frontend
+ frontend::LayerLifecycleManager lifecycleManager;
+ frontend::LayerHierarchyBuilder hierarchyBuilder{{}};
+ frontend::LayerSnapshotBuilder snapshotBuilder;
+ display::DisplayMap<ui::LayerStack, frontend::DisplayInfo> displayInfos;
- flingerPtr->setLayerTracingFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS);
- flingerPtr->setLayerTraceSize(512 * 1024); // 512MB buffer size
- flingerPtr->startLayerTracing(traceFile.entry(0).elapsed_realtime_nanos());
- std::unique_ptr<TraceGenFlingerDataMapper> mapper =
- std::make_unique<TraceGenFlingerDataMapper>();
- TraceGenFlingerDataMapper* dataMapper = mapper.get();
- TransactionProtoParser parser(std::move(mapper));
+ renderengine::ShadowSettings globalShadowSettings{.ambientColor = {1, 1, 1, 1}};
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.surface_flinger.supports_background_blur", value, "0");
+ bool supportsBlur = atoi(value);
+
+ LayerTracing layerTracing;
+ layerTracing.setTraceFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS);
+ layerTracing.setBufferSize(512 * 1024 * 1024); // 512MB buffer size
+ layerTracing.enable();
ALOGD("Generating %d transactions...", traceFile.entry_size());
for (int i = 0; i < traceFile.entry_size(); i++) {
+ // parse proto
proto::TransactionTraceEntry entry = traceFile.entry(i);
ALOGV(" Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
" layers +%d -%d handles -%d transactions=%d",
i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
- entry.added_layers_size(), entry.removed_layers_size(),
- entry.removed_layer_handles_size(), entry.transactions_size());
+ entry.added_layers_size(), entry.destroyed_layers_size(),
+ entry.destroyed_layer_handles_size(), entry.transactions_size());
+ std::vector<std::unique_ptr<frontend::RequestedLayerState>> addedLayers;
+ addedLayers.reserve((size_t)entry.added_layers_size());
for (int j = 0; j < entry.added_layers_size(); j++) {
- // create layers
- TracingLayerCreationArgs tracingArgs;
- parser.fromProto(entry.added_layers(j), tracingArgs);
-
- gui::CreateSurfaceResult outResult;
- LayerCreationArgs args(flinger.flinger(), nullptr /* client */, tracingArgs.name,
- tracingArgs.flags, LayerMetadata(),
- std::make_optional<int32_t>(tracingArgs.layerId));
-
- if (tracingArgs.mirrorFromId == -1) {
- sp<IBinder> parentHandle = nullptr;
- if ((tracingArgs.parentId != -1) &&
- (dataMapper->mLayerHandles.find(tracingArgs.parentId) ==
- dataMapper->mLayerHandles.end())) {
- args.addToRoot = false;
- } else if (tracingArgs.parentId != -1) {
- parentHandle = dataMapper->getLayerHandle(tracingArgs.parentId);
- }
- flinger.createLayer(args, parentHandle, outResult);
- } else {
- sp<IBinder> mirrorFromHandle = dataMapper->getLayerHandle(tracingArgs.mirrorFromId);
- flinger.mirrorLayer(args, mirrorFromHandle, outResult);
- }
- LOG_ALWAYS_FATAL_IF(outResult.layerId != tracingArgs.layerId,
- "Could not create layer expected:%d actual:%d", tracingArgs.layerId,
- outResult.layerId);
- dataMapper->mLayerHandles[tracingArgs.layerId] = outResult.handle;
+ LayerCreationArgs args;
+ parser.fromProto(entry.added_layers(j), args);
+ addedLayers.emplace_back(std::make_unique<frontend::RequestedLayerState>(args));
}
+ std::vector<TransactionState> transactions;
+ transactions.reserve((size_t)entry.transactions_size());
for (int j = 0; j < entry.transactions_size(); j++) {
// apply transactions
TransactionState transaction = parser.fromProto(entry.transactions(j));
- flinger.setTransactionStateInternal(transaction);
+ transactions.emplace_back(std::move(transaction));
}
- const auto frameTime = TimePoint::fromNs(entry.elapsed_realtime_nanos());
- const auto vsyncId = VsyncId{entry.vsync_id()};
- flinger.commit(frameTime, vsyncId);
+ std::vector<uint32_t> destroyedHandles;
+ destroyedHandles.reserve((size_t)entry.destroyed_layer_handles_size());
+ for (int j = 0; j < entry.destroyed_layer_handles_size(); j++) {
+ destroyedHandles.push_back(entry.destroyed_layer_handles(j));
+ }
- for (int j = 0; j < entry.removed_layer_handles_size(); j++) {
- dataMapper->mLayerHandles.erase(entry.removed_layer_handles(j));
+ bool displayChanged = entry.displays_changed();
+ if (displayChanged) {
+ parser.fromProto(entry.displays(), displayInfos);
+ }
+
+ // apply updates
+ lifecycleManager.addLayers(std::move(addedLayers));
+ lifecycleManager.applyTransactions(transactions);
+ lifecycleManager.onHandlesDestroyed(destroyedHandles, /*ignoreUnknownHandles=*/true);
+
+ if (lifecycleManager.getGlobalChanges().test(
+ frontend::RequestedLayerState::Changes::Hierarchy)) {
+ hierarchyBuilder.update(lifecycleManager.getLayers(),
+ lifecycleManager.getDestroyedLayers());
}
- }
- flingerPtr->stopLayerTracing(outputLayersTracePath);
+ frontend::LayerSnapshotBuilder::Args args{.root = hierarchyBuilder.getHierarchy(),
+ .layerLifecycleManager = lifecycleManager,
+ .displays = displayInfos,
+ .displayChanges = displayChanged,
+ .globalShadowSettings = globalShadowSettings,
+ .supportsBlur = supportsBlur,
+ .forceFullDamage = false,
+ .supportedLayerGenericMetadata = {},
+ .genericLayerMetadataKeyMap = {}};
+ snapshotBuilder.update(args);
+
+ bool visibleRegionsDirty = lifecycleManager.getGlobalChanges().any(
+ frontend::RequestedLayerState::Changes::VisibleRegion |
+ frontend::RequestedLayerState::Changes::Hierarchy |
+ frontend::RequestedLayerState::Changes::Visibility);
+
+ ALOGV(" layers:%04zu snapshots:%04zu changes:%s", lifecycleManager.getLayers().size(),
+ snapshotBuilder.getSnapshots().size(),
+ lifecycleManager.getGlobalChanges().string().c_str());
+
+ lifecycleManager.commitChanges();
+
+ LayersProto layersProto = LayerProtoFromSnapshotGenerator(snapshotBuilder, displayInfos, {},
+ layerTracing.getFlags())
+ .generate(hierarchyBuilder.getHierarchy());
+ auto displayProtos = LayerProtoHelper::writeDisplayInfoToProto(displayInfos);
+ layerTracing.notify(visibleRegionsDirty, entry.elapsed_realtime_nanos(), entry.vsync_id(),
+ &layersProto, {}, &displayProtos);
+ }
+ layerTracing.disable(outputLayersTracePath);
ALOGD("End of generating trace file. File written to %s", outputLayersTracePath);
- dataMapper->mLayerHandles.clear();
return true;
}
diff --git a/services/surfaceflinger/Tracing/tools/main.cpp b/services/surfaceflinger/Tracing/tools/main.cpp
index 9f9ae4815b..c440c19ccc 100644
--- a/services/surfaceflinger/Tracing/tools/main.cpp
+++ b/services/surfaceflinger/Tracing/tools/main.cpp
@@ -53,9 +53,6 @@ int main(int argc, char** argv) {
ALOGD("Generating %s...", outputLayersTracePath);
std::cout << "Generating " << outputLayersTracePath << "\n";
- // sink any log spam from the stubbed surfaceflinger
- __android_log_set_logger([](const struct __android_log_message* /* log_message */) {});
-
if (!LayerTraceGenerator().generate(transactionTraceFile, outputLayersTracePath)) {
std::cout << "Error: Failed to generate layers trace " << outputLayersTracePath;
return -1;
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 72cecc9f89..6074bb7a16 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -452,8 +452,7 @@ public:
LayersProto layersProto = mFlinger->dumpDrawingStateProto(fdp->ConsumeIntegral<uint32_t>());
mFlinger->dumpOffscreenLayersProto(layersProto);
- LayersTraceProto layersTraceProto{};
- mFlinger->dumpDisplayProto(layersTraceProto);
+ mFlinger->dumpDisplayProto();
result = fdp->ConsumeRandomLengthString().c_str();
mFlinger->dumpHwc(result);
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index 3598308338..e9add2e1a4 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -138,6 +138,8 @@ message LayerProto {
float requested_corner_radius = 56;
RectProto destination_frame = 57;
+
+ uint32 original_id = 58;
}
message PositionProto {
diff --git a/services/surfaceflinger/layerproto/transactions.proto b/services/surfaceflinger/layerproto/transactions.proto
index 4c6a9cf85b..2c4eb101e6 100644
--- a/services/surfaceflinger/layerproto/transactions.proto
+++ b/services/surfaceflinger/layerproto/transactions.proto
@@ -40,6 +40,7 @@ message TransactionTraceFile {
/* offset between real-time clock and elapsed time clock in nanoseconds.
Calculated as: systemTime(SYSTEM_TIME_REALTIME) - systemTime(SYSTEM_TIME_MONOTONIC) */
fixed64 real_to_elapsed_time_offset_nanos = 3;
+ uint32 version = 4;
}
message TransactionTraceEntry {
@@ -47,18 +48,47 @@ message TransactionTraceEntry {
int64 vsync_id = 2;
repeated TransactionState transactions = 3;
repeated LayerCreationArgs added_layers = 4;
- repeated int32 removed_layers = 5;
+ repeated uint32 destroyed_layers = 5;
repeated DisplayState added_displays = 6;
repeated int32 removed_displays = 7;
- repeated int32 removed_layer_handles = 8;
+ repeated uint32 destroyed_layer_handles = 8;
+ bool displays_changed = 9;
+ repeated DisplayInfo displays = 10;
+}
+
+message DisplayInfo {
+ uint32 layer_stack = 1;
+ int32 display_id = 2;
+ int32 logical_width = 3;
+ int32 logical_height = 4;
+ Transform transform_inverse = 5;
+ Transform transform = 6;
+ bool receives_input = 7;
+ bool is_secure = 8;
+ bool is_primary = 9;
+ bool is_virtual = 10;
+ int32 rotation_flags = 11;
+ int32 transform_hint = 12;
+
}
message LayerCreationArgs {
- int32 layer_id = 1;
+ uint32 layer_id = 1;
string name = 2;
uint32 flags = 3;
- int32 parent_id = 4;
- int32 mirror_from_id = 5;
+ uint32 parent_id = 4;
+ uint32 mirror_from_id = 5;
+ bool add_to_root = 6;
+ uint32 layer_stack_to_mirror = 7;
+}
+
+message Transform {
+ float dsdx = 1;
+ float dtdx = 2;
+ float dtdy = 3;
+ float dsdy = 4;
+ float tx = 5;
+ float ty = 6;
}
message TransactionState {
@@ -74,7 +104,7 @@ message TransactionState {
// Keep insync with layer_state_t
message LayerState {
- int64 layer_id = 1;
+ uint32 layer_id = 1;
// Changes are split into ChangesLsb and ChangesMsb. First 32 bits are in ChangesLsb
// and the next 32 bits are in ChangesMsb. This is needed because enums have to be
// 32 bits and there's no nice way to put 64bit constants into .proto files.
@@ -164,8 +194,8 @@ message LayerState {
Matrix22 matrix = 11;
float corner_radius = 12;
uint32 background_blur_radius = 13;
- int64 parent_id = 14;
- int64 relative_parent_id = 15;
+ uint32 parent_id = 14;
+ uint32 relative_parent_id = 15;
float alpha = 16;
message Color3 {
@@ -220,14 +250,6 @@ message LayerState {
ColorTransformProto color_transform = 25;
repeated BlurRegion blur_regions = 26;
- message Transform {
- float dsdx = 1;
- float dtdx = 2;
- float dtdy = 3;
- float dsdy = 4;
- float tx = 5;
- float ty = 6;
- }
message WindowInfo {
uint32 layout_params_flags = 1;
int32 layout_params_type = 2;
@@ -236,7 +258,7 @@ message LayerState {
bool focusable = 5;
bool has_wallpaper = 6;
float global_scale_factor = 7;
- int64 crop_layer_id = 8;
+ uint32 crop_layer_id = 8;
bool replace_touchable_region_with_crop = 9;
RectProto touchable_region_crop = 10;
Transform transform = 11;
diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
index 5f9214c548..7355c35131 100644
--- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
+++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
@@ -20,6 +20,7 @@
#include <fstream>
#include <iostream>
#include <string>
+#include <unordered_map>
#include <LayerTraceGenerator.h>
#include <Tracing/TransactionProtoParser.h>
@@ -84,9 +85,9 @@ protected:
std::vector<std::filesystem::path> TransactionTraceTestSuite::sTransactionTraces{};
struct LayerInfo {
- int id;
+ int32_t id;
std::string name;
- int parent;
+ int32_t parent;
int z;
uint64_t curr_frame;
float x;
@@ -143,16 +144,27 @@ TEST_P(TransactionTraceTestSuite, validateEndState) {
expectedLayers.reserve(static_cast<size_t>(expectedLastEntry.layers().layers_size()));
for (int i = 0; i < expectedLastEntry.layers().layers_size(); i++) {
auto layer = expectedLastEntry.layers().layers(i);
- expectedLayers.push_back(getLayerInfoFromProto(layer));
+ LayerInfo layerInfo = getLayerInfoFromProto(layer);
+ expectedLayers.push_back(layerInfo);
}
std::sort(expectedLayers.begin(), expectedLayers.end(), compareById);
+ std::unordered_map<int32_t /* snapshotId*/, int32_t /*layerId*/> snapshotIdToLayerId;
std::vector<LayerInfo> actualLayers;
actualLayers.reserve(static_cast<size_t>(actualLastEntry.layers().layers_size()));
for (int i = 0; i < actualLastEntry.layers().layers_size(); i++) {
auto layer = actualLastEntry.layers().layers(i);
- actualLayers.push_back(getLayerInfoFromProto(layer));
+ LayerInfo layerInfo = getLayerInfoFromProto(layer);
+ snapshotIdToLayerId[layerInfo.id] = static_cast<int32_t>(layer.original_id());
+ actualLayers.push_back(layerInfo);
+ }
+
+ for (auto& layer : actualLayers) {
+ layer.id = snapshotIdToLayerId[layer.id];
+ auto it = snapshotIdToLayerId.find(layer.parent);
+ layer.parent = it == snapshotIdToLayerId.end() ? -1 : it->second;
}
+
std::sort(actualLayers.begin(), actualLayers.end(), compareById);
size_t i = 0;
diff --git a/services/surfaceflinger/tests/tracing/testdata/layers_trace_boot.winscope b/services/surfaceflinger/tests/tracing/testdata/layers_trace_boot.winscope
index 9e4005c2cf..296d2fdec6 100644
--- a/services/surfaceflinger/tests/tracing/testdata/layers_trace_boot.winscope
+++ b/services/surfaceflinger/tests/tracing/testdata/layers_trace_boot.winscope
Binary files differ
diff --git a/services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscope b/services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscope
index 16a91ee6ee..ae5441550d 100644
--- a/services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscope
+++ b/services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscope
Binary files differ
diff --git a/services/surfaceflinger/tests/tracing/testdata/transactions_trace_boot.winscope b/services/surfaceflinger/tests/tracing/testdata/transactions_trace_boot.winscope
index 8356ae7992..8d03df4735 100644
--- a/services/surfaceflinger/tests/tracing/testdata/transactions_trace_boot.winscope
+++ b/services/surfaceflinger/tests/tracing/testdata/transactions_trace_boot.winscope
Binary files differ
diff --git a/services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscope b/services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscope
index cd62ab8ce0..022861c7ea 100644
--- a/services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscope
+++ b/services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscope
Binary files differ
diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
index b6427c0ffb..3dea189ca0 100644
--- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
@@ -19,6 +19,7 @@
#include <limits> // std::numeric_limits
#include <gui/SurfaceComposerClient.h>
+#include "LayerProtoHelper.h"
#include "Tracing/TransactionProtoParser.h"
@@ -27,7 +28,6 @@ using namespace android::surfaceflinger;
namespace android {
TEST(TransactionProtoParserTest, parse) {
- const sp<IBinder> layerHandle = sp<BBinder>::make();
const sp<IBinder> displayHandle = sp<BBinder>::make();
TransactionState t1;
t1.originPid = 1;
@@ -37,7 +37,6 @@ TEST(TransactionProtoParserTest, parse) {
t1.postTime = 5;
layer_state_t layer;
- layer.layerId = 6;
layer.what = std::numeric_limits<uint64_t>::max();
layer.what &= ~static_cast<uint64_t>(layer_state_t::eBufferChanged);
layer.x = 7;
@@ -48,10 +47,9 @@ TEST(TransactionProtoParserTest, parse) {
for (uint32_t i = 0; i < layerCount; i++) {
ResolvedComposerState s;
if (i == 1) {
- layer.parentSurfaceControlForChild =
- sp<SurfaceControl>::make(SurfaceComposerClient::getDefault(), layerHandle, 42,
- "#42");
+ s.parentId = 42;
}
+ s.layerId = 6 + i;
s.state = layer;
t1.states.emplace_back(s);
}
@@ -72,18 +70,10 @@ TEST(TransactionProtoParserTest, parse) {
class TestMapper : public TransactionProtoParser::FlingerDataMapper {
public:
- sp<IBinder> layerHandle;
sp<IBinder> displayHandle;
- TestMapper(sp<IBinder> layerHandle, sp<IBinder> displayHandle)
- : layerHandle(layerHandle), displayHandle(displayHandle) {}
+ TestMapper(sp<IBinder> displayHandle) : displayHandle(displayHandle) {}
- sp<IBinder> getLayerHandle(int32_t id) const override {
- return (id == 42) ? layerHandle : nullptr;
- }
- int64_t getLayerId(const sp<IBinder>& handle) const override {
- return (handle == layerHandle) ? 42 : -1;
- }
sp<IBinder> getDisplayHandle(int32_t id) const {
return (id == 43) ? displayHandle : nullptr;
}
@@ -92,7 +82,7 @@ TEST(TransactionProtoParserTest, parse) {
}
};
- TransactionProtoParser parser(std::make_unique<TestMapper>(layerHandle, displayHandle));
+ TransactionProtoParser parser(std::make_unique<TestMapper>(displayHandle));
proto::TransactionState proto = parser.toProto(t1);
TransactionState t2 = parser.fromProto(proto);
@@ -105,8 +95,8 @@ TEST(TransactionProtoParserTest, parse) {
ASSERT_EQ(t1.states.size(), t2.states.size());
ASSERT_EQ(t1.states[0].state.x, t2.states[0].state.x);
ASSERT_EQ(t1.states[0].state.matrix.dsdx, t2.states[0].state.matrix.dsdx);
- ASSERT_EQ(t1.states[1].state.parentSurfaceControlForChild->getHandle(),
- t2.states[1].state.parentSurfaceControlForChild->getHandle());
+ ASSERT_EQ(t1.states[1].layerId, t2.states[1].layerId);
+ ASSERT_EQ(t1.states[1].parentId, t2.states[1].parentId);
ASSERT_EQ(t1.displays.size(), t2.displays.size());
ASSERT_EQ(t1.displays[1].width, t2.displays[1].width);
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index 482c3a8e50..74541ace0b 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -18,7 +18,11 @@
#include <gtest/gtest.h>
#include <gui/SurfaceComposerClient.h>
+#include <cstdint>
+#include "Client.h"
+#include "FrontEnd/LayerCreationArgs.h"
+#include "FrontEnd/Update.h"
#include "Tracing/RingBuffer.h"
#include "Tracing/TransactionTracing.h"
@@ -42,14 +46,15 @@ protected:
}
void queueAndCommitTransaction(int64_t vsyncId) {
+ frontend::Update update;
TransactionState transaction;
transaction.id = static_cast<uint64_t>(vsyncId * 3);
transaction.originUid = 1;
transaction.originPid = 2;
mTracing.addQueuedTransaction(transaction);
std::vector<TransactionState> transactions;
- transactions.emplace_back(transaction);
- mTracing.addCommittedTransactions(transactions, vsyncId);
+ update.transactions.emplace_back(transaction);
+ mTracing.addCommittedTransactions(vsyncId, 0, update, {}, false);
flush(vsyncId);
}
@@ -57,13 +62,25 @@ protected:
const std::vector<TransactionState>& expectedTransactions,
int64_t expectedVsyncId) {
EXPECT_EQ(actualProto.vsync_id(), expectedVsyncId);
- EXPECT_EQ(actualProto.transactions().size(),
+ ASSERT_EQ(actualProto.transactions().size(),
static_cast<int32_t>(expectedTransactions.size()));
for (uint32_t i = 0; i < expectedTransactions.size(); i++) {
EXPECT_EQ(actualProto.transactions(static_cast<int32_t>(i)).pid(),
expectedTransactions[i].originPid);
}
}
+
+ LayerCreationArgs getLayerCreationArgs(uint32_t layerId, uint32_t parentId,
+ uint32_t layerIdToMirror, uint32_t flags,
+ bool addToRoot) {
+ LayerCreationArgs args;
+ args.sequence = layerId;
+ args.parentId = parentId;
+ args.layerIdToMirror = layerIdToMirror;
+ args.flags = flags;
+ args.addToRoot = addToRoot;
+ return args;
+ }
};
TEST_F(TransactionTracingTest, addTransactions) {
@@ -79,57 +96,59 @@ TEST_F(TransactionTracingTest, addTransactions) {
// Split incoming transactions into two and commit them in reverse order to test out of order
// commits.
- std::vector<TransactionState> firstTransactionSet =
- std::vector<TransactionState>(transactions.begin() + 50, transactions.end());
int64_t firstTransactionSetVsyncId = 42;
- mTracing.addCommittedTransactions(firstTransactionSet, firstTransactionSetVsyncId);
+ frontend::Update firstUpdate;
+ firstUpdate.transactions =
+ std::vector<TransactionState>(transactions.begin() + 50, transactions.end());
+ mTracing.addCommittedTransactions(firstTransactionSetVsyncId, 0, firstUpdate, {}, false);
int64_t secondTransactionSetVsyncId = 43;
- std::vector<TransactionState> secondTransactionSet =
+ frontend::Update secondUpdate;
+ secondUpdate.transactions =
std::vector<TransactionState>(transactions.begin(), transactions.begin() + 50);
- mTracing.addCommittedTransactions(secondTransactionSet, secondTransactionSetVsyncId);
+ mTracing.addCommittedTransactions(secondTransactionSetVsyncId, 0, secondUpdate, {}, false);
flush(secondTransactionSetVsyncId);
proto::TransactionTraceFile proto = writeToProto();
- EXPECT_EQ(proto.entry().size(), 2);
- verifyEntry(proto.entry(0), firstTransactionSet, firstTransactionSetVsyncId);
- verifyEntry(proto.entry(1), secondTransactionSet, secondTransactionSetVsyncId);
+ ASSERT_EQ(proto.entry().size(), 2);
+ verifyEntry(proto.entry(0), firstUpdate.transactions, firstTransactionSetVsyncId);
+ verifyEntry(proto.entry(1), secondUpdate.transactions, secondTransactionSetVsyncId);
}
class TransactionTracingLayerHandlingTest : public TransactionTracingTest {
protected:
void SetUp() override {
- // add layers
mTracing.setBufferSize(SMALL_BUFFER_SIZE);
- const sp<IBinder> fakeLayerHandle = sp<BBinder>::make();
- mTracing.onLayerAdded(fakeLayerHandle->localBinder(), mParentLayerId, "parent",
- 123 /* flags */, -1 /* parentId */);
- const sp<IBinder> fakeChildLayerHandle = sp<BBinder>::make();
- mTracing.onLayerAdded(fakeChildLayerHandle->localBinder(), mChildLayerId, "child",
- 456 /* flags */, mParentLayerId);
-
- // add some layer transaction
+
+ // add layers and add some layer transaction
{
+ frontend::Update update;
+ update.layerCreationArgs.emplace_back(std::move(
+ getLayerCreationArgs(mParentLayerId, /*parentId=*/UNASSIGNED_LAYER_ID,
+ /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/123,
+ /*addToRoot=*/true)));
+ update.layerCreationArgs.emplace_back(std::move(
+ getLayerCreationArgs(mChildLayerId, mParentLayerId,
+ /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/456,
+ /*addToRoot=*/true)));
TransactionState transaction;
transaction.id = 50;
ResolvedComposerState layerState;
- layerState.state.surface = fakeLayerHandle;
+ layerState.layerId = mParentLayerId;
layerState.state.what = layer_state_t::eLayerChanged;
layerState.state.z = 42;
transaction.states.emplace_back(layerState);
ResolvedComposerState childState;
- childState.state.surface = fakeChildLayerHandle;
+ childState.layerId = mChildLayerId;
childState.state.what = layer_state_t::eLayerChanged;
childState.state.z = 43;
transaction.states.emplace_back(childState);
mTracing.addQueuedTransaction(transaction);
- std::vector<TransactionState> transactions;
- transactions.emplace_back(transaction);
+ update.transactions.emplace_back(transaction);
VSYNC_ID_FIRST_LAYER_CHANGE = ++mVsyncId;
- mTracing.onLayerAddedToDrawingState(mParentLayerId, VSYNC_ID_FIRST_LAYER_CHANGE);
- mTracing.onLayerAddedToDrawingState(mChildLayerId, VSYNC_ID_FIRST_LAYER_CHANGE);
- mTracing.addCommittedTransactions(transactions, VSYNC_ID_FIRST_LAYER_CHANGE);
+ mTracing.addCommittedTransactions(VSYNC_ID_FIRST_LAYER_CHANGE, 0, update, {}, false);
+
flush(VSYNC_ID_FIRST_LAYER_CHANGE);
}
@@ -139,17 +158,17 @@ protected:
TransactionState transaction;
transaction.id = 51;
ResolvedComposerState layerState;
- layerState.state.surface = fakeLayerHandle;
+ layerState.layerId = mParentLayerId;
layerState.state.what = layer_state_t::eLayerChanged | layer_state_t::ePositionChanged;
layerState.state.z = 41;
layerState.state.x = 22;
transaction.states.emplace_back(layerState);
mTracing.addQueuedTransaction(transaction);
- std::vector<TransactionState> transactions;
- transactions.emplace_back(transaction);
+ frontend::Update update;
+ update.transactions.emplace_back(transaction);
VSYNC_ID_SECOND_LAYER_CHANGE = ++mVsyncId;
- mTracing.addCommittedTransactions(transactions, VSYNC_ID_SECOND_LAYER_CHANGE);
+ mTracing.addCommittedTransactions(VSYNC_ID_SECOND_LAYER_CHANGE, 0, update, {}, false);
flush(VSYNC_ID_SECOND_LAYER_CHANGE);
}
@@ -163,8 +182,8 @@ protected:
queueAndCommitTransaction(++mVsyncId);
}
- int mParentLayerId = 1;
- int mChildLayerId = 2;
+ uint32_t mParentLayerId = 1;
+ uint32_t mChildLayerId = 2;
int64_t mVsyncId = 0;
int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
int64_t VSYNC_ID_SECOND_LAYER_CHANGE;
@@ -232,42 +251,42 @@ TEST_F(TransactionTracingLayerHandlingTest, startingStateSurvivesBufferFlush) {
class TransactionTracingMirrorLayerTest : public TransactionTracingTest {
protected:
void SetUp() override {
- // add layers
mTracing.setBufferSize(SMALL_BUFFER_SIZE);
- const sp<IBinder> fakeLayerHandle = sp<BBinder>::make();
- mTracing.onLayerAdded(fakeLayerHandle->localBinder(), mLayerId, "Test Layer",
- 123 /* flags */, -1 /* parentId */);
- const sp<IBinder> fakeMirrorLayerHandle = sp<BBinder>::make();
- mTracing.onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror",
- mLayerId);
- mTracing.onLayerAddedToDrawingState(mLayerId, mVsyncId);
- mTracing.onLayerAddedToDrawingState(mMirrorLayerId, mVsyncId);
-
- // add some layer transaction
+
+ // add layers and some layer transaction
{
+ frontend::Update update;
+ update.layerCreationArgs.emplace_back(
+ getLayerCreationArgs(mLayerId, /*parentId=*/UNASSIGNED_LAYER_ID,
+ /*layerIdToMirror=*/UNASSIGNED_LAYER_ID, /*flags=*/123,
+ /*addToRoot=*/true));
+ update.layerCreationArgs.emplace_back(
+ getLayerCreationArgs(mMirrorLayerId, UNASSIGNED_LAYER_ID,
+ /*layerIdToMirror=*/mLayerId, /*flags=*/0,
+ /*addToRoot=*/false));
+
TransactionState transaction;
transaction.id = 50;
ResolvedComposerState layerState;
- layerState.state.surface = fakeLayerHandle;
+ layerState.layerId = mLayerId;
layerState.state.what = layer_state_t::eLayerChanged;
layerState.state.z = 42;
transaction.states.emplace_back(layerState);
ResolvedComposerState mirrorState;
- mirrorState.state.surface = fakeMirrorLayerHandle;
+ mirrorState.layerId = mMirrorLayerId;
mirrorState.state.what = layer_state_t::eLayerChanged;
mirrorState.state.z = 43;
transaction.states.emplace_back(mirrorState);
mTracing.addQueuedTransaction(transaction);
- std::vector<TransactionState> transactions;
- transactions.emplace_back(transaction);
- mTracing.addCommittedTransactions(transactions, mVsyncId);
+ update.transactions.emplace_back(transaction);
+ mTracing.addCommittedTransactions(mVsyncId, 0, update, {}, false);
flush(mVsyncId);
}
}
- int mLayerId = 5;
- int mMirrorLayerId = 55;
+ uint32_t mLayerId = 5;
+ uint32_t mMirrorLayerId = 55;
int64_t mVsyncId = 0;
int64_t VSYNC_ID_FIRST_LAYER_CHANGE;
int64_t VSYNC_ID_SECOND_LAYER_CHANGE;