12d4d9a4dSopenharmony_ci/*
22d4d9a4dSopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
32d4d9a4dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42d4d9a4dSopenharmony_ci * you may not use this file except in compliance with the License.
52d4d9a4dSopenharmony_ci * You may obtain a copy of the License at
62d4d9a4dSopenharmony_ci *
72d4d9a4dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82d4d9a4dSopenharmony_ci *
92d4d9a4dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102d4d9a4dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112d4d9a4dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122d4d9a4dSopenharmony_ci * See the License for the specific language governing permissions and
132d4d9a4dSopenharmony_ci * limitations under the License.
142d4d9a4dSopenharmony_ci */
152d4d9a4dSopenharmony_ci
162d4d9a4dSopenharmony_ci#include "dinput_sink_state.h"
172d4d9a4dSopenharmony_ci
182d4d9a4dSopenharmony_ci#include <dirent.h>
192d4d9a4dSopenharmony_ci#include <fcntl.h>
202d4d9a4dSopenharmony_ci#include <pthread.h>
212d4d9a4dSopenharmony_ci#include <thread>
222d4d9a4dSopenharmony_ci#include <unistd.h>
232d4d9a4dSopenharmony_ci#include <vector>
242d4d9a4dSopenharmony_ci
252d4d9a4dSopenharmony_ci#include "dinput_errcode.h"
262d4d9a4dSopenharmony_ci#include "dinput_log.h"
272d4d9a4dSopenharmony_ci#include "dinput_utils_tool.h"
282d4d9a4dSopenharmony_ci#include "distributed_input_collector.h"
292d4d9a4dSopenharmony_ci#include "distributed_input_sink_transport.h"
302d4d9a4dSopenharmony_ci
312d4d9a4dSopenharmony_cinamespace OHOS {
322d4d9a4dSopenharmony_cinamespace DistributedHardware {
332d4d9a4dSopenharmony_cinamespace DistributedInput {
342d4d9a4dSopenharmony_ciIMPLEMENT_SINGLE_INSTANCE(DInputSinkState);
352d4d9a4dSopenharmony_ciDInputSinkState::~DInputSinkState()
362d4d9a4dSopenharmony_ci{
372d4d9a4dSopenharmony_ci    Release();
382d4d9a4dSopenharmony_ci}
392d4d9a4dSopenharmony_ci
402d4d9a4dSopenharmony_ciint32_t DInputSinkState::Init()
412d4d9a4dSopenharmony_ci{
422d4d9a4dSopenharmony_ci    DHLOGI("DInputSinkState Init.");
432d4d9a4dSopenharmony_ci    touchPadEventFragMgr_ = std::make_shared<TouchPadEventFragmentMgr>();
442d4d9a4dSopenharmony_ci    return DH_SUCCESS;
452d4d9a4dSopenharmony_ci}
462d4d9a4dSopenharmony_ci
472d4d9a4dSopenharmony_ciint32_t DInputSinkState::Release()
482d4d9a4dSopenharmony_ci{
492d4d9a4dSopenharmony_ci    DHLOGI("DInputSinkState Release.");
502d4d9a4dSopenharmony_ci    {
512d4d9a4dSopenharmony_ci        std::lock_guard<std::mutex> mapLock(operationMutex_);
522d4d9a4dSopenharmony_ci        dhIdStateMap_.clear();
532d4d9a4dSopenharmony_ci    }
542d4d9a4dSopenharmony_ci    ClearDeviceStates();
552d4d9a4dSopenharmony_ci    return DH_SUCCESS;
562d4d9a4dSopenharmony_ci}
572d4d9a4dSopenharmony_ci
582d4d9a4dSopenharmony_ciint32_t DInputSinkState::RecordDhIds(const std::vector<std::string> &dhIds, DhIdState state, const int32_t sessionId)
592d4d9a4dSopenharmony_ci{
602d4d9a4dSopenharmony_ci    DHLOGI("RecordDhIds dhIds size = %{public}zu", dhIds.size());
612d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(operationMutex_);
622d4d9a4dSopenharmony_ci    for (const auto &dhid : dhIds) {
632d4d9a4dSopenharmony_ci        DHLOGD("add dhid : %{public}s, state : %{public}d.", GetAnonyString(dhid).c_str(), state);
642d4d9a4dSopenharmony_ci        dhIdStateMap_[dhid] = state;
652d4d9a4dSopenharmony_ci    }
662d4d9a4dSopenharmony_ci
672d4d9a4dSopenharmony_ci    if (state == DhIdState::THROUGH_OUT) {
682d4d9a4dSopenharmony_ci        SimulateEventInjectToSrc(sessionId, dhIds);
692d4d9a4dSopenharmony_ci    }
702d4d9a4dSopenharmony_ci    lastSessionId_ = sessionId;
712d4d9a4dSopenharmony_ci    return DH_SUCCESS;
722d4d9a4dSopenharmony_ci}
732d4d9a4dSopenharmony_ci
742d4d9a4dSopenharmony_ciint32_t DInputSinkState::RemoveDhIds(const std::vector<std::string> &dhIds)
752d4d9a4dSopenharmony_ci{
762d4d9a4dSopenharmony_ci    DHLOGI("RemoveDhIds dhIds size = %{public}zu", dhIds.size());
772d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(operationMutex_);
782d4d9a4dSopenharmony_ci    for (const auto &dhid : dhIds) {
792d4d9a4dSopenharmony_ci        DHLOGD("delete dhid : %{public}s", GetAnonyString(dhid).c_str());
802d4d9a4dSopenharmony_ci        dhIdStateMap_.erase(dhid);
812d4d9a4dSopenharmony_ci    }
822d4d9a4dSopenharmony_ci    return DH_SUCCESS;
832d4d9a4dSopenharmony_ci}
842d4d9a4dSopenharmony_ci
852d4d9a4dSopenharmony_cistd::shared_ptr<TouchPadEventFragmentMgr> DInputSinkState::GetTouchPadEventFragMgr()
862d4d9a4dSopenharmony_ci{
872d4d9a4dSopenharmony_ci    return this->touchPadEventFragMgr_;
882d4d9a4dSopenharmony_ci}
892d4d9a4dSopenharmony_ci
902d4d9a4dSopenharmony_ciDhIdState DInputSinkState::GetStateByDhid(const std::string &dhId)
912d4d9a4dSopenharmony_ci{
922d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(operationMutex_);
932d4d9a4dSopenharmony_ci    if (dhIdStateMap_.find(dhId) == dhIdStateMap_.end()) {
942d4d9a4dSopenharmony_ci        DHLOGE("dhId : %{public}s not exist.", GetAnonyString(dhId).c_str());
952d4d9a4dSopenharmony_ci        return DhIdState::THROUGH_IN;
962d4d9a4dSopenharmony_ci    }
972d4d9a4dSopenharmony_ci    return dhIdStateMap_[dhId];
982d4d9a4dSopenharmony_ci}
992d4d9a4dSopenharmony_ci
1002d4d9a4dSopenharmony_civoid DInputSinkState::SimulateMouseBtnMouseUpState(const std::string &dhId, const struct RawEvent &event)
1012d4d9a4dSopenharmony_ci{
1022d4d9a4dSopenharmony_ci    DHLOGI("Sinmulate Mouse BTN_MOUSE UP state to source, dhId: %{public}s", GetAnonyString(dhId).c_str());
1032d4d9a4dSopenharmony_ci    int32_t scanId = GetRandomInt32(0, INT32_MAX);
1042d4d9a4dSopenharmony_ci    RawEvent mscScanEv = { event.when, EV_MSC, MSC_SCAN, scanId, dhId, event.path };
1052d4d9a4dSopenharmony_ci    RawEvent btnMouseUpEv = { event.when, EV_KEY, BTN_MOUSE, KEY_UP_STATE, dhId, event.path };
1062d4d9a4dSopenharmony_ci    RawEvent sycReportEv = { event.when, EV_SYN, SYN_REPORT, 0x0, dhId, event.path };
1072d4d9a4dSopenharmony_ci
1082d4d9a4dSopenharmony_ci    std::vector<RawEvent> simEvents = { mscScanEv, btnMouseUpEv, sycReportEv };
1092d4d9a4dSopenharmony_ci    DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsgBatch(lastSessionId_, simEvents);
1102d4d9a4dSopenharmony_ci}
1112d4d9a4dSopenharmony_ci
1122d4d9a4dSopenharmony_civoid DInputSinkState::SimulateTouchPadStateReset(const std::vector<RawEvent> &events)
1132d4d9a4dSopenharmony_ci{
1142d4d9a4dSopenharmony_ci    DHLOGI("SimulateTouchPadStateReset events size: %{public}zu", events.size());
1152d4d9a4dSopenharmony_ci    DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsgBatch(lastSessionId_, events);
1162d4d9a4dSopenharmony_ci}
1172d4d9a4dSopenharmony_ci
1182d4d9a4dSopenharmony_civoid DInputSinkState::SimulateEventInjectToSrc(const int32_t sessionId, const std::vector<std::string> &dhIds)
1192d4d9a4dSopenharmony_ci{
1202d4d9a4dSopenharmony_ci    DHLOGI("SimulateEventInject enter, sessionId %{public}d, dhIds size %{public}zu", sessionId, dhIds.size());
1212d4d9a4dSopenharmony_ci    // mouse/keyboard/touchpad/touchscreen event send to remote device if these device pass through.
1222d4d9a4dSopenharmony_ci    if (sessionId == -1) {
1232d4d9a4dSopenharmony_ci        DHLOGE("SimulateEventInjectToSrc SessionId invalid");
1242d4d9a4dSopenharmony_ci        return;
1252d4d9a4dSopenharmony_ci    }
1262d4d9a4dSopenharmony_ci
1272d4d9a4dSopenharmony_ci    for (const std::string &dhId : dhIds) {
1282d4d9a4dSopenharmony_ci        SimulateKeyDownEvents(sessionId, dhId);
1292d4d9a4dSopenharmony_ci        SimulateTouchPadEvents(sessionId, dhId);
1302d4d9a4dSopenharmony_ci    }
1312d4d9a4dSopenharmony_ci}
1322d4d9a4dSopenharmony_ci
1332d4d9a4dSopenharmony_civoid DInputSinkState::SimulateKeyDownEvents(const int32_t sessionId, const std::string &dhId)
1342d4d9a4dSopenharmony_ci{
1352d4d9a4dSopenharmony_ci    // check if this device is key event
1362d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
1372d4d9a4dSopenharmony_ci    auto iter = keyDownStateMap_.find(dhId);
1382d4d9a4dSopenharmony_ci    if (iter == keyDownStateMap_.end()) {
1392d4d9a4dSopenharmony_ci        DHLOGI("The shared Device not has down state key, dhId: %{public}s", GetAnonyString(dhId).c_str());
1402d4d9a4dSopenharmony_ci        return;
1412d4d9a4dSopenharmony_ci    }
1422d4d9a4dSopenharmony_ci
1432d4d9a4dSopenharmony_ci    for (const auto &event : iter->second) {
1442d4d9a4dSopenharmony_ci        DHLOGI("Simulate Key event for device path: %{public}s, dhId: %{public}s",
1452d4d9a4dSopenharmony_ci            event.path.c_str(), GetAnonyString(event.descriptor).c_str());
1462d4d9a4dSopenharmony_ci        SimulateKeyDownEvent(sessionId, dhId, event);
1472d4d9a4dSopenharmony_ci    }
1482d4d9a4dSopenharmony_ci
1492d4d9a4dSopenharmony_ci    keyDownStateMap_.erase(dhId);
1502d4d9a4dSopenharmony_ci}
1512d4d9a4dSopenharmony_ci
1522d4d9a4dSopenharmony_civoid DInputSinkState::SimulateKeyDownEvent(const int32_t sessionId, const std::string &dhId,
1532d4d9a4dSopenharmony_ci    const struct RawEvent &event)
1542d4d9a4dSopenharmony_ci{
1552d4d9a4dSopenharmony_ci    DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsg(sessionId, dhId,
1562d4d9a4dSopenharmony_ci        EV_KEY, event.code, KEY_DOWN_STATE);
1572d4d9a4dSopenharmony_ci    DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsg(sessionId, dhId,
1582d4d9a4dSopenharmony_ci        EV_SYN, SYN_REPORT, 0x0);
1592d4d9a4dSopenharmony_ci}
1602d4d9a4dSopenharmony_ci
1612d4d9a4dSopenharmony_civoid DInputSinkState::SimulateTouchPadEvents(const int32_t sessionId, const std::string &dhId)
1622d4d9a4dSopenharmony_ci{
1632d4d9a4dSopenharmony_ci    std::vector<RawEvent> events = this->touchPadEventFragMgr_->GetAndClearEvents(dhId);
1642d4d9a4dSopenharmony_ci    if (events.empty()) {
1652d4d9a4dSopenharmony_ci        return;
1662d4d9a4dSopenharmony_ci    }
1672d4d9a4dSopenharmony_ci
1682d4d9a4dSopenharmony_ci    DHLOGI("SimulateTouchPadEvents dhId: %{public}s, event size: %{public}zu", GetAnonyString(dhId).c_str(),
1692d4d9a4dSopenharmony_ci        events.size());
1702d4d9a4dSopenharmony_ci    DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsgBatch(sessionId, events);
1712d4d9a4dSopenharmony_ci}
1722d4d9a4dSopenharmony_ci
1732d4d9a4dSopenharmony_cibool DInputSinkState::IsDhIdDown(const std::string &dhId)
1742d4d9a4dSopenharmony_ci{
1752d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
1762d4d9a4dSopenharmony_ci    auto iter = keyDownStateMap_.find(dhId);
1772d4d9a4dSopenharmony_ci    return iter != keyDownStateMap_.end();
1782d4d9a4dSopenharmony_ci}
1792d4d9a4dSopenharmony_ci
1802d4d9a4dSopenharmony_civoid DInputSinkState::AddKeyDownState(struct RawEvent event)
1812d4d9a4dSopenharmony_ci{
1822d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
1832d4d9a4dSopenharmony_ci    keyDownStateMap_[event.descriptor].push_back(event);
1842d4d9a4dSopenharmony_ci}
1852d4d9a4dSopenharmony_ci
1862d4d9a4dSopenharmony_civoid DInputSinkState::RemoveKeyDownState(struct RawEvent event)
1872d4d9a4dSopenharmony_ci{
1882d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
1892d4d9a4dSopenharmony_ci    auto iter = keyDownStateMap_.find(event.descriptor);
1902d4d9a4dSopenharmony_ci    if (iter == keyDownStateMap_.end()) {
1912d4d9a4dSopenharmony_ci        return;
1922d4d9a4dSopenharmony_ci    }
1932d4d9a4dSopenharmony_ci
1942d4d9a4dSopenharmony_ci    auto evIter = std::find(keyDownStateMap_[event.descriptor].begin(),
1952d4d9a4dSopenharmony_ci        keyDownStateMap_[event.descriptor].end(), event);
1962d4d9a4dSopenharmony_ci    if (evIter == keyDownStateMap_[event.descriptor].end()) {
1972d4d9a4dSopenharmony_ci        return;
1982d4d9a4dSopenharmony_ci    }
1992d4d9a4dSopenharmony_ci
2002d4d9a4dSopenharmony_ci    keyDownStateMap_[event.descriptor].erase(evIter);
2012d4d9a4dSopenharmony_ci    if (keyDownStateMap_[event.descriptor].empty()) {
2022d4d9a4dSopenharmony_ci        keyDownStateMap_.erase(event.descriptor);
2032d4d9a4dSopenharmony_ci    }
2042d4d9a4dSopenharmony_ci}
2052d4d9a4dSopenharmony_ci
2062d4d9a4dSopenharmony_civoid DInputSinkState::CheckAndSetLongPressedKeyOrder(struct RawEvent event)
2072d4d9a4dSopenharmony_ci{
2082d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
2092d4d9a4dSopenharmony_ci    auto iter = keyDownStateMap_.find(event.descriptor);
2102d4d9a4dSopenharmony_ci    if (iter == keyDownStateMap_.end()) {
2112d4d9a4dSopenharmony_ci        DHLOGI("Find new pressed key, save it, node id: %{public}s, type: %{public}d, key code: %{public}d, "
2122d4d9a4dSopenharmony_ci            "value: %{public}d", GetAnonyString(event.descriptor).c_str(), event.type, event.code, event.value);
2132d4d9a4dSopenharmony_ci        keyDownStateMap_[event.descriptor].push_back(event);
2142d4d9a4dSopenharmony_ci        return;
2152d4d9a4dSopenharmony_ci    }
2162d4d9a4dSopenharmony_ci
2172d4d9a4dSopenharmony_ci    auto evIter = std::find(keyDownStateMap_[event.descriptor].begin(),
2182d4d9a4dSopenharmony_ci        keyDownStateMap_[event.descriptor].end(), event);
2192d4d9a4dSopenharmony_ci    // If not find the cache key on pressing, save it
2202d4d9a4dSopenharmony_ci    if (evIter == keyDownStateMap_[event.descriptor].end()) {
2212d4d9a4dSopenharmony_ci        DHLOGI("Find new pressed key, save it, node id: %{public}s, type: %{public}d, key code: %{public}d, "
2222d4d9a4dSopenharmony_ci            "value: %{public}d", GetAnonyString(event.descriptor).c_str(), event.type, event.code, event.value);
2232d4d9a4dSopenharmony_ci        keyDownStateMap_[event.descriptor].push_back(event);
2242d4d9a4dSopenharmony_ci        return;
2252d4d9a4dSopenharmony_ci    }
2262d4d9a4dSopenharmony_ci
2272d4d9a4dSopenharmony_ci    // it is already the last one, just return
2282d4d9a4dSopenharmony_ci    if (evIter == (keyDownStateMap_[event.descriptor].end() - 1)) {
2292d4d9a4dSopenharmony_ci        DHLOGI("Pressed key already last one, node id: %{public}s, type: %{public}d, key code: %{public}d, "
2302d4d9a4dSopenharmony_ci            "value: %{public}d", GetAnonyString(event.descriptor).c_str(), event.type, event.code, event.value);
2312d4d9a4dSopenharmony_ci        return;
2322d4d9a4dSopenharmony_ci    }
2332d4d9a4dSopenharmony_ci
2342d4d9a4dSopenharmony_ci    // Ohterwhise, move the key to the last cached position.
2352d4d9a4dSopenharmony_ci    RawEvent backEv = *evIter;
2362d4d9a4dSopenharmony_ci    keyDownStateMap_[event.descriptor].erase(evIter);
2372d4d9a4dSopenharmony_ci    keyDownStateMap_[event.descriptor].push_back(backEv);
2382d4d9a4dSopenharmony_ci    DHLOGI("Find long pressed key: %{public}d, move the cached pressed key: %{public}d to the last position",
2392d4d9a4dSopenharmony_ci        event.code, backEv.code);
2402d4d9a4dSopenharmony_ci}
2412d4d9a4dSopenharmony_ci
2422d4d9a4dSopenharmony_civoid DInputSinkState::ClearDeviceStates()
2432d4d9a4dSopenharmony_ci{
2442d4d9a4dSopenharmony_ci    std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
2452d4d9a4dSopenharmony_ci    keyDownStateMap_.clear();
2462d4d9a4dSopenharmony_ci}
2472d4d9a4dSopenharmony_ci} // namespace DistributedInput
2482d4d9a4dSopenharmony_ci} // namespace DistributedHardware
2492d4d9a4dSopenharmony_ci} // namespace OHOSs