1 /*
2 * Copyright (C) 2022 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 "accessibility_short_key.h"
17 #include "accessible_ability_manager_service.h"
18 #include "hilog_wrapper.h"
19
20 namespace OHOS {
21 namespace Accessibility {
22 namespace {
23 constexpr size_t KEY_ITEM_COUNT_1 = 1;
24 constexpr uint32_t SHORT_KEY_TIMEOUT_MSG = 1;
25 constexpr int32_t MULTI_PRESS_TIMER = 300; // ms
26 constexpr int32_t TRIPLE_PRESS_COUNT = 3;
27 } // namespace
28
AccessibilityShortKey()29 AccessibilityShortKey::AccessibilityShortKey()
30 {
31 HILOG_DEBUG();
32
33 std::shared_ptr<AppExecFwk::EventRunner> runner =
34 Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner();
35 if (!runner) {
36 HILOG_ERROR("get runner failed");
37 return;
38 }
39
40 timeoutHandler_ = std::make_shared<ShortKeyEventHandler>(runner, *this);
41 if (!timeoutHandler_) {
42 HILOG_ERROR("create event handler failed");
43 }
44 }
45
~AccessibilityShortKey()46 AccessibilityShortKey::~AccessibilityShortKey()
47 {
48 HILOG_DEBUG();
49
50 cachedKeyEvents_.clear();
51 timeoutHandler_ = nullptr;
52 lastKeyAction_ = MMI::KeyEvent::KEY_ACTION_UNKNOWN;
53 }
54
OnKeyEvent(MMI::KeyEvent & event)55 bool AccessibilityShortKey::OnKeyEvent(MMI::KeyEvent &event)
56 {
57 HILOG_DEBUG();
58
59 int32_t keycode = event.GetKeyCode();
60 size_t pressedKeyCount = event.GetPressedKeys().size();
61 if ((keycode != MMI::KeyEvent::KEYCODE_POWER) ||
62 (pressedKeyCount > KEY_ITEM_COUNT_1)) {
63 HILOG_DEBUG("key[%{public}d] is not power key, or the number[%{public}zu]\
64 of keys pressed is greater than 1.", keycode, pressedKeyCount);
65 EventTransmission::OnKeyEvent(event);
66 return false;
67 }
68
69 RecognizeShortKey(event);
70 return true;
71 }
72
SendKeyEventToNext()73 void AccessibilityShortKey::SendKeyEventToNext()
74 {
75 HILOG_DEBUG();
76
77 for (const auto &keyEvent : cachedKeyEvents_) {
78 EventTransmission::OnKeyEvent(*keyEvent);
79 }
80
81 ClearCachedEventsAndMsg();
82 }
83
DestroyEvents()84 void AccessibilityShortKey::DestroyEvents()
85 {
86 HILOG_DEBUG();
87
88 ClearCachedEventsAndMsg();
89 EventTransmission::DestroyEvents();
90 }
91
RecognizeShortKey(MMI::KeyEvent & event)92 void AccessibilityShortKey::RecognizeShortKey(MMI::KeyEvent &event)
93 {
94 HILOG_DEBUG();
95
96 int32_t action = event.GetKeyAction();
97 size_t pressedKeyCount = event.GetPressedKeys().size();
98 std::shared_ptr<MMI::KeyEvent> keyEvent = std::make_shared<MMI::KeyEvent>(event);
99 AddCachedKeyEvent(keyEvent);
100
101 if (action == MMI::KeyEvent::KEY_ACTION_DOWN) {
102 if (pressedKeyCount != KEY_ITEM_COUNT_1) {
103 SendKeyEventToNext();
104 return;
105 }
106 if (lastKeyAction_ != MMI::KeyEvent::KEY_ACTION_DOWN) {
107 timeoutHandler_->RemoveEvent(SHORT_KEY_TIMEOUT_MSG);
108 timeoutHandler_->SendEvent(SHORT_KEY_TIMEOUT_MSG, 0, MULTI_PRESS_TIMER);
109 }
110 lastKeyAction_ = action;
111 } else if (action == MMI::KeyEvent::KEY_ACTION_UP) {
112 if (pressedKeyCount || !IsUpValid()) {
113 SendKeyEventToNext();
114 return;
115 }
116 lastKeyAction_ = action;
117 if (IsTriplePress()) {
118 OnShortKey();
119 }
120 } else {
121 SendKeyEventToNext();
122 }
123 }
124
OnShortKey()125 void AccessibilityShortKey::OnShortKey()
126 {
127 HILOG_DEBUG();
128
129 ClearCachedEventsAndMsg();
130 Singleton<AccessibleAbilityManagerService>::GetInstance().OnShortKeyProcess();
131 }
132
AddCachedKeyEvent(std::shared_ptr<MMI::KeyEvent> & event)133 void AccessibilityShortKey::AddCachedKeyEvent(std::shared_ptr<MMI::KeyEvent> &event)
134 {
135 HILOG_DEBUG();
136
137 cachedKeyEvents_.emplace_back(event);
138 }
139
IsTriplePress()140 bool AccessibilityShortKey::IsTriplePress()
141 {
142 HILOG_DEBUG();
143
144 uint32_t upEventCount = 0;
145 int32_t action = MMI::KeyEvent::KEY_ACTION_UNKNOWN;
146 for (auto &keyEvent : cachedKeyEvents_) {
147 action = keyEvent->GetKeyAction();
148 if (action == MMI::KeyEvent::KEY_ACTION_UP) {
149 upEventCount++;
150 }
151 }
152
153 if (upEventCount >= TRIPLE_PRESS_COUNT) {
154 return true;
155 }
156 return false;
157 }
158
IsUpValid()159 bool AccessibilityShortKey::IsUpValid()
160 {
161 HILOG_DEBUG();
162
163 if (lastKeyAction_ == MMI::KeyEvent::KEY_ACTION_DOWN) {
164 return true;
165 }
166 return false;
167 }
168
ClearCachedEventsAndMsg()169 void AccessibilityShortKey::ClearCachedEventsAndMsg()
170 {
171 HILOG_DEBUG();
172
173 cachedKeyEvents_.clear();
174 lastKeyAction_ = MMI::KeyEvent::KEY_ACTION_UNKNOWN;
175 timeoutHandler_->RemoveEvent(SHORT_KEY_TIMEOUT_MSG);
176 }
177
ShortKeyEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,AccessibilityShortKey & shortKey)178 AccessibilityShortKey::ShortKeyEventHandler::ShortKeyEventHandler(
179 const std::shared_ptr<AppExecFwk::EventRunner> &runner,
180 AccessibilityShortKey &shortKey) : AppExecFwk::EventHandler(runner), shortKey_(shortKey)
181 {
182 HILOG_DEBUG();
183 }
184
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)185 void AccessibilityShortKey::ShortKeyEventHandler::ProcessEvent(
186 const AppExecFwk::InnerEvent::Pointer &event)
187 {
188 HILOG_DEBUG();
189
190 switch (event->GetInnerEventId()) {
191 case SHORT_KEY_TIMEOUT_MSG:
192 shortKey_.SendKeyEventToNext();
193 break;
194 default:
195 break;
196 }
197 }
198 } // namespace Accessibility
199 } // namespace OHOS