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 "frame_report.h"
17
18 #include <dlfcn.h>
19 #include <cstdio>
20 #include <securec.h>
21 #include <unistd.h>
22 #include <hilog/log.h>
23
24 namespace OHOS {
25 namespace Rosen {
26
27 #undef LOG_DOMAIN
28 #define LOG_DOMAIN 0xD005830
29
30 #undef LOG_TAG
31 #define LOG_TAG "FrameReport"
32
33 #define LOGF(format, ...) HILOG_FATAL(LOG_CORE, format, ##__VA_ARGS__)
34 #define LOGE(format, ...) HILOG_ERROR(LOG_CORE, format, ##__VA_ARGS__)
35 #define LOGW(format, ...) HILOG_WARN(LOG_CORE, format, ##__VA_ARGS__)
36 #define LOGI(format, ...) HILOG_INFO(LOG_CORE, format, ##__VA_ARGS__)
37 #define LOGD(format, ...) HILOG_DEBUG(LOG_CORE, format, ##__VA_ARGS__)
38
39 const std::string GAME_ACCELERATE_SCHEDULE_SO_PATH = "libgame_acc_sched_client.z.so";
40 const std::string GAME_ACCELERATE_SCHEDULE_NOTIFYFRAMEINFO = "GAS_NotifyFrameInfo";
41 constexpr int32_t REPORT_BUFFER_SIZE = 256;
42 constexpr int32_t THOUSAND_COUNT = 1000;
43 constexpr int32_t SKIP_HINT_STATUS = 0;
44 constexpr int32_t FR_GAME_BACKGROUND = 0;
45 constexpr int32_t FR_GAME_FOREGROUND = 1;
46 constexpr int32_t FR_GAME_SCHED = 2;
47
GetInstance()48 FrameReport& FrameReport::GetInstance()
49 {
50 static FrameReport instance;
51 return instance;
52 }
53
FrameReport()54 FrameReport::FrameReport()
55 {
56 }
57
~FrameReport()58 FrameReport::~FrameReport()
59 {
60 CloseLibrary();
61 }
62
SetGameScene(int32_t pid,int32_t state)63 void FrameReport::SetGameScene(int32_t pid, int32_t state)
64 {
65 LOGI("FrameReport::SetGameScene pid = %{public}d state = %{public}d ", pid, state);
66 switch (state) {
67 case FR_GAME_BACKGROUND: {
68 if (IsActiveGameWithPid(pid)) {
69 LOGI("FrameReport::SetGameScene Game Background Current Pid = %{public}d "
70 "state = 0", pid);
71 DeletePidInfo();
72 }
73 break;
74 }
75 case FR_GAME_FOREGROUND: {
76 LoadLibrary();
77 break;
78 }
79 case FR_GAME_SCHED: {
80 activelyPid_.store(pid);
81 break;
82 }
83 default: {
84 LOGW("FrameReport::SetGameScene state error!");
85 break;
86 }
87 }
88 }
89
HasGameScene()90 bool FrameReport::HasGameScene()
91 {
92 return activelyPid_.load() != FR_DEFAULT_PID;
93 }
94
IsActiveGameWithPid(int32_t pid)95 bool FrameReport::IsActiveGameWithPid(int32_t pid)
96 {
97 if (pid <= FR_DEFAULT_PID) {
98 return false;
99 }
100 return pid == activelyPid_.load();
101 }
102
IsActiveGameWithUniqueId(uint64_t uniqueId)103 bool FrameReport::IsActiveGameWithUniqueId(uint64_t uniqueId)
104 {
105 if (uniqueId <= FR_DEFAULT_UNIQUEID) {
106 return false;
107 }
108 return uniqueId == activelyUniqueId_.load();
109 }
110
SetLastSwapBufferTime(int64_t lastSwapBufferTime)111 void FrameReport::SetLastSwapBufferTime(int64_t lastSwapBufferTime)
112 {
113 lastSwapBufferTime_.store(lastSwapBufferTime);
114 }
115
SetDequeueBufferTime(const std::string & layerName,int64_t dequeueBufferTime)116 void FrameReport::SetDequeueBufferTime(const std::string& layerName, int64_t dequeueBufferTime)
117 {
118 dequeueBufferTime_.store(dequeueBufferTime);
119 }
120
SetQueueBufferTime(uint64_t uniqueId,const std::string & layerName,int64_t queueBufferTime)121 void FrameReport::SetQueueBufferTime(uint64_t uniqueId, const std::string& layerName, int64_t queueBufferTime)
122 {
123 queueBufferTime_.store(queueBufferTime);
124 activelyUniqueId_.store(uniqueId);
125 }
126
SetPendingBufferNum(const std::string & layerName,int32_t pendingBufferNum)127 void FrameReport::SetPendingBufferNum(const std::string& layerName, int32_t pendingBufferNum)
128 {
129 pendingBufferNum_.store(pendingBufferNum);
130 }
131
LoadLibrary()132 void FrameReport::LoadLibrary()
133 {
134 std::unique_lock lock(mutex_);
135 if (!isGameSoLoaded_) {
136 dlerror();
137 gameSoHandle_ = dlopen(GAME_ACCELERATE_SCHEDULE_SO_PATH.c_str(), RTLD_LAZY);
138 if (gameSoHandle_ == nullptr) {
139 LOGE("FrameReport::LoadLibrary dlopen libgame_acc_sched_client.z.so failed! error = %{public}s", dlerror());
140 return;
141 }
142 LOGI("FrameReport::LoadLibrary dlopen libgame_acc_sched_client.z.so success!");
143 notifyFrameInfoFunc_ = reinterpret_cast<NotifyFrameInfoFunc>(
144 LoadSymbol(GAME_ACCELERATE_SCHEDULE_NOTIFYFRAMEINFO));
145 if (notifyFrameInfoFunc_ == nullptr) {
146 if (dlclose(gameSoHandle_) != 0) {
147 LOGE("FrameReport::CloseLibrary libgame_acc_sched_client.z.so close failed!");
148 } else {
149 gameSoHandle_ = nullptr;
150 LOGI("FrameReport::CloseLibrary libgame_acc_sched_client.z.so close success!");
151 }
152 return;
153 }
154 LOGI("FrameReport::LoadLibrary dlsym GAS_NotifyFrameInfo success!");
155 isGameSoLoaded_ = true;
156 }
157 }
158
CloseLibrary()159 void FrameReport::CloseLibrary()
160 {
161 std::unique_lock lock(mutex_);
162 notifyFrameInfoFunc_ = nullptr;
163 if (gameSoHandle_ != nullptr) {
164 if (dlclose(gameSoHandle_) != 0) {
165 LOGE("FrameReport::CloseLibrary libgame_acc_sched_client.z.so close failed!");
166 } else {
167 gameSoHandle_ = nullptr;
168 isGameSoLoaded_ = false;
169 LOGI("FrameReport::CloseLibrary libgame_acc_sched_client.z.so close success!");
170 }
171 }
172 }
173
LoadSymbol(const std::string & symName)174 void* FrameReport::LoadSymbol(const std::string& symName)
175 {
176 dlerror();
177 void *funcSym = dlsym(gameSoHandle_, symName.c_str());
178 if (funcSym == nullptr) {
179 LOGE("FrameReport::LoadSymbol Get %{public}s symbol failed: %{public}s", symName.c_str(), dlerror());
180 return nullptr;
181 }
182 return funcSym;
183 }
184
DeletePidInfo()185 void FrameReport::DeletePidInfo()
186 {
187 activelyPid_.store(FR_DEFAULT_PID);
188 activelyUniqueId_.store(FR_DEFAULT_UNIQUEID);
189 }
190
Report(const std::string & layerName)191 void FrameReport::Report(const std::string& layerName)
192 {
193 int64_t timeStamp = std::chrono::duration_cast<std::chrono::nanoseconds>(
194 std::chrono::steady_clock::now().time_since_epoch()).count();
195 std::string bufferMsg = "";
196 char msg[REPORT_BUFFER_SIZE] = { 0 };
197 int32_t ret = sprintf_s(msg, sizeof(msg),
198 "{\"dequeueBufferTime\":\"%d\",\"queueBufferTime\":\"%d\",\"pendingBufferNum\":\"%d\","
199 "\"swapBufferTime\":\"%d\", \"skipHint\":\"%d\"}",
200 static_cast<int32_t>(dequeueBufferTime_.load() / THOUSAND_COUNT),
201 static_cast<int32_t>(queueBufferTime_.load() / THOUSAND_COUNT),
202 pendingBufferNum_.load(),
203 static_cast<int32_t>(lastSwapBufferTime_.load() / THOUSAND_COUNT),
204 SKIP_HINT_STATUS);
205 if (ret == -1) {
206 return;
207 }
208 bufferMsg = msg;
209 NotifyFrameInfo(activelyPid_.load(), layerName, timeStamp, bufferMsg);
210 }
211
NotifyFrameInfo(int32_t pid,const std::string & layerName,int64_t timeStamp,const std::string & bufferMsg)212 void FrameReport::NotifyFrameInfo(int32_t pid, const std::string& layerName, int64_t timeStamp,
213 const std::string& bufferMsg)
214 {
215 std::shared_lock lock(mutex_);
216 if (notifyFrameInfoFunc_ == nullptr) {
217 return;
218 }
219 bool result = notifyFrameInfoFunc_(pid, layerName, timeStamp, bufferMsg);
220 if (!result) {
221 LOGW("FrameReport::NotifyFrameInfo Call GAS_NotifyFrameInfo Func Error");
222 DeletePidInfo();
223 }
224 }
225 } // namespace Rosen
226 } // namespace OHOS
227