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_keyevent_filter.h"
17 #include "accessible_ability_manager_service.h"
18 #include "hilog_wrapper.h"
19 
20 namespace OHOS {
21 namespace Accessibility {
22 namespace {
23     int64_t g_taskTime = 500;
24 } // namespace
25 
IsWantedKeyEvent(MMI::KeyEvent & event)26 static bool IsWantedKeyEvent(MMI::KeyEvent &event)
27 {
28     HILOG_DEBUG();
29 
30     int32_t keyCode = event.GetKeyCode();
31     if (keyCode == MMI::KeyEvent::KEYCODE_VOLUME_UP || keyCode == MMI::KeyEvent::KEYCODE_VOLUME_DOWN) {
32         return true;
33     }
34     return false;
35 }
36 
KeyEventFilter()37 KeyEventFilter::KeyEventFilter()
38 {
39     HILOG_DEBUG();
40 
41     runner_ = Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner();
42     if (!runner_) {
43         HILOG_ERROR("get runner failed");
44         return;
45     }
46 
47     timeoutHandler_ = std::make_shared<KeyEventFilterEventHandler>(runner_, *this);
48     if (!timeoutHandler_) {
49         HILOG_ERROR("create event handler failed");
50         return;
51     }
52 }
53 
~KeyEventFilter()54 KeyEventFilter::~KeyEventFilter()
55 {
56     HILOG_DEBUG();
57 
58     eventMaps_.clear();
59 }
60 
OnKeyEvent(MMI::KeyEvent & event)61 bool KeyEventFilter::OnKeyEvent(MMI::KeyEvent &event)
62 {
63     HILOG_DEBUG();
64 
65     bool whetherIntercept = IsWantedKeyEvent(event);
66     if (whetherIntercept) {
67         DispatchKeyEvent(event);
68         return true;
69     }
70     EventTransmission::OnKeyEvent(event);
71     return false;
72 }
73 
SetServiceOnKeyEventResult(AccessibleAbilityConnection & connection,bool isHandled,uint32_t sequenceNum)74 void KeyEventFilter::SetServiceOnKeyEventResult(AccessibleAbilityConnection &connection, bool isHandled,
75     uint32_t sequenceNum)
76 {
77     HILOG_DEBUG("isHandled[%{public}d], sequenceNum[%{public}u].", isHandled, sequenceNum);
78 
79     std::shared_ptr<ProcessingEvent> processingEvent = FindProcessingEvent(connection, sequenceNum);
80     if (!processingEvent) {
81         HILOG_DEBUG("No event being processed.");
82         return;
83     }
84 
85     if (!isHandled) {
86         if (!processingEvent->usedCount_) {
87             timeoutHandler_->RemoveEvent(processingEvent->seqNum_);
88             EventTransmission::OnKeyEvent(*processingEvent->event_);
89         }
90     } else {
91         timeoutHandler_->RemoveEvent(processingEvent->seqNum_);
92         RemoveProcessingEvent(processingEvent);
93     }
94 }
95 
ClearServiceKeyEvents(AccessibleAbilityConnection & connection)96 void KeyEventFilter::ClearServiceKeyEvents(AccessibleAbilityConnection &connection)
97 {
98     HILOG_DEBUG();
99 
100     for (auto iter = eventMaps_.begin(); iter != eventMaps_.end(); iter++) {
101         if (iter->first.GetRefPtr() != &connection) {
102             continue;
103         }
104 
105         for (auto &val : iter->second) {
106             val->usedCount_--;
107             if (!val->usedCount_) {
108                 EventTransmission::OnKeyEvent(*val->event_);
109             }
110         }
111         eventMaps_.erase(iter);
112         break;
113     }
114 }
115 
DispatchKeyEvent(MMI::KeyEvent & event)116 void KeyEventFilter::DispatchKeyEvent(MMI::KeyEvent &event)
117 {
118     HILOG_DEBUG();
119 
120     sptr<AccessibilityAccountData> accountData =
121         Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountData();
122     std::map<std::string, sptr<AccessibleAbilityConnection>> connectionMaps = accountData->GetConnectedA11yAbilities();
123 
124     std::shared_ptr<ProcessingEvent> processingEvent = nullptr;
125     std::shared_ptr<MMI::KeyEvent> copyEvent = nullptr;
126     sequenceNum_++;
127     for (auto iter = connectionMaps.begin(); iter != connectionMaps.end(); iter++) {
128         if (iter->second->OnKeyPressEvent(event, sequenceNum_)) {
129             if (!processingEvent) {
130                 processingEvent = std::make_shared<ProcessingEvent>();
131                 copyEvent = std::make_shared<MMI::KeyEvent>(event);
132                 processingEvent->event_ = copyEvent;
133                 processingEvent->seqNum_ = sequenceNum_;
134             }
135             processingEvent->usedCount_++;
136 
137             if (eventMaps_.find(iter->second) == eventMaps_.end()) {
138                 std::vector<std::shared_ptr<ProcessingEvent>> processingEvens;
139                 eventMaps_.insert(std::make_pair(iter->second, processingEvens));
140             }
141             eventMaps_.at(iter->second).emplace_back(processingEvent);
142         }
143     }
144 
145     if (!processingEvent) {
146         HILOG_DEBUG("No service handles the event.");
147         sequenceNum_--;
148         EventTransmission::OnKeyEvent(event);
149         return;
150     }
151 
152     timeoutHandler_->SendEvent(sequenceNum_, processingEvent, g_taskTime);
153 }
154 
RemoveProcessingEvent(std::shared_ptr<ProcessingEvent> event)155 bool KeyEventFilter::RemoveProcessingEvent(std::shared_ptr<ProcessingEvent> event)
156 {
157     HILOG_DEBUG();
158 
159     bool haveEvent = false;
160     for (auto iter = eventMaps_.begin(); iter != eventMaps_.end(); iter++) {
161         for (auto val = iter->second.begin(); val != iter->second.end(); val++) {
162             if (*val != event) {
163                 continue;
164             }
165             (*val)->usedCount_--;
166             iter->second.erase(val);
167             haveEvent = true;
168             break;
169         }
170     }
171 
172     return haveEvent;
173 }
174 
FindProcessingEvent(AccessibleAbilityConnection & connection,uint32_t sequenceNum)175 std::shared_ptr<KeyEventFilter::ProcessingEvent> KeyEventFilter::FindProcessingEvent(
176     AccessibleAbilityConnection &connection, uint32_t sequenceNum)
177 {
178     HILOG_DEBUG();
179 
180     std::shared_ptr<ProcessingEvent> processingEvent = nullptr;
181 
182     for (auto iter = eventMaps_.begin(); iter != eventMaps_.end(); iter++) {
183         if (iter->first.GetRefPtr() != &connection) {
184             continue;
185         }
186 
187         for (auto val = iter->second.begin(); val != iter->second.end(); val++) {
188             if ((*val)->seqNum_ != sequenceNum) {
189                 continue;
190             }
191             processingEvent = *val;
192             iter->second.erase(val);
193             processingEvent->usedCount_--;
194             break;
195         }
196         break;
197     }
198 
199     return processingEvent;
200 }
201 
DestroyEvents()202 void KeyEventFilter::DestroyEvents()
203 {
204     HILOG_DEBUG();
205 
206     timeoutHandler_->RemoveAllEvents();
207     eventMaps_.clear();
208     EventTransmission::DestroyEvents();
209 }
210 
SendEventToNext(MMI::KeyEvent & event)211 void KeyEventFilter::SendEventToNext(MMI::KeyEvent &event)
212 {
213     HILOG_DEBUG();
214     EventTransmission::OnKeyEvent(event);
215 }
216 
KeyEventFilterEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,KeyEventFilter & keyEventFilter)217 KeyEventFilterEventHandler::KeyEventFilterEventHandler(
218     const std::shared_ptr<AppExecFwk::EventRunner> &runner, KeyEventFilter &keyEventFilter)
219     : AppExecFwk::EventHandler(runner), keyEventFilter_(keyEventFilter)
220 {
221     HILOG_DEBUG();
222 }
223 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)224 void KeyEventFilterEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
225 {
226     HILOG_DEBUG();
227 
228     if (!event) {
229         HILOG_ERROR("event is null.");
230         return;
231     }
232 
233     auto processingEvent = event->GetSharedObject<KeyEventFilter::ProcessingEvent>();
234     if (processingEvent == nullptr) {
235         HILOG_ERROR("processingEvent is nullptr");
236         return;
237     }
238     if (processingEvent->seqNum_ != event->GetInnerEventId()) {
239         HILOG_ERROR("event is wrong.");
240         return;
241     }
242 
243     bool haveEvent = keyEventFilter_.RemoveProcessingEvent(processingEvent);
244     if (haveEvent) {
245         keyEventFilter_.SendEventToNext(*processingEvent->event_);
246     }
247 }
248 } // namespace Accessibility
249 } // namespace OHOS