1 /* 2 * Copyright 2021 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 <aidl/android/hardware/power/BnPowerHintSession.h> 20 #include <aidl/android/hardware/power/SessionHint.h> 21 #include <aidl/android/hardware/power/WorkDuration.h> 22 #include <utils/Looper.h> 23 #include <utils/Thread.h> 24 25 #include <mutex> 26 #include <unordered_map> 27 28 namespace aidl { 29 namespace google { 30 namespace hardware { 31 namespace power { 32 namespace impl { 33 namespace pixel { 34 35 using aidl::android::hardware::power::BnPowerHintSession; 36 using aidl::android::hardware::power::SessionHint; 37 using aidl::android::hardware::power::WorkDuration; 38 using ::android::Message; 39 using ::android::MessageHandler; 40 using ::android::sp; 41 using std::chrono::milliseconds; 42 using std::chrono::nanoseconds; 43 using std::chrono::steady_clock; 44 using std::chrono::time_point; 45 46 struct AppHintDesc { AppHintDescAppHintDesc47 AppHintDesc(int32_t tgid, int32_t uid, std::vector<int32_t> threadIds) 48 : tgid(tgid), 49 uid(uid), 50 threadIds(std::move(threadIds)), 51 duration(0LL), 52 current_min(0), 53 is_active(true), 54 update_count(0), 55 integral_error(0), 56 previous_error(0) {} 57 std::string toString() const; 58 const int32_t tgid; 59 const int32_t uid; 60 std::vector<int32_t> threadIds; 61 nanoseconds duration; 62 int current_min; 63 // status 64 std::atomic<bool> is_active; 65 // pid 66 uint64_t update_count; 67 int64_t integral_error; 68 int64_t previous_error; 69 }; 70 71 class PowerHintSession : public BnPowerHintSession { 72 public: 73 explicit PowerHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t> &threadIds, 74 int64_t durationNanos); 75 ~PowerHintSession(); 76 ndk::ScopedAStatus close() override; 77 ndk::ScopedAStatus pause() override; 78 ndk::ScopedAStatus resume() override; 79 ndk::ScopedAStatus updateTargetWorkDuration(int64_t targetDurationNanos) override; 80 ndk::ScopedAStatus reportActualWorkDuration( 81 const std::vector<WorkDuration> &actualDurations) override; 82 ndk::ScopedAStatus sendHint(SessionHint hint) override; 83 ndk::ScopedAStatus setThreads(const std::vector<int32_t> &threadIds) override; 84 bool isActive(); 85 bool isTimeout(); 86 void setStale(); 87 // Is this hint session for a user application 88 bool isAppSession(); 89 const std::vector<int> &getTidList() const; 90 int getUclampMin(); 91 void dumpToStream(std::ostream &stream); 92 93 // Disable any temporary boost and return to normal operation. It does not 94 // reset the actual uclamp value, and relies on the caller to do so, to 95 // prevent double-setting. Returns true if it actually disabled an active boost 96 bool disableTemporaryBoost(); 97 98 private: 99 class SessionTimerHandler : public MessageHandler { 100 public: SessionTimerHandler(PowerHintSession * session,std::string name)101 SessionTimerHandler(PowerHintSession *session, std::string name) 102 : mSession(session), mIsSessionDead(false), mName(name) {} 103 void updateTimer(nanoseconds delay); 104 void handleMessage(const Message &message) override; 105 void setSessionDead(); 106 virtual void onTimeout() = 0; 107 108 protected: 109 PowerHintSession *mSession; 110 std::mutex mClosedLock; 111 std::mutex mMessageLock; 112 std::atomic<time_point<steady_clock>> mTimeout; 113 bool mIsSessionDead; 114 const std::string mName; 115 }; 116 117 class StaleTimerHandler : public SessionTimerHandler { 118 public: StaleTimerHandler(PowerHintSession * session)119 StaleTimerHandler(PowerHintSession *session) : SessionTimerHandler(session, "stale") {} 120 void updateTimer(); 121 void onTimeout() override; 122 }; 123 124 class BoostTimerHandler : public SessionTimerHandler { 125 public: BoostTimerHandler(PowerHintSession * session)126 BoostTimerHandler(PowerHintSession *session) : SessionTimerHandler(session, "boost") {} 127 void onTimeout() override; 128 }; 129 130 private: 131 void updateUniveralBoostMode(); 132 int setSessionUclampMin(int32_t min, bool resetStale = true); 133 void tryToSendPowerHint(std::string hint); 134 int64_t convertWorkDurationToBoostByPid(const std::vector<WorkDuration> &actualDurations); 135 void traceSessionVal(char const *identifier, int64_t val) const; 136 AppHintDesc *mDescriptor = nullptr; 137 sp<StaleTimerHandler> mStaleTimerHandler; 138 sp<BoostTimerHandler> mBoostTimerHandler; 139 std::atomic<time_point<steady_clock>> mLastUpdatedTime; 140 sp<MessageHandler> mPowerManagerHandler; 141 std::mutex mSessionLock; 142 std::atomic<bool> mSessionClosed = false; 143 std::string mIdString; 144 // Used when setting a temporary boost value to hold the true boost 145 std::atomic<std::optional<int>> mNextUclampMin; 146 // To cache the status of whether ADPF hints are supported. 147 std::unordered_map<std::string, std::optional<bool>> mSupportedHints; 148 // Last session hint sent, used for logging 149 int mLastHintSent = -1; 150 }; 151 152 } // namespace pixel 153 } // namespace impl 154 } // namespace power 155 } // namespace hardware 156 } // namespace google 157 } // namespace aidl 158