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