1 /*
2 * Copyright (c) 2023 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 "cooperate.h"
17
18 #ifdef ENABLE_PERFORMANCE_CHECK
19 #include <sstream>
20 #include "utility.h"
21 #endif // ENABLE_PERFORMANCE_CHECK
22
23 #include "devicestatus_define.h"
24
25 #undef LOG_TAG
26 #define LOG_TAG "Cooperate"
27
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace Cooperate {
32
Cooperate(IContext *env)33 Cooperate::Cooperate(IContext *env)
34 : env_(env), context_(env), sm_(env)
35 {
36 auto [sender, receiver] = Channel<CooperateEvent>::OpenChannel();
37 receiver_ = receiver;
38 receiver_.Enable();
39 context_.AttachSender(sender);
40 context_.Enable();
41 StartWorker();
42 }
43
~Cooperate()44 Cooperate::~Cooperate()
45 {
46 StopWorker();
47 context_.Disable();
48 }
49
AddObserver(std::shared_ptr<ICooperateObserver> observer)50 void Cooperate::AddObserver(std::shared_ptr<ICooperateObserver> observer)
51 {
52 CALL_DEBUG_ENTER;
53 auto ret = context_.Sender().Send(CooperateEvent(
54 CooperateEventType::ADD_OBSERVER,
55 AddObserverEvent {
56 .observer = observer
57 }));
58 if (ret != Channel<CooperateEvent>::NO_ERROR) {
59 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
60 }
61 }
62
RemoveObserver(std::shared_ptr<ICooperateObserver> observer)63 void Cooperate::RemoveObserver(std::shared_ptr<ICooperateObserver> observer)
64 {
65 CALL_DEBUG_ENTER;
66 auto ret = context_.Sender().Send(CooperateEvent(
67 CooperateEventType::REMOVE_OBSERVER,
68 RemoveObserverEvent {
69 .observer = observer
70 }));
71 if (ret != Channel<CooperateEvent>::NO_ERROR) {
72 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
73 }
74 }
75
RegisterListener(int32_t pid)76 int32_t Cooperate::RegisterListener(int32_t pid)
77 {
78 CALL_DEBUG_ENTER;
79 auto ret = context_.Sender().Send(CooperateEvent(
80 CooperateEventType::REGISTER_LISTENER,
81 RegisterListenerEvent {
82 .pid = pid
83 }));
84 if (ret != Channel<CooperateEvent>::NO_ERROR) {
85 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
86 }
87 return RET_OK;
88 }
89
UnregisterListener(int32_t pid)90 int32_t Cooperate::UnregisterListener(int32_t pid)
91 {
92 CALL_DEBUG_ENTER;
93 auto ret = context_.Sender().Send(CooperateEvent(
94 CooperateEventType::UNREGISTER_LISTENER,
95 UnregisterListenerEvent {
96 .pid = pid
97 }));
98 if (ret != Channel<CooperateEvent>::NO_ERROR) {
99 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
100 }
101 return RET_OK;
102 }
103
RegisterHotAreaListener(int32_t pid)104 int32_t Cooperate::RegisterHotAreaListener(int32_t pid)
105 {
106 CALL_DEBUG_ENTER;
107 auto ret = context_.Sender().Send(CooperateEvent(
108 CooperateEventType::REGISTER_HOTAREA_LISTENER,
109 RegisterHotareaListenerEvent {
110 .pid = pid
111 }));
112 if (ret != Channel<CooperateEvent>::NO_ERROR) {
113 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
114 }
115 return RET_OK;
116 }
117
UnregisterHotAreaListener(int32_t pid)118 int32_t Cooperate::UnregisterHotAreaListener(int32_t pid)
119 {
120 CALL_DEBUG_ENTER;
121 auto ret = context_.Sender().Send(CooperateEvent(
122 CooperateEventType::UNREGISTER_HOTAREA_LISTENER,
123 UnregisterHotareaListenerEvent {
124 .pid = pid
125 }));
126 if (ret != Channel<CooperateEvent>::NO_ERROR) {
127 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
128 }
129 return RET_OK;
130 }
131
Enable(int32_t tokenId, int32_t pid, int32_t userData)132 int32_t Cooperate::Enable(int32_t tokenId, int32_t pid, int32_t userData)
133 {
134 CALL_DEBUG_ENTER;
135 auto ret = context_.Sender().Send(CooperateEvent(
136 CooperateEventType::ENABLE,
137 EnableCooperateEvent {
138 .tokenId = tokenId,
139 .pid = pid,
140 .userData = userData,
141 }));
142 if (ret != Channel<CooperateEvent>::NO_ERROR) {
143 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
144 }
145 return RET_OK;
146 }
147
Disable(int32_t pid, int32_t userData)148 int32_t Cooperate::Disable(int32_t pid, int32_t userData)
149 {
150 CALL_DEBUG_ENTER;
151 auto ret = context_.Sender().Send(CooperateEvent(
152 CooperateEventType::DISABLE,
153 DisableCooperateEvent {
154 .pid = pid,
155 .userData = userData,
156 }));
157 if (ret != Channel<CooperateEvent>::NO_ERROR) {
158 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
159 }
160 return RET_OK;
161 }
162
Start(int32_t pid, int32_t userData, const std::string &remoteNetworkId, int32_t startDeviceId)163 int32_t Cooperate::Start(int32_t pid, int32_t userData, const std::string &remoteNetworkId, int32_t startDeviceId)
164 {
165 CALL_DEBUG_ENTER;
166
167 #ifdef ENABLE_PERFORMANCE_CHECK
168 std::ostringstream ss;
169 ss << "start_cooperation_with_" << Utility::Anonymize(remoteNetworkId).c_str();
170 context_.StartTrace(ss.str());
171 #endif // ENABLE_PERFORMANCE_CHECK
172 StartCooperateEvent event {
173 .pid = pid,
174 .userData = userData,
175 .remoteNetworkId = remoteNetworkId,
176 .startDeviceId = startDeviceId,
177 .errCode = std::make_shared<std::promise<int32_t>>(),
178 };
179 auto errCode = event.errCode->get_future();
180 auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::START, event));
181 if (ret != Channel<CooperateEvent>::NO_ERROR) {
182 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
183 }
184 return errCode.get();
185 }
186
Stop(int32_t pid, int32_t userData, bool isUnchained)187 int32_t Cooperate::Stop(int32_t pid, int32_t userData, bool isUnchained)
188 {
189 CALL_DEBUG_ENTER;
190 auto ret = context_.Sender().Send(CooperateEvent(
191 CooperateEventType::STOP,
192 StopCooperateEvent {
193 .pid = pid,
194 .userData = userData,
195 .isUnchained = isUnchained,
196 }));
197 if (ret != Channel<CooperateEvent>::NO_ERROR) {
198 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
199 }
200 return RET_OK;
201 }
202
GetCooperateState(int32_t pid, int32_t userData, const std::string &networkId)203 int32_t Cooperate::GetCooperateState(int32_t pid, int32_t userData, const std::string &networkId)
204 {
205 CALL_DEBUG_ENTER;
206 auto ret = context_.Sender().Send(CooperateEvent(
207 CooperateEventType::GET_COOPERATE_STATE,
208 GetCooperateStateEvent {
209 .pid = pid,
210 .userData = userData,
211 .networkId = networkId,
212 }));
213 if (ret != Channel<CooperateEvent>::NO_ERROR) {
214 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
215 }
216 return RET_OK;
217 }
218
RegisterEventListener(int32_t pid, const std::string &networkId)219 int32_t Cooperate::RegisterEventListener(int32_t pid, const std::string &networkId)
220 {
221 CALL_DEBUG_ENTER;
222 auto ret = context_.Sender().Send(CooperateEvent(
223 CooperateEventType::REGISTER_EVENT_LISTENER,
224 RegisterEventListenerEvent {
225 .pid = pid,
226 .networkId = networkId,
227 }));
228 if (ret != Channel<CooperateEvent>::NO_ERROR) {
229 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
230 }
231 return RET_OK;
232 }
233
UnregisterEventListener(int32_t pid, const std::string &networkId)234 int32_t Cooperate::UnregisterEventListener(int32_t pid, const std::string &networkId)
235 {
236 CALL_DEBUG_ENTER;
237 auto ret = context_.Sender().Send(CooperateEvent(
238 CooperateEventType::UNREGISTER_EVENT_LISTENER,
239 UnregisterEventListenerEvent {
240 .pid = pid,
241 .networkId = networkId,
242 }));
243 if (ret != Channel<CooperateEvent>::NO_ERROR) {
244 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
245 }
246 return RET_OK;
247 }
248
GetCooperateState(const std::string &udId, bool &state)249 int32_t Cooperate::GetCooperateState(const std::string &udId, bool &state)
250 {
251 CALL_DEBUG_ENTER;
252 state = sm_.IsCooperateEnable();
253 return RET_OK;
254 }
255
Update(uint32_t mask, uint32_t flag)256 int32_t Cooperate::Update(uint32_t mask, uint32_t flag)
257 {
258 auto ret = context_.Sender().Send(CooperateEvent(
259 CooperateEventType::UPDATE_COOPERATE_FLAG,
260 UpdateCooperateFlagEvent {
261 .mask = mask,
262 .flag = flag,
263 }));
264 if (ret != Channel<CooperateEvent>::NO_ERROR) {
265 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
266 }
267 return RET_OK;
268 }
269
SetDamplingCoefficient(uint32_t direction, double coefficient)270 int32_t Cooperate::SetDamplingCoefficient(uint32_t direction, double coefficient)
271 {
272 auto ret = context_.Sender().Send(CooperateEvent(
273 CooperateEventType::SET_DAMPLING_COEFFICIENT,
274 SetDamplingCoefficientEvent {
275 .direction = direction,
276 .coefficient = coefficient,
277 }));
278 if (ret != Channel<CooperateEvent>::NO_ERROR) {
279 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
280 }
281 return RET_OK;
282 }
283
Dump(int32_t fd)284 void Cooperate::Dump(int32_t fd)
285 {
286 CALL_DEBUG_ENTER;
287 auto ret = context_.Sender().Send(CooperateEvent(
288 CooperateEventType::DUMP,
289 DumpEvent {
290 .fd = fd
291 }));
292 if (ret != Channel<CooperateEvent>::NO_ERROR) {
293 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
294 }
295 }
296
Loop()297 void Cooperate::Loop()
298 {
299 CALL_DEBUG_ENTER;
300 bool running = true;
301 SetThreadName("OS_Cooperate");
302 LoadMotionDrag();
303
304 while (running) {
305 CooperateEvent event = receiver_.Receive();
306 switch (event.type) {
307 case CooperateEventType::NOOP: {
308 break;
309 }
310 case CooperateEventType::QUIT: {
311 FI_HILOGI("Skip out of loop");
312 running = false;
313 break;
314 }
315 case CooperateEventType::SET_DAMPLING_COEFFICIENT: {
316 SetDamplingCoefficient(event);
317 break;
318 }
319 default: {
320 sm_.OnEvent(context_, event);
321 break;
322 }
323 }
324 }
325 }
326
StartWorker()327 void Cooperate::StartWorker()
328 {
329 CALL_DEBUG_ENTER;
330 std::lock_guard guard(lock_);
331 if (!workerStarted_) {
332 workerStarted_ = true;
333 worker_ = std::thread([this] { this->Loop(); });
334 }
335 }
336
StopWorker()337 void Cooperate::StopWorker()
338 {
339 CALL_DEBUG_ENTER;
340 std::lock_guard guard(lock_);
341 if (workerStarted_) {
342 auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::QUIT));
343 if (ret != Channel<CooperateEvent>::NO_ERROR) {
344 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
345 }
346 if (worker_.joinable()) {
347 worker_.join();
348 }
349 workerStarted_ = false;
350 }
351 }
352
LoadMotionDrag()353 void Cooperate::LoadMotionDrag()
354 {
355 FI_HILOGI("Load 'MotionDrag' module");
356 IMotionDrag *motionDrag = env_->GetPluginManager().LoadMotionDrag();
357 if (motionDrag == nullptr) {
358 FI_HILOGE("Failed to load motion drag");
359 return;
360 }
361 motionDrag->Enable(context_.EventHandler());
362 }
363
SetDamplingCoefficient(const CooperateEvent &event)364 void Cooperate::SetDamplingCoefficient(const CooperateEvent &event)
365 {
366 SetDamplingCoefficientEvent notice = std::get<SetDamplingCoefficientEvent>(event.event);
367 context_.inputEventBuilder_.SetDamplingCoefficient(notice.direction, notice.coefficient);
368 }
369
CreateInstance(IContext *env)370 extern "C" ICooperate* CreateInstance(IContext *env)
371 {
372 CHKPP(env);
373 return new Cooperate(env);
374 }
375
DestroyInstance(ICooperate *instance)376 extern "C" void DestroyInstance(ICooperate *instance)
377 {
378 if (instance != nullptr) {
379 delete instance;
380 }
381 }
382 } // namespace Cooperate
383 } // namespace DeviceStatus
384 } // namespace Msdp
385 } // namespace OHOS