1 /*
2 * Copyright (c) 2025 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 "key_monitor_manager.h"
17
18 #include "define_multimodal.h"
19 #include "event_log_helper.h"
20 #include "input_event_data_transformation.h"
21 #include "input_event_handler.h"
22 #include "key_auto_repeat.h"
23 #include "timer_manager.h"
24
25 #undef MMI_LOG_DOMAIN
26 #define MMI_LOG_DOMAIN MMI_LOG_HANDLER
27 #undef MMI_LOG_TAG
28 #define MMI_LOG_TAG "KeyMonitorManager"
29
30 namespace OHOS {
31 namespace MMI {
32 namespace {
33 constexpr int32_t REPEAT_ONCE { 1 };
34 }
35
36 std::mutex KeyMonitorManager::mutex_;
37 std::shared_ptr<KeyMonitorManager> KeyMonitorManager::instance_;
38
39 const std::set<int32_t> KeyMonitorManager::allowedKeys_ {
40 KeyEvent::KEYCODE_VOLUME_DOWN,
41 KeyEvent::KEYCODE_VOLUME_UP,
42 };
43
GetInstance()44 std::shared_ptr<KeyMonitorManager> KeyMonitorManager::GetInstance()
45 {
46 if (instance_ == nullptr) {
47 std::lock_guard<std::mutex> guard(mutex_);
48 if (instance_ == nullptr) {
49 instance_ = std::make_shared<KeyMonitorManager>();
50 }
51 }
52 return instance_;
53 }
54
operator <(const Monitor & other) const55 bool KeyMonitorManager::Monitor::operator<(const Monitor &other) const
56 {
57 if (session_ != other.session_) {
58 return (session_ < other.session_);
59 }
60 if (key_ != other.key_) {
61 return (key_ < other.key_);
62 }
63 if (action_ != other.action_) {
64 return (action_ < other.action_);
65 }
66 return (isRepeat_ < other.isRepeat_);
67 }
68
Dump() const69 std::string KeyMonitorManager::Monitor::Dump() const
70 {
71 std::ostringstream sMonitor;
72 sMonitor << "Session:" << session_ << ",Key:" << key_ << ",Action:" << action_
73 << ",IsRepeat:" << std::boolalpha << isRepeat_;
74 return std::move(sMonitor).str();
75 }
76
IsFocused() const77 bool KeyMonitorManager::Monitor::IsFocused() const
78 {
79 return WIN_MGR->IsFocusedSession(session_);
80 }
81
Want(std::shared_ptr<KeyEvent> keyEvent) const82 bool KeyMonitorManager::Monitor::Want(std::shared_ptr<KeyEvent> keyEvent) const
83 {
84 return ((key_ == keyEvent->GetKeyCode()) &&
85 (action_ == keyEvent->GetKeyAction()) &&
86 (isRepeat_ ||
87 (keyEvent->GetKeyAction() != KeyEvent::KEY_ACTION_DOWN) ||
88 (keyEvent->GetKeyCode() != KeyRepeat->GetRepeatKeyCode())));
89 }
90
KeyMonitorManager()91 KeyMonitorManager::KeyMonitorManager()
92 {
93 auto udsServer = InputHandler->GetUDSServer();
94 if (udsServer != nullptr) {
95 udsServer->AddSessionDeletedCallback([this](SessionPtr sess) {
96 CHKPV(sess);
97 OnSessionLost(sess->GetPid());
98 });
99 }
100 }
101
AddMonitor(const Monitor & monitor)102 int32_t KeyMonitorManager::AddMonitor(const Monitor &monitor)
103 {
104 MMI_HILOGI("Add key monitor(%{public}s)", monitor.Dump().c_str());
105 if (!CheckMonitor(monitor)) {
106 MMI_HILOGE("Invalid monitor(%{public}s)", monitor.Dump().c_str());
107 return KEY_MONITOR_ERROR_INVALID_MONITOR;
108 }
109 auto [_, isNew] = monitors_.emplace(monitor);
110 if (!isNew) {
111 MMI_HILOGW("Duplicate registration of monitor(%{public}s)", monitor.Dump().c_str());
112 }
113 return RET_OK;
114 }
115
RemoveMonitor(const Monitor & monitor)116 void KeyMonitorManager::RemoveMonitor(const Monitor &monitor)
117 {
118 MMI_HILOGI("Remove key monitor(%{public}s)", monitor.Dump().c_str());
119 auto iter = monitors_.find(monitor);
120 if (iter == monitors_.cend()) {
121 MMI_HILOGW("No key monitor(%{public}s)", monitor.Dump().c_str());
122 return;
123 }
124 monitors_.erase(iter);
125 }
126
Intercept(std::shared_ptr<KeyEvent> keyEvent)127 bool KeyMonitorManager::Intercept(std::shared_ptr<KeyEvent> keyEvent)
128 {
129 CHKPF(keyEvent);
130 std::set<int32_t> sessions;
131
132 auto nTriggered = std::count_if(monitors_.cbegin(), monitors_.cend(),
133 [this, keyEvent, &sessions](const auto &monitor) {
134 if (monitor.Want(keyEvent) &&
135 monitor.IsFocused() &&
136 (sessions.find(monitor.session_) == sessions.cend())) {
137 sessions.emplace(monitor.session_);
138 NotifyKeyMonitor(keyEvent, monitor.session_);
139 return true;
140 }
141 return false;
142 });
143 return (nTriggered > 0);
144 }
145
Intercept(std::shared_ptr<KeyEvent> keyEvent,int32_t delay)146 bool KeyMonitorManager::Intercept(std::shared_ptr<KeyEvent> keyEvent, int32_t delay)
147 {
148 CHKPF(keyEvent);
149 if ((keyEvent->GetKeyAction() != KeyEvent::KEY_ACTION_DOWN) || (delay <= 0)) {
150 return false;
151 }
152 std::set<int32_t> sessions;
153 auto nTriggered = std::count_if(monitors_.cbegin(), monitors_.cend(),
154 [this, keyEvent, delay, &sessions](const auto &monitor) {
155 if (!monitor.Want(keyEvent)) {
156 return false;
157 }
158 if (!monitor.IsFocused()) {
159 return false;
160 }
161 if (pending_.find(monitor) != pending_.cend()) {
162 return true;
163 }
164 if (sessions.find(monitor.session_) != sessions.cend()) {
165 return false;
166 }
167 sessions.emplace(monitor.session_);
168 auto tKeyEvent = KeyEvent::Clone(keyEvent);
169 auto timerId = TimerMgr->AddTimer(delay, REPEAT_ONCE,
170 [this, monitor, tKeyEvent]() {
171 pending_.erase(monitor);
172 NotifyKeyMonitor(tKeyEvent, monitor.session_);
173 });
174 if (timerId < 0) {
175 MMI_HILOGE("AddTimer fail");
176 return false;
177 }
178 pending_.emplace(monitor, PendingMonitor {
179 .timerId_ = timerId,
180 .keyEvent_ = tKeyEvent,
181 });
182 return true;
183 });
184 return (nTriggered > 0);
185 }
186
NotifyPendingMonitors()187 void KeyMonitorManager::NotifyPendingMonitors()
188 {
189 for (const auto &[monitor, pendingData] : pending_) {
190 TimerMgr->RemoveTimer(pendingData.timerId_);
191 NotifyKeyMonitor(pendingData.keyEvent_, monitor.session_);
192 };
193 pending_.clear();
194 }
195
ResetAll()196 void KeyMonitorManager::ResetAll()
197 {
198 std::for_each(pending_.cbegin(), pending_.cbegin(), [](const auto &item) {
199 TimerMgr->RemoveTimer(item.second.timerId_);
200 });
201 pending_.clear();
202 }
203
OnSessionLost(int32_t session)204 void KeyMonitorManager::OnSessionLost(int32_t session)
205 {
206 MMI_HILOGI("Session(%{public}d) is lost", session);
207 for (auto mIter = monitors_.cbegin(); mIter != monitors_.cend();) {
208 if (mIter->session_ == session) {
209 mIter = monitors_.erase(mIter);
210 } else {
211 ++mIter;
212 }
213 }
214 }
215
CheckMonitor(const Monitor & monitor)216 bool KeyMonitorManager::CheckMonitor(const Monitor &monitor)
217 {
218 return (allowedKeys_.find(monitor.key_) != allowedKeys_.cend());
219 }
220
NotifyKeyMonitor(std::shared_ptr<KeyEvent> keyEvent,int32_t session)221 void KeyMonitorManager::NotifyKeyMonitor(std::shared_ptr<KeyEvent> keyEvent, int32_t session)
222 {
223 CALL_DEBUG_ENTER;
224 NetPacket pkt(MmiMessageId::ON_SUBSCRIBE_KEY_MONITOR);
225 InputEventDataTransformation::KeyEventToNetPacket(keyEvent, pkt);
226 if (pkt.ChkRWError()) {
227 MMI_HILOGE("Failed to package key event(No:%{public}d)", keyEvent->GetId());
228 return;
229 }
230 auto udsServer = InputHandler->GetUDSServer();
231 CHKPV(udsServer);
232 auto fd = udsServer->GetClientFd(session);
233 if (!udsServer->SendMsg(fd, pkt)) {
234 MMI_HILOGE("Failed to nitofy key monitor");
235 return;
236 }
237 if (!EventLogHelper::IsBetaVersion()) {
238 MMI_HILOGI("Notify key monitor(PID:%{public}d)", session);
239 } else {
240 if (EventLogHelper::IsBetaVersion() && !keyEvent->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) {
241 MMI_HILOGI("Notify key monitor(KC:%d, KA:%{public}d, PID:%{public}d)",
242 keyEvent->GetKeyCode(), keyEvent->GetKeyAction(), session);
243 } else {
244 MMI_HILOGI("Notify key monitor(KC:%{private}d, KA:%{public}d, PID:%{public}d)",
245 keyEvent->GetKeyCode(), keyEvent->GetKeyAction(), session);
246 }
247 }
248 }
249 } // namespace MMI
250 } // namespace OHOS
251