• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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<PreferredType,std::shared_ptr<MonitorDeviceInfo>> & preferredDevices)162 int32_t MediaMonitorService::GetAudioRouteMsg(std::map<PreferredType,
163     std::shared_ptr<MonitorDeviceInfo>> &preferredDevices)
164 {
165     FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permission denied");
166     MEDIA_LOG_D("MediaMonitorService GetAudioRouteMsg");
167     return audioMemo_.GetAudioRouteMsg(preferredDevices);
168 }
169 
GetAudioExcludedDevicesMsg(std::map<AudioDeviceUsage,std::vector<std::shared_ptr<MonitorDeviceInfo>>> & excludedDevices)170 int32_t MediaMonitorService::GetAudioExcludedDevicesMsg(std::map<AudioDeviceUsage,
171     std::vector<std::shared_ptr<MonitorDeviceInfo>>> &excludedDevices)
172 {
173     FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permission denied");
174     MEDIA_LOG_D("MediaMonitorService GetAudioExcludedDevicesMsg");
175     return audioMemo_.GetAudioExcludedDevicesMsg(excludedDevices);
176 }
177 
AudioEncodeDump()178 void MediaMonitorService::AudioEncodeDump()
179 {
180     MEDIA_LOG_I("encode pcm start");
181     std::shared_ptr<MediaAudioEncoder> encoder = std::make_shared<MediaAudioEncoder>();
182     encoder->EncodePcmFiles(fileFloader_);
183     encoder = nullptr;
184 }
185 
VerifyIsAudio()186 bool MediaMonitorService::VerifyIsAudio()
187 {
188     int32_t callingUid = IPCSkeleton::GetCallingUid();
189     if (callingUid == AUDIO_UID) {
190         return true;
191     }
192     return false;
193 }
194 
IsNeedDump()195 bool MediaMonitorService::IsNeedDump()
196 {
197     MEDIA_LOG_D("dumpType_:%{public}s, dumpEnable:%{public}d", dumpType_.c_str(), dumpEnable_);
198     if (versionType_ != BETA_VERSION) {
199         return false;
200     }
201     if (dumpType_ == DEFAULT_DUMP_TYPE || dumpType_ == BETA_DUMP_TYPE) {
202         return dumpEnable_;
203     }
204     return false;
205 }
206 
WriteAudioBuffer(const std::string & fileName,void * ptr,size_t size)207 int32_t MediaMonitorService::WriteAudioBuffer(const std::string &fileName, void *ptr, size_t size)
208 {
209     return SUCCESS;
210 }
211 
GetInputBuffer(std::shared_ptr<DumpBuffer> & buffer,int32_t size)212 int32_t MediaMonitorService::GetInputBuffer(std::shared_ptr<DumpBuffer> &buffer, int32_t size)
213 {
214     if (versionType_ != BETA_VERSION) {
215         return ERROR;
216     }
217 
218     if (!IsNeedDump()) {
219         return ERR_ILLEGAL_STATE;
220     }
221 
222     FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permissionn denied");
223     unique_lock<mutex> lock(bufferMutex_);
224     if (audioBufferCache_) {
225         audioBufferCache_->RequestBuffer(buffer, size);
226     }
227     return SUCCESS;
228 }
229 
InputBufferFilled(const std::string & fileName,uint64_t bufferId,int32_t size)230 int32_t MediaMonitorService::InputBufferFilled(const std::string &fileName, uint64_t bufferId, int32_t size)
231 {
232     if (versionType_ != BETA_VERSION) {
233         return ERROR;
234     }
235 
236     FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permissionn denied");
237     FALSE_RETURN_V_MSG_E(audioBufferCache_ != nullptr, ERROR, "buffer cahce nullptr");
238     std::shared_ptr<DumpBuffer> buffer = nullptr;
239     audioBufferCache_->GetBufferById(buffer, bufferId);
240     FALSE_RETURN_V_MSG_E(buffer != nullptr, ERROR, "get buffer falied");
241     audioBufferCache_->SetBufferSize(buffer, size);
242     AddBufferToQueue(fileName, buffer);
243     return SUCCESS;
244 }
245 
GetPcmDumpStatus(int32_t & dumpEnable)246 int32_t MediaMonitorService::GetPcmDumpStatus(int32_t &dumpEnable)
247 {
248     if (versionType_ != BETA_VERSION) {
249         return ERROR;
250     }
251 
252     FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permissionn denied");
253     dumpEnable = dumpEnable_ ? 1 : 0;
254     return SUCCESS;
255 }
256 
SetMediaParameters(const std::string & dumpType,const std::string & dumpEnable)257 int32_t MediaMonitorService::SetMediaParameters(const std::string &dumpType, const std::string &dumpEnable)
258 {
259     if (versionType_ != BETA_VERSION) {
260         return ERROR;
261     }
262 
263     FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permissionn denied");
264     MEDIA_LOG_D("SetMediaParameters dumpEnable: %{public}s", dumpEnable.c_str());
265     unique_lock<mutex> lock(paramMutex_);
266     if (dumpType != DEFAULT_DUMP_TYPE && dumpType != BETA_DUMP_TYPE) {
267         MEDIA_LOG_E("dumpType:%{public}s isvaild", dumpType.c_str());
268         return ERROR;
269     }
270 
271     bool isDumpEnable = (dumpEnable == "true") ? true : false;
272     if (dumpEnable_ == isDumpEnable) {
273         MEDIA_LOG_D("set dumpType is repeate, current enable:%{public}d", dumpEnable_);
274         return ERROR;
275     }
276 
277     dumpType_ = dumpType;
278     dumpEnable_ = isDumpEnable;
279     fileFloader_ = (dumpType_ == BETA_DUMP_TYPE) ? BETA_DUMP_DIR : DEFAULT_DUMP_DIR;
280     dumpThreadTime_ = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
281 
282     int32_t ret = DumpThreadProcess();
283     return ret;
284 }
285 
DumpThreadProcess()286 int32_t MediaMonitorService::DumpThreadProcess()
287 {
288     if (dumpSignal_ != nullptr) {
289         dumpSignal_->isRunning_.store(false);
290     }
291     if (dumpEnable_) {
292         isDumpExit_ = false;
293         if (dumpLoopThread_ && dumpLoopThread_->joinable()) {
294             dumpLoopThread_->join();
295         }
296         dumpBufferWrap_ = std::make_shared<DumpBufferWrap>();
297         if (!dumpBufferWrap_->Open()) {
298             return ERROR;
299         }
300         DumpThreadStart();
301     } else {
302         DumpThreadStop();
303     }
304     return SUCCESS;
305 }
306 
DumpThreadStart()307 void MediaMonitorService::DumpThreadStart()
308 {
309     MEDIA_LOG_I("DumpThreadStart enter");
310     DumpFileClear();
311     audioBufferCache_ = std::make_shared<AudioBufferCache>(dumpBufferWrap_);
312     dumpSignal_ = std::make_shared<DumpSignal>();
313     dumpSignal_->isRunning_.store(true);
314     dumpLoopThread_ = std::make_unique<thread>(&MediaMonitorService::DumpLoopFunc, this);
315     pthread_setname_np(dumpLoopThread_->native_handle(), "MDLoopThread");
316 }
317 
DumpThreadStop()318 void MediaMonitorService::DumpThreadStop()
319 {
320     MEDIA_LOG_I("DumpThreadStop enter");
321     dumpSignal_->isRunning_.store(false);
322     dumpEnable_ = false;
323     DumpBufferClear();
324     if (dumpType_ == BETA_DUMP_TYPE) {
325         HistoryFilesHandle();
326         AudioEncodeDump();
327     }
328     dumpType_ = DEFAULT_DUMP_TYPE;
329     fileFloader_ = DEFAULT_DUMP_DIR;
330 }
331 
DumpThreadExit()332 void MediaMonitorService::DumpThreadExit()
333 {
334     MEDIA_LOG_I("DumpThreadExit enter");
335     dumpEnable_ = false;
336     isDumpExit_ = true;
337     dumpSignal_->isRunning_.store(false);
338 }
339 
DumpLoopFunc()340 void MediaMonitorService::DumpLoopFunc()
341 {
342     MEDIA_LOG_I("DumpLoopFunc enter");
343     FALSE_RETURN_MSG(dumpSignal_ != nullptr, "signal is nullptr");
344     FALSE_RETURN_MSG(dumpBufferWrap_ != nullptr, "buffer wrap is nullptr");
345     while (!isDumpExit_) {
346         if (!dumpSignal_->isRunning_.load()) {
347             MEDIA_LOG_I("DumpLoopFunc running exit");
348             break;
349         }
350         std::queue<std::pair<std::string, std::shared_ptr<DumpBuffer>>> tmpBufferQue;
351         {
352             unique_lock<mutex> lock(dumpSignal_->dumpMutex_);
353             dumpSignal_->dumpCond_.wait_for(lock, std::chrono::seconds(WAIT_DUMP_TIMEOUT_S), [this]() {
354                 return dumpSignal_->dumpQueue_.size() > 0;
355             });
356             tmpBufferQue.swap(dumpSignal_->dumpQueue_);
357         }
358 
359         DumpBufferWrite(tmpBufferQue);
360         int duration = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) - dumpThreadTime_;
361         if (dumpType_ == BETA_DUMP_TYPE && duration >= MAX_DUMP_TIME) {
362             MEDIA_LOG_I("dump duration %{public}d", duration);
363             DumpThreadStop();
364         }
365     }
366     if (audioBufferCache_ != nullptr) {
367         audioBufferCache_->Clear();
368         audioBufferCache_ = nullptr;
369     }
370     if (dumpBufferWrap_ != nullptr) {
371         dumpBufferWrap_->Close();
372         dumpBufferWrap_ = nullptr;
373     }
374 }
375 
DumpBufferWrite(std::queue<std::pair<std::string,std::shared_ptr<DumpBuffer>>> & bufferQueue)376 void MediaMonitorService::DumpBufferWrite(std::queue<std::pair<std::string, std::shared_ptr<DumpBuffer>>> &bufferQueue)
377 {
378     std::pair<std::string, std::shared_ptr<DumpBuffer>> dumpData;
379     while (!bufferQueue.empty()) {
380         dumpData = bufferQueue.front();
381         bufferQueue.pop();
382         if (dumpEnable_) {
383             WriteBufferFromQueue(dumpData.first, dumpData.second);
384         }
385         AudioBufferRelease(dumpData.second);
386     }
387 }
388 
AddBufferToQueue(const std::string & fileName,std::shared_ptr<DumpBuffer> & buffer)389 void MediaMonitorService::AddBufferToQueue(const std::string &fileName, std::shared_ptr<DumpBuffer> &buffer)
390 {
391     MEDIA_LOG_D("AddBufferToQueue enter");
392     FALSE_RETURN_MSG(dumpSignal_ != nullptr, "signal is nullptr");
393     unique_lock<mutex> lock(dumpSignal_->dumpMutex_);
394     if (!dumpSignal_->isRunning_.load()) {
395         MEDIA_LOG_E("not running");
396         return;
397     }
398     dumpSignal_->dumpQueue_.push(std::make_pair(fileName, buffer));
399     dumpSignal_->dumpCond_.notify_all();
400 }
401 
WriteBufferFromQueue(const std::string & fileName,std::shared_ptr<DumpBuffer> & buffer)402 void MediaMonitorService::WriteBufferFromQueue(const std::string &fileName, std::shared_ptr<DumpBuffer> &buffer)
403 {
404     MEDIA_LOG_D("WriteBufferFromQueue enter");
405     FALSE_RETURN_MSG(buffer != nullptr, "buffer is nullptr");
406     std::string realFilePath = fileFloader_ + fileName;
407     FALSE_RETURN_MSG(IsRealPath(fileFloader_), "check path failed");
408     FILE *dumpFile = fopen(realFilePath.c_str(), "a");
409     FALSE_RETURN_MSG(dumpFile != nullptr, "pcm file %{public}s open failed", realFilePath.c_str());
410     if (fseek(dumpFile, 0, SEEK_END)) {
411         (void)fclose(dumpFile);
412         return;
413     }
414     int filelen = ftell(dumpFile);
415     if (filelen >= FILE_MAX_SIZE && dumpType_ == BETA_DUMP_TYPE) {
416         (void)fclose(dumpFile);
417         (void)DeleteHistoryFile(realFilePath);
418         dumpFile = fopen(realFilePath.c_str(), "a");
419         FALSE_RETURN_MSG(dumpFile != nullptr, "reopen file failed");
420     }
421     size_t bufferSize = static_cast<size_t>(dumpBufferWrap_->GetSize(buffer.get()));
422     uint8_t *bufferAddr = dumpBufferWrap_->GetAddr(buffer.get());
423     if (bufferAddr == nullptr) {
424         (void)fclose(dumpFile);
425         dumpFile = nullptr;
426         return;
427     }
428     (void)fwrite(bufferAddr, 1, bufferSize, dumpFile);
429     (void)fclose(dumpFile);
430     dumpFile = nullptr;
431 }
432 
DumpFileClear()433 void MediaMonitorService::DumpFileClear()
434 {
435     std::error_code errorCode;
436     std::filesystem::directory_iterator iter(BETA_DUMP_DIR, errorCode);
437     if (errorCode) {
438         MEDIA_LOG_E("get file failed");
439         return;
440     }
441 
442     for (const auto &elem : iter) {
443         (void)DeleteHistoryFile(elem.path().string());
444     }
445 }
446 
DumpBufferClear()447 void MediaMonitorService::DumpBufferClear()
448 {
449     dumpSignal_->dumpMutex_.lock();
450     while (!dumpSignal_->dumpQueue_.empty()) {
451         auto &dumpData = dumpSignal_->dumpQueue_.front();
452         AudioBufferRelease(dumpData.second);
453         dumpSignal_->dumpQueue_.pop();
454     }
455     dumpSignal_->dumpMutex_.unlock();
456 }
457 
AudioBufferRelease(std::shared_ptr<DumpBuffer> & buffer)458 void MediaMonitorService::AudioBufferRelease(std::shared_ptr<DumpBuffer> &buffer)
459 {
460     FALSE_RETURN_MSG(buffer != nullptr, "buffer is nullptr");
461     if (audioBufferCache_) {
462         audioBufferCache_->ReleaseBuffer(buffer);
463     }
464 }
465 
HistoryFilesHandle()466 void MediaMonitorService::HistoryFilesHandle()
467 {
468     MEDIA_LOG_D("HistoryFilesHandle enter");
469     if (dumpType_ != BETA_DUMP_TYPE) {
470         return;
471     }
472 
473     std::error_code errorCode;
474     std::filesystem::directory_iterator iter(fileFloader_, errorCode);
475     if (errorCode) {
476         MEDIA_LOG_E("get file failed");
477         return;
478     }
479     std::vector<std::filesystem::path> mediaFileVecs;
480     for (const auto &elem : iter) {
481         if (std::filesystem::is_regular_file(elem.status())) {
482             mediaFileVecs.emplace_back(elem.path());
483         }
484     }
485     MEDIA_LOG_D("HistoryFilesHandle dumpType %{public}s size: %{public}d",
486         dumpType_.c_str(), (int)mediaFileVecs.size());
487     std::sort(mediaFileVecs.begin(), mediaFileVecs.end(),
488         [](const std::filesystem::path &file1, const std::filesystem::path &file2) {
489             return std::filesystem::file_time_type(std::filesystem::last_write_time(file1)) <
490             std::filesystem::file_time_type(std::filesystem::last_write_time(file2));
491     });
492     while (static_cast<int>(mediaFileVecs.size()) > MAX_FILE_COUNT) {
493         std::string delFilePath = (mediaFileVecs.front()).string();
494         if (DeleteHistoryFile(delFilePath) && !mediaFileVecs.empty()) {
495             mediaFileVecs.erase(mediaFileVecs.begin());
496         }
497     }
498     MEDIA_LOG_I("HistoryFilesHandle exit");
499 }
500 
DeleteHistoryFile(const std::string & filePath)501 bool MediaMonitorService::DeleteHistoryFile(const std::string &filePath)
502 {
503     MEDIA_LOG_I("DeleteHistoryFile enter");
504     if (!IsRealPath(filePath)) {
505         return false;
506     }
507     (void)chmod(filePath.c_str(), FILE_MODE);
508     if (remove(filePath.c_str()) != 0) {
509         MEDIA_LOG_E("remove file %{public}s failed ", filePath.c_str());
510         return false;
511     }
512     return true;
513 }
514 
ErasePreferredDeviceByType(const PreferredType preferredType)515 int32_t MediaMonitorService::ErasePreferredDeviceByType(const PreferredType preferredType)
516 {
517     FALSE_RETURN_V_MSG_E(VerifyIsAudio(), ERROR, "client permission denied");
518     MEDIA_LOG_D("ErasePreferredDeviceByType enter");
519     return audioMemo_.ErasePreferredDeviceByType(preferredType);
520 }
521 } // namespace MediaMonitor
522 } // namespace Media
523 } // namespace OHOS