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