1 /*
2 * Copyright (C) 2020 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 #define LOG_TAG "powerhal-libperfmgr"
18
19 #include "Power.h"
20
21 #include <mutex>
22
23 #include <android-base/file.h>
24 #include <android-base/logging.h>
25 #include <android-base/properties.h>
26 #include <android-base/stringprintf.h>
27 #include <android-base/strings.h>
28
29 #include <utils/Log.h>
30
31 #include "PowerHintSession.h"
32 #include "PowerSessionManager.h"
33 #include "disp-power/DisplayLowPower.h"
34
35 namespace aidl {
36 namespace google {
37 namespace hardware {
38 namespace power {
39 namespace impl {
40 namespace pixel {
41
42 using ::aidl::google::hardware::power::impl::pixel::PowerHintSession;
43
44 constexpr char kPowerHalStateProp[] = "vendor.powerhal.state";
45 constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio";
46 constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering";
47 constexpr char kPowerHalAdpfRateProp[] = "vendor.powerhal.adpf.rate";
48 constexpr int64_t kPowerHalAdpfRateDefault = -1;
49
Power(std::shared_ptr<HintManager> hm,std::shared_ptr<DisplayLowPower> dlpw)50 Power::Power(std::shared_ptr<HintManager> hm, std::shared_ptr<DisplayLowPower> dlpw)
51 : mHintManager(hm),
52 mDisplayLowPower(dlpw),
53 mInteractionHandler(nullptr),
54 mVRModeOn(false),
55 mSustainedPerfModeOn(false),
56 mAdpfRateNs(
57 ::android::base::GetIntProperty(kPowerHalAdpfRateProp, kPowerHalAdpfRateDefault)) {
58 mInteractionHandler = std::make_unique<InteractionHandler>(mHintManager);
59 mInteractionHandler->Init();
60
61 std::string state = ::android::base::GetProperty(kPowerHalStateProp, "");
62 if (state == "SUSTAINED_PERFORMANCE") {
63 LOG(INFO) << "Initialize with SUSTAINED_PERFORMANCE on";
64 mHintManager->DoHint("SUSTAINED_PERFORMANCE");
65 mSustainedPerfModeOn = true;
66 } else if (state == "VR") {
67 LOG(INFO) << "Initialize with VR on";
68 mHintManager->DoHint(state);
69 mVRModeOn = true;
70 } else if (state == "VR_SUSTAINED_PERFORMANCE") {
71 LOG(INFO) << "Initialize with SUSTAINED_PERFORMANCE and VR on";
72 mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
73 mSustainedPerfModeOn = true;
74 mVRModeOn = true;
75 } else {
76 LOG(INFO) << "Initialize PowerHAL";
77 }
78
79 state = ::android::base::GetProperty(kPowerHalAudioProp, "");
80 if (state == "AUDIO_STREAMING_LOW_LATENCY") {
81 LOG(INFO) << "Initialize with AUDIO_LOW_LATENCY on";
82 mHintManager->DoHint(state);
83 }
84
85 state = ::android::base::GetProperty(kPowerHalRenderingProp, "");
86 if (state == "EXPENSIVE_RENDERING") {
87 LOG(INFO) << "Initialize with EXPENSIVE_RENDERING on";
88 mHintManager->DoHint("EXPENSIVE_RENDERING");
89 }
90
91 // Now start to take powerhint
92 LOG(INFO) << "PowerHAL ready to take hints, Adpf update rate: " << mAdpfRateNs;
93 }
94
setMode(Mode type,bool enabled)95 ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
96 LOG(DEBUG) << "Power setMode: " << toString(type) << " to: " << enabled;
97 PowerSessionManager::getInstance()->updateHintMode(toString(type), enabled);
98 switch (type) {
99 case Mode::LOW_POWER:
100 mDisplayLowPower->SetDisplayLowPower(enabled);
101 if (enabled) {
102 mHintManager->DoHint(toString(type));
103 } else {
104 mHintManager->EndHint(toString(type));
105 }
106 break;
107 case Mode::SUSTAINED_PERFORMANCE:
108 if (enabled && !mSustainedPerfModeOn) {
109 if (!mVRModeOn) { // Sustained mode only.
110 mHintManager->DoHint("SUSTAINED_PERFORMANCE");
111 } else { // Sustained + VR mode.
112 mHintManager->EndHint("VR");
113 mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
114 }
115 mSustainedPerfModeOn = true;
116 } else if (!enabled && mSustainedPerfModeOn) {
117 mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
118 mHintManager->EndHint("SUSTAINED_PERFORMANCE");
119 if (mVRModeOn) { // Switch back to VR Mode.
120 mHintManager->DoHint("VR");
121 }
122 mSustainedPerfModeOn = false;
123 }
124 break;
125 case Mode::VR:
126 if (enabled && !mVRModeOn) {
127 if (!mSustainedPerfModeOn) { // VR mode only.
128 mHintManager->DoHint("VR");
129 } else { // Sustained + VR mode.
130 mHintManager->EndHint("SUSTAINED_PERFORMANCE");
131 mHintManager->DoHint("VR_SUSTAINED_PERFORMANCE");
132 }
133 mVRModeOn = true;
134 } else if (!enabled && mVRModeOn) {
135 mHintManager->EndHint("VR_SUSTAINED_PERFORMANCE");
136 mHintManager->EndHint("VR");
137 if (mSustainedPerfModeOn) { // Switch back to sustained Mode.
138 mHintManager->DoHint("SUSTAINED_PERFORMANCE");
139 }
140 mVRModeOn = false;
141 }
142 break;
143 case Mode::LAUNCH:
144 if (mVRModeOn || mSustainedPerfModeOn) {
145 break;
146 }
147 [[fallthrough]];
148 case Mode::DOUBLE_TAP_TO_WAKE:
149 [[fallthrough]];
150 case Mode::FIXED_PERFORMANCE:
151 [[fallthrough]];
152 case Mode::EXPENSIVE_RENDERING:
153 [[fallthrough]];
154 case Mode::INTERACTIVE:
155 [[fallthrough]];
156 case Mode::DEVICE_IDLE:
157 [[fallthrough]];
158 case Mode::DISPLAY_INACTIVE:
159 [[fallthrough]];
160 case Mode::AUDIO_STREAMING_LOW_LATENCY:
161 [[fallthrough]];
162 case Mode::CAMERA_STREAMING_SECURE:
163 [[fallthrough]];
164 case Mode::CAMERA_STREAMING_LOW:
165 [[fallthrough]];
166 case Mode::CAMERA_STREAMING_MID:
167 [[fallthrough]];
168 case Mode::CAMERA_STREAMING_HIGH:
169 [[fallthrough]];
170 default:
171 if (enabled) {
172 mHintManager->DoHint(toString(type));
173 } else {
174 mHintManager->EndHint(toString(type));
175 }
176 break;
177 }
178
179 return ndk::ScopedAStatus::ok();
180 }
181
isModeSupported(Mode type,bool * _aidl_return)182 ndk::ScopedAStatus Power::isModeSupported(Mode type, bool *_aidl_return) {
183 bool supported = mHintManager->IsHintSupported(toString(type));
184 // LOW_POWER handled insides PowerHAL specifically
185 if (type == Mode::LOW_POWER) {
186 supported = true;
187 }
188 LOG(INFO) << "Power mode " << toString(type) << " isModeSupported: " << supported;
189 *_aidl_return = supported;
190 return ndk::ScopedAStatus::ok();
191 }
192
setBoost(Boost type,int32_t durationMs)193 ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
194 LOG(DEBUG) << "Power setBoost: " << toString(type) << " duration: " << durationMs;
195 switch (type) {
196 case Boost::INTERACTION:
197 if (mVRModeOn || mSustainedPerfModeOn) {
198 break;
199 }
200 mInteractionHandler->Acquire(durationMs);
201 break;
202 case Boost::DISPLAY_UPDATE_IMMINENT:
203 [[fallthrough]];
204 case Boost::ML_ACC:
205 [[fallthrough]];
206 case Boost::AUDIO_LAUNCH:
207 [[fallthrough]];
208 case Boost::CAMERA_LAUNCH:
209 [[fallthrough]];
210 case Boost::CAMERA_SHOT:
211 [[fallthrough]];
212 default:
213 if (mVRModeOn || mSustainedPerfModeOn) {
214 break;
215 }
216 if (durationMs > 0) {
217 mHintManager->DoHint(toString(type), std::chrono::milliseconds(durationMs));
218 } else if (durationMs == 0) {
219 mHintManager->DoHint(toString(type));
220 } else {
221 mHintManager->EndHint(toString(type));
222 }
223 break;
224 }
225
226 return ndk::ScopedAStatus::ok();
227 }
228
isBoostSupported(Boost type,bool * _aidl_return)229 ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool *_aidl_return) {
230 bool supported = mHintManager->IsHintSupported(toString(type));
231 LOG(INFO) << "Power boost " << toString(type) << " isBoostSupported: " << supported;
232 *_aidl_return = supported;
233 return ndk::ScopedAStatus::ok();
234 }
235
boolToString(bool b)236 constexpr const char *boolToString(bool b) {
237 return b ? "true" : "false";
238 }
239
dump(int fd,const char **,uint32_t)240 binder_status_t Power::dump(int fd, const char **, uint32_t) {
241 std::string buf(::android::base::StringPrintf(
242 "HintManager Running: %s\n"
243 "VRMode: %s\n"
244 "SustainedPerformanceMode: %s\n",
245 boolToString(mHintManager->IsRunning()), boolToString(mVRModeOn),
246 boolToString(mSustainedPerfModeOn)));
247 // Dump nodes through libperfmgr
248 mHintManager->DumpToFd(fd);
249 if (!::android::base::WriteStringToFd(buf, fd)) {
250 PLOG(ERROR) << "Failed to dump state to fd";
251 }
252 fsync(fd);
253 return STATUS_OK;
254 }
255
createHintSession(int32_t tgid,int32_t uid,const std::vector<int32_t> & threadIds,int64_t durationNanos,std::shared_ptr<IPowerHintSession> * _aidl_return)256 ndk::ScopedAStatus Power::createHintSession(int32_t tgid, int32_t uid,
257 const std::vector<int32_t> &threadIds,
258 int64_t durationNanos,
259 std::shared_ptr<IPowerHintSession> *_aidl_return) {
260 if (mAdpfRateNs <= 0) {
261 *_aidl_return = nullptr;
262 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
263 }
264 if (threadIds.size() == 0) {
265 LOG(ERROR) << "Error: threadIds.size() shouldn't be " << threadIds.size();
266 *_aidl_return = nullptr;
267 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
268 }
269 std::shared_ptr<IPowerHintSession> session = ndk::SharedRefBase::make<PowerHintSession>(
270 tgid, uid, threadIds, durationNanos, nanoseconds(mAdpfRateNs));
271 *_aidl_return = session;
272 return ndk::ScopedAStatus::ok();
273 }
274
getHintSessionPreferredRate(int64_t * outNanoseconds)275 ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t *outNanoseconds) {
276 *outNanoseconds = mAdpfRateNs;
277 if (mAdpfRateNs <= 0) {
278 return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
279 }
280
281 return ndk::ScopedAStatus::ok();
282 }
283
284 } // namespace pixel
285 } // namespace impl
286 } // namespace power
287 } // namespace hardware
288 } // namespace google
289 } // namespace aidl
290