1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#include "key_gesture_manager.h"
17c29fa5a6Sopenharmony_ci
18c29fa5a6Sopenharmony_ci#include <algorithm>
19c29fa5a6Sopenharmony_ci
20c29fa5a6Sopenharmony_ci#include "account_manager.h"
21c29fa5a6Sopenharmony_ci#include "app_state_observer.h"
22c29fa5a6Sopenharmony_ci#include "define_multimodal.h"
23c29fa5a6Sopenharmony_ci#include "display_event_monitor.h"
24c29fa5a6Sopenharmony_ci#include "event_log_helper.h"
25c29fa5a6Sopenharmony_ci#include "timer_manager.h"
26c29fa5a6Sopenharmony_ci#include "util.h"
27c29fa5a6Sopenharmony_ci
28c29fa5a6Sopenharmony_ci#undef MMI_LOG_DOMAIN
29c29fa5a6Sopenharmony_ci#define MMI_LOG_DOMAIN MMI_LOG_HANDLER
30c29fa5a6Sopenharmony_ci#undef MMI_LOG_TAG
31c29fa5a6Sopenharmony_ci#define MMI_LOG_TAG "KeyGestureManager"
32c29fa5a6Sopenharmony_ci
33c29fa5a6Sopenharmony_cinamespace OHOS {
34c29fa5a6Sopenharmony_cinamespace MMI {
35c29fa5a6Sopenharmony_cinamespace {
36c29fa5a6Sopenharmony_ciconstexpr int32_t COMBINATION_KEY_TIMEOUT { 150 };
37c29fa5a6Sopenharmony_ciconstexpr int32_t INVALID_ENTITY_ID { -1 };
38c29fa5a6Sopenharmony_ciconstexpr int32_t REPEAT_ONCE { 1 };
39c29fa5a6Sopenharmony_ciconstexpr size_t MAX_N_PRINTABLE_ITEMS { 5 };
40c29fa5a6Sopenharmony_ciconstexpr size_t SINGLE_KEY_PRESSED { 1 };
41c29fa5a6Sopenharmony_ci}
42c29fa5a6Sopenharmony_ci
43c29fa5a6Sopenharmony_ciKeyGestureManager::Handler::~Handler()
44c29fa5a6Sopenharmony_ci{
45c29fa5a6Sopenharmony_ci    ResetTimer();
46c29fa5a6Sopenharmony_ci}
47c29fa5a6Sopenharmony_ci
48c29fa5a6Sopenharmony_civoid KeyGestureManager::Handler::ResetTimer()
49c29fa5a6Sopenharmony_ci{
50c29fa5a6Sopenharmony_ci    if (timerId_ >= 0) {
51c29fa5a6Sopenharmony_ci        TimerMgr->RemoveTimer(timerId_);
52c29fa5a6Sopenharmony_ci        timerId_ = INVALID_ENTITY_ID;
53c29fa5a6Sopenharmony_ci    }
54c29fa5a6Sopenharmony_ci}
55c29fa5a6Sopenharmony_ci
56c29fa5a6Sopenharmony_civoid KeyGestureManager::Handler::Trigger(std::shared_ptr<KeyEvent> keyEvent)
57c29fa5a6Sopenharmony_ci{
58c29fa5a6Sopenharmony_ci    MMI_HILOGI("[Handler] Handler will run after %{public}dms", GetLongPressTime());
59c29fa5a6Sopenharmony_ci    keyEvent_ = KeyEvent::Clone(keyEvent);
60c29fa5a6Sopenharmony_ci    timerId_ = TimerMgr->AddTimer(GetLongPressTime(), REPEAT_ONCE,
61c29fa5a6Sopenharmony_ci        [this]() {
62c29fa5a6Sopenharmony_ci            CHKPV(keyEvent_);
63c29fa5a6Sopenharmony_ci            Run(keyEvent_);
64c29fa5a6Sopenharmony_ci            keyEvent_ = nullptr;
65c29fa5a6Sopenharmony_ci            timerId_ = INVALID_ENTITY_ID;
66c29fa5a6Sopenharmony_ci        });
67c29fa5a6Sopenharmony_ci    if (timerId_ < 0) {
68c29fa5a6Sopenharmony_ci        MMI_HILOGI("[Handler] AddTimer fail");
69c29fa5a6Sopenharmony_ci    }
70c29fa5a6Sopenharmony_ci}
71c29fa5a6Sopenharmony_ci
72c29fa5a6Sopenharmony_civoid KeyGestureManager::Handler::Run(std::shared_ptr<KeyEvent> keyEvent) const
73c29fa5a6Sopenharmony_ci{
74c29fa5a6Sopenharmony_ci    if (callback_ != nullptr) {
75c29fa5a6Sopenharmony_ci        callback_(keyEvent);
76c29fa5a6Sopenharmony_ci    }
77c29fa5a6Sopenharmony_ci}
78c29fa5a6Sopenharmony_ci
79c29fa5a6Sopenharmony_civoid KeyGestureManager::Handler::RunPending()
80c29fa5a6Sopenharmony_ci{
81c29fa5a6Sopenharmony_ci    if (keyEvent_ != nullptr) {
82c29fa5a6Sopenharmony_ci        Run(keyEvent_);
83c29fa5a6Sopenharmony_ci        keyEvent_ = nullptr;
84c29fa5a6Sopenharmony_ci    }
85c29fa5a6Sopenharmony_ci}
86c29fa5a6Sopenharmony_ci
87c29fa5a6Sopenharmony_cibool KeyGestureManager::KeyGesture::IsWorking()
88c29fa5a6Sopenharmony_ci{
89c29fa5a6Sopenharmony_ci    return true;
90c29fa5a6Sopenharmony_ci}
91c29fa5a6Sopenharmony_ci
92c29fa5a6Sopenharmony_ciint32_t KeyGestureManager::KeyGesture::AddHandler(int32_t pid, int32_t longPressTime,
93c29fa5a6Sopenharmony_ci    std::function<void(std::shared_ptr<KeyEvent>)> callback)
94c29fa5a6Sopenharmony_ci{
95c29fa5a6Sopenharmony_ci    static int32_t baseId { 0 };
96c29fa5a6Sopenharmony_ci
97c29fa5a6Sopenharmony_ci    longPressTime = std::max(longPressTime, COMBINATION_KEY_TIMEOUT);
98c29fa5a6Sopenharmony_ci    return handlers_.emplace_back(++baseId, pid, longPressTime, callback).GetId();
99c29fa5a6Sopenharmony_ci}
100c29fa5a6Sopenharmony_ci
101c29fa5a6Sopenharmony_cibool KeyGestureManager::KeyGesture::RemoveHandler(int32_t id)
102c29fa5a6Sopenharmony_ci{
103c29fa5a6Sopenharmony_ci    for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) {
104c29fa5a6Sopenharmony_ci        if (iter->GetId() == id) {
105c29fa5a6Sopenharmony_ci            iter->ResetTimer();
106c29fa5a6Sopenharmony_ci            handlers_.erase(iter);
107c29fa5a6Sopenharmony_ci            MMI_HILOGI("Handler(%{public}d) of key gesture was removed", iter->GetId());
108c29fa5a6Sopenharmony_ci            return true;
109c29fa5a6Sopenharmony_ci        }
110c29fa5a6Sopenharmony_ci    }
111c29fa5a6Sopenharmony_ci    return false;
112c29fa5a6Sopenharmony_ci}
113c29fa5a6Sopenharmony_ci
114c29fa5a6Sopenharmony_civoid KeyGestureManager::KeyGesture::Reset()
115c29fa5a6Sopenharmony_ci{
116c29fa5a6Sopenharmony_ci    MarkActive(false);
117c29fa5a6Sopenharmony_ci    ResetTimers();
118c29fa5a6Sopenharmony_ci}
119c29fa5a6Sopenharmony_ci
120c29fa5a6Sopenharmony_civoid KeyGestureManager::KeyGesture::ResetTimers()
121c29fa5a6Sopenharmony_ci{
122c29fa5a6Sopenharmony_ci    for (auto &handler : handlers_) {
123c29fa5a6Sopenharmony_ci        handler.ResetTimer();
124c29fa5a6Sopenharmony_ci    }
125c29fa5a6Sopenharmony_ci}
126c29fa5a6Sopenharmony_ci
127c29fa5a6Sopenharmony_cistd::set<int32_t> KeyGestureManager::KeyGesture::GetForegroundPids() const
128c29fa5a6Sopenharmony_ci{
129c29fa5a6Sopenharmony_ci    std::set<int32_t> pids;
130c29fa5a6Sopenharmony_ci    std::vector<AppExecFwk::AppStateData> appStates = APP_OBSERVER_MGR->GetForegroundAppData();
131c29fa5a6Sopenharmony_ci    std::for_each(appStates.cbegin(), appStates.cend(), [&pids](auto &appState) {
132c29fa5a6Sopenharmony_ci        pids.insert(appState.pid);
133c29fa5a6Sopenharmony_ci    });
134c29fa5a6Sopenharmony_ci
135c29fa5a6Sopenharmony_ci    std::ostringstream sPids;
136c29fa5a6Sopenharmony_ci    size_t nItems = 0;
137c29fa5a6Sopenharmony_ci
138c29fa5a6Sopenharmony_ci    if (auto iter = pids.cbegin(); iter != pids.cend()) {
139c29fa5a6Sopenharmony_ci        sPids << *iter;
140c29fa5a6Sopenharmony_ci        ++nItems;
141c29fa5a6Sopenharmony_ci
142c29fa5a6Sopenharmony_ci        for (++iter; iter != pids.cend(); ++iter) {
143c29fa5a6Sopenharmony_ci            if (nItems > MAX_N_PRINTABLE_ITEMS) {
144c29fa5a6Sopenharmony_ci                sPids << ",...";
145c29fa5a6Sopenharmony_ci                break;
146c29fa5a6Sopenharmony_ci            }
147c29fa5a6Sopenharmony_ci            sPids << "," << *iter;
148c29fa5a6Sopenharmony_ci            ++nItems;
149c29fa5a6Sopenharmony_ci        }
150c29fa5a6Sopenharmony_ci    }
151c29fa5a6Sopenharmony_ci    MMI_HILOGI("Foreground pids: {%{public}zu}[%{public}s]", pids.size(), sPids.str().c_str());
152c29fa5a6Sopenharmony_ci    return pids;
153c29fa5a6Sopenharmony_ci}
154c29fa5a6Sopenharmony_ci
155c29fa5a6Sopenharmony_cibool KeyGestureManager::KeyGesture::HaveForegroundHandler(const std::set<int32_t> &foregroundApps) const
156c29fa5a6Sopenharmony_ci{
157c29fa5a6Sopenharmony_ci    return std::any_of(handlers_.cbegin(), handlers_.cend(), [&foregroundApps](const auto &handler) {
158c29fa5a6Sopenharmony_ci        return (foregroundApps.find(handler.GetPid()) != foregroundApps.cend());
159c29fa5a6Sopenharmony_ci    });
160c29fa5a6Sopenharmony_ci}
161c29fa5a6Sopenharmony_ci
162c29fa5a6Sopenharmony_civoid KeyGestureManager::KeyGesture::TriggerHandlers(std::shared_ptr<KeyEvent> keyEvent)
163c29fa5a6Sopenharmony_ci{
164c29fa5a6Sopenharmony_ci    std::set<int32_t> foregroundPids = GetForegroundPids();
165c29fa5a6Sopenharmony_ci    bool haveForeground = HaveForegroundHandler(foregroundPids);
166c29fa5a6Sopenharmony_ci    ShowHandlers(std::string("TriggerHandlers"), foregroundPids);
167c29fa5a6Sopenharmony_ci
168c29fa5a6Sopenharmony_ci    for (auto &handler : handlers_) {
169c29fa5a6Sopenharmony_ci        if (!haveForeground || (foregroundPids.find(handler.GetPid()) != foregroundPids.end())) {
170c29fa5a6Sopenharmony_ci            handler.Trigger(keyEvent);
171c29fa5a6Sopenharmony_ci        }
172c29fa5a6Sopenharmony_ci    }
173c29fa5a6Sopenharmony_ci}
174c29fa5a6Sopenharmony_ci
175c29fa5a6Sopenharmony_civoid KeyGestureManager::KeyGesture::RunHandler(int32_t handlerId, std::shared_ptr<KeyEvent> keyEvent)
176c29fa5a6Sopenharmony_ci{
177c29fa5a6Sopenharmony_ci    for (auto &handler : handlers_) {
178c29fa5a6Sopenharmony_ci        if (handler.GetId() == handlerId) {
179c29fa5a6Sopenharmony_ci            handler.ResetTimer();
180c29fa5a6Sopenharmony_ci            handler.Run(keyEvent);
181c29fa5a6Sopenharmony_ci            break;
182c29fa5a6Sopenharmony_ci        }
183c29fa5a6Sopenharmony_ci    }
184c29fa5a6Sopenharmony_ci}
185c29fa5a6Sopenharmony_ci
186c29fa5a6Sopenharmony_civoid KeyGestureManager::KeyGesture::NotifyHandlers(std::shared_ptr<KeyEvent> keyEvent)
187c29fa5a6Sopenharmony_ci{
188c29fa5a6Sopenharmony_ci    std::set<int32_t> foregroundPids = GetForegroundPids();
189c29fa5a6Sopenharmony_ci    bool haveForeground = HaveForegroundHandler(foregroundPids);
190c29fa5a6Sopenharmony_ci    ShowHandlers(std::string("NotifyHandlers"), foregroundPids);
191c29fa5a6Sopenharmony_ci
192c29fa5a6Sopenharmony_ci    for (auto &handler : handlers_) {
193c29fa5a6Sopenharmony_ci        if (!haveForeground || (foregroundPids.find(handler.GetPid()) != foregroundPids.end())) {
194c29fa5a6Sopenharmony_ci            handler.Run(keyEvent);
195c29fa5a6Sopenharmony_ci        }
196c29fa5a6Sopenharmony_ci    }
197c29fa5a6Sopenharmony_ci}
198c29fa5a6Sopenharmony_ci
199c29fa5a6Sopenharmony_civoid KeyGestureManager::KeyGesture::ShowHandlers(
200c29fa5a6Sopenharmony_ci    const std::string &prefix, const std::set<int32_t> &foregroundPids) const
201c29fa5a6Sopenharmony_ci{
202c29fa5a6Sopenharmony_ci    std::ostringstream output;
203c29fa5a6Sopenharmony_ci    size_t nHandlers = 0;
204c29fa5a6Sopenharmony_ci
205c29fa5a6Sopenharmony_ci    for (const auto &handler : handlers_) {
206c29fa5a6Sopenharmony_ci        if (nHandlers > MAX_N_PRINTABLE_ITEMS) {
207c29fa5a6Sopenharmony_ci            output << "...";
208c29fa5a6Sopenharmony_ci            break;
209c29fa5a6Sopenharmony_ci        }
210c29fa5a6Sopenharmony_ci        ++nHandlers;
211c29fa5a6Sopenharmony_ci        output << "[" << handler.GetId() << "," << handler.GetPid()
212c29fa5a6Sopenharmony_ci            << (foregroundPids.find(handler.GetPid()) != foregroundPids.cend() ? ",F]" : ",B]");
213c29fa5a6Sopenharmony_ci    }
214c29fa5a6Sopenharmony_ci    MMI_HILOGI("[KeyGesture] %{public}s {%{public}zu}%{public}s",
215c29fa5a6Sopenharmony_ci        prefix.c_str(), handlers_.size(), output.str().c_str());
216c29fa5a6Sopenharmony_ci}
217c29fa5a6Sopenharmony_ci
218c29fa5a6Sopenharmony_cibool KeyGestureManager::LongPressSingleKey::ShouldIntercept(std::shared_ptr<KeyOption> keyOption) const
219c29fa5a6Sopenharmony_ci{
220c29fa5a6Sopenharmony_ci    std::set<int32_t> keys = keyOption->GetPreKeys();
221c29fa5a6Sopenharmony_ci    return (keys.empty() &&
222c29fa5a6Sopenharmony_ci            (keyOption->GetFinalKey() == keyCode_) &&
223c29fa5a6Sopenharmony_ci            keyOption->IsFinalKeyDown() &&
224c29fa5a6Sopenharmony_ci            (keyOption->GetFinalKeyDownDuration() < COMBINATION_KEY_TIMEOUT));
225c29fa5a6Sopenharmony_ci}
226c29fa5a6Sopenharmony_ci
227c29fa5a6Sopenharmony_cibool KeyGestureManager::LongPressSingleKey::Intercept(std::shared_ptr<KeyEvent> keyEvent)
228c29fa5a6Sopenharmony_ci{
229c29fa5a6Sopenharmony_ci    if ((keyEvent->GetKeyCode() == keyCode_) && (keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_DOWN)) {
230c29fa5a6Sopenharmony_ci        if (IsActive()) {
231c29fa5a6Sopenharmony_ci            int64_t now = GetSysClockTime();
232c29fa5a6Sopenharmony_ci            if (now >= (firstDownTime_ + MS2US(COMBINATION_KEY_TIMEOUT))) {
233c29fa5a6Sopenharmony_ci                NotifyHandlers(keyEvent);
234c29fa5a6Sopenharmony_ci            }
235c29fa5a6Sopenharmony_ci        } else {
236c29fa5a6Sopenharmony_ci            firstDownTime_ = GetSysClockTime();
237c29fa5a6Sopenharmony_ci            MarkActive(true);
238c29fa5a6Sopenharmony_ci            TriggerHandlers(keyEvent);
239c29fa5a6Sopenharmony_ci        }
240c29fa5a6Sopenharmony_ci        return true;
241c29fa5a6Sopenharmony_ci    }
242c29fa5a6Sopenharmony_ci    if (IsActive()) {
243c29fa5a6Sopenharmony_ci        Reset();
244c29fa5a6Sopenharmony_ci        RunPendingHandlers();
245c29fa5a6Sopenharmony_ci    }
246c29fa5a6Sopenharmony_ci    return false;
247c29fa5a6Sopenharmony_ci}
248c29fa5a6Sopenharmony_ci
249c29fa5a6Sopenharmony_civoid KeyGestureManager::LongPressSingleKey::Dump(std::ostringstream &output) const
250c29fa5a6Sopenharmony_ci{
251c29fa5a6Sopenharmony_ci    output << "[" << keyCode_ << "] --> {";
252c29fa5a6Sopenharmony_ci    if (auto iter = handlers_.begin(); iter != handlers_.end()) {
253c29fa5a6Sopenharmony_ci        output << iter->GetLongPressTime();
254c29fa5a6Sopenharmony_ci        for (++iter; iter != handlers_.end(); ++iter) {
255c29fa5a6Sopenharmony_ci            output << "," << iter->GetLongPressTime();
256c29fa5a6Sopenharmony_ci        }
257c29fa5a6Sopenharmony_ci    }
258c29fa5a6Sopenharmony_ci    output << "}";
259c29fa5a6Sopenharmony_ci}
260c29fa5a6Sopenharmony_ci
261c29fa5a6Sopenharmony_civoid KeyGestureManager::LongPressSingleKey::RunPendingHandlers()
262c29fa5a6Sopenharmony_ci{
263c29fa5a6Sopenharmony_ci    std::set<int32_t> foregroundPids = GetForegroundPids();
264c29fa5a6Sopenharmony_ci    bool haveForeground = HaveForegroundHandler(foregroundPids);
265c29fa5a6Sopenharmony_ci    ShowHandlers(std::string("RunPendingHandlers"), foregroundPids);
266c29fa5a6Sopenharmony_ci
267c29fa5a6Sopenharmony_ci    for (auto &handler : handlers_) {
268c29fa5a6Sopenharmony_ci        if (!haveForeground || (foregroundPids.find(handler.GetPid()) != foregroundPids.end())) {
269c29fa5a6Sopenharmony_ci            handler.RunPending();
270c29fa5a6Sopenharmony_ci        }
271c29fa5a6Sopenharmony_ci    }
272c29fa5a6Sopenharmony_ci}
273c29fa5a6Sopenharmony_ci
274c29fa5a6Sopenharmony_cibool KeyGestureManager::LongPressCombinationKey::ShouldIntercept(std::shared_ptr<KeyOption> keyOption) const
275c29fa5a6Sopenharmony_ci{
276c29fa5a6Sopenharmony_ci    std::set<int32_t> keys = keyOption->GetPreKeys();
277c29fa5a6Sopenharmony_ci    keys.insert(keyOption->GetFinalKey());
278c29fa5a6Sopenharmony_ci    return (keys_ == keys);
279c29fa5a6Sopenharmony_ci}
280c29fa5a6Sopenharmony_ci
281c29fa5a6Sopenharmony_cibool KeyGestureManager::LongPressCombinationKey::Intercept(std::shared_ptr<KeyEvent> keyEvent)
282c29fa5a6Sopenharmony_ci{
283c29fa5a6Sopenharmony_ci    if ((keys_.find(keyEvent->GetKeyCode()) != keys_.end()) &&
284c29fa5a6Sopenharmony_ci        (keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_DOWN)) {
285c29fa5a6Sopenharmony_ci        if (IsActive()) {
286c29fa5a6Sopenharmony_ci            std::ostringstream output;
287c29fa5a6Sopenharmony_ci            Dump(output);
288c29fa5a6Sopenharmony_ci            if (EventLogHelper::IsBetaVersion() && !keyEvent->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) {
289c29fa5a6Sopenharmony_ci                MMI_HILOGI("[LongPressCombinationKey] %{public}s is active now", output.str().c_str());
290c29fa5a6Sopenharmony_ci            } else {
291c29fa5a6Sopenharmony_ci                MMI_HILOGI("[LongPressCombinationKey] %s is active now", output.str().c_str());
292c29fa5a6Sopenharmony_ci            }
293c29fa5a6Sopenharmony_ci            return true;
294c29fa5a6Sopenharmony_ci        }
295c29fa5a6Sopenharmony_ci        if (!IsWorking()) {
296c29fa5a6Sopenharmony_ci            std::ostringstream output;
297c29fa5a6Sopenharmony_ci            Dump(output);
298c29fa5a6Sopenharmony_ci            if (EventLogHelper::IsBetaVersion() && !keyEvent->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) {
299c29fa5a6Sopenharmony_ci                MMI_HILOGI("[LongPressCombinationKey] Switch off %{public}s", output.str().c_str());
300c29fa5a6Sopenharmony_ci            } else {
301c29fa5a6Sopenharmony_ci                MMI_HILOGI("[LongPressCombinationKey] Switch off %s", output.str().c_str());
302c29fa5a6Sopenharmony_ci            }
303c29fa5a6Sopenharmony_ci            return false;
304c29fa5a6Sopenharmony_ci        }
305c29fa5a6Sopenharmony_ci        if (handlers_.empty()) {
306c29fa5a6Sopenharmony_ci            std::ostringstream output;
307c29fa5a6Sopenharmony_ci            Dump(output);
308c29fa5a6Sopenharmony_ci            if (EventLogHelper::IsBetaVersion() && !keyEvent->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) {
309c29fa5a6Sopenharmony_ci                MMI_HILOGI("[LongPressCombinationKey] No handler for %{public}s", output.str().c_str());
310c29fa5a6Sopenharmony_ci            } else {
311c29fa5a6Sopenharmony_ci                MMI_HILOGI("[LongPressCombinationKey] No handler for %s", output.str().c_str());
312c29fa5a6Sopenharmony_ci            }
313c29fa5a6Sopenharmony_ci            return false;
314c29fa5a6Sopenharmony_ci        }
315c29fa5a6Sopenharmony_ci        if (RecognizeGesture(keyEvent)) {
316c29fa5a6Sopenharmony_ci            TriggerAll(keyEvent);
317c29fa5a6Sopenharmony_ci            return true;
318c29fa5a6Sopenharmony_ci        }
319c29fa5a6Sopenharmony_ci    }
320c29fa5a6Sopenharmony_ci    if (IsActive()) {
321c29fa5a6Sopenharmony_ci        Reset();
322c29fa5a6Sopenharmony_ci    }
323c29fa5a6Sopenharmony_ci    return false;
324c29fa5a6Sopenharmony_ci}
325c29fa5a6Sopenharmony_ci
326c29fa5a6Sopenharmony_civoid KeyGestureManager::LongPressCombinationKey::Dump(std::ostringstream &output) const
327c29fa5a6Sopenharmony_ci{
328c29fa5a6Sopenharmony_ci    output << "[";
329c29fa5a6Sopenharmony_ci    if (auto keyIter = keys_.begin(); keyIter != keys_.end()) {
330c29fa5a6Sopenharmony_ci        output << *keyIter;
331c29fa5a6Sopenharmony_ci        for (++keyIter; keyIter != keys_.end(); ++keyIter) {
332c29fa5a6Sopenharmony_ci            output << "," << *keyIter;
333c29fa5a6Sopenharmony_ci        }
334c29fa5a6Sopenharmony_ci    }
335c29fa5a6Sopenharmony_ci    output << "] --> {";
336c29fa5a6Sopenharmony_ci    if (auto iter = handlers_.begin(); iter != handlers_.end()) {
337c29fa5a6Sopenharmony_ci        output << "(ID:" << iter->GetId() << ",T:" << iter->GetLongPressTime() << ")";
338c29fa5a6Sopenharmony_ci        for (++iter; iter != handlers_.end(); ++iter) {
339c29fa5a6Sopenharmony_ci            output << ",(ID:" << iter->GetId() << ",T:" << iter->GetLongPressTime() << ")";
340c29fa5a6Sopenharmony_ci        }
341c29fa5a6Sopenharmony_ci    }
342c29fa5a6Sopenharmony_ci    output << "}";
343c29fa5a6Sopenharmony_ci}
344c29fa5a6Sopenharmony_ci
345c29fa5a6Sopenharmony_cibool KeyGestureManager::LongPressCombinationKey::RecognizeGesture(std::shared_ptr<KeyEvent> keyEvent)
346c29fa5a6Sopenharmony_ci{
347c29fa5a6Sopenharmony_ci    if (keyEvent->GetPressedKeys().size() == SINGLE_KEY_PRESSED) {
348c29fa5a6Sopenharmony_ci        firstDownTime_ = GetSysClockTime();
349c29fa5a6Sopenharmony_ci    }
350c29fa5a6Sopenharmony_ci    int64_t now = GetSysClockTime();
351c29fa5a6Sopenharmony_ci    return std::all_of(keys_.cbegin(), keys_.cend(), [this, keyEvent, now](auto keyCode) {
352c29fa5a6Sopenharmony_ci        auto itemOpt = keyEvent->GetKeyItem(keyCode);
353c29fa5a6Sopenharmony_ci        return (itemOpt && itemOpt->IsPressed() &&
354c29fa5a6Sopenharmony_ci                (now < (firstDownTime_ + MS2US(COMBINATION_KEY_TIMEOUT))));
355c29fa5a6Sopenharmony_ci    });
356c29fa5a6Sopenharmony_ci}
357c29fa5a6Sopenharmony_ci
358c29fa5a6Sopenharmony_civoid KeyGestureManager::LongPressCombinationKey::TriggerAll(std::shared_ptr<KeyEvent> keyEvent)
359c29fa5a6Sopenharmony_ci{
360c29fa5a6Sopenharmony_ci    MarkActive(true);
361c29fa5a6Sopenharmony_ci    std::ostringstream output;
362c29fa5a6Sopenharmony_ci    Dump(output);
363c29fa5a6Sopenharmony_ci    if (EventLogHelper::IsBetaVersion() && !keyEvent->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) {
364c29fa5a6Sopenharmony_ci        MMI_HILOGI("[LongPressCombinationKey] trigger %{public}s", output.str().c_str());
365c29fa5a6Sopenharmony_ci    } else {
366c29fa5a6Sopenharmony_ci        MMI_HILOGI("[LongPressCombinationKey] trigger %s", output.str().c_str());
367c29fa5a6Sopenharmony_ci    }
368c29fa5a6Sopenharmony_ci    OnTriggerAll(keyEvent);
369c29fa5a6Sopenharmony_ci    TriggerHandlers(keyEvent);
370c29fa5a6Sopenharmony_ci}
371c29fa5a6Sopenharmony_ci
372c29fa5a6Sopenharmony_ciKeyGestureManager::PullUpAccessibility::PullUpAccessibility()
373c29fa5a6Sopenharmony_ci    : LongPressCombinationKey(std::set({ KeyEvent::KEYCODE_VOLUME_DOWN, KeyEvent::KEYCODE_VOLUME_UP }))
374c29fa5a6Sopenharmony_ci{}
375c29fa5a6Sopenharmony_ci
376c29fa5a6Sopenharmony_cibool KeyGestureManager::PullUpAccessibility::IsWorking()
377c29fa5a6Sopenharmony_ci{
378c29fa5a6Sopenharmony_ci    if ((DISPLAY_MONITOR->GetScreenStatus() == EventFwk::CommonEventSupport::COMMON_EVENT_SCREEN_OFF)) {
379c29fa5a6Sopenharmony_ci        return false;
380c29fa5a6Sopenharmony_ci    }
381c29fa5a6Sopenharmony_ci    if (DISPLAY_MONITOR->GetScreenLocked()) {
382c29fa5a6Sopenharmony_ci        return ACCOUNT_MGR->GetCurrentAccountSetting().GetAccShortcutEnabledOnScreenLocked();
383c29fa5a6Sopenharmony_ci    } else {
384c29fa5a6Sopenharmony_ci        return ACCOUNT_MGR->GetCurrentAccountSetting().GetAccShortcutEnabled();
385c29fa5a6Sopenharmony_ci    }
386c29fa5a6Sopenharmony_ci}
387c29fa5a6Sopenharmony_ci
388c29fa5a6Sopenharmony_ciint32_t KeyGestureManager::PullUpAccessibility::AddHandler(int32_t pid,
389c29fa5a6Sopenharmony_ci    int32_t longPressTime, std::function<void(std::shared_ptr<KeyEvent>)> callback)
390c29fa5a6Sopenharmony_ci{
391c29fa5a6Sopenharmony_ci    return KeyGesture::AddHandler(pid, ACCOUNT_MGR->GetCurrentAccountSetting().GetAccShortcutTimeout(), callback);
392c29fa5a6Sopenharmony_ci}
393c29fa5a6Sopenharmony_ci
394c29fa5a6Sopenharmony_civoid KeyGestureManager::PullUpAccessibility::OnTriggerAll(std::shared_ptr<KeyEvent> keyEvent)
395c29fa5a6Sopenharmony_ci{
396c29fa5a6Sopenharmony_ci    MMI_HILOGI("[PullUpAccessibility] Current AccShortcutTimeout setting: %{public}dms",
397c29fa5a6Sopenharmony_ci        ACCOUNT_MGR->GetCurrentAccountSetting().GetAccShortcutTimeout());
398c29fa5a6Sopenharmony_ci    for (auto &handler : handlers_) {
399c29fa5a6Sopenharmony_ci        handler.SetLongPressTime(ACCOUNT_MGR->GetCurrentAccountSetting().GetAccShortcutTimeout());
400c29fa5a6Sopenharmony_ci    }
401c29fa5a6Sopenharmony_ci}
402c29fa5a6Sopenharmony_ci
403c29fa5a6Sopenharmony_ciKeyGestureManager::KeyGestureManager()
404c29fa5a6Sopenharmony_ci{
405c29fa5a6Sopenharmony_ci    keyGestures_.push_back(std::make_unique<PullUpAccessibility>());
406c29fa5a6Sopenharmony_ci    keyGestures_.push_back(std::make_unique<LongPressSingleKey>(KeyEvent::KEYCODE_VOLUME_DOWN));
407c29fa5a6Sopenharmony_ci    keyGestures_.push_back(std::make_unique<LongPressSingleKey>(KeyEvent::KEYCODE_VOLUME_UP));
408c29fa5a6Sopenharmony_ci}
409c29fa5a6Sopenharmony_ci
410c29fa5a6Sopenharmony_cibool KeyGestureManager::ShouldIntercept(std::shared_ptr<KeyOption> keyOption) const
411c29fa5a6Sopenharmony_ci{
412c29fa5a6Sopenharmony_ci    CALL_INFO_TRACE;
413c29fa5a6Sopenharmony_ci    CHKPF(keyOption);
414c29fa5a6Sopenharmony_ci    return std::any_of(keyGestures_.cbegin(), keyGestures_.cend(),
415c29fa5a6Sopenharmony_ci        [keyOption](const auto &keyGesture) {
416c29fa5a6Sopenharmony_ci            return keyGesture->ShouldIntercept(keyOption);
417c29fa5a6Sopenharmony_ci        });
418c29fa5a6Sopenharmony_ci}
419c29fa5a6Sopenharmony_ci
420c29fa5a6Sopenharmony_ciint32_t KeyGestureManager::AddKeyGesture(int32_t pid, std::shared_ptr<KeyOption> keyOption,
421c29fa5a6Sopenharmony_ci    std::function<void(std::shared_ptr<KeyEvent>)> callback)
422c29fa5a6Sopenharmony_ci{
423c29fa5a6Sopenharmony_ci    CHKPR(keyOption, INVALID_ENTITY_ID);
424c29fa5a6Sopenharmony_ci    for (auto &keyGesture : keyGestures_) {
425c29fa5a6Sopenharmony_ci        if (keyGesture->ShouldIntercept(keyOption)) {
426c29fa5a6Sopenharmony_ci            auto downDuration = std::max(keyOption->GetFinalKeyDownDuration(), COMBINATION_KEY_TIMEOUT);
427c29fa5a6Sopenharmony_ci            return keyGesture->AddHandler(pid, downDuration, callback);
428c29fa5a6Sopenharmony_ci        }
429c29fa5a6Sopenharmony_ci    }
430c29fa5a6Sopenharmony_ci    return INVALID_ENTITY_ID;
431c29fa5a6Sopenharmony_ci}
432c29fa5a6Sopenharmony_ci
433c29fa5a6Sopenharmony_civoid KeyGestureManager::RemoveKeyGesture(int32_t id)
434c29fa5a6Sopenharmony_ci{
435c29fa5a6Sopenharmony_ci    for (auto &keyGesture : keyGestures_) {
436c29fa5a6Sopenharmony_ci        if (keyGesture->RemoveHandler(id)) {
437c29fa5a6Sopenharmony_ci            break;
438c29fa5a6Sopenharmony_ci        }
439c29fa5a6Sopenharmony_ci    }
440c29fa5a6Sopenharmony_ci}
441c29fa5a6Sopenharmony_ci
442c29fa5a6Sopenharmony_cibool KeyGestureManager::Intercept(std::shared_ptr<KeyEvent> keyEvent)
443c29fa5a6Sopenharmony_ci{
444c29fa5a6Sopenharmony_ci    CALL_INFO_TRACE;
445c29fa5a6Sopenharmony_ci    CHKPF(keyEvent);
446c29fa5a6Sopenharmony_ci    for (auto iter = keyGestures_.begin(); iter != keyGestures_.end(); ++iter) {
447c29fa5a6Sopenharmony_ci        if ((*iter)->Intercept(keyEvent)) {
448c29fa5a6Sopenharmony_ci            std::ostringstream output;
449c29fa5a6Sopenharmony_ci            (*iter)->Dump(output);
450c29fa5a6Sopenharmony_ci            if (EventLogHelper::IsBetaVersion() && !keyEvent->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) {
451c29fa5a6Sopenharmony_ci                MMI_HILOGI("Intercepted by %{public}s", output.str().c_str());
452c29fa5a6Sopenharmony_ci            } else {
453c29fa5a6Sopenharmony_ci                MMI_HILOGI("Intercepted by %s", output.str().c_str());
454c29fa5a6Sopenharmony_ci            }
455c29fa5a6Sopenharmony_ci            for (++iter; iter != keyGestures_.end(); ++iter) {
456c29fa5a6Sopenharmony_ci                (*iter)->Reset();
457c29fa5a6Sopenharmony_ci            }
458c29fa5a6Sopenharmony_ci            return true;
459c29fa5a6Sopenharmony_ci        }
460c29fa5a6Sopenharmony_ci    }
461c29fa5a6Sopenharmony_ci    return false;
462c29fa5a6Sopenharmony_ci}
463c29fa5a6Sopenharmony_ci
464c29fa5a6Sopenharmony_civoid KeyGestureManager::ResetAll()
465c29fa5a6Sopenharmony_ci{
466c29fa5a6Sopenharmony_ci    for (auto &keyGesture : keyGestures_) {
467c29fa5a6Sopenharmony_ci        keyGesture->Reset();
468c29fa5a6Sopenharmony_ci    }
469c29fa5a6Sopenharmony_ci}
470c29fa5a6Sopenharmony_ci
471c29fa5a6Sopenharmony_civoid KeyGestureManager::Dump() const
472c29fa5a6Sopenharmony_ci{
473c29fa5a6Sopenharmony_ci    for (const auto &keyGesture : keyGestures_) {
474c29fa5a6Sopenharmony_ci        std::ostringstream output;
475c29fa5a6Sopenharmony_ci        keyGesture->Dump(output);
476c29fa5a6Sopenharmony_ci        MMI_HILOGI("%s", output.str().c_str());
477c29fa5a6Sopenharmony_ci    }
478c29fa5a6Sopenharmony_ci}
479c29fa5a6Sopenharmony_ci} // namespace MMI
480c29fa5a6Sopenharmony_ci} // namespace OHOS
481