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