1 /*
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 #pragma once
18 
19 #include "InputThread.h"
20 #include "InputTracingPerfettoBackend.h"
21 
22 #include <android-base/thread_annotations.h>
23 #include <mutex>
24 #include <variant>
25 #include <vector>
26 
27 namespace android::inputdispatcher::trace::impl {
28 
29 /**
30  * A wrapper around an InputTracingBackend implementation that writes to the inner tracing backend
31  * from a single new thread that it creates. The new tracing thread is started when the
32  * ThreadedBackend is created, and is stopped when it is destroyed. The ThreadedBackend is
33  * thread-safe.
34  */
35 template <typename Backend>
36 class ThreadedBackend : public InputTracingBackendInterface {
37 public:
38     ThreadedBackend(Backend&& innerBackend);
39     ~ThreadedBackend() override;
40 
41     void traceKeyEvent(const TracedKeyEvent&, const TracedEventMetadata&) override;
42     void traceMotionEvent(const TracedMotionEvent&, const TracedEventMetadata&) override;
43     void traceWindowDispatch(const WindowDispatchArgs&, const TracedEventMetadata&) override;
44 
45     /** Returns a function that, when called, will block until the tracing thread is idle. */
46     std::function<void()> getIdleWaiterForTesting();
47 
48 private:
49     std::mutex mLock;
GUARDED_BY(mLock)50     bool mThreadExit GUARDED_BY(mLock){false};
51     std::condition_variable mThreadWakeCondition;
52     Backend mBackend;
53     using TraceEntry =
54             std::pair<std::variant<TracedKeyEvent, TracedMotionEvent, WindowDispatchArgs>,
55                       TracedEventMetadata>;
56     std::vector<TraceEntry> mQueue GUARDED_BY(mLock);
57 
58     struct IdleWaiter {
59         std::mutex idleLock;
60         std::condition_variable threadIdleCondition;
GUARDED_BYIdleWaiter61         bool isIdle GUARDED_BY(idleLock){false};
62     };
63     // The lazy-initialized object used to wait for the tracing thread to idle.
64     std::shared_ptr<IdleWaiter> mIdleWaiter GUARDED_BY(mLock);
65 
66     // InputThread stops when its destructor is called. Initialize it last so that it is the
67     // first thing to be destructed. This will guarantee the thread will not access other
68     // members that have already been destructed.
69     InputThread mTracerThread;
70 
71     void threadLoop();
72     void setIdleStatus(bool isIdle) REQUIRES(mLock);
73 };
74 
75 } // namespace android::inputdispatcher::trace::impl
76