• 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 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