1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
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 "monitor_client.h"
17 #include "i_media_service.h"
18 #include "media_log.h"
19 #include "media_errors.h"
20 #include "scope_guard.h"
21
22 namespace {
23 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_PLAYER, "MonitorClient" };
24 }
25
26 namespace OHOS {
27 namespace Media {
28 std::mutex MonitorClient::instanceMutex_;
29 std::shared_ptr<MonitorClient> MonitorClient::monitorClient_ = std::make_shared<MonitorClient>();
30 MonitorClient::Destroy MonitorClient::destroy_;
31
32 constexpr uint8_t TIME_INTERVAL = 1; // Heartbeat once per second
33
MonitorClient()34 MonitorClient::MonitorClient()
35 {
36 MEDIA_LOGI("Instances create");
37 }
38
~MonitorClient()39 MonitorClient::~MonitorClient()
40 {
41 MEDIA_LOGI("Instances destroy");
42 clientDestroy_ = true;
43 std::lock_guard<std::mutex> threadLock(thredMutex_);
44 if (clickThread_ != nullptr) {
45 MEDIA_LOGI("clear monitor client thread");
46 if (clickThread_->joinable()) {
47 clickCond_.notify_all();
48 clickThread_->join();
49 }
50 clickThread_.reset();
51 clickThread_ = nullptr;
52 }
53 MEDIA_LOGI("Instances Destroy end");
54 }
55
GetInstance()56 std::shared_ptr<MonitorClient> MonitorClient::GetInstance()
57 {
58 std::lock_guard<std::mutex> lock(instanceMutex_);
59 return monitorClient_;
60 }
61
IsVaildProxy()62 bool MonitorClient::IsVaildProxy()
63 {
64 {
65 std::lock_guard<std::mutex> lock(mutex_);
66 if (!isVaildProxy_) {
67 monitorProxy_ = nullptr;
68 }
69 }
70
71 if (monitorProxy_ == nullptr) {
72 monitorProxy_ = MediaServiceFactory::GetInstance().GetMonitorProxy();
73 CHECK_AND_RETURN_RET_LOG(monitorProxy_ != nullptr, false, "monitorProxy_ is nullptr!");
74 std::lock_guard<std::mutex> lock(mutex_);
75 isVaildProxy_ = true;
76 }
77
78 return true;
79 }
80
StartClick(MonitorClientObject * obj)81 int32_t MonitorClient::StartClick(MonitorClientObject *obj)
82 {
83 MEDIA_LOGI("0x%{public}06" PRIXPTR " StartClick", FAKE_POINTER(obj));
84 {
85 std::lock_guard<std::mutex> lock(mutex_);
86 CHECK_AND_RETURN_RET_LOG(objSet_.count(obj) == 0, MSERR_OK, "It has already been activated");
87 objSet_.insert(obj);
88 if (threadRunning_) {
89 return MSERR_OK;
90 }
91 threadRunning_ = true;
92 }
93
94 std::lock_guard<std::mutex> threadLock(thredMutex_);
95 // The original thread has already exited. Need to recycle resources
96 if (clickThread_ != nullptr) {
97 if (clickThread_->joinable()) {
98 clickThread_->join();
99 }
100 clickThread_.reset();
101 clickThread_ = nullptr;
102 }
103
104 // Start Thread
105 CHECK_AND_RETURN_RET(!clientDestroy_, MSERR_OK);
106 clickThread_ = std::make_unique<std::thread>([this] () -> void { this->ClickThreadCtrl(); });
107
108 return MSERR_OK;
109 }
110
StopClick(MonitorClientObject * obj)111 int32_t MonitorClient::StopClick(MonitorClientObject *obj)
112 {
113 MEDIA_LOGI("0x%{public}06" PRIXPTR " StopClick", FAKE_POINTER(obj));
114 std::lock_guard<std::mutex> lock(mutex_);
115 CHECK_AND_RETURN_RET_LOG(objSet_.count(obj), MSERR_OK, "Not started");
116
117 objSet_.erase(obj);
118 if (objSet_.empty()) {
119 clickCond_.notify_all();
120 }
121
122 return MSERR_OK;
123 }
124
MediaServerDied()125 void MonitorClient::MediaServerDied()
126 {
127 MEDIA_LOGI("MediaServerDied");
128 std::lock_guard<std::mutex> lock(mutex_);
129 objSet_.clear();
130 isVaildProxy_ = false;
131 clickCond_.notify_all();
132 }
133
ClickThread()134 void MonitorClient::ClickThread()
135 {
136 pthread_setname_np(pthread_self(), "OS_MonitorClick");
137 MEDIA_LOGD("ClickThread start");
138
139 CHECK_AND_RETURN_LOG(IsVaildProxy(), "Proxy is invaild!");
140 CHECK_AND_RETURN_LOG(monitorProxy_->EnableMonitor() == MSERR_OK, "failed to EnableMonitor");
141
142 while (true) {
143 {
144 std::unique_lock<std::mutex> lock(mutex_);
145 clickCond_.wait_for(lock, std::chrono::seconds(TIME_INTERVAL), [this] {
146 return objSet_.empty() || !isVaildProxy_ || clientDestroy_;
147 });
148
149 CHECK_AND_RETURN_LOG(!clientDestroy_, "clientDestroy, Normal exit");
150
151 if (objSet_.empty()) {
152 MEDIA_LOGI("0x%{public}06" PRIXPTR " objSet empty.", FAKE_POINTER(this));
153 break;
154 }
155 if (!isVaildProxy_) {
156 monitorProxy_ = nullptr;
157 MEDIA_LOGI("Proxy is invaild.");
158 return;
159 }
160 }
161 CHECK_AND_RETURN_LOG(monitorProxy_ != nullptr, "monitorProxy_ is nullptr!");
162 CHECK_AND_CONTINUE(monitorProxy_->Click() == MSERR_OK);
163 }
164
165 CHECK_AND_RETURN_LOG(IsVaildProxy(), "Proxy is invaild!");
166 CHECK_AND_RETURN_LOG(monitorProxy_->DisableMonitor() == MSERR_OK, "failed to DisableMonitor");
167 MEDIA_LOGI("0x%{public}06" PRIXPTR " ClickThread End", FAKE_POINTER(this));
168 }
169
ClickThreadCtrl()170 void MonitorClient::ClickThreadCtrl()
171 {
172 while (true) {
173 ClickThread();
174 std::unique_lock<std::mutex> lock(mutex_);
175 clickCond_.wait_for(lock, std::chrono::seconds(TIME_INTERVAL), [this] {
176 return objSet_.empty() || clientDestroy_;
177 });
178 if (objSet_.empty() || clientDestroy_) {
179 threadRunning_ = false;
180 MEDIA_LOGI("objSetsize %{public}zu, clientDestroy %{public}d.",
181 objSet_.size(), clientDestroy_.load());
182 return;
183 }
184 }
185 }
186
~Destroy()187 MonitorClient::Destroy::~Destroy()
188 {
189 MEDIA_LOGI("MonitorClient Destroy start");
190 std::shared_ptr<MonitorClient> temp;
191 std::lock_guard<std::mutex> lock(instanceMutex_);
192 CHECK_AND_RETURN_LOG(monitorClient_ != nullptr, "MonitorClient Destroy end");
193 temp = monitorClient_;
194 monitorClient_ = nullptr;
195 MEDIA_LOGI("MonitorClient Destroy end");
196 }
197 } // namespace Media
198 } // namespace OHOS
199