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
Dump(int32_t fd)270 void Cooperate::Dump(int32_t fd)
271 {
272 CALL_DEBUG_ENTER;
273 auto ret = context_.Sender().Send(CooperateEvent(
274 CooperateEventType::DUMP,
275 DumpEvent {
276 .fd = fd
277 }));
278 if (ret != Channel<CooperateEvent>::NO_ERROR) {
279 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
280 }
281 }
282
Loop()283 void Cooperate::Loop()
284 {
285 CALL_DEBUG_ENTER;
286 bool running = true;
287 SetThreadName("OS_Cooperate");
288 LoadMotionDrag();
289
290 while (running) {
291 CooperateEvent event = receiver_.Receive();
292 switch (event.type) {
293 case CooperateEventType::NOOP: {
294 break;
295 }
296 case CooperateEventType::QUIT: {
297 FI_HILOGI("Skip out of loop");
298 running = false;
299 break;
300 }
301 default: {
302 sm_.OnEvent(context_, event);
303 break;
304 }
305 }
306 }
307 }
308
StartWorker()309 void Cooperate::StartWorker()
310 {
311 CALL_DEBUG_ENTER;
312 std::lock_guard guard(lock_);
313 if (!workerStarted_) {
314 workerStarted_ = true;
315 worker_ = std::thread([this] { this->Loop(); });
316 }
317 }
318
StopWorker()319 void Cooperate::StopWorker()
320 {
321 CALL_DEBUG_ENTER;
322 std::lock_guard guard(lock_);
323 if (workerStarted_) {
324 auto ret = context_.Sender().Send(CooperateEvent(CooperateEventType::QUIT));
325 if (ret != Channel<CooperateEvent>::NO_ERROR) {
326 FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
327 }
328 if (worker_.joinable()) {
329 worker_.join();
330 }
331 workerStarted_ = false;
332 }
333 }
334
LoadMotionDrag()335 void Cooperate::LoadMotionDrag()
336 {
337 FI_HILOGI("Load 'MotionDrag' module");
338 IMotionDrag *motionDrag = env_->GetPluginManager().LoadMotionDrag();
339 if (motionDrag == nullptr) {
340 FI_HILOGE("Failed to load motion drag");
341 return;
342 }
343 motionDrag->Enable(context_.EventHandler());
344 }
345
CreateInstance(IContext * env)346 extern "C" ICooperate* CreateInstance(IContext *env)
347 {
348 CHKPP(env);
349 return new Cooperate(env);
350 }
351
DestroyInstance(ICooperate * instance)352 extern "C" void DestroyInstance(ICooperate *instance)
353 {
354 if (instance != nullptr) {
355 delete instance;
356 }
357 }
358 } // namespace Cooperate
359 } // namespace DeviceStatus
360 } // namespace Msdp
361 } // namespace OHOS