1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hgm_idle_detector.h"
17 #include "rs_trace.h"
18 #include "hgm_task_handle_thread.h"
19
20 namespace OHOS {
21 namespace Rosen {
22 namespace {
23 constexpr uint64_t BUFFER_IDLE_TIME_OUT = 200000000; // 200ms
24 constexpr uint64_t MAX_CACHED_VALID_SURFACE_NAME_COUNT = 60;
25 constexpr int32_t ANIMATOR_NO_EXPECTED_FRAME_RATE = 0;
26 const std::string ACE_ANIMATOR_NAME = "AceAnimato";
27 const std::string OTHER_SURFACE = "Other_SF";
28 }
29
SetAppSupportedState(bool appSupported)30 void HgmIdleDetector::SetAppSupportedState(bool appSupported)
31 {
32 appSupported_ = appSupported;
33 if (!appSupported_) {
34 aceAnimatorIdleState_ = true;
35 aceAnimatorExpectedFrameRate_ = ANIMATOR_NOT_RUNNING;
36 surfaceTimeMap_.clear();
37 bufferFpsMap_.clear();
38 }
39 }
40
SetAceAnimatorIdleState(bool aceAnimatorIdleState)41 void HgmIdleDetector::SetAceAnimatorIdleState(bool aceAnimatorIdleState)
42 {
43 if (!appSupported_ || bufferFpsMap_.find(ACE_ANIMATOR_NAME) == bufferFpsMap_.end() ||
44 bufferFpsMap_[ACE_ANIMATOR_NAME] == 0) {
45 // only if bufferFpsMap_ contains ACE_ANIMATOR_NAME, aceAnimatorIdleState_ can be set to false
46 aceAnimatorIdleState_ = true;
47 return;
48 }
49
50 aceAnimatorIdleState_ = aceAnimatorIdleState;
51 }
52
UpdateSurfaceTime(const std::string & surfaceName,uint64_t timestamp,pid_t pid,UIFWKType uiFwkType)53 void HgmIdleDetector::UpdateSurfaceTime(const std::string& surfaceName, uint64_t timestamp,
54 pid_t pid, UIFWKType uiFwkType)
55 {
56 if (surfaceName.empty()) {
57 return;
58 }
59
60 if (!GetAppSupportedState() || surfaceTimeMap_.size() > MAX_CACHED_VALID_SURFACE_NAME_COUNT) {
61 surfaceTimeMap_.clear();
62 return;
63 }
64
65 std::string validSurfaceType = "";
66 bool hasValidFramework = false;
67 switch (uiFwkType) {
68 case UIFWKType::FROM_UNKNOWN:
69 hasValidFramework = GetUnknownFrameworkState(surfaceName, validSurfaceType);
70 break;
71 case UIFWKType::FROM_SURFACE:
72 hasValidFramework = GetSurfaceFrameworkState(surfaceName, validSurfaceType);
73 break;
74 default:
75 break;
76 }
77 if (!hasValidFramework) {
78 return;
79 }
80
81 RS_TRACE_NAME_FMT("UpdateSurfaceTime:: Not Idle SurFace Name = [%s] From Pid = [%d]",
82 surfaceName.c_str(), pid);
83 // only types contained by bufferFpsMap_ can be add to surfaceTimeMap_
84 surfaceTimeMap_[validSurfaceType] = timestamp;
85 }
86
GetUnknownFrameworkState(const std::string & surfaceName,std::string & uiFwkType)87 bool HgmIdleDetector::GetUnknownFrameworkState(const std::string& surfaceName,
88 std::string& uiFwkType)
89 {
90 for (const auto& [supportedAppBuffer, fps] : bufferFpsMap_) {
91 if (surfaceName.rfind(supportedAppBuffer, 0) == 0) {
92 if (fps > 0) {
93 uiFwkType = supportedAppBuffer;
94 return true;
95 } else {
96 return false;
97 }
98 }
99 }
100 return false;
101 }
102
GetSurfaceFrameworkState(const std::string & surfaceName,std::string & validSurfaceName)103 bool HgmIdleDetector::GetSurfaceFrameworkState(const std::string& surfaceName,
104 std::string& validSurfaceName)
105 {
106 for (const auto& [supportedAppBuffer, fps] : bufferFpsMap_) {
107 if (surfaceName.rfind(supportedAppBuffer, 0) == 0) {
108 if (fps > 0) {
109 validSurfaceName = supportedAppBuffer;
110 return true;
111 } else {
112 return false;
113 }
114 }
115 }
116 if (bufferFpsMap_.find(OTHER_SURFACE) != bufferFpsMap_.end() &&
117 bufferFpsMap_[OTHER_SURFACE] > 0) {
118 validSurfaceName = OTHER_SURFACE;
119 return true;
120 }
121 return false;
122 }
123
UpdateSurfaceState(uint64_t timestamp)124 void HgmIdleDetector::UpdateSurfaceState(uint64_t timestamp)
125 {
126 for (auto iter = surfaceTimeMap_.begin(); iter != surfaceTimeMap_.end();) {
127 if (timestamp > iter->second && (timestamp - iter->second) > BUFFER_IDLE_TIME_OUT) {
128 iter = surfaceTimeMap_.erase(iter);
129 } else {
130 ++iter;
131 }
132 }
133 }
134
GetTouchUpExpectedFPS()135 int32_t HgmIdleDetector::GetTouchUpExpectedFPS()
136 {
137 if (aceAnimatorIdleState_ && surfaceTimeMap_.empty()) {
138 return 0;
139 }
140
141 int32_t aceAnimatorVote = 0;
142 if (!aceAnimatorIdleState_) {
143 // only if bufferFpsMap_ contains ACE_ANIMATOR_NAME, aceAnimatorIdleState_ can be set to false
144 aceAnimatorVote = aceAnimatorExpectedFrameRate_ > ANIMATOR_NO_EXPECTED_FRAME_RATE
145 ? std::min(aceAnimatorExpectedFrameRate_, bufferFpsMap_[ACE_ANIMATOR_NAME])
146 : bufferFpsMap_[ACE_ANIMATOR_NAME];
147 }
148
149 int32_t surfaceVote = 0;
150 for (const auto& [surfaceName, _] : surfaceTimeMap_) {
151 // only types contained by bufferFpsMap_ can be add to surfaceTimeMap_
152 surfaceVote = std::max(surfaceVote, bufferFpsMap_[surfaceName]);
153 }
154
155 RS_TRACE_NAME_FMT("GetTouchUpExpectedFPS: aceAnimatorVote:[%d], surfaceVote:[%d]", aceAnimatorVote, surfaceVote);
156 return std::max(aceAnimatorVote, surfaceVote);
157 }
158
159 } // namespace Rosen
160 } // namespace OHOS