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 "dsoftbus_handler.h"
17
18#include "ipc_skeleton.h"
19#include "token_setproc.h"
20
21#include "device.h"
22#include "devicestatus_define.h"
23#include "utility.h"
24
25#undef LOG_TAG
26#define LOG_TAG "DSoftbusHandler"
27
28namespace OHOS {
29namespace Msdp {
30namespace DeviceStatus {
31namespace Cooperate {
32constexpr int32_t MAX_INPUT_DEV_NUM { 100 };
33constexpr int32_t INVALID_DEVICE_ID { -1 };
34
35DSoftbusHandler::DSoftbusHandler(IContext *env)
36    : env_(env)
37{
38    handles_ = {
39        { static_cast<int32_t>(MessageId::DSOFTBUS_START_COOPERATE),
40        [this] (const std::string &networkId, NetPacket &packet) {
41            this->OnStartCooperate(networkId, packet);}},
42        { static_cast<int32_t>(MessageId::DSOFTBUS_STOP_COOPERATE),
43        [this] (const std::string &networkId, NetPacket &packet) {
44            this->OnStopCooperate(networkId, packet);}},
45        { static_cast<int32_t>(MessageId::DSOFTBUS_COME_BACK),
46        [this] (const std::string &networkId, NetPacket &packet) {
47            this->OnComeBack(networkId, packet);}},
48        { static_cast<int32_t>(MessageId::DSOFTBUS_RELAY_COOPERATE),
49        [this] (const std::string &networkId, NetPacket &packet) {
50            this->OnRelayCooperate(networkId, packet);}},
51        { static_cast<int32_t>(MessageId::DSOFTBUS_RELAY_COOPERATE_FINISHED),
52        [this] (const std::string &networkId, NetPacket &packet) {
53            this->OnRelayCooperateFinish(networkId, packet);}},
54        { static_cast<int32_t>(MessageId::DSOFTBUS_SUBSCRIBE_MOUSE_LOCATION),
55        [this] (const std::string &networkId, NetPacket &packet) {
56            this->OnSubscribeMouseLocation(networkId, packet);}},
57        { static_cast<int32_t>(MessageId::DSOFTBUS_UNSUBSCRIBE_MOUSE_LOCATION),
58        [this] (const std::string &networkId, NetPacket &packet) {
59            this->OnUnSubscribeMouseLocation(networkId, packet);}},
60        { static_cast<int32_t>(MessageId::DSOFTBUS_REPLY_SUBSCRIBE_MOUSE_LOCATION),
61        [this] (const std::string &networkId, NetPacket &packet) {
62            this->OnReplySubscribeLocation(networkId, packet);}},
63        { static_cast<int32_t>(MessageId::DSOFTBUS_REPLY_UNSUBSCRIBE_MOUSE_LOCATION),
64        [this] (const std::string &networkId, NetPacket &packet) {
65            this->OnReplyUnSubscribeLocation(networkId, packet);}},
66        { static_cast<int32_t>(MessageId::DSOFTBUS_MOUSE_LOCATION),
67        [this] (const std::string &networkId, NetPacket &packet) {
68            this->OnRemoteMouseLocation(networkId, packet);}},
69        { static_cast<int32_t>(MessageId::DSOFTBUS_INPUT_DEV_SYNC),
70        [this] (const std::string &networkId, NetPacket &packet) {
71            this->OnRemoteInputDevice(networkId, packet);}},
72        { static_cast<int32_t>(MessageId::DSOFTBUS_INPUT_DEV_HOT_PLUG),
73        [this] (const std::string &networkId, NetPacket &packet) {
74            this->OnRemoteHotPlug(networkId, packet);}}
75    };
76    observer_ = std::make_shared<DSoftbusObserver>(*this);
77    CHKPV(env_);
78    env_->GetDSoftbus().AddObserver(observer_);
79}
80
81DSoftbusHandler::~DSoftbusHandler()
82{
83    CHKPV(env_);
84    env_->GetDSoftbus().RemoveObserver(observer_);
85}
86
87void DSoftbusHandler::AttachSender(Channel<CooperateEvent>::Sender sender)
88{
89    CALL_DEBUG_ENTER;
90    std::lock_guard guard(lock_);
91    sender_ = sender;
92}
93
94int32_t DSoftbusHandler::OpenSession(const std::string &networkId)
95{
96    CALL_INFO_TRACE;
97    auto tokenId = OHOS::IPCSkeleton::GetCallingTokenID();
98    int ret = SetFirstCallerTokenID(tokenId);
99    if (ret != RET_OK) {
100        FI_HILOGW("Failed to SetFirstCallerTokenID, ret:%{public}d", ret);
101    }
102    return env_->GetDSoftbus().OpenSession(networkId);
103}
104
105void DSoftbusHandler::CloseSession(const std::string &networkId)
106{
107    CALL_INFO_TRACE;
108    env_->GetDSoftbus().CloseSession(networkId);
109}
110
111void DSoftbusHandler::CloseAllSessions()
112{
113    CALL_INFO_TRACE;
114    env_->GetDSoftbus().CloseAllSessions();
115}
116
117int32_t DSoftbusHandler::StartCooperate(const std::string &networkId, const DSoftbusStartCooperate &event)
118{
119    CALL_INFO_TRACE;
120    NetPacket packet(MessageId::DSOFTBUS_START_COOPERATE);
121    packet << event.originNetworkId << event.cursorPos.x
122        << event.cursorPos.y << event.success << event.extra.priv;
123    if (packet.ChkRWError()) {
124        FI_HILOGE("Failed to write data packet");
125        return RET_ERR;
126    }
127    int32_t ret = env_->GetDSoftbus().SendPacket(networkId, packet);
128    if (ret != RET_OK) {
129        OnCommunicationFailure(networkId);
130    }
131    return ret;
132}
133
134int32_t DSoftbusHandler::StopCooperate(const std::string &networkId, const DSoftbusStopCooperate &event)
135{
136    CALL_INFO_TRACE;
137    NetPacket packet(MessageId::DSOFTBUS_STOP_COOPERATE);
138    int32_t ret = env_->GetDSoftbus().SendPacket(networkId, packet);
139    if (ret != RET_OK) {
140        OnCommunicationFailure(networkId);
141    }
142    return ret;
143}
144
145int32_t DSoftbusHandler::ComeBack(const std::string &networkId, const DSoftbusComeBack &event)
146{
147    CALL_INFO_TRACE;
148    NetPacket packet(MessageId::DSOFTBUS_COME_BACK);
149    packet << event.originNetworkId << event.cursorPos.x << event.cursorPos.y << event.extra.priv;
150    if (packet.ChkRWError()) {
151        FI_HILOGE("Failed to write data packet");
152        return RET_ERR;
153    }
154    int32_t ret = env_->GetDSoftbus().SendPacket(networkId, packet);
155    if (ret != RET_OK) {
156        OnCommunicationFailure(networkId);
157    }
158    return ret;
159}
160
161int32_t DSoftbusHandler::RelayCooperate(const std::string &networkId, const DSoftbusRelayCooperate &event)
162{
163    CALL_INFO_TRACE;
164    NetPacket packet(MessageId::DSOFTBUS_RELAY_COOPERATE);
165    packet << event.targetNetworkId;
166    if (packet.ChkRWError()) {
167        FI_HILOGE("Failed to write data packet");
168        return RET_ERR;
169    }
170    int32_t ret = env_->GetDSoftbus().SendPacket(networkId, packet);
171    if (ret != RET_OK) {
172        OnCommunicationFailure(networkId);
173    }
174    return ret;
175}
176
177int32_t DSoftbusHandler::RelayCooperateFinish(const std::string &networkId, const DSoftbusRelayCooperateFinished &event)
178{
179    CALL_INFO_TRACE;
180    NetPacket packet(MessageId::DSOFTBUS_RELAY_COOPERATE_FINISHED);
181    packet << event.targetNetworkId << event.normal;
182    if (packet.ChkRWError()) {
183        FI_HILOGE("Failed to write data packet");
184        return RET_ERR;
185    }
186    int32_t ret = env_->GetDSoftbus().SendPacket(networkId, packet);
187    if (ret != RET_OK) {
188        OnCommunicationFailure(networkId);
189    }
190    return ret;
191}
192
193std::string DSoftbusHandler::GetLocalNetworkId()
194{
195    return IDSoftbusAdapter::GetLocalNetworkId();
196}
197
198void DSoftbusHandler::OnBind(const std::string &networkId)
199{
200    FI_HILOGI("Bind to \'%{public}s\'", Utility::Anonymize(networkId).c_str());
201    SendEvent(CooperateEvent(
202        CooperateEventType::DSOFTBUS_SESSION_OPENED,
203        DSoftbusSessionOpened {
204            .networkId = networkId
205        }));
206}
207
208void DSoftbusHandler::OnShutdown(const std::string &networkId)
209{
210    FI_HILOGI("Connection with \'%{public}s\' shutdown", Utility::Anonymize(networkId).c_str());
211    SendEvent(CooperateEvent(
212        CooperateEventType::DSOFTBUS_SESSION_CLOSED,
213        DSoftbusSessionClosed {
214            .networkId = networkId
215        }));
216}
217
218void DSoftbusHandler::OnConnected(const std::string &networkId)
219{
220    FI_HILOGI("Connection to \'%{public}s\' successfully", Utility::Anonymize(networkId).c_str());
221    SendEvent(CooperateEvent(
222        CooperateEventType::DSOFTBUS_SESSION_OPENED,
223        DSoftbusSessionOpened {
224            .networkId = networkId
225        }));
226}
227
228bool DSoftbusHandler::OnPacket(const std::string &networkId, NetPacket &packet)
229{
230    CALL_DEBUG_ENTER;
231    int32_t messageId = static_cast<int32_t>(packet.GetMsgId());
232    auto it = handles_.find(messageId);
233    if (it != handles_.end()) {
234        (it->second)(networkId, packet);
235        return true;
236    }
237    FI_HILOGD("Unsupported messageId: %{public}d from %{public}s", messageId,
238        Utility::Anonymize(networkId).c_str());
239    return false;
240}
241
242void DSoftbusHandler::SendEvent(const CooperateEvent &event)
243{
244    std::lock_guard guard(lock_);
245    auto ret = sender_.Send(event);
246    if (ret != Channel<CooperateEvent>::NO_ERROR) {
247        FI_HILOGE("Failed to send event via channel, error:%{public}d", ret);
248    }
249}
250
251void DSoftbusHandler::OnCommunicationFailure(const std::string &networkId)
252{
253    env_->GetDSoftbus().CloseSession(networkId);
254    FI_HILOGI("Notify communication failure with peer(%{public}s)", Utility::Anonymize(networkId).c_str());
255    SendEvent(CooperateEvent(
256        CooperateEventType::DSOFTBUS_SESSION_CLOSED,
257        DSoftbusSessionClosed {
258            .networkId = networkId
259        }));
260}
261
262void DSoftbusHandler::OnStartCooperate(const std::string &networkId, NetPacket &packet)
263{
264    CALL_INFO_TRACE;
265    DSoftbusStartCooperate event {
266        .networkId = networkId,
267    };
268    packet >> event.originNetworkId >> event.cursorPos.x
269        >> event.cursorPos.y >> event.success;
270    if (packet.ChkRWError()) {
271        FI_HILOGE("Failed to read data packet");
272        return;
273    }
274    packet >> event.extra.priv;
275    if (packet.ChkRWError()) {
276        event.extra.priv = 0;
277    }
278    SendEvent(CooperateEvent(
279        CooperateEventType::DSOFTBUS_START_COOPERATE,
280        event));
281}
282
283void DSoftbusHandler::OnStopCooperate(const std::string &networkId, NetPacket &packet)
284{
285    CALL_INFO_TRACE;
286    DSoftbusStopCooperate event {
287        .networkId = networkId,
288        .normal = true,
289    };
290    SendEvent(CooperateEvent(
291        CooperateEventType::DSOFTBUS_STOP_COOPERATE,
292        event));
293}
294
295void DSoftbusHandler::OnComeBack(const std::string &networkId, NetPacket &packet)
296{
297    CALL_INFO_TRACE;
298    DSoftbusComeBack event {
299        .networkId = networkId,
300        .success = true,
301    };
302    packet >> event.originNetworkId >> event.cursorPos.x >> event.cursorPos.y;
303    if (packet.ChkRWError()) {
304        FI_HILOGE("Failed to read data packet");
305        return;
306    }
307    packet >> event.extra.priv;
308    if (packet.ChkRWError()) {
309        event.extra.priv = 0;
310    }
311    SendEvent(CooperateEvent(
312        CooperateEventType::DSOFTBUS_COME_BACK,
313        event));
314}
315
316void DSoftbusHandler::OnRelayCooperate(const std::string &networkId, NetPacket &packet)
317{
318    CALL_INFO_TRACE;
319    DSoftbusRelayCooperate event {
320        .networkId = networkId,
321        .normal = true,
322    };
323    packet >> event.targetNetworkId;
324    if (packet.ChkRWError()) {
325        FI_HILOGE("Failed to read data packet");
326        return;
327    }
328    SendEvent(CooperateEvent(
329        CooperateEventType::DSOFTBUS_RELAY_COOPERATE,
330        event));
331}
332
333void DSoftbusHandler::OnRelayCooperateFinish(const std::string &networkId, NetPacket &packet)
334{
335    CALL_INFO_TRACE;
336    DSoftbusRelayCooperate event {
337        .networkId = networkId,
338    };
339    packet >> event.targetNetworkId >> event.normal;
340    if (packet.ChkRWError()) {
341        FI_HILOGE("Failed to read data packet");
342        return;
343    }
344    SendEvent(CooperateEvent(
345        CooperateEventType::DSOFTBUS_RELAY_COOPERATE_FINISHED,
346        event));
347}
348
349void DSoftbusHandler::OnSubscribeMouseLocation(const std::string &networKId, NetPacket &packet)
350{
351    CALL_INFO_TRACE;
352    DSoftbusSubscribeMouseLocation event;
353    packet >> event.networkId >> event.remoteNetworkId;
354    if (packet.ChkRWError()) {
355        FI_HILOGE("Failed to read data packet");
356        return;
357    }
358    SendEvent(CooperateEvent(
359        CooperateEventType::DSOFTBUS_SUBSCRIBE_MOUSE_LOCATION,
360        event));
361}
362
363void DSoftbusHandler::OnUnSubscribeMouseLocation(const std::string& networKId, NetPacket &packet)
364{
365    CALL_INFO_TRACE;
366    DSoftbusUnSubscribeMouseLocation event;
367    packet >> event.networkId >> event.remoteNetworkId;
368    if (packet.ChkRWError()) {
369        FI_HILOGE("Failed to read data packet");
370        return;
371    }
372    SendEvent(CooperateEvent(
373        CooperateEventType::DSOFTBUS_UNSUBSCRIBE_MOUSE_LOCATION,
374        event));
375}
376
377void DSoftbusHandler::OnReplySubscribeLocation(const std::string& networKId, NetPacket &packet)
378{
379    CALL_INFO_TRACE;
380    DSoftbusReplySubscribeMouseLocation event;
381    packet >> event.networkId >> event.remoteNetworkId >> event.result;
382    if (packet.ChkRWError()) {
383        FI_HILOGE("Failed to read data packet");
384        return;
385    }
386    SendEvent(CooperateEvent(
387        CooperateEventType::DSOFTBUS_REPLY_SUBSCRIBE_MOUSE_LOCATION,
388        event));
389}
390
391void DSoftbusHandler::OnReplyUnSubscribeLocation(const std::string& networKId, NetPacket &packet)
392{
393    CALL_INFO_TRACE;
394    DSoftbusReplyUnSubscribeMouseLocation event;
395    packet >> event.networkId >> event.remoteNetworkId >> event.result;
396    if (packet.ChkRWError()) {
397        FI_HILOGE("Failed to read data packet");
398        return;
399    }
400    SendEvent(CooperateEvent(
401        CooperateEventType::DSOFTBUS_REPLY_UNSUBSCRIBE_MOUSE_LOCATION,
402        event));
403}
404
405void DSoftbusHandler::OnRemoteMouseLocation(const std::string& networKId, NetPacket &packet)
406{
407    CALL_DEBUG_ENTER;
408    DSoftbusSyncMouseLocation event;
409    packet >> event.networkId >> event.remoteNetworkId >> event.mouseLocation.displayX >>
410        event.mouseLocation.displayY >> event.mouseLocation.displayWidth >> event.mouseLocation.displayHeight;
411    if (packet.ChkRWError()) {
412        FI_HILOGE("Failed to read data packet");
413        return;
414    }
415    SendEvent(CooperateEvent(
416        CooperateEventType::DSOFTBUS_MOUSE_LOCATION,
417        event));
418}
419
420void DSoftbusHandler::OnRemoteInputDevice(const std::string& networkId, NetPacket &packet)
421{
422    CALL_INFO_TRACE;
423    DSoftbusSyncInputDevice event;
424    int32_t devNum { -1 };
425    packet >> devNum;
426    event.networkId = networkId;
427    FI_HILOGI("devNum:%{public}d", devNum);
428    if (devNum <= 0 || devNum >= MAX_INPUT_DEV_NUM) {
429        FI_HILOGE("Invalid devNum:%{public}d", devNum);
430        return;
431    }
432    for (int32_t i = 0; i < devNum; i++) {
433        auto device = std::make_shared<Device>(INVALID_DEVICE_ID);
434        if (DeserializeDevice(device, packet) != RET_OK) {
435            FI_HILOGE("DeserializeDevice failed");
436            return;
437        }
438        event.devices.push_back(device);
439    }
440    SendEvent(CooperateEvent(
441        CooperateEventType::DSOFTBUS_INPUT_DEV_SYNC,
442        event));
443}
444
445void DSoftbusHandler::OnRemoteHotPlug(const std::string &networkId, NetPacket &packet)
446{
447    CALL_INFO_TRACE;
448    DSoftbusHotPlugEvent event;
449    packet >> event.type;
450    FI_HILOGI("Hot plug type:%{public}d", event.type);
451    auto device = std::make_shared<Device>(INVALID_DEVICE_ID);
452    if (DeserializeDevice(device, packet) != RET_OK) {
453        FI_HILOGE("DeserializeDevice failed");
454        return;
455    }
456    event.device = device;
457    SendEvent(CooperateEvent(
458        CooperateEventType::DSOFTBUS_INPUT_DEV_HOT_PLUG,
459        event));
460}
461
462int32_t DSoftbusHandler::DeserializeDevice(std::shared_ptr<IDevice> device, NetPacket &packet)
463{
464    CALL_DEBUG_ENTER;
465    CHKPR(device, RET_ERR);
466    int32_t data;
467    std::string str;
468    packet >> data;
469    device->SetId(data);
470    packet >> str;
471    device->SetDevPath(str);
472    packet >> str;
473    device->SetSysPath(str);
474    packet >> data;
475    device->SetBus(data);
476    packet >> data;
477    device->SetVendor(data);
478    packet >> data;
479    device->SetProduct(data);
480    packet >> data;
481    device->SetVersion(data);
482    packet >> str;
483    device->SetName(str);
484    packet >> str;
485    device->SetPhys(str);
486    packet >> str;
487    device->SetUniq(str);
488    bool isPointerDevice { false };
489    packet >> isPointerDevice;
490    if (isPointerDevice) {
491        device->AddCapability(IDevice::Capability::DEVICE_CAP_POINTER);
492    }
493    bool isKeyboard { false };
494    packet >> isKeyboard;
495    if (isKeyboard) {
496        device->AddCapability(IDevice::Capability::DEVICE_CAP_KEYBOARD);
497    }
498    int32_t keyboardType { static_cast<int32_t> (IDevice::KeyboardType::KEYBOARD_TYPE_NONE) };
499    packet >> keyboardType;
500    device->SetKeyboardType(static_cast<IDevice::KeyboardType>(keyboardType));
501    if (packet.ChkRWError()) {
502        FI_HILOGE("Packet read type failed");
503        return RET_ERR;
504    }
505    return RET_OK;
506}
507} // namespace Cooperate
508} // namespace DeviceStatus
509} // namespace Msdp
510} // namespace OHOS
511