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 <ui/DisplayIdentification.h> 31 #include "../Scheduler/OneShotTimer.h" 32 33 using namespace std::chrono_literals; 34 35 namespace android { 36 37 class SurfaceFlinger; 38 39 namespace Hwc2 { 40 41 class PowerAdvisor { 42 public: 43 virtual ~PowerAdvisor(); 44 45 // Initializes resources that cannot be initialized on construction 46 virtual void init() = 0; 47 virtual void onBootFinished() = 0; 48 virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0; 49 virtual bool isUsingExpensiveRendering() = 0; 50 virtual void notifyDisplayUpdateImminent() = 0; 51 // Checks both if it supports and if it's enabled 52 virtual bool usePowerHintSession() = 0; 53 virtual bool supportsPowerHintSession() = 0; 54 virtual bool isPowerHintSessionRunning() = 0; 55 // Sends a power hint that updates to the target work duration for the frame 56 virtual void setTargetWorkDuration(nsecs_t targetDuration) = 0; 57 // Sends a power hint for the actual known work duration at the end of the frame 58 virtual void sendActualWorkDuration() = 0; 59 // Sends a power hint for the upcoming frame predicted from previous frame timing 60 virtual void sendPredictedWorkDuration() = 0; 61 // Sets whether the power hint session is enabled 62 virtual void enablePowerHint(bool enabled) = 0; 63 // Initializes the power hint session 64 virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0; 65 // Provides PowerAdvisor with a copy of the gpu fence so it can determine the gpu end time 66 virtual void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) = 0; 67 // Reports the start and end times of a hwc validate call this frame for a given display 68 virtual void setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime, 69 nsecs_t validateEndTime) = 0; 70 // Reports the start and end times of a hwc present call this frame for a given display 71 virtual void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime, 72 nsecs_t presentEndTime) = 0; 73 // Reports the expected time that the current frame will present to the display 74 virtual void setExpectedPresentTime(nsecs_t expectedPresentTime) = 0; 75 // Reports the most recent present fence time and end time once known 76 virtual void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) = 0; 77 // Reports whether a display used client composition this frame 78 virtual void setRequiresClientComposition(DisplayId displayId, 79 bool requiresClientComposition) = 0; 80 // Reports whether a given display skipped validation this frame 81 virtual void setSkippedValidate(DisplayId displayId, bool skipped) = 0; 82 // Reports when a hwc present is delayed, and the time that it will resume 83 virtual void setHwcPresentDelayedTime( 84 DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) = 0; 85 // Reports the start delay for SurfaceFlinger this frame 86 virtual void setFrameDelay(nsecs_t frameDelayDuration) = 0; 87 // Reports the SurfaceFlinger commit start time this frame 88 virtual void setCommitStart(nsecs_t commitStartTime) = 0; 89 // Reports the SurfaceFlinger composite end time this frame 90 virtual void setCompositeEnd(nsecs_t compositeEndTime) = 0; 91 // Reports the list of the currently active displays 92 virtual void setDisplays(std::vector<DisplayId>& displayIds) = 0; 93 // Sets the target duration for the entire pipeline including the gpu 94 virtual void setTotalFrameTargetWorkDuration(nsecs_t targetDuration) = 0; 95 }; 96 97 namespace impl { 98 99 // PowerAdvisor is a wrapper around IPower HAL which takes into account the 100 // full state of the system when sending out power hints to things like the GPU. 101 class PowerAdvisor final : public Hwc2::PowerAdvisor { 102 public: 103 class HalWrapper { 104 public: 105 virtual ~HalWrapper() = default; 106 107 virtual bool setExpensiveRendering(bool enabled) = 0; 108 virtual bool notifyDisplayUpdateImminent() = 0; 109 virtual bool supportsPowerHintSession() = 0; 110 virtual bool isPowerHintSessionRunning() = 0; 111 virtual void restartPowerHintSession() = 0; 112 virtual void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) = 0; 113 virtual bool startPowerHintSession() = 0; 114 virtual void setTargetWorkDuration(nsecs_t targetDuration) = 0; 115 virtual void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) = 0; 116 virtual bool shouldReconnectHAL() = 0; 117 virtual std::vector<int32_t> getPowerHintSessionThreadIds() = 0; 118 virtual std::optional<nsecs_t> getTargetWorkDuration() = 0; 119 }; 120 121 PowerAdvisor(SurfaceFlinger& flinger); 122 ~PowerAdvisor() override; 123 124 void init() override; 125 void onBootFinished() override; 126 void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override; isUsingExpensiveRendering()127 bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; }; 128 void notifyDisplayUpdateImminent() override; 129 bool usePowerHintSession() override; 130 bool supportsPowerHintSession() override; 131 bool isPowerHintSessionRunning() override; 132 void setTargetWorkDuration(nsecs_t targetDuration) override; 133 void sendActualWorkDuration() override; 134 void sendPredictedWorkDuration() override; 135 void enablePowerHint(bool enabled) override; 136 bool startPowerHintSession(const std::vector<int32_t>& threadIds) override; 137 void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime); 138 void setHwcValidateTiming(DisplayId displayId, nsecs_t valiateStartTime, 139 nsecs_t validateEndTime) override; 140 void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime, 141 nsecs_t presentEndTime) override; 142 void setSkippedValidate(DisplayId displayId, bool skipped) override; 143 void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override; 144 void setExpectedPresentTime(nsecs_t expectedPresentTime) override; 145 void setSfPresentTiming(nsecs_t presentFenceTime, nsecs_t presentEndTime) override; 146 void setHwcPresentDelayedTime( 147 DisplayId displayId, 148 std::chrono::steady_clock::time_point earliestFrameStartTime) override; 149 150 void setFrameDelay(nsecs_t frameDelayDuration) override; 151 void setCommitStart(nsecs_t commitStartTime) override; 152 void setCompositeEnd(nsecs_t compositeEndTime) override; 153 void setDisplays(std::vector<DisplayId>& displayIds) override; 154 void setTotalFrameTargetWorkDuration(nsecs_t targetDuration) override; 155 156 private: 157 friend class PowerAdvisorTest; 158 159 // Tracks if powerhal exists 160 bool mHasHal = true; 161 // Holds the hal wrapper for getPowerHal 162 std::unique_ptr<HalWrapper> mHalWrapper GUARDED_BY(mPowerHalMutex) = nullptr; 163 164 HalWrapper* getPowerHal() REQUIRES(mPowerHalMutex); 165 bool mReconnectPowerHal GUARDED_BY(mPowerHalMutex) = false; 166 std::mutex mPowerHalMutex; 167 168 std::atomic_bool mBootFinished = false; 169 170 std::unordered_set<DisplayId> mExpensiveDisplays; 171 bool mNotifiedExpensiveRendering = false; 172 173 SurfaceFlinger& mFlinger; 174 std::atomic_bool mSendUpdateImminent = true; 175 std::atomic<nsecs_t> mLastScreenUpdatedTime = 0; 176 std::optional<scheduler::OneShotTimer> mScreenUpdateTimer; 177 178 // Higher-level timing data used for estimation 179 struct DisplayTimeline { 180 // The start of hwc present, or the start of validate if it happened there instead 181 nsecs_t hwcPresentStartTime = -1; 182 // The end of hwc present or validate, whichever one actually presented 183 nsecs_t hwcPresentEndTime = -1; 184 // How long the actual hwc present was delayed after hwcPresentStartTime 185 nsecs_t hwcPresentDelayDuration = 0; 186 // When we think we started waiting for the present fence after calling into hwc present and 187 // after potentially waiting for the earliest present time 188 nsecs_t presentFenceWaitStartTime = -1; 189 // How long we ran after we finished waiting for the fence but before hwc present finished 190 nsecs_t postPresentFenceHwcPresentDuration = 0; 191 // Are we likely to have waited for the present fence during composition 192 bool probablyWaitsForPresentFence = false; 193 // Estimate one frame's timeline from that of a previous frame 194 DisplayTimeline estimateTimelineFromReference(nsecs_t fenceTime, nsecs_t displayStartTime); 195 }; 196 197 struct GpuTimeline { 198 nsecs_t duration = 0; 199 nsecs_t startTime = -1; 200 }; 201 202 // Power hint session data recorded from the pipeline 203 struct DisplayTimingData { 204 std::unique_ptr<FenceTime> gpuEndFenceTime; 205 std::optional<nsecs_t> gpuStartTime; 206 std::optional<nsecs_t> lastValidGpuEndTime; 207 std::optional<nsecs_t> lastValidGpuStartTime; 208 std::optional<nsecs_t> hwcPresentStartTime; 209 std::optional<nsecs_t> hwcPresentEndTime; 210 std::optional<nsecs_t> hwcValidateStartTime; 211 std::optional<nsecs_t> hwcValidateEndTime; 212 std::optional<nsecs_t> hwcPresentDelayedTime; 213 bool usedClientComposition = false; 214 bool skippedValidate = false; 215 // Calculate high-level timing milestones from more granular display timing data 216 DisplayTimeline calculateDisplayTimeline(nsecs_t fenceTime); 217 // Estimate the gpu duration for a given display from previous gpu timing data 218 std::optional<GpuTimeline> estimateGpuTiming(std::optional<nsecs_t> previousEnd); 219 }; 220 221 template <class T, size_t N> 222 class RingBuffer { 223 std::array<T, N> elements = {}; 224 size_t mIndex = 0; 225 size_t numElements = 0; 226 227 public: append(T item)228 void append(T item) { 229 mIndex = (mIndex + 1) % N; 230 numElements = std::min(N, numElements + 1); 231 elements[mIndex] = item; 232 } isFull()233 bool isFull() const { return numElements == N; } 234 // Allows access like [0] == current, [-1] = previous, etc.. 235 T& operator[](int offset) { 236 size_t positiveOffset = 237 static_cast<size_t>((offset % static_cast<int>(N)) + static_cast<int>(N)); 238 return elements[(mIndex + positiveOffset) % N]; 239 } 240 }; 241 242 // Filter and sort the display ids by a given property 243 std::vector<DisplayId> getOrderedDisplayIds(std::optional<nsecs_t> DisplayTimingData::*sortBy); 244 // Estimates a frame's total work duration including gpu time. 245 // Runs either at the beginning or end of a frame, using the most recent data available 246 std::optional<nsecs_t> estimateWorkDuration(bool earlyHint); 247 // There are two different targets and actual work durations we care about, 248 // this normalizes them together and takes the max of the two 249 nsecs_t combineTimingEstimates(nsecs_t totalDuration, nsecs_t flingerDuration); 250 251 std::unordered_map<DisplayId, DisplayTimingData> mDisplayTimingData; 252 253 // Current frame's delay 254 nsecs_t mFrameDelayDuration = 0; 255 // Last frame's post-composition duration 256 nsecs_t mLastPostcompDuration = 0; 257 // Buffer of recent commit start times 258 RingBuffer<nsecs_t, 2> mCommitStartTimes; 259 // Buffer of recent expected present times 260 RingBuffer<nsecs_t, 2> mExpectedPresentTimes; 261 // Most recent present fence time, set at the end of the frame once known 262 nsecs_t mLastPresentFenceTime = -1; 263 // Most recent present fence time, set at the end of the frame once known 264 nsecs_t mLastSfPresentEndTime = -1; 265 // Target for the entire pipeline including gpu 266 std::optional<nsecs_t> mTotalFrameTargetDuration; 267 // Updated list of display IDs 268 std::vector<DisplayId> mDisplayIds; 269 270 std::optional<bool> mPowerHintEnabled; 271 std::optional<bool> mSupportsPowerHint; 272 bool mPowerHintSessionRunning = false; 273 274 // An adjustable safety margin which pads the "actual" value sent to PowerHAL, 275 // encouraging more aggressive boosting to give SurfaceFlinger a larger margin for error 276 static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 1ms; 277 278 // How long we expect hwc to run after the present call until it waits for the fence 279 static constexpr const std::chrono::nanoseconds kFenceWaitStartDelayValidated = 150us; 280 static constexpr const std::chrono::nanoseconds kFenceWaitStartDelaySkippedValidate = 250us; 281 }; 282 283 class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper { 284 public: 285 explicit AidlPowerHalWrapper(sp<hardware::power::IPower> powerHal); 286 ~AidlPowerHalWrapper() override; 287 288 static std::unique_ptr<HalWrapper> connect(); 289 290 bool setExpensiveRendering(bool enabled) override; 291 bool notifyDisplayUpdateImminent() override; 292 bool supportsPowerHintSession() override; 293 bool isPowerHintSessionRunning() override; 294 void restartPowerHintSession() override; 295 void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override; 296 bool startPowerHintSession() override; 297 void setTargetWorkDuration(nsecs_t targetDuration) override; 298 void sendActualWorkDuration(nsecs_t actualDuration, nsecs_t timestamp) override; 299 bool shouldReconnectHAL() override; 300 std::vector<int32_t> getPowerHintSessionThreadIds() override; 301 std::optional<nsecs_t> getTargetWorkDuration() override; 302 303 private: 304 friend class AidlPowerHalWrapperTest; 305 306 bool checkPowerHintSessionSupported(); 307 void closePowerHintSession(); 308 bool shouldReportActualDurations(); 309 310 // Used for testing 311 void setAllowedActualDeviation(nsecs_t); 312 313 const sp<hardware::power::IPower> mPowerHal = nullptr; 314 bool mHasExpensiveRendering = false; 315 bool mHasDisplayUpdateImminent = false; 316 // Used to indicate an error state and need for reconstruction 317 bool mShouldReconnectHal = false; 318 319 // Power hint session data 320 321 // Concurrent access for this is protected by mPowerHalMutex 322 sp<hardware::power::IPowerHintSession> mPowerHintSession = nullptr; 323 // Queue of actual durations saved to report 324 std::vector<hardware::power::WorkDuration> mPowerHintQueue; 325 // The latest values we have received for target and actual 326 nsecs_t mTargetDuration = kDefaultTarget.count(); 327 std::optional<nsecs_t> mActualDuration; 328 // The list of thread ids, stored so we can restart the session from this class if needed 329 std::vector<int32_t> mPowerHintThreadIds; 330 bool mSupportsPowerHint = false; 331 // Keep track of the last messages sent for rate limiter change detection 332 std::optional<nsecs_t> mLastActualDurationSent; 333 // Timestamp of the last report we sent, used to avoid stale sessions 334 nsecs_t mLastActualReportTimestamp = 0; 335 nsecs_t mLastTargetDurationSent = kDefaultTarget.count(); 336 // Max amount the error term can vary without causing an actual value report 337 nsecs_t mAllowedActualDeviation = -1; 338 // Whether we should emit ATRACE_INT data for hint sessions 339 static const bool sTraceHintSessionData; 340 static constexpr const std::chrono::nanoseconds kDefaultTarget = 16ms; 341 // Amount of time after the last message was sent before the session goes stale 342 // actually 100ms but we use 80 here to ideally avoid going stale 343 static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms; 344 }; 345 346 } // namespace impl 347 } // namespace Hwc2 348 } // namespace android 349