• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 "JankInfo.h"
20 
21 #include <binder/IInterface.h>
22 #include <binder/Parcel.h>
23 #include <binder/Parcelable.h>
24 #include <binder/SafeInterface.h>
25 
26 #include <gui/FrameTimestamps.h>
27 #include <ui/Fence.h>
28 #include <utils/Timers.h>
29 
30 #include <cstdint>
31 #include <unordered_map>
32 #include <unordered_set>
33 #include <variant>
34 
35 namespace android {
36 
37 class ITransactionCompletedListener;
38 class ListenerCallbacks;
39 
40 class CallbackId : public Parcelable {
41 public:
42     int64_t id;
43     enum class Type : int32_t { ON_COMPLETE, ON_COMMIT } type;
44 
CallbackId()45     CallbackId() {}
CallbackId(int64_t id,Type type)46     CallbackId(int64_t id, Type type) : id(id), type(type) {}
47     status_t writeToParcel(Parcel* output) const override;
48     status_t readFromParcel(const Parcel* input) override;
49 
50     bool operator==(const CallbackId& rhs) const { return id == rhs.id && type == rhs.type; }
51 };
52 
53 struct CallbackIdHash {
operatorCallbackIdHash54     std::size_t operator()(const CallbackId& key) const { return std::hash<int64_t>()(key.id); }
55 };
56 
57 class ReleaseCallbackId : public Parcelable {
58 public:
59     static const ReleaseCallbackId INVALID_ID;
60 
61     uint64_t bufferId;
62     uint64_t framenumber;
ReleaseCallbackId()63     ReleaseCallbackId() {}
ReleaseCallbackId(uint64_t bufferId,uint64_t framenumber)64     ReleaseCallbackId(uint64_t bufferId, uint64_t framenumber)
65           : bufferId(bufferId), framenumber(framenumber) {}
66     status_t writeToParcel(Parcel* output) const override;
67     status_t readFromParcel(const Parcel* input) override;
68 
69     bool operator==(const ReleaseCallbackId& rhs) const {
70         return bufferId == rhs.bufferId && framenumber == rhs.framenumber;
71     }
72     bool operator!=(const ReleaseCallbackId& rhs) const { return !operator==(rhs); }
to_string()73     std::string to_string() const {
74         if (*this == INVALID_ID) return "INVALID_ID";
75 
76         return "bufferId:" + std::to_string(bufferId) +
77                 " framenumber:" + std::to_string(framenumber);
78     }
79 };
80 
81 struct ReleaseBufferCallbackIdHash {
operatorReleaseBufferCallbackIdHash82     std::size_t operator()(const ReleaseCallbackId& key) const {
83         return std::hash<uint64_t>()(key.bufferId);
84     }
85 };
86 
87 class FrameEventHistoryStats : public Parcelable {
88 public:
89     status_t writeToParcel(Parcel* output) const override;
90     status_t readFromParcel(const Parcel* input) override;
91 
92     FrameEventHistoryStats() = default;
FrameEventHistoryStats(uint64_t fn,const sp<Fence> & gpuCompFence,CompositorTiming compTiming,nsecs_t refreshTime,nsecs_t dequeueReadyTime)93     FrameEventHistoryStats(uint64_t fn, const sp<Fence>& gpuCompFence, CompositorTiming compTiming,
94                            nsecs_t refreshTime, nsecs_t dequeueReadyTime)
95           : frameNumber(fn),
96             gpuCompositionDoneFence(gpuCompFence),
97             compositorTiming(compTiming),
98             refreshStartTime(refreshTime),
99             dequeueReadyTime(dequeueReadyTime) {}
100 
101     uint64_t frameNumber;
102     sp<Fence> gpuCompositionDoneFence;
103     CompositorTiming compositorTiming;
104     nsecs_t refreshStartTime;
105     nsecs_t dequeueReadyTime;
106 };
107 
108 /**
109  * Jank information representing SurfaceFlinger's jank classification about frames for a specific
110  * surface.
111  */
112 class JankData : public Parcelable {
113 public:
114     status_t writeToParcel(Parcel* output) const override;
115     status_t readFromParcel(const Parcel* input) override;
116 
117     JankData();
JankData(int64_t frameVsyncId,int32_t jankType)118     JankData(int64_t frameVsyncId, int32_t jankType)
119           : frameVsyncId(frameVsyncId), jankType(jankType) {}
120 
121     // Identifier for the frame submitted with Transaction.setFrameTimelineVsyncId
122     int64_t frameVsyncId;
123 
124     // Bitmask of janks that occurred
125     int32_t jankType;
126 };
127 
128 class SurfaceStats : public Parcelable {
129 public:
130     status_t writeToParcel(Parcel* output) const override;
131     status_t readFromParcel(const Parcel* input) override;
132 
133     SurfaceStats() = default;
SurfaceStats(const sp<IBinder> & sc,std::variant<nsecs_t,sp<Fence>> acquireTimeOrFence,const sp<Fence> & prevReleaseFence,uint32_t hint,uint32_t currentMaxAcquiredBuffersCount,FrameEventHistoryStats frameEventStats,std::vector<JankData> jankData,ReleaseCallbackId previousReleaseCallbackId)134     SurfaceStats(const sp<IBinder>& sc, std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence,
135                  const sp<Fence>& prevReleaseFence, uint32_t hint,
136                  uint32_t currentMaxAcquiredBuffersCount, FrameEventHistoryStats frameEventStats,
137                  std::vector<JankData> jankData, ReleaseCallbackId previousReleaseCallbackId)
138           : surfaceControl(sc),
139             acquireTimeOrFence(std::move(acquireTimeOrFence)),
140             previousReleaseFence(prevReleaseFence),
141             transformHint(hint),
142             currentMaxAcquiredBufferCount(currentMaxAcquiredBuffersCount),
143             eventStats(frameEventStats),
144             jankData(std::move(jankData)),
145             previousReleaseCallbackId(previousReleaseCallbackId) {}
146 
147     sp<IBinder> surfaceControl;
148     std::variant<nsecs_t, sp<Fence>> acquireTimeOrFence = -1;
149     sp<Fence> previousReleaseFence;
150     uint32_t transformHint = 0;
151     uint32_t currentMaxAcquiredBufferCount = 0;
152     FrameEventHistoryStats eventStats;
153     std::vector<JankData> jankData;
154     ReleaseCallbackId previousReleaseCallbackId;
155 };
156 
157 class TransactionStats : public Parcelable {
158 public:
159     status_t writeToParcel(Parcel* output) const override;
160     status_t readFromParcel(const Parcel* input) override;
161 
162     TransactionStats() = default;
TransactionStats(const std::vector<CallbackId> & ids)163     TransactionStats(const std::vector<CallbackId>& ids) : callbackIds(ids) {}
TransactionStats(const std::unordered_set<CallbackId,CallbackIdHash> & ids)164     TransactionStats(const std::unordered_set<CallbackId, CallbackIdHash>& ids)
165           : callbackIds(ids.begin(), ids.end()) {}
TransactionStats(const std::vector<CallbackId> & ids,nsecs_t latch,const sp<Fence> & present,const std::vector<SurfaceStats> & surfaces)166     TransactionStats(const std::vector<CallbackId>& ids, nsecs_t latch, const sp<Fence>& present,
167                      const std::vector<SurfaceStats>& surfaces)
168           : callbackIds(ids), latchTime(latch), presentFence(present), surfaceStats(surfaces) {}
169 
170     std::vector<CallbackId> callbackIds;
171     nsecs_t latchTime = -1;
172     sp<Fence> presentFence = nullptr;
173     std::vector<SurfaceStats> surfaceStats;
174 };
175 
176 class ListenerStats : public Parcelable {
177 public:
178     status_t writeToParcel(Parcel* output) const override;
179     status_t readFromParcel(const Parcel* input) override;
180 
181     static ListenerStats createEmpty(
182             const sp<IBinder>& listener,
183             const std::unordered_set<CallbackId, CallbackIdHash>& callbackIds);
184 
185     sp<IBinder> listener;
186     std::vector<TransactionStats> transactionStats;
187 };
188 
189 class ITransactionCompletedListener : public IInterface {
190 public:
191     DECLARE_META_INTERFACE(TransactionCompletedListener)
192 
193     virtual void onTransactionCompleted(ListenerStats stats) = 0;
194 
195     virtual void onReleaseBuffer(ReleaseCallbackId callbackId, sp<Fence> releaseFence,
196                                  uint32_t currentMaxAcquiredBufferCount) = 0;
197     virtual void onTransactionQueueStalled() = 0;
198 };
199 
200 class BnTransactionCompletedListener : public SafeBnInterface<ITransactionCompletedListener> {
201 public:
BnTransactionCompletedListener()202     BnTransactionCompletedListener()
203           : SafeBnInterface<ITransactionCompletedListener>("BnTransactionCompletedListener") {}
204 
205     status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
206                         uint32_t flags = 0) override;
207 };
208 
209 class ListenerCallbacks {
210 public:
ListenerCallbacks(const sp<IBinder> & listener,const std::unordered_set<CallbackId,CallbackIdHash> & callbacks)211     ListenerCallbacks(const sp<IBinder>& listener,
212                       const std::unordered_set<CallbackId, CallbackIdHash>& callbacks)
213           : transactionCompletedListener(listener),
214             callbackIds(callbacks.begin(), callbacks.end()) {}
215 
ListenerCallbacks(const sp<IBinder> & listener,const std::vector<CallbackId> & ids)216     ListenerCallbacks(const sp<IBinder>& listener, const std::vector<CallbackId>& ids)
217           : transactionCompletedListener(listener), callbackIds(ids) {}
218 
219     bool operator==(const ListenerCallbacks& rhs) const {
220         if (transactionCompletedListener != rhs.transactionCompletedListener) {
221             return false;
222         }
223         if (callbackIds.empty()) {
224             return rhs.callbackIds.empty();
225         }
226         return callbackIds.front().id == rhs.callbackIds.front().id;
227     }
228 
229     // Returns a new ListenerCallbacks filtered by type
230     ListenerCallbacks filter(CallbackId::Type type) const;
231 
232     sp<IBinder> transactionCompletedListener;
233     std::vector<CallbackId> callbackIds;
234 };
235 
236 struct IListenerHash {
operatorIListenerHash237     std::size_t operator()(const sp<IBinder>& strongPointer) const {
238         return std::hash<IBinder*>{}(strongPointer.get());
239     }
240 };
241 
242 struct CallbackIdsHash {
243     // CallbackId vectors have several properties that let us get away with this simple hash.
244     // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is
245     // empty we can still hash 0.
246     // 2) CallbackId vectors for the same listener either are identical or contain none of the
247     // same members. It is sufficient to just check the first CallbackId in the vectors. If
248     // they match, they are the same. If they do not match, they are not the same.
operatorCallbackIdsHash249     std::size_t operator()(const std::vector<CallbackId>& callbackIds) const {
250         return std::hash<int64_t>{}((callbackIds.empty()) ? 0 : callbackIds.front().id);
251     }
252 };
253 
254 struct ListenerCallbacksHash {
HashCombineListenerCallbacksHash255     std::size_t HashCombine(size_t value1, size_t value2) const {
256         return value1 ^ (value2 + 0x9e3779b9 + (value1 << 6) + (value1 >> 2));
257     }
258 
operatorListenerCallbacksHash259     std::size_t operator()(const ListenerCallbacks& listenerCallbacks) const {
260         struct IListenerHash listenerHasher;
261         struct CallbackIdsHash callbackIdsHasher;
262 
263         std::size_t listenerHash = listenerHasher(listenerCallbacks.transactionCompletedListener);
264         std::size_t callbackIdsHash = callbackIdsHasher(listenerCallbacks.callbackIds);
265 
266         return HashCombine(listenerHash, callbackIdsHash);
267     }
268 };
269 
270 } // namespace android
271