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