blob: a58d52a08c9e5e32b60150cabfe08e65bc452b2b [file] [log] [blame]
Prabir Pradhanbb7a0202024-02-10 02:09:01 +00001/*
2 * Copyright 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "InputTracer"
18
19#include "ThreadedBackend.h"
20
21#include "InputTracingPerfettoBackend.h"
22
23#include <android-base/logging.h>
24#include <utils/AndroidThreads.h>
25
26namespace android::inputdispatcher::trace::impl {
27
28namespace {
29
30// Helper to std::visit with lambdas.
31template <typename... V>
32struct Visitor : V... {
33 using V::operator()...;
34};
35
36} // namespace
37
38// --- ThreadedBackend ---
39
40template <typename Backend>
41ThreadedBackend<Backend>::ThreadedBackend(Backend&& innerBackend)
42 : mTracerThread(&ThreadedBackend::threadLoop, this), mBackend(std::move(innerBackend)) {}
43
44template <typename Backend>
45ThreadedBackend<Backend>::~ThreadedBackend() {
46 {
47 std::scoped_lock lock(mLock);
48 mThreadExit = true;
49 }
50 mThreadWakeCondition.notify_all();
51 mTracerThread.join();
52}
53
54template <typename Backend>
55void ThreadedBackend<Backend>::traceMotionEvent(const TracedMotionEvent& event) {
56 std::scoped_lock lock(mLock);
57 mQueue.emplace_back(event);
58 mThreadWakeCondition.notify_all();
59}
60
61template <typename Backend>
62void ThreadedBackend<Backend>::traceKeyEvent(const TracedKeyEvent& event) {
63 std::scoped_lock lock(mLock);
64 mQueue.emplace_back(event);
65 mThreadWakeCondition.notify_all();
66}
67
68template <typename Backend>
69void ThreadedBackend<Backend>::traceWindowDispatch(const WindowDispatchArgs& dispatchArgs) {
70 std::scoped_lock lock(mLock);
71 mQueue.emplace_back(dispatchArgs);
72 mThreadWakeCondition.notify_all();
73}
74
75template <typename Backend>
76void ThreadedBackend<Backend>::threadLoop() {
77 androidSetThreadName("InputTracer");
78
79 std::vector<std::variant<TracedKeyEvent, TracedMotionEvent, WindowDispatchArgs>> events;
80
81 while (true) {
82 { // acquire lock
83 std::unique_lock lock(mLock);
84 base::ScopedLockAssertion assumeLocked(mLock);
85
86 // Wait until we need to process more events or exit.
87 mThreadWakeCondition.wait(lock, [&]() REQUIRES(mLock) {
88 return mThreadExit || !mQueue.empty();
89 });
90 if (mThreadExit) {
91 return;
92 }
93
94 mQueue.swap(events);
95 } // release lock
96
97 // Trace the events into the backend without holding the lock to reduce the amount of
98 // work performed in the critical section.
99 for (const auto& event : events) {
100 std::visit(Visitor{[&](const TracedMotionEvent& e) { mBackend.traceMotionEvent(e); },
101 [&](const TracedKeyEvent& e) { mBackend.traceKeyEvent(e); },
102 [&](const WindowDispatchArgs& args) {
103 mBackend.traceWindowDispatch(args);
104 }},
105 event);
106 }
107 events.clear();
108 }
109}
110
111// Explicit template instantiation for the PerfettoBackend.
112template class ThreadedBackend<PerfettoBackend>;
113
114} // namespace android::inputdispatcher::trace::impl