diff --git a/bundle.json b/bundle.json index 993070c..5e3419c 100755 --- a/bundle.json +++ b/bundle.json @@ -62,6 +62,7 @@ "//foundation/distributedhardware/distributed_input/services/sink/transport:libdinput_sink_trans", "//foundation/distributedhardware/distributed_input/services/sink/inputcollector:libdinput_collector", "//foundation/distributedhardware/distributed_input/services/transportbase:libdinput_trans_base", + "//foundation/distributedhardware/distributed_input/services/state:libdinput_state", "//foundation/distributedhardware/distributed_input/sourcehandler:libdinput_source_handler", "//foundation/distributedhardware/distributed_input/sinkhandler:libdinput_sink_handler", "//foundation/distributedhardware/distributed_input/inputdevicehandler:libdinput_handler", diff --git a/common/include/constants_dinput.h b/common/include/constants_dinput.h index fd19bf7..1fc7b40 100644 --- a/common/include/constants_dinput.h +++ b/common/include/constants_dinput.h @@ -38,6 +38,7 @@ namespace DistributedInput { const char INPUT_STRING_SPLIT_POINT = '.'; const uint32_t KEY_DOWN_STATE = 1; + const uint32_t KEY_UP_STATE = 0; const uint32_t READ_SLEEP_TIME_MS = 50; const uint32_t READ_RETRY_MAX = 5; const uint32_t DH_ID_LENGTH_MAX = 256; @@ -194,6 +195,8 @@ namespace DistributedInput { constexpr const char* CHECK_KEY_STATUS_THREAD_NAME = "checkKeyStatus"; + constexpr const char* KEYBOARD_UP_INJECT_THREAD_NAME = "KeyboardUpInject"; + constexpr int32_t LOG_MAX_LEN = 4096; constexpr uint32_t SCREEN_ID_DEFAULT = 0; diff --git a/common/include/input_hub.cpp b/common/include/input_hub.cpp index 410e4f4..0d3387b 100644 --- a/common/include/input_hub.cpp +++ b/common/include/input_hub.cpp @@ -1140,6 +1140,28 @@ void InputHub::GetShareMousePathByDhId(std::vector dhIds, std::stri } } +void InputHub::GetShareKeyboardPathByDhId(std::vector dhIds, + std::vector &shareDhidsPath, std::vector &shareDhIds) +{ + DHLOGI("GetShareKeyboardPathByDhId: devices_.size:%d,", devices_.size()); + std::unique_lock deviceLock(devicesMutex_); + for (auto dhId_ : dhIds) { + for (const auto &[id, device] : devices_) { + if (device == nullptr) { + DHLOGE("device is nullptr"); + continue; + } + DHLOGI("descriptor:%s, isShare[%d], type[%d]", GetAnonyString(device->identifier.descriptor).c_str(), + device->isShare, device->classes); + if ((device->identifier.descriptor == dhId_) && + ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) { + shareDhIds.push_back(dhId_); + shareDhidsPath.push_back(device->path); + } + } + } +} + void InputHub::GetDevicesInfoByType(const uint32_t inputTypes, std::map &datas) { uint32_t dhType = 0; diff --git a/common/include/input_hub.h b/common/include/input_hub.h index 71ab4a7..82d951f 100644 --- a/common/include/input_hub.h +++ b/common/include/input_hub.h @@ -53,6 +53,8 @@ public: void GetDevicesInfoByType(const uint32_t inputTypes, std::map &datas); void GetDevicesInfoByDhId(std::vector dhidsVec, std::map &datas); void GetShareMousePathByDhId(std::vector dhIds, std::string &path, std::string &dhId); + void GetShareKeyboardPathByDhId(std::vector dhIds, + std::vector &shareDhidsPath, std::vector &shareDhIds); bool IsAllDevicesStoped(); void ScanInputDevices(const std::string& dirname); diff --git a/services/sink/inputcollector/include/distributed_input_collector.h b/services/sink/inputcollector/include/distributed_input_collector.h index 6cad8f6..1f95ea7 100644 --- a/services/sink/inputcollector/include/distributed_input_collector.h +++ b/services/sink/inputcollector/include/distributed_input_collector.h @@ -43,6 +43,8 @@ public: AffectDhIds SetSharingTypes(bool enabled, const uint32_t &inputType); AffectDhIds SetSharingDhIds(bool enabled, std::vector dhIds); void GetMouseNodePath(std::vector dhIds, std::string &mouseNodePath, std::string &dhid); + void GetKeyboardNodePath( + std::vector dhIds, std::vector &shareDhidsPaths, std::vector &shareDhIds); // false for sharing device exist, true for all devices stop sharing bool IsAllDevicesStoped(); int32_t RegisterSharingDhIdListener(sptr sharingDhIdListener); diff --git a/services/sink/inputcollector/src/distributed_input_collector.cpp b/services/sink/inputcollector/src/distributed_input_collector.cpp index 0f664f4..0725244 100644 --- a/services/sink/inputcollector/src/distributed_input_collector.cpp +++ b/services/sink/inputcollector/src/distributed_input_collector.cpp @@ -214,6 +214,16 @@ void DistributedInputCollector::GetMouseNodePath( inputHub_->GetShareMousePathByDhId(dhIds, mouseNodePath, dhid); } +void DistributedInputCollector::GetKeyboardNodePath( + std::vector dhIds, std::vector &shareDhidsPaths, std::vector &shareDhIds) +{ + if (inputHub_ == nullptr) { + DHLOGI("inputHub is nullptr!"); + return; + } + inputHub_->GetShareKeyboardPathByDhId(dhIds, shareDhidsPaths, shareDhIds); +} + bool DistributedInputCollector::IsAllDevicesStoped() { if (inputHub_ == nullptr) { diff --git a/services/sink/sinkmanager/BUILD.gn b/services/sink/sinkmanager/BUILD.gn index 49a96ba..7b02237 100644 --- a/services/sink/sinkmanager/BUILD.gn +++ b/services/sink/sinkmanager/BUILD.gn @@ -35,6 +35,7 @@ ohos_shared_library("libdinput_sink") { "${utils_path}/include", "${fwk_interfaces_path}/include", "${fwk_interfaces_path}/include/ipc", + "${distributedinput_path}/services/state/include", ] sources = [ @@ -55,6 +56,7 @@ ohos_shared_library("libdinput_sink") { "${innerkits_path}:libdinput_sdk", "${services_sink_path}/inputcollector:libdinput_collector", "${services_sink_path}/transport:libdinput_sink_trans", + "${distributedinput_path}/services/state:libdinput_state", "${utils_path}:libdinput_utils", "//third_party/libevdev:libevdev", ] diff --git a/services/sink/sinkmanager/include/distributed_input_sink_manager.h b/services/sink/sinkmanager/include/distributed_input_sink_manager.h index 1fd3bda..0fa973c 100644 --- a/services/sink/sinkmanager/include/distributed_input_sink_manager.h +++ b/services/sink/sinkmanager/include/distributed_input_sink_manager.h @@ -37,6 +37,7 @@ #include "dinput_sink_trans_callback.h" #include "distributed_input_sink_stub.h" #include "distributed_input_sink_event_handler.h" +#include "dinput_state.h" namespace OHOS { namespace DistributedHardware { diff --git a/services/sink/sinkmanager/src/distributed_input_sink_manager.cpp b/services/sink/sinkmanager/src/distributed_input_sink_manager.cpp index a986d3d..099f733 100644 --- a/services/sink/sinkmanager/src/distributed_input_sink_manager.cpp +++ b/services/sink/sinkmanager/src/distributed_input_sink_manager.cpp @@ -276,6 +276,8 @@ void DistributedInputSinkManager::DInputSinkListener::OnStartRemoteInputDhid(con AffectDhIds affDhIds = DistributedInputCollector::GetInstance().SetSharingDhIds(true, vecStr); sinkManagerObj_->StoreStartDhids(sessionId, affDhIds.sharingDhIds); DistributedInputCollector::GetInstance().ReportDhIdSharingState(affDhIds); + StateMachine::GetInstance().AddDhids(vecStr); + StateMachine::GetInstance().SwitchState(vecStr, DhidState::THROUGH_OUT); } } @@ -292,6 +294,9 @@ void DistributedInputSinkManager::DInputSinkListener::OnStopRemoteInputDhid(cons stopIndeedOnes.noSharingDhIds = stopIndeedDhIds; DistributedInputCollector::GetInstance().ReportDhIdSharingState(stopIndeedOnes); + StateMachine::GetInstance().AddDhids(stopOnCmdDhIds); + StateMachine::GetInstance().SwitchState(stopOnCmdDhIds, DhidState::THROUGH_IN); + if (DistributedInputCollector::GetInstance().IsAllDevicesStoped()) { DHLOGE("All dhid stop sharing, sessionId: %d is closed.", sessionId); DistributedInputSinkSwitch::GetInstance().StopSwitch(sessionId); @@ -345,6 +350,8 @@ void DistributedInputSinkManager::DInputSinkListener::OnRelayStartDhidRemoteInpu AffectDhIds affDhIds = DistributedInputCollector::GetInstance().SetSharingDhIds(true, vecStr); sinkManagerObj_->StoreStartDhids(toSinkSessionId, affDhIds.sharingDhIds); DistributedInputCollector::GetInstance().ReportDhIdSharingState(affDhIds); + StateMachine::GetInstance().AddDhids(vecStr); + StateMachine::GetInstance().SwitchState(vecStr, DhidState::THROUGH_OUT); } } @@ -361,6 +368,9 @@ void DistributedInputSinkManager::DInputSinkListener::OnRelayStopDhidRemoteInput stopIndeedOnes.noSharingDhIds = stopIndeedDhIds; DistributedInputCollector::GetInstance().ReportDhIdSharingState(stopIndeedOnes); + StateMachine::GetInstance().AddDhids(stopOnCmdDhIds); + StateMachine::GetInstance().SwitchState(stopOnCmdDhIds, DhidState::THROUGH_IN); + if (DistributedInputCollector::GetInstance().IsAllDevicesStoped()) { DHLOGE("All dhid stop sharing, sessionId: %d is closed.", toSinkSessionId); DistributedInputSinkSwitch::GetInstance().StopSwitch(toSinkSessionId); @@ -695,6 +705,12 @@ int32_t DistributedInputSinkManager::Init() return ERR_DH_INPUT_SERVER_SINK_MANAGER_INIT_FAIL; } + ret = StateMachine::GetInstance().Init(); + if (ret != DH_SUCCESS) { + DHLOGE("StateMachine init fail!"); + return ERR_DH_INPUT_SERVER_SINK_MANAGER_INIT_FAIL; + } + statuslistener_ = std::make_shared(this); DistributedInputSinkTransport::GetInstance().RegistSinkRespCallback(statuslistener_); diff --git a/services/source/inputinject/BUILD.gn b/services/source/inputinject/BUILD.gn index 34e49dd..07b4208 100644 --- a/services/source/inputinject/BUILD.gn +++ b/services/source/inputinject/BUILD.gn @@ -30,6 +30,7 @@ ohos_shared_library("libdinput_inject") { "${fwk_interfaces_path}/include", "${fwk_interfaces_path}/include/ipc", "${distributedinput_path}/inputdevicehandler/include", + "${distributedinput_path}/services/state/include", ] sources = [ diff --git a/services/source/inputinject/include/distributed_input_inject.h b/services/source/inputinject/include/distributed_input_inject.h index 0da45f7..fe351b8 100644 --- a/services/source/inputinject/include/distributed_input_inject.h +++ b/services/source/inputinject/include/distributed_input_inject.h @@ -56,6 +56,9 @@ public: const std::string &sinkNodeDesc); void SyncNodeOfflineInfo(const std::string &srcDevId, const std::string &sinkDevId, const std::string &sinkNodeId); + void GetVirtualKeyboardPathByDhId(std::vector &dhIds, std::vector &shareDhidsPaths, + std::vector &shareDhIds); + private: DistributedInputInject(); ~DistributedInputInject(); diff --git a/services/source/inputinject/include/distributed_input_node_manager.h b/services/source/inputinject/include/distributed_input_node_manager.h index 9c3d037..a217138 100644 --- a/services/source/inputinject/include/distributed_input_node_manager.h +++ b/services/source/inputinject/include/distributed_input_node_manager.h @@ -56,6 +56,8 @@ public: void GetDevicesInfoByDhId(std::vector dhidsVec, std::map &datas); void ProcessInjectEvent(const std::shared_ptr &rawEvent); + void GetVirtualKeyboardPathByDhId(std::vector &dhIds, std::vector &shareDhidsPaths, + std::vector &shareDhIds); private: void AddDeviceLocked(const std::string& dhId, std::unique_ptr device); int32_t CreateHandle(const InputDevice& inputDevice, const std::string& devId, const std::string& dhId); @@ -63,6 +65,14 @@ private: void VerifyInputDevice(const nlohmann::json& inputDeviceJson, InputDevice& pBuf); void InjectEvent(); + void ScanSinkInputDevices(const std::string& dirName); + void OpenInputDevice(const std::string& devicePath); + int OpenInputDeviceFdByPath(std::string& canonicalDevicePath); + bool IsVirtualDev(int fd); + bool GetDevDhIdFd(int fd, std::string& dhId, std::string& physicalPath); + void SetPathForDevMap(std::string& dhId, const std::string& devicePath); + + /* the key is dhId, and the value is virtualDevice */ std::map> virtualDeviceMap_; std::mutex virtualDeviceMapMutex_; diff --git a/services/source/inputinject/include/virtual_device.h b/services/source/inputinject/include/virtual_device.h index 6bbe883..9dc0b36 100644 --- a/services/source/inputinject/include/virtual_device.h +++ b/services/source/inputinject/include/virtual_device.h @@ -43,7 +43,10 @@ public: bool SetUp(const InputDevice& inputDevice, const std::string &devId, const std::string &dhId); bool InjectInputEvent(const input_event &event); void SetNetWorkId(const std::string netWorkId); + void SetPath(const std::string path); std::string GetNetWorkId(); + std::string GetPath(); + uint16_t GetClasses(); int32_t GetDeviceFd(); uint16_t GetDeviceType(); @@ -52,6 +55,7 @@ private: int32_t fd_ = -1; std::string deviceName_; std::string netWorkId_; + std::string path_ {""}; const uint16_t busType_; const uint16_t vendorId_; const uint16_t productId_; diff --git a/services/source/inputinject/src/distributed_input_inject.cpp b/services/source/inputinject/src/distributed_input_inject.cpp index b3511b2..5a64585 100644 --- a/services/source/inputinject/src/distributed_input_inject.cpp +++ b/services/source/inputinject/src/distributed_input_inject.cpp @@ -255,6 +255,16 @@ int32_t DistributedInputInject::GetVirtualTouchScreenFd() } return inputNodeManager_->GetVirtualTouchScreenFd(); } + +void GetVirtualKeyboardPathByDhId(std::vector &dhIds, std::vector &shareDhidsPaths, + std::vector &shareDhIds) +{ + if (inputNodeManager_ == nullptr) { + DHLOGI("inputNodeManager_ is nullptr!"); + return; + } + inputNodeManager_->GetVirtualKeyboardPathByDhId(dhIds, shareDhidsPaths, shareDhIds); +} } // namespace DistributedInput } // namespace DistributedHardware } // namespace OHOS \ No newline at end of file diff --git a/services/source/inputinject/src/distributed_input_node_manager.cpp b/services/source/inputinject/src/distributed_input_node_manager.cpp index 6c4838b..fa541b8 100644 --- a/services/source/inputinject/src/distributed_input_node_manager.cpp +++ b/services/source/inputinject/src/distributed_input_node_manager.cpp @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "softbus_bus_center.h" @@ -33,6 +35,11 @@ namespace OHOS { namespace DistributedHardware { namespace DistributedInput { + +const uint32_t SLEEP_TIME_US = 100 * 1000; +const uint32_t ERROR_MSG_MAX_LEN = 256; +constexpr int32_t MAX_RETRY_COUNT = 10; + DistributedInputNodeManager::DistributedInputNodeManager() : isInjectThreadCreated_(false), isInjectThreadRunning_(false), inputHub_(std::make_unique()), virtualTouchScreenFd_(UN_INIT_FD_VALUE) { @@ -130,6 +137,167 @@ void DistributedInputNodeManager::VerifyInputDevice(const nlohmann::json& inputD } } +static std::string ConvertErrNo() +{ + char errMsg[ERROR_MSG_MAX_LEN] = {0}; + strerror_r(errno, errMsg, ERROR_MSG_MAX_LEN); + std::string errNoMsg(errMsg); + return errNoMsg; +} + +void Closed(int fd) +{ + if (fd < 0) { + DHLOGE("No fd need to beclosed."); + return; + } + close(fd); + fd = -1; +} + +void DistributedInputNodeManager::ScanSinkInputDevices(const std::string& dirName) +{ + DIR *dir; + struct dirent *de; + dir = opendir(dirName.c_str()); + if (dir == nullptr) { + DHLOGE("error opendir /dev/input :%{public}s\n", ConvertErrNo().c_str()); + return; + } + size_t dirNameFirstPos = 0; + size_t dirNameSecondPos = 1; + size_t dirNameThirdPos = 2; + while ((de = readdir(dir))) { + if (de->d_name[dirNameFirstPos] == '.' && (de->d_name[dirNameSecondPos] == '\0' || + (de->d_name[dirNameSecondPos] == '.' && de->d_name[dirNameThirdPos] == '\0'))) { + continue; + } + std::string tmpDevName = dirName + "/" + std::string(de->d_name); + OpenInputDeviceLocked(tmpDevName); + } + closedir(dir); +} + +bool DistributedInputNodeManager::IsVirtualDev(int fd) +{ + char buffer[256] = {0}; + std::string deviceName; + if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) { + DHLOGE("Could not get device name for %s", ConvertErrNo().c_str()); + return false; + } + buffer[sizeof(buffer) - 1] = '\0'; + deviceName = buffer; + + DHLOGD("IsVirtualDev deviceName: %s", buffer); + if (identifier.name.find(VIRTUAL_DEVICE_NAME) == std::string::npos) { + DHLOGD("This is not a virtual device, fd %d, deviceName: %s", fd, deviceName.c_str()); + return false; + } + return true; +} + +bool DistributedInputNodeManager::GetDevDhIdFd(int fd, std::string& dhId, std::string& physicalPath) +{ + char buffer[256] = {0}; + if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) { + DHLOGE("Could not get device name for %s", ConvertErrNo().c_str()); + return false; + } + buffer[sizeof(buffer) - 1] = '\0'; + physicalPath = buffer; + + DHLOGD("GetDevDhIdFd physicalPath: %s", physicalPath.c_str()); + dhId = physicalPath.substr(physicalPath.find("Input_")); + if (dhId.size() == 0) { + DHLOGE("Get dev dhid failed."); + return false; + } + DHLOGD("Device dhId %s", GetAnonyString(dhId).c_str()); + return true; +} + +void DistributedInputNodeManager::SetPathForDevMap(std::string& dhId, const std::string& devicePath) +{ + auto iter = virtualDeviceMap_.begin(); + while (iter != virtualDeviceMap_.end()) { + DHLOGD("Virtual device map dhid %s.", iter->first.c_str()); + if (dhId.compare(iter->first) == 0) { + DHLOGI("Found the virtual device, set path :%s", devicePath.c_str()); + iter->second->SetPath(devicePath) + break; + } + iter++; + } +} + +void DistributedInputNodeManager::OpenInputDevice(const std::string& devicePath) +{ + DHLOGI("Opening input device path: %s", devicePath.c_str()); + std::string dhId; + std::string physicalPath; + struct stat s; + int fd = -1; + chmod(devicePath.c_str(), S_IREAD); + char canonicalDevicePath[PATH_MAX + 1] = {0x00}; + + if (devicePath.length() == 0 || devicePath.length() > PATH_MAX || + realpath(devicePath.c_str(), canonicalDevicePath) == nullptr) { + DHLOGE("path check fail, error path: %s", devicePath.c_str()); + return; + } + if ((stat(canonicalDevicePath, &s) == 0) && (s.st_mode & S_IFDIR)) { + DHLOGI("path: %s is a dir.", devicePath.c_str()); + return; + } + fd = open(canonicalDevicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK); + int32_t count = 0; + while ((fd < 0) && (count < MAX_RETRY_COUNT)) { + ++count; + usleep(SLEEP_TIME_US); + fd = open(canonicalDevicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK); + DHLOGE("could not open %s, %s; retry %d\n", devicePath.c_str(), ConvertErrNo().c_str(), count); + } + if (count >= MAX_RETRY_COUNT) { + DHLOGE("could not open %s, %s\n", devicePath.c_str(), ConvertErrNo().c_str()); + CloseFd(fd); + return; + } + if (fd =-1) { + DHLOGE("The fd open failed, devicePath %s\n", devicePath.c_str()); + return; + } + if (IsVirtualDev(fd) == false) { + DHLOGE("The dev not virtual, devicePath %s\n", devicePath.c_str()); + return; + } + if (GetDevDhIdFd(fd, dhId, physicalPath) == false) { + DHLOGE("Get dev dhid failed, devicePath %s\n", devicePath.c_str()); + return; + } + SetPathForDevMap(dhId, devicePath); +} + +void GetVirtualKeyboardPathByDhId(std::vector &dhIds, std::vector &shareDhidsPaths, + std::vector &shareDhIds); +{ + for (auto dhId_ : dhIds) { + auto iter = virtualDeviceMap_.begin(); + while (iter != virtualDeviceMap_.end()) { + if (iter->second == nullptr) { + DHLOGE("device is nullptr"); + continue; + } + if ((iter->first.compare(dhId_) == 0) && ((iter->second->GetClasses() & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) { + DHLOGI("Found vir keyboard path %s, dhid %s", itersecond->GetPath().c_str()); + shareDhidsPath.push_back(diter->second->GetPath()); + shareDhIds.push_back(dhId_); + } + iter++; + } + } +} + int32_t DistributedInputNodeManager::CreateHandle(const InputDevice& inputDevice, const std::string& devId, const std::string& dhId) { @@ -144,6 +312,7 @@ int32_t DistributedInputNodeManager::CreateHandle(const InputDevice& inputDevice return ERR_DH_INPUT_SERVER_SOURCE_CREATE_HANDLE_FAIL; } AddDeviceLocked(inputDevice.descriptor, std::move(virtualDevice)); + ScanSinkInputDevices(DEVICE_PATH); return DH_SUCCESS; } diff --git a/services/source/inputinject/src/virtual_device.cpp b/services/source/inputinject/src/virtual_device.cpp index feef9e2..7e7e1cc 100644 --- a/services/source/inputinject/src/virtual_device.cpp +++ b/services/source/inputinject/src/virtual_device.cpp @@ -185,11 +185,26 @@ void VirtualDevice::SetNetWorkId(const std::string netWorkId) netWorkId_ = netWorkId; } +void SetPath(const std::string path) +{ + path_ = path; +} + std::string VirtualDevice::GetNetWorkId() { return netWorkId_; } +std::string GetPath() +{ + return path_; +} + +uint16_t GetClasses() +{ + return classes_; +} + void VirtualDevice::RecordEventLog(const input_event& event) { std::string eventType = ""; diff --git a/services/source/sourcemanager/BUILD.gn b/services/source/sourcemanager/BUILD.gn index 08e3a55..8a8b872 100644 --- a/services/source/sourcemanager/BUILD.gn +++ b/services/source/sourcemanager/BUILD.gn @@ -37,6 +37,7 @@ ohos_shared_library("libdinput_source") { "${fwk_interfaces_path}/include", "${fwk_interfaces_path}/include/ipc", "${distributedinput_path}/inputdevicehandler/include", + "${distributedinput_path}/services/state/include", ] sources = [ @@ -91,6 +92,7 @@ ohos_shared_library("libdinput_source") { "${services_source_path}/inputinject:libdinput_inject", "${services_source_path}/transport:libdinput_source_trans", "${utils_path}:libdinput_utils", + "${distributedinput_path}/services/state:libdinput_state", "//third_party/libevdev:libevdev", ] diff --git a/services/source/sourcemanager/include/distributed_input_source_manager.h b/services/source/sourcemanager/include/distributed_input_source_manager.h index 412c2a4..f7cda1e 100644 --- a/services/source/sourcemanager/include/distributed_input_source_manager.h +++ b/services/source/sourcemanager/include/distributed_input_source_manager.h @@ -37,6 +37,7 @@ #include "distributed_input_source_event_handler.h" #include "distributed_input_source_sa_cli_mgr.h" #include "distributed_input_source_stub.h" +#include "dinput_state.h" namespace OHOS { namespace DistributedHardware { diff --git a/services/source/sourcemanager/src/distributed_input_source_manager.cpp b/services/source/sourcemanager/src/distributed_input_source_manager.cpp index 39a78ef..e99bf1f 100644 --- a/services/source/sourcemanager/src/distributed_input_source_manager.cpp +++ b/services/source/sourcemanager/src/distributed_input_source_manager.cpp @@ -34,6 +34,7 @@ #include "dinput_errcode.h" #include "dinput_hitrace.h" #include "dinput_log.h" +#include "dinput_state.h" #include "dinput_utils_tool.h" #include "distributed_input_client.h" #include "distributed_input_inject.h" @@ -282,6 +283,11 @@ void DistributedInputSourceManager::DInputSourceListener::OnResponseStartRemoteI sourceManagerObj_->SetDeviceMapValue(deviceId, DINPUT_SOURCE_SWITCH_ON); } + std::vector vecStr; + sourceManagerObj_->StringSplitToVector(dhids, INPUT_STRING_SPLIT_POINT, vecStr); + StateMachine::GetInstance().AddDhid(vecStr); + StateMachine::GetInstance().SwitchState(vecStr, DhidState::THROUGH_IN); + std::shared_ptr jsonArrayMsg = std::make_shared(); nlohmann::json tmpJson; tmpJson[INPUT_SOURCEMANAGER_KEY_DEVID] = deviceId; @@ -971,6 +977,12 @@ int32_t DistributedInputSourceManager::Init() dhFwkKit->RegisterPublisherListener(DHTopic::TOPIC_STOP_DSCREEN, stopDScreenListener_); dhFwkKit->RegisterPublisherListener(DHTopic::TOPIC_DEV_OFFLINE, deviceOfflineListener_); + ret = StateMachine::GetInstance().Init(); + if (ret != DH_SUCCESS) { + DHLOGE("StateMachine init fail!"); + return ERR_DH_INPUT_SERVER_SOURCE_MANAGER_INIT_FAIL; + } + return DH_SUCCESS; } diff --git a/services/source/transport/BUILD.gn b/services/source/transport/BUILD.gn index 5796bcb..ad1bb96 100755 --- a/services/source/transport/BUILD.gn +++ b/services/source/transport/BUILD.gn @@ -31,6 +31,7 @@ ohos_shared_library("libdinput_source_trans") { "${frameworks_path}/include", "${distributedinput_path}/inputdevicehandler/include", "${distributedinput_path}/services/transportbase/include", + "${distributedinput_path}/services/state/include", ] sources = [ "src/distributed_input_source_transport.cpp" ] @@ -45,6 +46,7 @@ ohos_shared_library("libdinput_source_trans") { "${dfx_utils_path}:libdinput_dfx_utils", "${distributedinput_path}/services/transportbase:libdinput_trans_base", "${services_source_path}/inputinject:libdinput_inject", + "${services_source_path}/services/state:libdinput_state", "${utils_path}:libdinput_utils", "//third_party/libevdev:libevdev", ] diff --git a/services/source/transport/include/distributed_input_source_transport.h b/services/source/transport/include/distributed_input_source_transport.h index 08d40df..6daf67c 100644 --- a/services/source/transport/include/distributed_input_source_transport.h +++ b/services/source/transport/include/distributed_input_source_transport.h @@ -29,6 +29,7 @@ #include "nlohmann/json.hpp" #include "securec.h" +#include "dinput_state.h" #include "dinput_source_trans_callback.h" #include "dinput_transbase_source_callback.h" @@ -137,6 +138,8 @@ private: std::string JointDhIds(const std::vector &dhids); void RegRespFunMap(); + void StringSplitToVector(const std::string &str, const char split, std::vector &vecStr); + private: std::mutex operationMutex_; std::set sessionIdSet_; diff --git a/services/source/transport/src/distributed_input_source_transport.cpp b/services/source/transport/src/distributed_input_source_transport.cpp index e8676da..a49e6e0 100644 --- a/services/source/transport/src/distributed_input_source_transport.cpp +++ b/services/source/transport/src/distributed_input_source_transport.cpp @@ -286,6 +286,24 @@ int32_t DistributedInputSourceTransport::UnprepareRemoteInput(int32_t srcTsrcSeI return DH_SUCCESS; } +void DistributedInputSourceTransport::StringSplitToVector(const std::string &str, const char split, + std::vector &vecStr) +{ + if (str.empty()) { + DHLOGE("StringSplitToVector param str is error."); + return; + } + std::string strTmp = str + split; + size_t pos = strTmp.find(split); + while (pos != strTmp.npos) { + std::string matchTmp = strTmp.substr(0, pos); + vecStr.push_back(matchTmp); + + strTmp = strTmp.substr(pos + 1, strTmp.size()); + pos = strTmp.find(split); + } +} + int32_t DistributedInputSourceTransport::StartRemoteInputDhids(int32_t srcTsrcSeId, const std::string &deviceId, const std::string &dhids) { @@ -296,6 +314,11 @@ int32_t DistributedInputSourceTransport::StartRemoteInputDhids(int32_t srcTsrcSe } DHLOGI("StartRemoteInputDhids srcTsrcSeId:%d, sinkSessionId:%d.", srcTsrcSeId, sinkSessionId); + std::vector vecStr; + StringSplitToVector(dhids, INPUT_STRING_SPLIT_POINT, vecStr); + StateMachine::GetInstance().AddDhids(vecStr); + StateMachine::GetInstance().SwitchState(vecStr,DhidState::THROUGH_IN); + nlohmann::json jsonStr; jsonStr[DINPUT_SOFTBUS_KEY_CMD_TYPE] = TRANS_SOURCE_MSG_START_DHID_FOR_REL; jsonStr[DINPUT_SOFTBUS_KEY_DEVICE_ID] = deviceId; @@ -759,6 +782,9 @@ int32_t DistributedInputSourceTransport::StopRemoteInput(const std::string &devi } DHLOGI("StopRemoteInput sessionId:%d.", sessionId); + StateMachine::GetInstance().AddDhids(dhids); + StateMachine::GetInstance().SwitchState(dhids,DhidState::THROUGH_OUT); + nlohmann::json jsonStr; jsonStr[DINPUT_SOFTBUS_KEY_CMD_TYPE] = TRANS_SOURCE_MSG_STOP_DHID; jsonStr[DINPUT_SOFTBUS_KEY_DEVICE_ID] = deviceId; diff --git a/services/state/BUILD.gn b/services/state/BUILD.gn new file mode 100644 index 0000000..97ab868 --- /dev/null +++ b/services/state/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/ohos.gni") +import( + "//foundation/distributedhardware/distributed_input/distributedinput.gni") + +ohos_shared_library("libdinput_state") { + include_dirs = [ + "include", + "${common_path}/include", + "${utils_path}/include", + "${services_sink_path}/inputcollector/include", + "${services_source_path}/inputdevicehandler/include", + "${services_sink_path}/inputcollector/include", + "${frameworks_path}/include", + "${fWK_common_path}/utils/include", + ] + + sources = [ "src/dinput_state.cpp" ] + + defines = [ + "HI_LOG_ENABLE", + "DH_LOG_TAG=\"distributedinputstate\"", + "LOG_DOMAIN=0xD004100", + ] + + deps = [ + "${dfx_utils_path}:libdinput_dfx_utils", + "${services_source_path}/inputinject:libdinput_inject", + "${services_sink_path}/inputcollector:libdinput_collector", + "${utils_path}:libdinput_utils", + "//third_party/libevdev:libevdev", + ] + + external_deps = [ + "c_utils:utils", + "distributed_hardware_fwk:libdhfwk_sdk", + "dsoftbus:softbus_client", + "eventhandler:libeventhandler", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + cflags_cc = [ "-DHILOG_ENABLE" ] + + subsystem_name = "distributedhardware" + + part_name = "distributed_input" +} diff --git a/services/state/include/dinput_state.h b/services/state/include/dinput_state.h new file mode 100644 index 0000000..cbfb450 --- /dev/null +++ b/services/state/include/dinput_state.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DISTRIBUTED_INPUT_STATE_BASE_H +#define DISTRIBUTED_INPUT_STATE_BASE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace OHOS { +namespace DistributedHardware { +namespace DistributedInput { + +enum class DhidState +{ + INIT = 0, + THROUGH_IN, + THROUGH_OUT, +}; + +class StateMachine{ +public: + static StateMachine &GetInstance() { + static StateMachine instance; + return instance; + }; + + int32_t Init(); + int32_t Release(); + int32_t AddDhids(const std::vector &dhids); + int32_t DeleteDhids(const std::vector &dhids); + int32_t SwitchState(const std::vector &dhids, DhidState state); + DhidState GetStateByDhid(std::string &dhid); + +private: + ~StateMachine(); + + void CreateKeyUpInjectThread(const std::vector &dhids); + void CheckKeyState(std::string &dhid, std::string &keyboardNodePath); + void UpInject(int fd, std::vector &keyboardPressedKeys, std::string &dhid); + void KeyUpInject(std::vector &shareDhidsPaths, std::vector &shareDhIds); + bool IsExistDhid(const std::string &dhid); + void RecordEventLog(const input_event& event); + +private: + std::map dhidStateMap_; +}; + +} // namespace DistributedInput +} // namespace DistributedHardware +} // namespace OHOS +#endif // DISTRIBUTED_INPUT_STATE_BASE_H \ No newline at end of file diff --git a/services/state/src/dinput_state.cpp b/services/state/src/dinput_state.cpp new file mode 100644 index 0000000..9b96352 --- /dev/null +++ b/services/state/src/dinput_state.cpp @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "dinput_state.h" + +#include "dinput_errcode.h" +#include "dinput_log.h" +#include "dinput_utils_tool.h" +#include "constants_dinput.h" +#include "distributed_input_collector.h" + +namespace OHOS { +namespace DistributedHardware { +namespace DistributedInput { + +StateMachine::~StateMachine() +{ + Release(); +} + +int32_t StateMachine::Init() +{ + DHLOGI("StateMachine Init."); + return DH_SUCCESS; +} + +int32_t StateMachine::Release() +{ + DHLOGI("StateMachine Release."); + dhidStateMap_.clear(); + return DH_SUCCESS; +} + +int32_t StateMachine::AddDhids(std::vector &dhids) +{ + DHLOGI("AddDhid dhids size = %zu", dhids.size()); + for (auto &dhid : dhids) { + DHLOGD("add dhid : %s", GetAnonyString(dhid).c_str()); + if (IsExistDhid(dhid)) { + DHLOGI("dhid : %s already exist.", GetAnonyString(dhid).c_str()); + } else { + dhidStateMap_[dhid] = DhidState::INIT; + } + } + return DH_SUCCESS; +} + +int32_t StateMachine::DeleteDhids(std::vector &dhids) +{ + DHLOGI("DeleteDhid dhids size = %zu", dhids.size()); + for (auto &dhid : dhids) { + DHLOGD("delete dhid : %s", GetAnonyString(dhid).c_str()); + if (!IsExistDhid(dhid)) { + DHLOGE("dhid : %s not exist.", GetAnonyString(dhid).c_str()); + } else { + dhidStateMap_.erase(dhid); + } + } + return DH_SUCCESS; +} + +int32_t StateMachine::SwitchState(std::vector &dhids, DhidState state) +{ + for (auto &dhid : dhids) { + DHLOGD("SwitchState dhid : %s, state : %d.", GetAnonyString(dhid).c_str(), state); + if (!IsExistDhid(dhid)) { + DHLOGE("dhid : %s not exist.", GetAnonyString(dhid).c_str()); + } else { + dhidStateMap_[dhid] = state; + } + } + + if (state == DhidState::THROUGH_OUT) { + CreateKeyUpInjectThread(dhids); + } + + return DH_SUCCESS; +} + +DhidState StateMachine::GetStateByDhid(std::string &dhid) +{ + if (!IsExistDhid(dhid)) { + DHLOGE("dhid : %s not exist.", GetAnonyString(dhid).c_str()); + return DhidState::INIT; + } + return dhidStateMap_[dhid]; +} + +bool StateMachine::IsExistDhid(std::string &dhid) +{ + if (dhidStateMap_.find(dhid) == dhidStateMap_.end()) { + return false; + } + return true; +} + +void StateMachine::CreateKeyUpInjectThread(const std::vector &dhids) +{ + std::vector keyboardNodePaths; + std::vector shareDhIds; + DistributedInputCollector::GetInstance().GetKeyboardNodePath(dhids, keyboardNodePaths, shareDhIds); + + DistributedInputInject::GetInstance().GetVirtualKeyboardPathByDhId(dhids, keyboardNodePaths, shareDhIds); + + std::thread keyUpInjectThread = + std::thread(&StateMachine::KeyUpInject, this, std::ref(keyboardNodePaths), std::ref(shareDhIds)); + int32_t ret = pthread_setname_np(keyUpInjectThread.native_handle(), KEYBOARD_UP_INJECT_THREAD_NAME); + if (ret != 0) { + DHLOGE("CreateKeyUpInjectThread setname failed."); + } + keyUpInjectThread.detach(); +} + +void StateMachine::KeyUpInject(std::vector &shareDhidsPaths, std::vector &shareDhIds) +{ + ssize len = shareDhidsPaths.size(); + for (int32_t i = 0; i < len; ++i) { + CheckKeyState(shareDhIds[i], shareDhidsPaths[i]); + } +} + +int BitIsSet(const unsigned long *array, int bit) +{ + return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS))); +} + +void StateMachine::CheckKeyState(std::string &dhid, std::string &keyboardNodePath) +{ + char canonicalPath[PATH_MAX + 1] = {0x00}; + if (keyboardNodePath.length() == 0 || keyboardNodePath.length() > PATH_MAX || + realpath(keyboardNodePath.c_str(), canonicalPath) == nullptr) { + DHLOGE("keyboard Nodepath check fail, error path: %s", keyboardNodePath.c_str()); + return; + } + + int fd = open(canonicalPath, O_WRONLY | O_NONBLOCK); + if (fd < 0) { + DHLOGE("open keyboard Node Path error:", errno); + return; + } + + uint32_t count = 0; + std::vector keyboardPressedKeys; + unsigned long keystate[NLONGS(KEY_CNT)] = { 0 }; + while (true) { + if (count > READ_RETRY_MAX) { + break; + } + // Query all key state + int rc = ioctl(fd, EVIOCGKEY(sizeof(keystate)), keystate); + if (rc < 0) { + DHLOGE("read all key state failed, rc=%d ", rc); + count += 1; + std::this_thread::sleep_for(std::chrono::milliseconds(READ_SLEEP_TIME_MS)); + continue; + } + for (int32_t yalv = 0; yalv < KEY_MAX; yalv++) { + if (BitIsSet(keystate, yalv)) { + keyboardPressedKeys.push_back(yalv); + } + } + break; + } + UpInject(fd, keyboardPressedKeys, dhid); + if (fd >= 0) { + close(fd); + fd = -1; + } +} + +void StateMachine::UpInject(int fd, std::vector &keyboardPressedKeys, std::string &dhid) +{ + for (auto &code: keyboardPressedKeys) { + struct input_event event = { + .type = EV_KEY, + .code = code, + .value = KEY_UP_STATE + }; + if (write(fd, &event, sizeof(event)) < static_cast(sizeof(event))) { + DHLOGE("could not inject event, removed? (fd: %d)", fd); + return; + } + RecordEventLog(event); + + struct input_event event = { + .type = EV_SYN, + .code = 0, + .value = KEY_UP_STATE + }; + if (write(fd, &event, sizeof(event)) < static_cast(sizeof(event))) { + DHLOGE("could not inject event, removed? (fd: %d)", fd); + return; + } + RecordEventLog(event); + } +} + +void StateMachine::RecordEventLog(const input_event& event) +{ + std::string eventType = ""; + switch (event.type) { + case EV_KEY: + eventType = "EV_KEY"; + break; + case EV_REL: + eventType = "EV_REL"; + break; + case EV_ABS: + eventType = "EV_ABS"; + break; + default: + eventType = "other type"; + break; + } + DHLOGD("4.E2E-Test Source write event into input driver, EventType: %s, Code: %d, Value: %d, Sec: %ld, Sec1: %ld", + eventType.c_str(), event.code, event.value, event.input_event_sec, event.input_event_usec); +} + +} // namespace DistributedInput +} // namespace DistributedHardware +} // namespace OHOSs \ No newline at end of file diff --git a/sourcehandler/BUILD.gn b/sourcehandler/BUILD.gn index 2c927d1..2cf11d7 100644 --- a/sourcehandler/BUILD.gn +++ b/sourcehandler/BUILD.gn @@ -33,6 +33,7 @@ ohos_shared_library("libdinput_source_handler") { "${fwk_interfaces_path}/include/ipc", "${utils_path}/include", "${services_source_path}/inputinject/include", + "${distributedinput_path}/services/state/include", ] sources = [