1/*
2 * Copyright (c) 2023-2024 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 "event_manager.h"
17#ifdef MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
18#include "cooperate_hisysevent.h"
19#endif // MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
20#include "devicestatus_define.h"
21#include "utility.h"
22
23#undef LOG_TAG
24#define LOG_TAG "EventManager"
25
26namespace OHOS {
27namespace Msdp {
28namespace DeviceStatus {
29namespace Cooperate {
30
31EventManager::EventManager(IContext *env)
32    : env_(env)
33{}
34
35void EventManager::RegisterListener(const RegisterListenerEvent &event)
36{
37    CALL_INFO_TRACE;
38    std::shared_ptr<EventInfo> eventInfo = std::make_shared<EventInfo>();
39    eventInfo->type = EventType::LISTENER;
40    eventInfo->msgId = MessageId::COORDINATION_ADD_LISTENER;
41    eventInfo->pid = event.pid;
42
43    FI_HILOGI("Add cooperate listener (%{public}d)", eventInfo->pid);
44    auto iter = std::find_if(listeners_.begin(), listeners_.end(),
45        [eventInfo](const auto &item) {
46            return ((item != nullptr) && (item->pid == eventInfo->pid));
47        });
48    if (iter != listeners_.end()) {
49        *iter = eventInfo;
50    } else {
51        listeners_.emplace_back(eventInfo);
52    }
53}
54
55void EventManager::UnregisterListener(const UnregisterListenerEvent &event)
56{
57    FI_HILOGI("Remove cooperate listener (%{public}d)", event.pid);
58    listeners_.erase(std::remove_if(listeners_.begin(), listeners_.end(),
59        [pid = event.pid](const auto &item) {
60            return ((item == nullptr) || (item->pid == pid));
61        }), listeners_.end());
62}
63
64void EventManager::EnableCooperate(const EnableCooperateEvent &event)
65{
66    CALL_INFO_TRACE;
67    CooperateNotice notice {
68        .pid = event.pid,
69        .msgId = MessageId::COORDINATION_MESSAGE,
70        .userData = event.userData,
71        .msg = CoordinationMessage::PREPARE
72    };
73    NotifyCooperateMessage(notice);
74}
75
76void EventManager::DisableCooperate(const DisableCooperateEvent &event)
77{
78    CALL_INFO_TRACE;
79    CooperateNotice notice {
80        .pid = event.pid,
81        .msgId = MessageId::COORDINATION_MESSAGE,
82        .userData = event.userData,
83        .msg = CoordinationMessage::UNPREPARE
84    };
85    NotifyCooperateMessage(notice);
86}
87
88void EventManager::StartCooperate(const StartCooperateEvent &event)
89{
90    std::shared_ptr<EventInfo> eventInfo = std::make_shared<EventInfo>();
91    eventInfo->type = EventType::START;
92    eventInfo->msgId = MessageId::COORDINATION_MESSAGE;
93    eventInfo->pid = event.pid;
94    eventInfo->networkId = event.remoteNetworkId;
95    eventInfo->userData = event.userData;
96    calls_[EventType::START] = eventInfo;
97}
98
99void EventManager::StartCooperateFinish(const DSoftbusStartCooperateFinished &event)
100{
101    std::shared_ptr<EventInfo> eventInfo = calls_[EventType::START];
102    CHKPV(eventInfo);
103    CooperateNotice notice {
104        .pid = eventInfo->pid,
105        .msgId = eventInfo->msgId,
106        .userData = eventInfo->userData,
107        .networkId = eventInfo->networkId,
108        .msg = (event.success ? CoordinationMessage::ACTIVATE_SUCCESS : CoordinationMessage::ACTIVATE_FAIL),
109        .errCode = event.errCode
110    };
111    calls_[EventType::START] = nullptr;
112    NotifyCooperateMessage(notice);
113}
114
115void EventManager::RemoteStart(const DSoftbusStartCooperate &event)
116{
117    CALL_INFO_TRACE;
118    OnCooperateMessage(CoordinationMessage::ACTIVATE, event.networkId);
119}
120
121void EventManager::RemoteStartFinish(const DSoftbusStartCooperateFinished &event)
122{
123    CALL_INFO_TRACE;
124    CoordinationMessage msg { event.success ?
125                              CoordinationMessage::ACTIVATE_SUCCESS :
126                              CoordinationMessage::ACTIVATE_FAIL };
127    OnCooperateMessage(msg, event.networkId);
128    if (msg == CoordinationMessage::ACTIVATE_SUCCESS) {
129#ifdef MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
130        CooperateDFX::WriteRemoteStart(OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR);
131#endif // MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
132    } else {
133#ifdef MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
134        CooperateDFX::WriteRemoteStart(OHOS::HiviewDFX::HiSysEvent::EventType::FAULT);
135#endif // MSDP_HIVIEWDFX_HISYSEVENT_ENABLE
136    }
137}
138
139void EventManager::OnUnchain(const StopCooperateEvent &event)
140{
141    CALL_INFO_TRACE;
142    OnCooperateMessage(CoordinationMessage::SESSION_CLOSED, event.networkId);
143}
144
145void EventManager::StopCooperate(const StopCooperateEvent &event)
146{
147    std::shared_ptr<EventInfo> eventInfo = std::make_shared<EventInfo>();
148    eventInfo->type = EventType::STOP;
149    eventInfo->msgId = MessageId::COORDINATION_MESSAGE;
150    eventInfo->pid = event.pid;
151    eventInfo->userData = event.userData;
152    calls_[EventType::STOP] = eventInfo;
153}
154
155void EventManager::StopCooperateFinish(const DSoftbusStopCooperateFinished &event)
156{
157    std::shared_ptr<EventInfo> eventInfo = calls_[EventType::STOP];
158    CHKPV(eventInfo);
159    CooperateNotice notice {
160        .pid = eventInfo->pid,
161        .msgId = eventInfo->msgId,
162        .userData = eventInfo->userData,
163        .networkId = eventInfo->networkId,
164        .msg = (event.normal ? CoordinationMessage::DEACTIVATE_SUCCESS : CoordinationMessage::DEACTIVATE_FAIL),
165        .errCode = event.errCode
166    };
167    NotifyCooperateMessage(notice);
168    calls_[EventType::STOP] = nullptr;
169}
170
171void EventManager::RemoteStop(const DSoftbusStopCooperate &event)
172{
173    CALL_DEBUG_ENTER;
174}
175
176void EventManager::RemoteStopFinish(const DSoftbusStopCooperateFinished &event)
177{
178    CALL_DEBUG_ENTER;
179}
180
181void EventManager::OnProfileChanged(const DDPCooperateSwitchChanged &event)
182{
183    CALL_INFO_TRACE;
184    FI_HILOGI("Switch status of \'%{public}s\' has changed to %{public}d",
185        Utility::Anonymize(event.networkId).c_str(), event.normal);
186    CoordinationMessage msg = (event.normal ? CoordinationMessage::PREPARE : CoordinationMessage::UNPREPARE);
187    OnCooperateMessage(msg, event.networkId);
188}
189
190void EventManager::OnSoftbusSessionClosed(const DSoftbusSessionClosed &event)
191{
192    FI_HILOGI("Connection with \'%{public}s\' is closed", Utility::Anonymize(event.networkId).c_str());
193    OnCooperateMessage(CoordinationMessage::SESSION_CLOSED, event.networkId);
194}
195
196void EventManager::GetCooperateState(const CooperateStateNotice &notice)
197{
198    CALL_INFO_TRACE;
199    NotifyCooperateState(notice);
200}
201
202void EventManager::OnCooperateMessage(CoordinationMessage msg, const std::string &networkId)
203{
204    CALL_INFO_TRACE;
205    for (auto iter = listeners_.begin(); iter != listeners_.end(); ++iter) {
206        std::shared_ptr<EventInfo> listener = *iter;
207        CHKPC(listener);
208        FI_HILOGD("Notify cooperate listener (%{public}d, %{public}d)", listener->pid, listener->msgId);
209        CooperateNotice notice {
210            .pid = listener->pid,
211            .msgId = listener->msgId,
212            .userData = listener->userData,
213            .networkId = networkId,
214            .msg = msg
215        };
216        NotifyCooperateMessage(notice);
217    }
218}
219
220void EventManager::OnClientDied(const ClientDiedEvent &event)
221{
222    FI_HILOGI("Remove client died listener, pid: %{public}d", event.pid);
223    for (auto iter = listeners_.begin(); iter != listeners_.end();) {
224        std::shared_ptr<EventInfo> listener = *iter;
225        CHKPC(listener);
226        if (event.pid == listener->pid) {
227            iter = listeners_.erase(iter);
228            break;
229        } else {
230            ++iter;
231        }
232    }
233}
234
235void EventManager::NotifyCooperateMessage(const CooperateNotice &notice)
236{
237    auto session = env_->GetSocketSessionManager().FindSessionByPid(notice.pid);
238    if (session == nullptr) {
239        FI_HILOGD("session is null");
240        return;
241    }
242    CHKPV(session);
243    NetPacket pkt(notice.msgId);
244    pkt << notice.userData << notice.networkId << static_cast<int32_t>(notice.msg) << notice.errCode;
245    if (pkt.ChkRWError()) {
246        FI_HILOGE("Packet write data failed");
247        return;
248    }
249    if (!session->SendMsg(pkt)) {
250        FI_HILOGE("Sending failed");
251    }
252}
253
254void EventManager::NotifyCooperateState(const CooperateStateNotice &notice)
255{
256    CALL_INFO_TRACE;
257    CHKPV(env_);
258    auto session = env_->GetSocketSessionManager().FindSessionByPid(notice.pid);
259    CHKPV(session);
260    NetPacket pkt(notice.msgId);
261    pkt << notice.userData << notice.state << static_cast<int32_t>(notice.errCode);
262    if (pkt.ChkRWError()) {
263        FI_HILOGE("Packet write data failed");
264        return;
265    }
266    if (!session->SendMsg(pkt)) {
267        FI_HILOGE("Sending failed");
268        return;
269    }
270}
271} // namespace Cooperate
272} // namespace DeviceStatus
273} // namespace Msdp
274} // namespace OHOS
275