• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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