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