blob: 61bb32b8bd862e71034b1fe7b6b81f364b826bc6 [file] [log] [blame]
Michael Wright5d22d4f2018-06-21 02:50:34 +01001/*
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
Dan Stoza030fbc12020-02-19 15:32:01 -080019#include <atomic>
Matt Buckleyef51fba2021-10-12 19:30:12 +000020#include <chrono>
Peiyong Lin74ca2f42019-01-14 19:36:57 -080021#include <unordered_set>
22
Dan Stoza20950002020-06-18 14:56:58 -070023#include <utils/Mutex.h>
24
Xiang Wange12b4fa2022-03-25 23:48:40 +000025#include <android/hardware/power/IPower.h>
Alec Mouriff793872022-01-13 17:45:06 -080026#include <ui/DisplayIdentification.h>
Dan Stoza030fbc12020-02-19 15:32:01 -080027#include "../Scheduler/OneShotTimer.h"
Michael Wright5d22d4f2018-06-21 02:50:34 +010028
Matt Buckleyef51fba2021-10-12 19:30:12 +000029using namespace std::chrono_literals;
30
Michael Wright5d22d4f2018-06-21 02:50:34 +010031namespace android {
Alec Mouridea1ac52021-06-23 18:12:18 -070032
33class SurfaceFlinger;
34
Michael Wright5d22d4f2018-06-21 02:50:34 +010035namespace Hwc2 {
36
37class PowerAdvisor {
38public:
39 virtual ~PowerAdvisor();
40
Alec Mouridea1ac52021-06-23 18:12:18 -070041 // Initializes resources that cannot be initialized on construction
42 virtual void init() = 0;
Dan Stoza29e7bdf2020-03-23 14:43:09 -070043 virtual void onBootFinished() = 0;
Peiyong Lin74ca2f42019-01-14 19:36:57 -080044 virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
Alec Mouridea1ac52021-06-23 18:12:18 -070045 virtual bool isUsingExpensiveRendering() = 0;
Dan Stoza030fbc12020-02-19 15:32:01 -080046 virtual void notifyDisplayUpdateImminent() = 0;
Matt Buckley06f299a2021-09-24 19:43:51 +000047 virtual bool usePowerHintSession() = 0;
48 virtual bool supportsPowerHintSession() = 0;
49 virtual bool isPowerHintSessionRunning() = 0;
50 virtual void setTargetWorkDuration(int64_t targetDurationNanos) = 0;
Matt Buckley06f299a2021-09-24 19:43:51 +000051 virtual void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timestamp) = 0;
52 virtual void enablePowerHint(bool enabled) = 0;
Matt Buckleyef51fba2021-10-12 19:30:12 +000053 virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0;
Michael Wright5d22d4f2018-06-21 02:50:34 +010054};
55
56namespace impl {
57
Michael Wright5d22d4f2018-06-21 02:50:34 +010058// PowerAdvisor is a wrapper around IPower HAL which takes into account the
59// full state of the system when sending out power hints to things like the GPU.
60class PowerAdvisor final : public Hwc2::PowerAdvisor {
61public:
Dan Stoza030fbc12020-02-19 15:32:01 -080062 class HalWrapper {
63 public:
64 virtual ~HalWrapper() = default;
65
66 virtual bool setExpensiveRendering(bool enabled) = 0;
67 virtual bool notifyDisplayUpdateImminent() = 0;
Matt Buckley06f299a2021-09-24 19:43:51 +000068 virtual bool supportsPowerHintSession() = 0;
69 virtual bool isPowerHintSessionRunning() = 0;
70 virtual void restartPowerHintSession() = 0;
71 virtual void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) = 0;
72 virtual bool startPowerHintSession() = 0;
73 virtual void setTargetWorkDuration(int64_t targetDurationNanos) = 0;
74 virtual void sendActualWorkDuration(int64_t actualDurationNanos,
75 nsecs_t timeStampNanos) = 0;
76 virtual bool shouldReconnectHAL() = 0;
77 virtual std::vector<int32_t> getPowerHintSessionThreadIds() = 0;
78 virtual std::optional<int64_t> getTargetWorkDuration() = 0;
Dan Stoza030fbc12020-02-19 15:32:01 -080079 };
80
Alec Mouridea1ac52021-06-23 18:12:18 -070081 PowerAdvisor(SurfaceFlinger& flinger);
Michael Wright5d22d4f2018-06-21 02:50:34 +010082 ~PowerAdvisor() override;
83
Alec Mouridea1ac52021-06-23 18:12:18 -070084 void init() override;
Dan Stoza29e7bdf2020-03-23 14:43:09 -070085 void onBootFinished() override;
Peiyong Lin74ca2f42019-01-14 19:36:57 -080086 void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
Matt Buckley06f299a2021-09-24 19:43:51 +000087 bool isUsingExpensiveRendering() override { return mNotifiedExpensiveRendering; };
Dan Stoza030fbc12020-02-19 15:32:01 -080088 void notifyDisplayUpdateImminent() override;
Matt Buckley06f299a2021-09-24 19:43:51 +000089 bool usePowerHintSession() override;
90 bool supportsPowerHintSession() override;
91 bool isPowerHintSessionRunning() override;
92 void setTargetWorkDuration(int64_t targetDurationNanos) override;
Matt Buckley06f299a2021-09-24 19:43:51 +000093 void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timestamp) override;
94 void enablePowerHint(bool enabled) override;
Matt Buckleyef51fba2021-10-12 19:30:12 +000095 bool startPowerHintSession(const std::vector<int32_t>& threadIds) override;
Michael Wright5d22d4f2018-06-21 02:50:34 +010096
97private:
Dan Stoza20950002020-06-18 14:56:58 -070098 HalWrapper* getPowerHal() REQUIRES(mPowerHalMutex);
99 bool mReconnectPowerHal GUARDED_BY(mPowerHalMutex) = false;
100 std::mutex mPowerHalMutex;
Dan Stoza030fbc12020-02-19 15:32:01 -0800101
Dan Stoza29e7bdf2020-03-23 14:43:09 -0700102 std::atomic_bool mBootFinished = false;
Matt Buckley06f299a2021-09-24 19:43:51 +0000103 std::optional<bool> mPowerHintEnabled;
104 std::optional<bool> mSupportsPowerHint;
105 bool mPowerHintSessionRunning = false;
Michael Wright5d22d4f2018-06-21 02:50:34 +0100106
Matt Buckleyef51fba2021-10-12 19:30:12 +0000107 // An adjustable safety margin which moves the "target" earlier to allow flinger to
108 // go a bit over without dropping a frame, especially since we can't measure
109 // the exact time HWC finishes composition so "actual" durations are measured
110 // from the end of present() instead, which is a bit later.
111 static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 2ms;
112
Peiyong Lin74ca2f42019-01-14 19:36:57 -0800113 std::unordered_set<DisplayId> mExpensiveDisplays;
Michael Wright5d22d4f2018-06-21 02:50:34 +0100114 bool mNotifiedExpensiveRendering = false;
Dan Stoza030fbc12020-02-19 15:32:01 -0800115
Alec Mouridea1ac52021-06-23 18:12:18 -0700116 SurfaceFlinger& mFlinger;
117 const bool mUseScreenUpdateTimer;
Dan Stoza030fbc12020-02-19 15:32:01 -0800118 std::atomic_bool mSendUpdateImminent = true;
Alec Mouridea1ac52021-06-23 18:12:18 -0700119 scheduler::OneShotTimer mScreenUpdateTimer;
Michael Wright5d22d4f2018-06-21 02:50:34 +0100120};
121
Xiang Wange12b4fa2022-03-25 23:48:40 +0000122class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
123public:
124 explicit AidlPowerHalWrapper(sp<hardware::power::IPower> powerHal);
125 ~AidlPowerHalWrapper() override;
126
127 static std::unique_ptr<HalWrapper> connect();
128
129 bool setExpensiveRendering(bool enabled) override;
130 bool notifyDisplayUpdateImminent() override;
131 bool supportsPowerHintSession() override;
132 bool isPowerHintSessionRunning() override;
133 void restartPowerHintSession() override;
134 void setPowerHintSessionThreadIds(const std::vector<int32_t>& threadIds) override;
135 bool startPowerHintSession() override;
136 void setTargetWorkDuration(int64_t targetDurationNanos) override;
137 void sendActualWorkDuration(int64_t actualDurationNanos, nsecs_t timeStampNanos) override;
138 bool shouldReconnectHAL() override;
139 std::vector<int32_t> getPowerHintSessionThreadIds() override;
140 std::optional<int64_t> getTargetWorkDuration() override;
141
142private:
143 bool checkPowerHintSessionSupported();
144 void closePowerHintSession();
145 bool shouldReportActualDurationsNow();
146 bool shouldSetTargetDuration(int64_t targetDurationNanos);
147
148 const sp<hardware::power::IPower> mPowerHal = nullptr;
149 bool mHasExpensiveRendering = false;
150 bool mHasDisplayUpdateImminent = false;
151 // Used to indicate an error state and need for reconstruction
152 bool mShouldReconnectHal = false;
153 // This is not thread safe, but is currently protected by mPowerHalMutex so it needs no lock
154 sp<hardware::power::IPowerHintSession> mPowerHintSession = nullptr;
155 // Queue of actual durations saved to report
156 std::vector<hardware::power::WorkDuration> mPowerHintQueue;
157 // The latest un-normalized values we have received for target and actual
158 int64_t mTargetDuration = kDefaultTarget.count();
159 std::optional<int64_t> mActualDuration;
160 // The list of thread ids, stored so we can restart the session from this class if needed
161 std::vector<int32_t> mPowerHintThreadIds;
162 bool mSupportsPowerHint;
163 // Keep track of the last messages sent for rate limiter change detection
164 std::optional<int64_t> mLastActualDurationSent;
165 // timestamp of the last report we sent, used to avoid stale sessions
166 int64_t mLastActualReportTimestamp = 0;
167 int64_t mLastTargetDurationSent = kDefaultTarget.count();
168 // Whether to normalize all the actual values as error terms relative to a constant target
169 // This saves a binder call by not setting the target, and should not affect the pid values
170 static const bool sNormalizeTarget;
171 // Whether we should emit ATRACE_INT data for hint sessions
172 static const bool sTraceHintSessionData;
173
174 // Max percent the actual duration can vary without causing a report (eg: 0.1 = 10%)
175 static constexpr double kAllowedActualDeviationPercent = 0.1;
Xiang Wang0aba49e2022-04-06 16:13:59 +0000176 // Max percent the target duration can vary without causing a report (eg: 0.1 = 10%)
177 static constexpr double kAllowedTargetDeviationPercent = 0.1;
Xiang Wange12b4fa2022-03-25 23:48:40 +0000178 // Target used for init and normalization, the actual value does not really matter
179 static constexpr const std::chrono::nanoseconds kDefaultTarget = 50ms;
180 // Amount of time after the last message was sent before the session goes stale
181 // actually 100ms but we use 80 here to ideally avoid going stale
182 static constexpr const std::chrono::nanoseconds kStaleTimeout = 80ms;
183};
184
Michael Wright5d22d4f2018-06-21 02:50:34 +0100185} // namespace impl
186} // namespace Hwc2
187} // namespace android