1 /*
2 * Copyright (c) 2022 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 "avsession_sysevent.h"
17 #include "avsession_log.h"
18
19 namespace OHOS::AVSession {
20 #ifdef ENABLE_AVSESSION_SYSEVENT_CONTROL
21 static const int32_t REPORT_SIZE = 100;
22
GetInstance()23 AVSessionSysEvent& AVSessionSysEvent::GetInstance()
24 {
25 static AVSessionSysEvent avSessionSysEvent;
26 return avSessionSysEvent;
27 }
28
AVSessionSysEvent()29 AVSessionSysEvent::AVSessionSysEvent() : optCounts_ {},
30 timer_(nullptr), timerId_(0), lifeCycleInfos_ {}, controllerCommandInfos_ {}, lowQualityInfos_ {}
31 {
32 }
33
~AVSessionSysEvent()34 AVSessionSysEvent::~AVSessionSysEvent()
35 {
36 SLOGI("AVSessionSysEvent destruct");
37 Unregister();
38 }
39
AddOperationCount(Operation operation)40 void AVSessionSysEvent::AddOperationCount(Operation operation)
41 {
42 std::lock_guard lockGuard(lock_);
43 auto it = optCounts_.find(operation);
44 if (it == optCounts_.end()) {
45 optCounts_.insert(std::make_pair(operation, 0));
46 it = optCounts_.find(operation);
47 }
48 it->second++;
49 }
50
Reset()51 void AVSessionSysEvent::Reset()
52 {
53 std::lock_guard lockGuard(lock_);
54 optCounts_.clear();
55 lifeCycleInfos_.clear();
56 controllerCommandInfos_.clear();
57 audioStatuses_.clear();
58 lowQualityInfos_.clear();
59 }
60
ReportLowQuality()61 void AVSessionSysEvent::ReportLowQuality()
62 {
63 for (auto it = lowQualityInfos_.begin(); it != lowQualityInfos_.end(); it++) {
64 SLOGD("report low quality for %{public}s", it->second.bundleName_.c_str());
65 HiSysWriteStatistic("PLAYING_COMBIND_AVSESSION_STATIS",
66 "BUNDLE_NAME", it->second.bundleName_,
67 "PLAY_DURATION", it->second.playDuration_,
68 "STREAM_USAGE", it->second.streamUsage_,
69 "PLAY_BACK", it->second.isBack_,
70 "AUDIO_ACTIVE", it->second.isAudioActive_,
71 "AVSESSION_META_QUALITY", it->second.metaDataQuality_,
72 "AVSESSION_COMMAND_QUALITY", it->second.cmdQuality_,
73 "AVSESSION_PLAYBACK_STATE", it->second.playbackState_);
74 }
75 }
76
Regiter()77 void AVSessionSysEvent::Regiter()
78 {
79 CHECK_AND_RETURN(timer_ == nullptr);
80
81 timer_ = std::make_unique<OHOS::Utils::Timer>("EventStatisticTimer");
82 auto timeCallback = [this]() {
83 std::lock_guard lockGuard(lock_);
84 HiSysWriteStatistic("CONTROL_COMMAND_STATISTICS", "PLAY_COUNT", optCounts_[Operation::OPT_PLAY],
85 "PAUSE_COUNT", optCounts_[Operation::OPT_PAUSE], "STOP_COUNT", optCounts_[Operation::OPT_STOP],
86 "PLAY_NEXT_COUNT", optCounts_[Operation::OPT_PLAY_NEXT],
87 "PLAY_PREVIOUS_COUNT", optCounts_[Operation::OPT_PLAY_PREVIOUS],
88 "FAST_FORWARD_COUNT", optCounts_[Operation::OPT_FAST_FORWARD],
89 "REWIND_COUNT", optCounts_[Operation::OPT_REWIND],
90 "SEEK_COUNT", optCounts_[Operation::OPT_SEEK],
91 "SET_SPEED_COUNT", optCounts_[Operation::OPT_SET_SPEED],
92 "SET_LOOP_MODE_COUNT", optCounts_[Operation::OPT_SET_LOOP_MODE],
93 "SET_TARGET_LOOP_MODE_COUNT", optCounts_[Operation::OPT_SET_TARGET_LOOP_MODE],
94 "TOGGLE_FAVORITE_COUNT", optCounts_[Operation::OPT_TOGGLE_FAVORITE]);
95
96 for (const auto& it : lifeCycleInfos_) {
97 HiSysWriteStatistic("SESSION_LIFECYCLE_STATISTICS", "BUNDLE_NAME", it.bundleName_,
98 "APP_STATUS", it.appStatus_, "SESSION_TYPE", it.sessionType_,
99 "SESSION_LIFE_CYCLE", it.isCreateSession_);
100 }
101
102 for (const auto& it : controllerCommandInfos_) {
103 HiSysWriteStatistic("CONTROL_COMMAND_STATISTICS", "BUNDLE_NAME", it.bundleName_,
104 "CONTROLLER_PID", it.controllerPid_, "CMD", it.controllerCmd_,
105 "DETAILED_MSG", "receiver handle command");
106 }
107
108 ReportLowQuality();
109
110 HiSysWriteStatistic("SESSION_LIFECYCLE_STATISTICS",
111 "CREATE_SESSION_COUNT", optCounts_[Operation::OPT_CREATE_SESSION],
112 "DELETE_SESSION_COUNT", optCounts_[Operation::OPT_DELETE_SESSION]);
113
114 uint32_t allCtrlCmdCount = optCounts_[Operation::OPT_ALL_CTRL_COMMAND];
115 uint32_t allSuccCmdCount = optCounts_[Operation::OPT_SUCCESS_CTRL_COMMAND];
116 if ((allCtrlCmdCount != 0) && (allSuccCmdCount <= allCtrlCmdCount)) {
117 // LCOV_EXCL_START
118 float failedRate = (allCtrlCmdCount - allSuccCmdCount) / (allCtrlCmdCount * MULTIPLE);
119 HiSysWriteStatistic("CONTROL_COMMAND_FAILED_RATE", "ALL_CTRL_COMMAND_COUNT", allCtrlCmdCount,
120 "ALL_SUCCESS_CTRL_COMMAND", allSuccCmdCount, "COMMAND_FAILED_RATE", failedRate);
121 } else {
122 HiSysWriteStatistic("CONTROL_COMMAND_FAILED_RATE", "ALL_CTRL_COMMAND_COUNT", allCtrlCmdCount,
123 "ALL_SUCCESS_CTRL_COMMAND", allSuccCmdCount, "COMMAND_FAILED_RATE", 0);
124 // LCOV_EXCL_STOP
125 }
126 Reset();
127 playingStateTriggerCount++;
128 if (playingStateTriggerCount == 24) {
129 ReportPlayingStateAll();
130 playingStateTriggerCount = 0;
131 }
132 };
133 timerId_ = timer_->Register(timeCallback, NOTIFY_TIME_INTERVAL, false);
134 timer_->Setup();
135 }
136
137 // LCOV_EXCL_START
Unregister()138 void AVSessionSysEvent::Unregister()
139 {
140 if (timer_ != nullptr) {
141 timer_->Shutdown();
142 timer_->Unregister(timerId_);
143 timer_ = nullptr;
144 }
145 }
146 // LCOV_EXCL_STOP
147
AddLifeCycleInfo(const std::string & bundleName,bool appStatus,const int32_t & sessionType,bool isCreateSession)148 void AVSessionSysEvent::AddLifeCycleInfo(const std::string& bundleName, bool appStatus,
149 const int32_t& sessionType, bool isCreateSession)
150 {
151 AVSessionSysEvent::LifeCycleInfo lifeCycleInfo;
152 lifeCycleInfo.bundleName_ = bundleName;
153 lifeCycleInfo.appStatus_ = appStatus;
154 lifeCycleInfo.sessionType_ = sessionType;
155 lifeCycleInfo.isCreateSession_ = isCreateSession;
156 lifeCycleInfos_.push_back(lifeCycleInfo);
157 }
158
AddLowQualityInfo(AVSessionSysEvent::BackControlReportInfo & reportInfo)159 void AVSessionSysEvent::AddLowQualityInfo(AVSessionSysEvent::BackControlReportInfo &reportInfo)
160 {
161 if (lowQualityInfos_.find(reportInfo.bundleName_) == lowQualityInfos_.end()) {
162 lowQualityInfos_.insert(std::make_pair(reportInfo.bundleName_, reportInfo));
163 }
164 }
165
166 // LCOV_EXCL_START
AddControllerCommandInfo(const std::string & bundleName,const pid_t & controllerPid,const int32_t & controllerCmd,const int32_t & sessionType)167 void AVSessionSysEvent::AddControllerCommandInfo(const std::string& bundleName, const pid_t& controllerPid,
168 const int32_t& controllerCmd, const int32_t& sessionType)
169 {
170 AVSessionSysEvent::ControllerCommandInfo controllerCommandInfo;
171 controllerCommandInfo.bundleName_ = bundleName;
172 controllerCommandInfo.controllerPid_ = controllerPid;
173 controllerCommandInfo.controllerCmd_ = controllerCmd;
174 controllerCommandInfos_.push_back(controllerCommandInfo);
175 }
176
GetAudioStatus(pid_t uid)177 int32_t AVSessionSysEvent::GetAudioStatus(pid_t uid)
178 {
179 std::lock_guard lockGuard(lock_);
180 if (audioStatuses_.find(uid) != audioStatuses_.end()) {
181 return audioStatuses_[uid];
182 }
183 return 0;
184 }
185 // LCOV_EXCL_STOP
186
SetAudioStatus(pid_t uid,int32_t rendererState)187 void AVSessionSysEvent::SetAudioStatus(pid_t uid, int32_t rendererState)
188 {
189 std::lock_guard lockGuard(lock_);
190 audioStatuses_[uid] = rendererState;
191 }
192
ReportPlayingState(const std::string & bundleName)193 void AVSessionSysEvent::ReportPlayingState(const std::string& bundleName)
194 {
195 std::lock_guard lockGuard(lock_);
196 CHECK_AND_RETURN(!playingStateInfos_.empty() && playingStateInfos_.find(bundleName) != playingStateInfos_.end());
197 auto playingStateInfo = playingStateInfos_[bundleName].get();
198 if (playingStateInfo != nullptr) {
199 SLOGD("report playing state for %{public}s", playingStateInfo->bundleName_.c_str());
200 HiSysWriteStatistic("PLAYING_AVSESSION_STATS",
201 "APP_NAME", playingStateInfo->bundleName_,
202 "APP_VERSION", playingStateInfo->appVersion_,
203 "AVSESSION_STATE", playingStateInfo->state_,
204 "AVSESSION_STATE_TIMESTAMP", playingStateInfo->stateTime_,
205 "AVSESSION_META_QUALITY", playingStateInfo->metaQuality_,
206 "AVSESSION_META_QUALITY_TIMESTAMP", playingStateInfo->metaQualityTime_,
207 "AVSESSION_COMMAND_QUALITY", playingStateInfo->commandQuality_,
208 "AVSESSION_COMMAND_QUA_TIMESTAMP", playingStateInfo->commandQualityTime_,
209 "AVSESSION_PLAYSTATE", playingStateInfo->playbackState_,
210 "AVSESSION_PLAYSTATE_TIMESTAMP", playingStateInfo->playbackStateTime_,
211 "AVSESSION_CONTROL", playingStateInfo->control_,
212 "AVSESSION_CONTROL_BUNDLE_NAME", playingStateInfo->callerBundleName_,
213 "AVSESSION_CONTROL_TIMESTAMP", playingStateInfo->controlTime_);
214 }
215 playingStateInfos_.erase(bundleName);
216 }
217
ReportPlayingStateAll()218 void AVSessionSysEvent::ReportPlayingStateAll()
219 {
220 std::lock_guard lockGuard(lock_);
221 std::vector<std::string> keys;
222 for (const auto& it : playingStateInfos_) {
223 keys.push_back(it.first);
224 }
225 for (const auto& key : keys) {
226 ReportPlayingState(key);
227 }
228 }
229
UTCTimeMilliSeconds()230 static int64_t UTCTimeMilliSeconds()
231 {
232 struct timespec t;
233 constexpr int64_t SEC_TO_MSEC = 1e3;
234 constexpr int64_t MSEC_TO_NSEC = 1e6;
235 clock_gettime(CLOCK_REALTIME, &t);
236 return t.tv_sec * SEC_TO_MSEC + t.tv_nsec / MSEC_TO_NSEC;
237 }
238
GetPlayingStateInfo(const std::string & bundleName)239 PlayingStateInfo* AVSessionSysEvent::GetPlayingStateInfo(const std::string& bundleName)
240 {
241 std::lock_guard lockGuard(lock_);
242 if (playingStateInfos_.find(bundleName) == playingStateInfos_.end()) {
243 playingStateInfos_.insert({bundleName, std::make_unique<PlayingStateInfo>()});
244 playingStateInfos_[bundleName]->bundleName_ = bundleName;
245 }
246 return playingStateInfos_[bundleName].get();
247 }
248
UpdateState(const std::string & bundleName,const std::string & appVersion,SessionState state)249 void AVSessionSysEvent::UpdateState(const std::string& bundleName, const std::string& appVersion, SessionState state)
250 {
251 std::lock_guard lockGuard(lock_);
252 PlayingStateInfo* playingStateInfo = GetPlayingStateInfo(bundleName);
253 bool isPlayInfoValid = playingStateInfo != nullptr;
254 CHECK_AND_RETURN(isPlayInfoValid);
255 playingStateInfo->bundleName_ = bundleName;
256 playingStateInfo->appVersion_ = appVersion;
257 playingStateInfo->updateState(state);
258 bool isReportOverSize = playingStateInfo->state_.size() >= REPORT_SIZE;
259 CHECK_AND_RETURN(isReportOverSize);
260 AVSessionSysEvent::GetInstance().ReportPlayingState(bundleName);
261 }
262
UpdateMetaQuality(const std::string & bundleName,MetadataQuality metaQuality)263 void AVSessionSysEvent::UpdateMetaQuality(const std::string& bundleName, MetadataQuality metaQuality)
264 {
265 std::lock_guard lockGuard(lock_);
266 PlayingStateInfo* playingStateInfo = GetPlayingStateInfo(bundleName);
267 bool isPlayInfoValid = playingStateInfo != nullptr;
268 CHECK_AND_RETURN(isPlayInfoValid);
269 playingStateInfo->updateMetaQuality(metaQuality);
270 bool isReportOverSize = playingStateInfo->metaQuality_.size() >= REPORT_SIZE;
271 CHECK_AND_RETURN(isReportOverSize);
272 AVSessionSysEvent::GetInstance().ReportPlayingState(bundleName);
273 }
274
UpdateCommandQuality(const std::string & bundleName,uint32_t commandQuality)275 void AVSessionSysEvent::UpdateCommandQuality(const std::string& bundleName, uint32_t commandQuality)
276 {
277 std::lock_guard lockGuard(lock_);
278 PlayingStateInfo* playingStateInfo = GetPlayingStateInfo(bundleName);
279 bool isPlayInfoValid = playingStateInfo != nullptr;
280 CHECK_AND_RETURN(isPlayInfoValid);
281 playingStateInfo->updateCommandQuality(commandQuality);
282 bool isReportOverSize = playingStateInfo->commandQuality_.size() >= REPORT_SIZE;
283 CHECK_AND_RETURN(isReportOverSize);
284 AVSessionSysEvent::GetInstance().ReportPlayingState(bundleName);
285 }
286
UpdatePlaybackState(const std::string & bundleName,uint8_t playbackState)287 void AVSessionSysEvent::UpdatePlaybackState(const std::string& bundleName, uint8_t playbackState)
288 {
289 std::lock_guard lockGuard(lock_);
290 PlayingStateInfo* playingStateInfo = GetPlayingStateInfo(bundleName);
291 bool isPlayInfoValid = playingStateInfo != nullptr;
292 CHECK_AND_RETURN(isPlayInfoValid);
293 playingStateInfo->updatePlaybackState(playbackState);
294 bool isReportOverSize = playingStateInfo->playbackState_.size() >= REPORT_SIZE;
295 CHECK_AND_RETURN(isReportOverSize);
296 AVSessionSysEvent::GetInstance().ReportPlayingState(bundleName);
297 }
298
UpdateControl(const std::string & bundleName,uint8_t control,std::string callerBundleName)299 void AVSessionSysEvent::UpdateControl(const std::string& bundleName, uint8_t control, std::string callerBundleName)
300 {
301 std::lock_guard lockGuard(lock_);
302 PlayingStateInfo* playingStateInfo = GetPlayingStateInfo(bundleName);
303 CHECK_AND_RETURN(playingStateInfo != nullptr);
304 playingStateInfo->updateControl(control, callerBundleName);
305 CHECK_AND_RETURN(playingStateInfo->control_.size() >= REPORT_SIZE);
306 AVSessionSysEvent::GetInstance().ReportPlayingState(bundleName);
307 }
308
updateState(SessionState state)309 void PlayingStateInfo::updateState(SessionState state)
310 {
311 std::lock_guard lockGuard(lock_);
312 if (state != lastState_) {
313 lastState_ = state;
314 state_.push_back(static_cast<uint8_t>(state));
315 stateTime_.push_back(UTCTimeMilliSeconds());
316 }
317 }
318
updateMetaQuality(MetadataQuality metaQuality)319 void PlayingStateInfo::updateMetaQuality(MetadataQuality metaQuality)
320 {
321 std::lock_guard lockGuard(lock_);
322 metaQuality_.push_back(static_cast<uint8_t>(metaQuality));
323 metaQualityTime_.push_back(UTCTimeMilliSeconds());
324 }
325
updateCommandQuality(uint32_t commandQuality)326 void PlayingStateInfo::updateCommandQuality(uint32_t commandQuality)
327 {
328 std::lock_guard lockGuard(lock_);
329 if (commandQuality != lastCommandQuality_) {
330 lastCommandQuality_ = commandQuality;
331 commandQuality_.push_back(commandQuality);
332 commandQualityTime_.push_back(UTCTimeMilliSeconds());
333 }
334 }
335
updatePlaybackState(uint8_t playbackState)336 void PlayingStateInfo::updatePlaybackState(uint8_t playbackState)
337 {
338 std::lock_guard lockGuard(lock_);
339 if (playbackState != lastPlaybackState_) {
340 lastPlaybackState_ = playbackState;
341 playbackState_.push_back(playbackState);
342 playbackStateTime_.push_back(UTCTimeMilliSeconds());
343 }
344 }
345
updateControl(uint8_t control,std::string callerBundleName)346 void PlayingStateInfo::updateControl(uint8_t control, std::string callerBundleName)
347 {
348 std::lock_guard lockGuard(lock_);
349 if (control != lastControl_) {
350 lastControl_ = control;
351 control_.push_back(control);
352 callerBundleName_.push_back(callerBundleName);
353 controlTime_.push_back(UTCTimeMilliSeconds());
354 }
355 }
356 #endif
357 } // namespace OHOS::AVSession