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