blob: 59173587976f0c0b3937203927dd392aa4da5d5b [file] [log] [blame]
Pascal Mütschardd56514e2024-05-24 17:37:13 +02001/*
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 <cstdint>
20#include <mutex>
21#include <unordered_map>
22
23#include <android/gui/JankData.h>
24#include <binder/IBinder.h>
25#include <utils/Mutex.h>
26
27namespace android {
28namespace frametimeline {
29class FrameTimelineTest;
30}
31
32/**
33 * JankTracker maintains a backlog of frame jank classification and manages and notififies any
34 * registered jank data listeners.
35 */
36class JankTracker {
37public:
38 ~JankTracker();
39
40 static void addJankListener(int32_t layerId, sp<IBinder> listener);
41 static void flushJankData(int32_t layerId);
42 static void removeJankListener(int32_t layerId, sp<IBinder> listener, int64_t afterVysnc);
43
44 static void onJankData(int32_t layerId, gui::JankData data);
45
46protected:
47 // The following methods can be used to force the tracker to collect all jank data and not
48 // flush it for a short time period and should *only* be used for testing. Every call to
49 // clearAndStartCollectingAllJankDataForTesting needs to be followed by a call to
50 // clearAndStopCollectingAllJankDataForTesting.
51 static void clearAndStartCollectingAllJankDataForTesting();
52 static std::vector<gui::JankData> getCollectedJankDataForTesting(int32_t layerId);
53 static void clearAndStopCollectingAllJankDataForTesting();
54
55 friend class frametimeline::FrameTimelineTest;
56
57private:
58 JankTracker() {}
59 JankTracker(const JankTracker&) = delete;
60 JankTracker(JankTracker&&) = delete;
61
62 JankTracker& operator=(const JankTracker&) = delete;
63 JankTracker& operator=(JankTracker&&) = delete;
64
65 static JankTracker& getInstance() {
66 static JankTracker instance;
67 return instance;
68 }
69
70 void addJankListenerLocked(int32_t layerId, sp<IBinder> listener) REQUIRES(mLock);
71 void doFlushJankData(int32_t layerId);
72 void markJankListenerForRemovalLocked(int32_t layerId, sp<IBinder> listener, int64_t afterVysnc)
73 REQUIRES(mLock);
74
75 int64_t transferAvailableJankData(int32_t layerId, std::vector<gui::JankData>& jankData);
76 void dropJankListener(int32_t layerId, sp<IBinder> listener);
77
78 struct Listener {
79 sp<IBinder> mListener;
80 int64_t mRemoveAfter;
81
82 Listener(sp<IBinder>&& listener) : mListener(listener), mRemoveAfter(-1) {}
83 };
84
85 // We keep track of the current listener count, so that the onJankData call, which is on the
86 // main thread, can short-curcuit the scheduling on the background thread (which involves
87 // locking) if there are no listeners registered, which is the most common case.
88 static std::atomic<size_t> sListenerCount;
89 static std::atomic<bool> sCollectAllJankDataForTesting;
90
91 std::mutex mLock;
92 std::unordered_multimap<int32_t, Listener> mJankListeners GUARDED_BY(mLock);
93 std::mutex mJankDataLock;
94 std::unordered_multimap<int32_t, gui::JankData> mJankData GUARDED_BY(mJankDataLock);
95
96 friend class JankTrackerTest;
97};
98
99} // namespace android