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 <perfmgr/HintManager.h>
21 #include <utils/Looper.h>
22 #include <utils/Thread.h>
23 
24 #include <array>
25 #include <unordered_map>
26 
27 #include "AdpfTypes.h"
28 #include "AppDescriptorTrace.h"
29 #include "PowerSessionManager.h"
30 #include "SessionRecords.h"
31 
32 namespace aidl {
33 namespace google {
34 namespace hardware {
35 namespace power {
36 namespace impl {
37 namespace pixel {
38 
39 using aidl::android::hardware::power::BnPowerHintSession;
40 using ::android::Message;
41 using ::android::MessageHandler;
42 using ::android::sp;
43 using ::android::perfmgr::AdpfConfig;
44 using std::chrono::milliseconds;
45 using std::chrono::nanoseconds;
46 using std::chrono::steady_clock;
47 using std::chrono::time_point;
48 
49 // The Power Hint Session is responsible for providing an
50 // interface for creating, updating, and closing power hints
51 // for a Session. Each sesion that is mapped to multiple
52 // threads (or task ids).
53 template <class HintManagerT = ::android::perfmgr::HintManager,
54           class PowerSessionManagerT = PowerSessionManager<>>
55 class PowerHintSession : public BnPowerHintSession, public Immobile {
56   public:
57     explicit PowerHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t> &threadIds,
58                               int64_t durationNanos, SessionTag tag);
59     ~PowerHintSession();
60     ndk::ScopedAStatus close() override;
61     ndk::ScopedAStatus pause() override;
62     ndk::ScopedAStatus resume() override;
63     ndk::ScopedAStatus updateTargetWorkDuration(int64_t targetDurationNanos) override;
64     ndk::ScopedAStatus reportActualWorkDuration(
65             const std::vector<WorkDuration> &actualDurations) override;
66     ndk::ScopedAStatus sendHint(SessionHint hint) override;
67     ndk::ScopedAStatus setMode(SessionMode mode, bool enabled) override;
68     ndk::ScopedAStatus setThreads(const std::vector<int32_t> &threadIds) override;
69     ndk::ScopedAStatus getSessionConfig(SessionConfig *_aidl_return) override;
70 
71     void dumpToStream(std::ostream &stream);
72     SessionTag getSessionTag() const;
73     void setAdpfProfile(const std::shared_ptr<AdpfConfig> profile);
74 
75   private:
76     // In practice this lock should almost never get contested, but it's necessary for FMQ
77     std::mutex mPowerHintSessionLock;
78     bool isTimeout() REQUIRES(mPowerHintSessionLock);
79     // Is hint session for a user application
80     bool isAppSession() REQUIRES(mPowerHintSessionLock);
81     void tryToSendPowerHint(std::string hint);
82     void updatePidControlVariable(int pidControlVariable, bool updateVote = true)
83             REQUIRES(mPowerHintSessionLock);
84     int64_t convertWorkDurationToBoostByPid(const std::vector<WorkDuration> &actualDurations)
85             REQUIRES(mPowerHintSessionLock);
86     SessionJankyLevel updateSessionJankState(SessionJankyLevel oldState, int32_t numOfJankFrames,
87                                              double durationVariance, bool isLowFPS)
88             REQUIRES(mPowerHintSessionLock);
89     void updateHeuristicBoost() REQUIRES(mPowerHintSessionLock);
90     void resetSessionHeuristicStates() REQUIRES(mPowerHintSessionLock);
91     const std::shared_ptr<AdpfConfig> getAdpfProfile() const;
92     ProcessTag getProcessTag(int32_t tgid);
93     ndk::ScopedAStatus setModeLocked(SessionMode mode, bool enabled)
94             REQUIRES(mPowerHintSessionLock);
95 
96     // Data
97     PowerSessionManagerT *mPSManager;
98     const int64_t mSessionId = 0;
99     // Tag labeling what kind of session this is
100     const SessionTag mSessTag;
101     // Pixel process tag for more granular session control.
102     const ProcessTag mProcTag{ProcessTag::DEFAULT};
103     const std::string mIdString;
104     std::shared_ptr<AppHintDesc> mDescriptor GUARDED_BY(mPowerHintSessionLock);
105 
106     // Trace strings, this is thread safe since only assigned during construction
107     std::shared_ptr<AppDescriptorTrace> mAppDescriptorTrace;
108     time_point<steady_clock> mLastUpdatedTime GUARDED_BY(mPowerHintSessionLock);
109     bool mSessionClosed GUARDED_BY(mPowerHintSessionLock) = false;
110     // Are cpu load change related hints are supported
111     std::unordered_map<std::string, std::optional<bool>> mSupportedHints;
112     // Use the value of the last enum in enum_range +1 as array size
GUARDED_BY(mPowerHintSessionLock)113     std::array<bool, enum_size<SessionMode>()> mModes GUARDED_BY(mPowerHintSessionLock){};
114     std::shared_ptr<AdpfConfig> mAdpfProfile;
115     std::function<void(const std::shared_ptr<AdpfConfig>)> mOnAdpfUpdate;
116     std::unique_ptr<SessionRecords> mSessionRecords GUARDED_BY(mPowerHintSessionLock) = nullptr;
GUARDED_BY(mPowerHintSessionLock)117     bool mHeuristicBoostActive GUARDED_BY(mPowerHintSessionLock){false};
GUARDED_BY(mPowerHintSessionLock)118     SessionJankyLevel mJankyLevel GUARDED_BY(mPowerHintSessionLock){SessionJankyLevel::LIGHT};
GUARDED_BY(mPowerHintSessionLock)119     uint32_t mJankyFrameNum GUARDED_BY(mPowerHintSessionLock){0};
120 };
121 
122 }  // namespace pixel
123 }  // namespace impl
124 }  // namespace power
125 }  // namespace hardware
126 }  // namespace google
127 }  // namespace aidl
128