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 <atomic> 20 #include <chrono> 21 #include <unordered_map> 22 #include <unordered_set> 23 24 #include <ui/DisplayId.h> 25 #include <ui/FenceTime.h> 26 #include <utils/Mutex.h> 27 28 #include <android/hardware/power/IPower.h> 29 #include <compositionengine/impl/OutputCompositionState.h> 30 #include <powermanager/PowerHalController.h> 31 #include <scheduler/Time.h> 32 #include <ui/DisplayIdentification.h> 33 #include "../Scheduler/OneShotTimer.h" 34 35 using namespace std::chrono_literals; 36 37 namespace android { 38 39 class SurfaceFlinger; 40 41 namespace Hwc2 { 42 43 class PowerAdvisor { 44 public: 45 virtual ~PowerAdvisor(); 46 47 // Initializes resources that cannot be initialized on construction 48 virtual void init() = 0; 49 virtual void onBootFinished() = 0; 50 virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0; 51 virtual bool isUsingExpensiveRendering() = 0; 52 virtual void notifyCpuLoadUp() = 0; 53 virtual void notifyDisplayUpdateImminentAndCpuReset() = 0; 54 // Checks both if it supports and if it's enabled 55 virtual bool usePowerHintSession() = 0; 56 virtual bool supportsPowerHintSession() = 0; 57 58 virtual bool ensurePowerHintSessionRunning() = 0; 59 // Sends a power hint that updates to the target work duration for the frame 60 virtual void updateTargetWorkDuration(Duration targetDuration) = 0; 61 // Sends a power hint for the actual known work duration at the end of the frame 62 virtual void reportActualWorkDuration() = 0; 63 // Sets whether the power hint session is enabled 64 virtual void enablePowerHintSession(bool enabled) = 0; 65 // Initializes the power hint session 66 virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0; 67 // Provides PowerAdvisor with a copy of the gpu fence so it can determine the gpu end time 68 virtual void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) = 0; 69 // Reports the start and end times of a hwc validate call this frame for a given display 70 virtual void setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime, 71 TimePoint validateEndTime) = 0; 72 // Reports the start and end times of a hwc present call this frame for a given display 73 virtual void setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime, 74 TimePoint presentEndTime) = 0; 75 // Reports the expected time that the current frame will present to the display 76 virtual void setExpectedPresentTime(TimePoint expectedPresentTime) = 0; 77 // Reports the most recent present fence time and end time once known 78 virtual void setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) = 0; 79 // Reports whether a display used client composition this frame 80 virtual void setRequiresClientComposition(DisplayId displayId, 81 bool requiresClientComposition) = 0; 82 // Reports whether a given display skipped validation this frame 83 virtual void setSkippedValidate(DisplayId displayId, bool skipped) = 0; 84 // Reports when a hwc present is delayed, and the time that it will resume 85 virtual void setHwcPresentDelayedTime(DisplayId displayId, 86 TimePoint earliestFrameStartTime) = 0; 87 // Reports the start delay for SurfaceFlinger this frame 88 virtual void setFrameDelay(Duration frameDelayDuration) = 0; 89 // Reports the SurfaceFlinger commit start time this frame 90 virtual void setCommitStart(TimePoint commitStartTime) = 0; 91 // Reports the SurfaceFlinger composite end time this frame 92 virtual void setCompositeEnd(TimePoint compositeEndTime) = 0; 93 // Reports the list of the currently active displays 94 virtual void setDisplays(std::vector<DisplayId>& displayIds) = 0; 95 // Sets the target duration for the entire pipeline including the gpu 96 virtual void setTotalFrameTargetWorkDuration(Duration targetDuration) = 0; 97 }; 98 99 namespace impl { 100 101 // PowerAdvisor is a wrapper around IPower HAL which takes into account the 102 // full state of the system when sending out power hints to things like the GPU. 103 class PowerAdvisor final : public Hwc2::PowerAdvisor { 104 public: 105 PowerAdvisor(SurfaceFlinger& flinger); 106 ~PowerAdvisor() override; 107 108 void init() override; 109 void onBootFinished() override; 110 void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override; isUsingExpensiveRendering()111 bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; }; 112 void notifyCpuLoadUp() override; 113 void notifyDisplayUpdateImminentAndCpuReset() override; 114 bool usePowerHintSession() override; 115 bool supportsPowerHintSession() override; 116 bool ensurePowerHintSessionRunning() override; 117 void updateTargetWorkDuration(Duration targetDuration) override; 118 void reportActualWorkDuration() override; 119 void enablePowerHintSession(bool enabled) override; 120 bool startPowerHintSession(const std::vector<int32_t>& threadIds) override; 121 void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime); 122 void setHwcValidateTiming(DisplayId displayId, TimePoint validateStartTime, 123 TimePoint validateEndTime) override; 124 void setHwcPresentTiming(DisplayId displayId, TimePoint presentStartTime, 125 TimePoint presentEndTime) override; 126 void setSkippedValidate(DisplayId displayId, bool skipped) override; 127 void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override; 128 void setExpectedPresentTime(TimePoint expectedPresentTime) override; 129 void setSfPresentTiming(TimePoint presentFenceTime, TimePoint presentEndTime) override; 130 void setHwcPresentDelayedTime(DisplayId displayId, TimePoint earliestFrameStartTime) override; 131 132 void setFrameDelay(Duration frameDelayDuration) override; 133 void setCommitStart(TimePoint commitStartTime) override; 134 void setCompositeEnd(TimePoint compositeEndTime) override; 135 void setDisplays(std::vector<DisplayId>& displayIds) override; 136 void setTotalFrameTargetWorkDuration(Duration targetDuration) override; 137 138 private: 139 friend class PowerAdvisorTest; 140 141 std::unique_ptr<power::PowerHalController> mPowerHal; 142 std::atomic_bool mBootFinished = false; 143 144 std::unordered_set<DisplayId> mExpensiveDisplays; 145 bool mNotifiedExpensiveRendering = false; 146 147 SurfaceFlinger& mFlinger; 148 std::atomic_bool mSendUpdateImminent = true; 149 std::atomic<nsecs_t> mLastScreenUpdatedTime = 0; 150 std::optional<scheduler::OneShotTimer> mScreenUpdateTimer; 151 152 // Higher-level timing data used for estimation 153 struct DisplayTimeline { 154 // The start of hwc present, or the start of validate if it happened there instead 155 TimePoint hwcPresentStartTime; 156 // The end of hwc present or validate, whichever one actually presented 157 TimePoint hwcPresentEndTime; 158 // How long the actual hwc present was delayed after hwcPresentStartTime 159 Duration hwcPresentDelayDuration{0ns}; 160 // When we think we started waiting for the present fence after calling into hwc present and 161 // after potentially waiting for the earliest present time 162 TimePoint presentFenceWaitStartTime; 163 // How long we ran after we finished waiting for the fence but before hwc present finished 164 Duration postPresentFenceHwcPresentDuration{0ns}; 165 // Are we likely to have waited for the present fence during composition 166 bool probablyWaitsForPresentFence = false; 167 }; 168 169 struct GpuTimeline { 170 Duration duration{0ns}; 171 TimePoint startTime; 172 }; 173 174 // Power hint session data recorded from the pipeline 175 struct DisplayTimingData { 176 std::unique_ptr<FenceTime> gpuEndFenceTime; 177 std::optional<TimePoint> gpuStartTime; 178 std::optional<TimePoint> lastValidGpuEndTime; 179 std::optional<TimePoint> lastValidGpuStartTime; 180 std::optional<TimePoint> hwcPresentStartTime; 181 std::optional<TimePoint> hwcPresentEndTime; 182 std::optional<TimePoint> hwcValidateStartTime; 183 std::optional<TimePoint> hwcValidateEndTime; 184 std::optional<TimePoint> hwcPresentDelayedTime; 185 bool usedClientComposition = false; 186 bool skippedValidate = false; 187 // Calculate high-level timing milestones from more granular display timing data 188 DisplayTimeline calculateDisplayTimeline(TimePoint fenceTime); 189 // Estimate the gpu duration for a given display from previous gpu timing data 190 std::optional<GpuTimeline> estimateGpuTiming(std::optional<TimePoint> previousEndTime); 191 }; 192 193 template <class T, size_t N> 194 class RingBuffer { 195 std::array<T, N> elements = {}; 196 size_t mIndex = 0; 197 size_t numElements = 0; 198 199 public: append(T item)200 void append(T item) { 201 mIndex = (mIndex + 1) % N; 202 numElements = std::min(N, numElements + 1); 203 elements[mIndex] = item; 204 } isFull()205 bool isFull() const { return numElements == N; } 206 // Allows access like [0] == current, [-1] = previous, etc.. 207 T& operator[](int offset) { 208 size_t positiveOffset = 209 static_cast<size_t>((offset % static_cast<int>(N)) + static_cast<int>(N)); 210 return elements[(mIndex + positiveOffset) % N]; 211 } 212 }; 213 214 // Filter and sort the display ids by a given property 215 std::vector<DisplayId> getOrderedDisplayIds( 216 std::optional<TimePoint> DisplayTimingData::*sortBy); 217 // Estimates a frame's total work duration including gpu time. 218 std::optional<Duration> estimateWorkDuration(); 219 // There are two different targets and actual work durations we care about, 220 // this normalizes them together and takes the max of the two 221 Duration combineTimingEstimates(Duration totalDuration, Duration flingerDuration); 222 223 std::unordered_map<DisplayId, DisplayTimingData> mDisplayTimingData; 224 225 // Current frame's delay 226 Duration mFrameDelayDuration{0ns}; 227 // Last frame's post-composition duration 228 Duration mLastPostcompDuration{0ns}; 229 // Buffer of recent commit start times 230 RingBuffer<TimePoint, 2> mCommitStartTimes; 231 // Buffer of recent expected present times 232 RingBuffer<TimePoint, 2> mExpectedPresentTimes; 233 // Most recent present fence time, provided by SF after composition engine finishes presenting 234 TimePoint mLastPresentFenceTime; 235 // Most recent composition engine present end time, returned with the present fence from SF 236 TimePoint mLastSfPresentEndTime; 237 // Target duration for the entire pipeline including gpu 238 std::optional<Duration> mTotalFrameTargetDuration; 239 // Updated list of display IDs 240 std::vector<DisplayId> mDisplayIds; 241 242 // Ensure powerhal connection is initialized 243 power::PowerHalController& getPowerHal(); 244 245 std::optional<bool> mHintSessionEnabled; 246 std::optional<bool> mSupportsHintSession; 247 bool mHintSessionRunning = false; 248 249 std::mutex mHintSessionMutex; 250 sp<hardware::power::IPowerHintSession> mHintSession GUARDED_BY(mHintSessionMutex) = nullptr; 251 252 // Initialize to true so we try to call, to check if it's supported 253 bool mHasExpensiveRendering = true; 254 bool mHasDisplayUpdateImminent = true; 255 // Queue of actual durations saved to report 256 std::vector<hardware::power::WorkDuration> mHintSessionQueue; 257 // The latest values we have received for target and actual 258 Duration mTargetDuration = kDefaultTargetDuration; 259 std::optional<Duration> mActualDuration; 260 // The list of thread ids, stored so we can restart the session from this class if needed 261 std::vector<int32_t> mHintSessionThreadIds; 262 Duration mLastTargetDurationSent = kDefaultTargetDuration; 263 // Whether we should emit ATRACE_INT data for hint sessions 264 static const bool sTraceHintSessionData; 265 266 // Default target duration for the hint session 267 static constexpr const Duration kDefaultTargetDuration{16ms}; 268 269 // An adjustable safety margin which pads the "actual" value sent to PowerHAL, 270 // encouraging more aggressive boosting to give SurfaceFlinger a larger margin for error 271 static const Duration sTargetSafetyMargin; 272 static constexpr const Duration kDefaultTargetSafetyMargin{1ms}; 273 274 // Whether we should send reportActualWorkDuration calls 275 static const bool sUseReportActualDuration; 276 277 // How long we expect hwc to run after the present call until it waits for the fence 278 static constexpr const Duration kFenceWaitStartDelayValidated{150us}; 279 static constexpr const Duration kFenceWaitStartDelaySkippedValidate{250us}; 280 }; 281 282 } // namespace impl 283 } // namespace Hwc2 284 } // namespace android 285