1*38e8c45fSAndroid Build Coastguard Worker /* 2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2021 The Android Open Source Project 3*38e8c45fSAndroid Build Coastguard Worker * 4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*38e8c45fSAndroid Build Coastguard Worker * 8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*38e8c45fSAndroid Build Coastguard Worker * 10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License. 15*38e8c45fSAndroid Build Coastguard Worker */ 16*38e8c45fSAndroid Build Coastguard Worker 17*38e8c45fSAndroid Build Coastguard Worker #pragma once 18*38e8c45fSAndroid Build Coastguard Worker 19*38e8c45fSAndroid Build Coastguard Worker #include <android-base/thread_annotations.h> 20*38e8c45fSAndroid Build Coastguard Worker #include <android/gui/IHdrLayerInfoListener.h> 21*38e8c45fSAndroid Build Coastguard Worker #include <binder/IBinder.h> 22*38e8c45fSAndroid Build Coastguard Worker #include <utils/Timers.h> 23*38e8c45fSAndroid Build Coastguard Worker 24*38e8c45fSAndroid Build Coastguard Worker #include <unordered_map> 25*38e8c45fSAndroid Build Coastguard Worker 26*38e8c45fSAndroid Build Coastguard Worker #include "Utils/RingBuffer.h" 27*38e8c45fSAndroid Build Coastguard Worker #include "WpHash.h" 28*38e8c45fSAndroid Build Coastguard Worker 29*38e8c45fSAndroid Build Coastguard Worker namespace android { 30*38e8c45fSAndroid Build Coastguard Worker 31*38e8c45fSAndroid Build Coastguard Worker class HdrLayerInfoReporter final : public IBinder::DeathRecipient { 32*38e8c45fSAndroid Build Coastguard Worker public: 33*38e8c45fSAndroid Build Coastguard Worker struct HdrLayerInfo { 34*38e8c45fSAndroid Build Coastguard Worker int32_t numberOfHdrLayers = 0; 35*38e8c45fSAndroid Build Coastguard Worker int32_t maxW = 0; 36*38e8c45fSAndroid Build Coastguard Worker int32_t maxH = 0; 37*38e8c45fSAndroid Build Coastguard Worker int32_t flags = 0; 38*38e8c45fSAndroid Build Coastguard Worker // Counter-intuitively a value of "1" means "as much as you can give me" due to "1" being 39*38e8c45fSAndroid Build Coastguard Worker // the default value for all layers, so any HDR layer with a value of 1.f means no 40*38e8c45fSAndroid Build Coastguard Worker // reduced maximum has been requested 41*38e8c45fSAndroid Build Coastguard Worker // TODO: Should the max desired ratio have a better meaning for HLG/PQ so this can be 42*38e8c45fSAndroid Build Coastguard Worker // eliminated? If we assume an SDR white point of even just 100 nits for those content 43*38e8c45fSAndroid Build Coastguard Worker // then HLG could have a meaningful max ratio of 10.f and PQ of 100.f instead of needing 44*38e8c45fSAndroid Build Coastguard Worker // to treat 1.f as "uncapped" 45*38e8c45fSAndroid Build Coastguard Worker // With peak display brightnesses exceeding 1,000 nits currently, HLG's request could 46*38e8c45fSAndroid Build Coastguard Worker // actually be satisfied in some ambient conditions such that limiting that max for that 47*38e8c45fSAndroid Build Coastguard Worker // content in theory makes sense 48*38e8c45fSAndroid Build Coastguard Worker float maxDesiredHdrSdrRatio = 0.f; 49*38e8c45fSAndroid Build Coastguard Worker 50*38e8c45fSAndroid Build Coastguard Worker bool operator==(const HdrLayerInfo& other) const { 51*38e8c45fSAndroid Build Coastguard Worker return numberOfHdrLayers == other.numberOfHdrLayers && maxW == other.maxW && 52*38e8c45fSAndroid Build Coastguard Worker maxH == other.maxH && flags == other.flags && 53*38e8c45fSAndroid Build Coastguard Worker maxDesiredHdrSdrRatio == other.maxDesiredHdrSdrRatio; 54*38e8c45fSAndroid Build Coastguard Worker } 55*38e8c45fSAndroid Build Coastguard Worker 56*38e8c45fSAndroid Build Coastguard Worker bool operator!=(const HdrLayerInfo& other) const { return !(*this == other); } 57*38e8c45fSAndroid Build Coastguard Worker mergeDesiredRatioHdrLayerInfo58*38e8c45fSAndroid Build Coastguard Worker void mergeDesiredRatio(float update) { 59*38e8c45fSAndroid Build Coastguard Worker maxDesiredHdrSdrRatio = std::max(maxDesiredHdrSdrRatio, update); 60*38e8c45fSAndroid Build Coastguard Worker } 61*38e8c45fSAndroid Build Coastguard Worker }; 62*38e8c45fSAndroid Build Coastguard Worker 63*38e8c45fSAndroid Build Coastguard Worker HdrLayerInfoReporter() = default; 64*38e8c45fSAndroid Build Coastguard Worker ~HdrLayerInfoReporter() final = default; 65*38e8c45fSAndroid Build Coastguard Worker 66*38e8c45fSAndroid Build Coastguard Worker // Dispatches updated layer fps values for the registered listeners 67*38e8c45fSAndroid Build Coastguard Worker // This method promotes Layer weak pointers and performs layer stack traversals, so mStateLock 68*38e8c45fSAndroid Build Coastguard Worker // must be held when calling this method. 69*38e8c45fSAndroid Build Coastguard Worker void dispatchHdrLayerInfo(const HdrLayerInfo& info) EXCLUDES(mMutex); 70*38e8c45fSAndroid Build Coastguard Worker 71*38e8c45fSAndroid Build Coastguard Worker // Override for IBinder::DeathRecipient 72*38e8c45fSAndroid Build Coastguard Worker void binderDied(const wp<IBinder>&) override EXCLUDES(mMutex); 73*38e8c45fSAndroid Build Coastguard Worker 74*38e8c45fSAndroid Build Coastguard Worker // Registers an Fps listener that listens to fps updates for the provided layer 75*38e8c45fSAndroid Build Coastguard Worker void addListener(const sp<gui::IHdrLayerInfoListener>& listener) EXCLUDES(mMutex); 76*38e8c45fSAndroid Build Coastguard Worker // Deregisters an Fps listener 77*38e8c45fSAndroid Build Coastguard Worker void removeListener(const sp<gui::IHdrLayerInfoListener>& listener) EXCLUDES(mMutex); 78*38e8c45fSAndroid Build Coastguard Worker hasListeners()79*38e8c45fSAndroid Build Coastguard Worker bool hasListeners() const EXCLUDES(mMutex) { 80*38e8c45fSAndroid Build Coastguard Worker std::scoped_lock lock(mMutex); 81*38e8c45fSAndroid Build Coastguard Worker return !mListeners.empty(); 82*38e8c45fSAndroid Build Coastguard Worker } 83*38e8c45fSAndroid Build Coastguard Worker 84*38e8c45fSAndroid Build Coastguard Worker void dump(std::string& result) const; 85*38e8c45fSAndroid Build Coastguard Worker 86*38e8c45fSAndroid Build Coastguard Worker private: 87*38e8c45fSAndroid Build Coastguard Worker mutable std::mutex mMutex; 88*38e8c45fSAndroid Build Coastguard Worker 89*38e8c45fSAndroid Build Coastguard Worker struct TrackedListener { 90*38e8c45fSAndroid Build Coastguard Worker sp<gui::IHdrLayerInfoListener> listener; 91*38e8c45fSAndroid Build Coastguard Worker HdrLayerInfo lastInfo; 92*38e8c45fSAndroid Build Coastguard Worker }; 93*38e8c45fSAndroid Build Coastguard Worker 94*38e8c45fSAndroid Build Coastguard Worker std::unordered_map<wp<IBinder>, TrackedListener, WpHash> mListeners GUARDED_BY(mMutex); 95*38e8c45fSAndroid Build Coastguard Worker 96*38e8c45fSAndroid Build Coastguard Worker struct EventHistoryEntry { 97*38e8c45fSAndroid Build Coastguard Worker nsecs_t timestamp = -1; 98*38e8c45fSAndroid Build Coastguard Worker HdrLayerInfo info; 99*38e8c45fSAndroid Build Coastguard Worker EventHistoryEntryEventHistoryEntry100*38e8c45fSAndroid Build Coastguard Worker EventHistoryEntry() {} 101*38e8c45fSAndroid Build Coastguard Worker EventHistoryEntryEventHistoryEntry102*38e8c45fSAndroid Build Coastguard Worker EventHistoryEntry(const HdrLayerInfo& info) : info(info) { timestamp = systemTime(); } 103*38e8c45fSAndroid Build Coastguard Worker }; 104*38e8c45fSAndroid Build Coastguard Worker 105*38e8c45fSAndroid Build Coastguard Worker utils::RingBuffer<EventHistoryEntry, 32> mHdrInfoHistory; 106*38e8c45fSAndroid Build Coastguard Worker }; 107*38e8c45fSAndroid Build Coastguard Worker 108*38e8c45fSAndroid Build Coastguard Worker } // namespace android