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 "media_monitor_service.h"
17 #include <filesystem>
18 #include <sys/stat.h>
19 #include "system_ability_definition.h"
20 #include "parameters.h"
21 #include "log.h"
22 #include "monitor_error.h"
23 #include "media_audio_encoder.h"
24 #include "media_monitor_death_recipient.h"
25 #include "iservice_registry.h"
26
27 namespace {
28 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_FOUNDATION, "MediaMonitorService"};
29 }
30
31 using namespace std;
32
33 namespace OHOS {
34 namespace Media {
35 namespace MediaMonitor {
36 constexpr int32_t WAIT_DUMP_TIMEOUT_S = 1;
37 constexpr int32_t AUDIO_UID = 1041;
REGISTER_SYSTEM_ABILITY_BY_ID(MediaMonitorService,MEDIA_MONITOR_SERVICE_ID,true)38 REGISTER_SYSTEM_ABILITY_BY_ID(MediaMonitorService, MEDIA_MONITOR_SERVICE_ID, true)
39
40 MediaMonitorService::MediaMonitorService(int32_t systemAbilityId, bool runOnCreate)
41 : SystemAbility(systemAbilityId, runOnCreate),
42 eventAggregate_(EventAggregate::GetEventAggregate()),
43 audioMemo_(AudioMemo::GetAudioMemo())
44 {
45 MEDIA_LOG_I("MediaMonitorService constructor");
46 }
47
OnDump()48 void MediaMonitorService::OnDump()
49 {
50 MEDIA_LOG_I("OnDump");
51 }
52
Dump(int32_t fd,const std::vector<std::u16string> & args)53 int32_t MediaMonitorService::Dump(int32_t fd, const std::vector<std::u16string> &args)
54 {
55 MEDIA_LOG_I("MediaMonitorService Dump");
56 std::string dumpString = "------------------MediaMonitor------------------\n";
57
58 eventAggregate_.WriteInfo(fd, dumpString);
59 audioMemo_.WriteInfo(fd, dumpString);
60 write(fd, dumpString.c_str(), dumpString.size());
61 return SUCCESS;
62 }
63
OnStart()64 void MediaMonitorService::OnStart()
65 {
66 MEDIA_LOG_I("OnStart");
67 bool res = Publish(this);
68 if (!res) {
69 MEDIA_LOG_I("publish sa err");
70 return;
71 }
72 signal_ = std::make_shared<MessageSignal>();
73 signal_->isRunning_.store(true);
74 messageLoopThread_ = make_unique<thread>(&MediaMonitorService::MessageLoopFunc, this);
75 pthread_setname_np(messageLoopThread_->native_handle(), "MMLoopThread");
76 versionType_ = OHOS::system::GetParameter("const.logsystem.versiontype", COMMERCIAL_VERSION);
77 MEDIA_LOG_I("MediaMonitorService get version type %{public}s", versionType_.c_str());
78 }
79
OnStop()80 void MediaMonitorService::OnStop()
81 {
82 MEDIA_LOG_I("OnStop");
83 isExit_ = true;
84 signal_->isRunning_.store(false);
85 DumpThreadExit();
86 }
87
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)88 void MediaMonitorService::OnAddSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
89 {
90 MEDIA_LOG_I("systemAbilityId:%{public}d", systemAbilityId);
91 }
92
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)93 void MediaMonitorService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId)
94 {
95 MEDIA_LOG_I("OnRemoveSystemAbility systemAbilityId:%{public}d removed", systemAbilityId);
96 }
97
WriteLogMsg(std::shared_ptr<EventBean> & bean)98 void MediaMonitorService::WriteLogMsg(std::shared_ptr<EventBean> &bean)
99 {
100 MEDIA_LOG_D("Write event");
101 if (bean == nullptr) {
102 MEDIA_LOG_E("eventBean is nullptr");
103 return;
104 }
105 AddMessageToQueue(bean);
106 }
107
MessageLoopFunc()108 void MediaMonitorService::MessageLoopFunc()
109 {
110 MEDIA_LOG_D("MediaMonitorService MessageLoopFunc");
111 if (signal_ == nullptr) {
112 MEDIA_LOG_E("MediaMonitorService MessageLoopFunc signal_ is nullptr");
113 return;
114 }
115 while (!isExit_) {
116 if (!signal_->isRunning_.load()) {
117 break;
118 }
119 std::shared_ptr<EventBean> msg;
120 {
121 unique_lock<mutex> lock(signal_->messageMutex_);
122 signal_->messageCond_.wait(lock, [this]() { return signal_->messageQueue_.size() > 0; });
123 if (!signal_->isRunning_.load()) {
124 break;
125 }
126 msg = signal_->messageQueue_.front();
127 if (msg == nullptr) {
128 signal_->messageQueue_.pop();
129 continue;
130 }
131 signal_->messageQueue_.pop();
132 }
133 GetMessageFromQueue(msg);
134 }
135 }
136
GetMessageFromQueue(std::shared_ptr<EventBean> & message)137 void MediaMonitorService::GetMessageFromQueue(std::shared_ptr<EventBean> &message)
138 {
139 if (message == nullptr) {
140 MEDIA_LOG_E("eventBean is nullptr");
141 return;
142 }
143 eventAggregate_.WriteEvent(message);
144 }
145
AddMessageToQueue(std::shared_ptr<EventBean> & message)146 void MediaMonitorService::AddMessageToQueue(std::shared_ptr<EventBean> &message)
147 {
148 MEDIA_LOG_D("MediaMonitorService AddMessageToQueue");
149 if (signal_ == nullptr) {
150 MEDIA_LOG_E("signal_ is null");
151 return;
152 }
153 unique_lock<mutex> lock(signal_->messageMutex_);
154 if (!signal_->isRunning_.load()) {
155 MEDIA_LOG_E("!isRunning_");
156 return;
157 }
158 signal_->messageQueue_.push(message);
159 signal_->messageCond_.notify_all();
160 }
161
GetAudioRouteMsg(std::map<PerferredType,std::shared_ptr<MonitorDeviceInfo>> & perferredDevices)162 int32_t MediaMonitorService::GetAudioRouteMsg(std::map<PerferredType,
163 std::shared_ptr<MonitorDeviceInfo>> &perferredDevices)
164 {
165 FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permission denied");
166 MEDIA_LOG_D("MediaMonitorService GetAudioRouteMsg");
167 return audioMemo_.GetAudioRouteMsg(perferredDevices);
168 }
169
AudioEncodeDump()170 void MediaMonitorService::AudioEncodeDump()
171 {
172 MEDIA_LOG_I("encode pcm start");
173 std::shared_ptr<MediaAudioEncoder> encoder = std::make_shared<MediaAudioEncoder>();
174 encoder->EncodePcmFiles(fileFloader_);
175 encoder = nullptr;
176 }
177
VerifyIsAudio()178 bool MediaMonitorService::VerifyIsAudio()
179 {
180 int32_t callingUid = IPCSkeleton::GetCallingUid();
181 if (callingUid == AUDIO_UID) {
182 return true;
183 }
184 return false;
185 }
186
IsNeedDump()187 bool MediaMonitorService::IsNeedDump()
188 {
189 MEDIA_LOG_D("dumpType_:%{public}s, dumpEnable:%{public}d", dumpType_.c_str(), dumpEnable_);
190 if (versionType_ != BETA_VERSION) {
191 return false;
192 }
193 if (dumpType_ == DEFAULT_DUMP_TYPE || dumpType_ == BETA_DUMP_TYPE) {
194 return dumpEnable_;
195 }
196 return false;
197 }
198
WriteAudioBuffer(const std::string & fileName,void * ptr,size_t size)199 int32_t MediaMonitorService::WriteAudioBuffer(const std::string &fileName, void *ptr, size_t size)
200 {
201 return SUCCESS;
202 }
203
GetInputBuffer(std::shared_ptr<DumpBuffer> & buffer,int32_t size)204 int32_t MediaMonitorService::GetInputBuffer(std::shared_ptr<DumpBuffer> &buffer, int32_t size)
205 {
206 if (versionType_ != BETA_VERSION) {
207 return ERROR;
208 }
209
210 if (!IsNeedDump()) {
211 return ERR_ILLEGAL_STATE;
212 }
213
214 FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permissionn denied");
215 unique_lock<mutex> lock(bufferMutex_);
216 if (audioBufferCache_) {
217 audioBufferCache_->RequestBuffer(buffer, size);
218 }
219 return SUCCESS;
220 }
221
InputBufferFilled(const std::string & fileName,uint64_t bufferId,int32_t size)222 int32_t MediaMonitorService::InputBufferFilled(const std::string &fileName, uint64_t bufferId, int32_t size)
223 {
224 if (versionType_ != BETA_VERSION) {
225 return ERROR;
226 }
227
228 FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permissionn denied");
229 FALSE_RETURN_V_MSG_E(audioBufferCache_ != nullptr, ERROR, "buffer cahce nullptr");
230 std::shared_ptr<DumpBuffer> buffer = nullptr;
231 audioBufferCache_->GetBufferById(buffer, bufferId);
232 FALSE_RETURN_V_MSG_E(buffer != nullptr, ERROR, "get buffer falied");
233 audioBufferCache_->SetBufferSize(buffer, size);
234 AddBufferToQueue(fileName, buffer);
235 return SUCCESS;
236 }
237
SetMediaParameters(const std::string & dumpType,const std::string & dumpEnable)238 int32_t MediaMonitorService::SetMediaParameters(const std::string &dumpType, const std::string &dumpEnable)
239 {
240 if (versionType_ != BETA_VERSION) {
241 return ERROR;
242 }
243
244 FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permissionn denied");
245 MEDIA_LOG_D("SetMediaParameters dumpEnable: %{public}s", dumpEnable.c_str());
246 unique_lock<mutex> lock(paramMutex_);
247 if (dumpType != DEFAULT_DUMP_TYPE && dumpType != BETA_DUMP_TYPE) {
248 MEDIA_LOG_E("dumpType:%{public}s isvaild", dumpType.c_str());
249 return ERROR;
250 }
251
252 bool isDumpEnable = (dumpEnable == "true") ? true : false;
253 if (dumpEnable_ == isDumpEnable) {
254 MEDIA_LOG_D("set dumpType is repeate, current enable:%{public}d", dumpEnable_);
255 return ERROR;
256 }
257
258 dumpType_ = dumpType;
259 dumpEnable_ = isDumpEnable;
260 fileFloader_ = (dumpType_ == BETA_DUMP_TYPE) ? BETA_DUMP_DIR : DEFAULT_DUMP_DIR;
261 dumpThreadTime_ = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
262
263 int32_t ret = DumpThreadProcess();
264 return ret;
265 }
266
DumpThreadProcess()267 int32_t MediaMonitorService::DumpThreadProcess()
268 {
269 if (dumpSignal_ != nullptr) {
270 dumpSignal_->isRunning_.store(false);
271 }
272 if (dumpEnable_) {
273 isDumpExit_ = false;
274 if (dumpLoopThread_ && dumpLoopThread_->joinable()) {
275 dumpLoopThread_->join();
276 }
277 dumpBufferWrap_ = std::make_shared<DumpBufferWrap>();
278 if (!dumpBufferWrap_->Open()) {
279 return ERROR;
280 }
281 DumpThreadStart();
282 } else {
283 DumpThreadStop();
284 }
285 return SUCCESS;
286 }
287
DumpThreadStart()288 void MediaMonitorService::DumpThreadStart()
289 {
290 MEDIA_LOG_I("DumpThreadStart enter");
291 DumpFileClear();
292 audioBufferCache_ = std::make_shared<AudioBufferCache>(dumpBufferWrap_);
293 dumpSignal_ = std::make_shared<DumpSignal>();
294 dumpSignal_->isRunning_.store(true);
295 dumpLoopThread_ = std::make_unique<thread>(&MediaMonitorService::DumpLoopFunc, this);
296 pthread_setname_np(dumpLoopThread_->native_handle(), "MDLoopThread");
297 }
298
DumpThreadStop()299 void MediaMonitorService::DumpThreadStop()
300 {
301 MEDIA_LOG_I("DumpThreadStop enter");
302 dumpSignal_->isRunning_.store(false);
303 dumpEnable_ = false;
304 DumpBufferClear();
305 if (dumpType_ == BETA_DUMP_TYPE) {
306 HistoryFilesHandle();
307 AudioEncodeDump();
308 }
309 dumpType_ = DEFAULT_DUMP_TYPE;
310 fileFloader_ = DEFAULT_DUMP_DIR;
311 }
312
DumpThreadExit()313 void MediaMonitorService::DumpThreadExit()
314 {
315 MEDIA_LOG_I("DumpThreadExit enter");
316 dumpEnable_ = false;
317 isDumpExit_ = true;
318 dumpSignal_->isRunning_.store(false);
319 }
320
DumpLoopFunc()321 void MediaMonitorService::DumpLoopFunc()
322 {
323 MEDIA_LOG_I("DumpLoopFunc enter");
324 FALSE_RETURN_MSG(dumpSignal_ != nullptr, "signal is nullptr");
325 FALSE_RETURN_MSG(dumpBufferWrap_ != nullptr, "buffer wrap is nullptr");
326 while (!isDumpExit_) {
327 if (!dumpSignal_->isRunning_.load()) {
328 MEDIA_LOG_I("DumpLoopFunc running exit");
329 break;
330 }
331 std::queue<std::pair<std::string, std::shared_ptr<DumpBuffer>>> tmpBufferQue;
332 {
333 unique_lock<mutex> lock(dumpSignal_->dumpMutex_);
334 dumpSignal_->dumpCond_.wait_for(lock, std::chrono::seconds(WAIT_DUMP_TIMEOUT_S), [this]() {
335 return dumpSignal_->dumpQueue_.size() > 0;
336 });
337 tmpBufferQue.swap(dumpSignal_->dumpQueue_);
338 }
339
340 DumpBufferWrite(tmpBufferQue);
341 int duration = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - dumpThreadTime_;
342 if (dumpType_ == BETA_DUMP_TYPE && duration >= MAX_DUMP_TIME) {
343 MEDIA_LOG_I("dump duration %{public}d", duration);
344 DumpThreadStop();
345 }
346 }
347 if (audioBufferCache_ != nullptr) {
348 audioBufferCache_->Clear();
349 audioBufferCache_ = nullptr;
350 }
351 if (dumpBufferWrap_ != nullptr) {
352 dumpBufferWrap_->Close();
353 dumpBufferWrap_ = nullptr;
354 }
355 }
356
DumpBufferWrite(std::queue<std::pair<std::string,std::shared_ptr<DumpBuffer>>> & bufferQueue)357 void MediaMonitorService::DumpBufferWrite(std::queue<std::pair<std::string, std::shared_ptr<DumpBuffer>>> &bufferQueue)
358 {
359 std::pair<std::string, std::shared_ptr<DumpBuffer>> dumpData;
360 while (!bufferQueue.empty()) {
361 dumpData = bufferQueue.front();
362 bufferQueue.pop();
363 if (dumpEnable_) {
364 WriteBufferFromQueue(dumpData.first, dumpData.second);
365 }
366 AudioBufferRelease(dumpData.second);
367 }
368 }
369
AddBufferToQueue(const std::string & fileName,std::shared_ptr<DumpBuffer> & buffer)370 void MediaMonitorService::AddBufferToQueue(const std::string &fileName, std::shared_ptr<DumpBuffer> &buffer)
371 {
372 MEDIA_LOG_D("AddBufferToQueue enter");
373 FALSE_RETURN_MSG(dumpSignal_ != nullptr, "signal is nullptr");
374 unique_lock<mutex> lock(dumpSignal_->dumpMutex_);
375 if (!dumpSignal_->isRunning_.load()) {
376 MEDIA_LOG_E("not running");
377 return;
378 }
379 dumpSignal_->dumpQueue_.push(std::make_pair(fileName, buffer));
380 dumpSignal_->dumpCond_.notify_all();
381 }
382
WriteBufferFromQueue(const std::string & fileName,std::shared_ptr<DumpBuffer> & buffer)383 void MediaMonitorService::WriteBufferFromQueue(const std::string &fileName, std::shared_ptr<DumpBuffer> &buffer)
384 {
385 MEDIA_LOG_D("WriteBufferFromQueue enter");
386 FALSE_RETURN_MSG(buffer != nullptr, "buffer is nullptr");
387 std::string realFilePath = fileFloader_ + fileName;
388 FALSE_RETURN_MSG(IsRealPath(fileFloader_), "check path failed");
389 FILE *dumpFile = fopen(realFilePath.c_str(), "a");
390 FALSE_RETURN_MSG(dumpFile != nullptr, "pcm file %{public}s open failed", realFilePath.c_str());
391 if (fseek(dumpFile, 0, SEEK_END)) {
392 (void)fclose(dumpFile);
393 return;
394 }
395 int filelen = ftell(dumpFile);
396 if (filelen >= FILE_MAX_SIZE && dumpType_ == BETA_DUMP_TYPE) {
397 (void)fclose(dumpFile);
398 (void)DeleteHistoryFile(realFilePath);
399 dumpFile = fopen(realFilePath.c_str(), "a");
400 FALSE_RETURN_MSG(dumpFile != nullptr, "reopen file failed");
401 }
402 size_t bufferSize = static_cast<size_t>(dumpBufferWrap_->GetSize(buffer.get()));
403 uint8_t *bufferAddr = dumpBufferWrap_->GetAddr(buffer.get());
404 if (bufferAddr == nullptr) {
405 (void)fclose(dumpFile);
406 dumpFile = nullptr;
407 return;
408 }
409 (void)fwrite(bufferAddr, 1, bufferSize, dumpFile);
410 (void)fclose(dumpFile);
411 dumpFile = nullptr;
412 }
413
DumpFileClear()414 void MediaMonitorService::DumpFileClear()
415 {
416 std::error_code errorCode;
417 std::filesystem::directory_iterator iter(BETA_DUMP_DIR, errorCode);
418 if (errorCode) {
419 MEDIA_LOG_E("get file failed");
420 return;
421 }
422
423 for (const auto &elem : iter) {
424 (void)DeleteHistoryFile(elem.path().string());
425 }
426 }
427
DumpBufferClear()428 void MediaMonitorService::DumpBufferClear()
429 {
430 dumpSignal_->dumpMutex_.lock();
431 while (!dumpSignal_->dumpQueue_.empty()) {
432 auto &dumpData = dumpSignal_->dumpQueue_.front();
433 AudioBufferRelease(dumpData.second);
434 dumpSignal_->dumpQueue_.pop();
435 }
436 dumpSignal_->dumpMutex_.unlock();
437 }
438
AudioBufferRelease(std::shared_ptr<DumpBuffer> & buffer)439 void MediaMonitorService::AudioBufferRelease(std::shared_ptr<DumpBuffer> &buffer)
440 {
441 FALSE_RETURN_MSG(buffer != nullptr, "buffer is nullptr");
442 if (audioBufferCache_) {
443 audioBufferCache_->ReleaseBuffer(buffer);
444 }
445 }
446
HistoryFilesHandle()447 void MediaMonitorService::HistoryFilesHandle()
448 {
449 MEDIA_LOG_D("HistoryFilesHandle enter");
450 if (dumpType_ != BETA_DUMP_TYPE) {
451 return;
452 }
453
454 std::error_code errorCode;
455 std::filesystem::directory_iterator iter(fileFloader_, errorCode);
456 if (errorCode) {
457 MEDIA_LOG_E("get file failed");
458 return;
459 }
460 std::vector<std::filesystem::path> mediaFileVecs;
461 for (const auto &elem : iter) {
462 if (std::filesystem::is_regular_file(elem.status())) {
463 mediaFileVecs.emplace_back(elem.path());
464 }
465 }
466 MEDIA_LOG_D("HistoryFilesHandle dumpType %{public}s size: %{public}d",
467 dumpType_.c_str(), (int)mediaFileVecs.size());
468 std::sort(mediaFileVecs.begin(), mediaFileVecs.end(),
469 [](const std::filesystem::path &file1, const std::filesystem::path &file2) {
470 return std::filesystem::file_time_type(std::filesystem::last_write_time(file1)) <
471 std::filesystem::file_time_type(std::filesystem::last_write_time(file2));
472 });
473 while (static_cast<int>(mediaFileVecs.size()) > MAX_FILE_COUNT) {
474 std::string delFilePath = (mediaFileVecs.front()).string();
475 if (DeleteHistoryFile(delFilePath) && !mediaFileVecs.empty()) {
476 mediaFileVecs.erase(mediaFileVecs.begin());
477 }
478 }
479 MEDIA_LOG_I("HistoryFilesHandle exit");
480 }
481
DeleteHistoryFile(const std::string & filePath)482 bool MediaMonitorService::DeleteHistoryFile(const std::string &filePath)
483 {
484 MEDIA_LOG_I("DeleteHistoryFile enter");
485 if (!IsRealPath(filePath)) {
486 return false;
487 }
488 (void)chmod(filePath.c_str(), FILE_MODE);
489 if (remove(filePath.c_str()) != 0) {
490 MEDIA_LOG_E("remove file %{public}s failed ", filePath.c_str());
491 return false;
492 }
493 return true;
494 }
495
ErasePreferredDeviceByType(const PerferredType preferredType)496 int32_t MediaMonitorService::ErasePreferredDeviceByType(const PerferredType preferredType)
497 {
498 FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permission denied");
499 MEDIA_LOG_D("ErasePreferredDeviceByType enter");
500 return audioMemo_.ErasePreferredDeviceByType(preferredType);
501 }
502 } // namespace MediaMonitor
503 } // namespace Media
504 } // namespace OHOS