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