1 /*
2  * Copyright (c) 2021-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 "key_event_input_subscribe_manager.h"
17 
18 #include <cinttypes>
19 
20 #include "bytrace_adapter.h"
21 #include "define_multimodal.h"
22 #include "error_multimodal.h"
23 #include "multimodal_event_handler.h"
24 
25 #undef MMI_LOG_TAG
26 #define MMI_LOG_TAG "KeyEventInputSubscribeManager"
27 
28 namespace OHOS {
29 namespace MMI {
30 namespace {
31 constexpr int32_t INVALID_SUBSCRIBE_ID { -1 };
32 constexpr size_t PRE_KEYS_NUM { 4 };
33 } // namespace
34 int32_t KeyEventInputSubscribeManager::subscribeIdManager_ = 0;
35 
KeyEventInputSubscribeManager()36 KeyEventInputSubscribeManager::KeyEventInputSubscribeManager() {}
~KeyEventInputSubscribeManager()37 KeyEventInputSubscribeManager::~KeyEventInputSubscribeManager() {}
38 
SubscribeKeyEventInfo(std::shared_ptr<KeyOption> keyOption,std::function<void (std::shared_ptr<KeyEvent>)> callback)39 KeyEventInputSubscribeManager::SubscribeKeyEventInfo::SubscribeKeyEventInfo(
40     std::shared_ptr<KeyOption> keyOption,
41     std::function<void(std::shared_ptr<KeyEvent>)> callback)
42     : keyOption_(keyOption), callback_(callback)
43 {
44     if (KeyEventInputSubscribeManager::subscribeIdManager_ >= std::numeric_limits<int32_t>::max()) {
45         subscribeId_ = -1;
46         MMI_HILOGE("The subscribeId has reached the upper limit, cannot continue the subscription");
47         return;
48     }
49     subscribeId_ = KeyEventInputSubscribeManager::subscribeIdManager_;
50     ++KeyEventInputSubscribeManager::subscribeIdManager_;
51 }
52 
operator <(const KeyOption & first,const KeyOption & second)53 static bool operator<(const KeyOption &first, const KeyOption &second)
54 {
55     if (first.GetFinalKey() != second.GetFinalKey()) {
56         return (first.GetFinalKey() < second.GetFinalKey());
57     }
58     const std::set<int32_t> sPrekeys { first.GetPreKeys() };
59     const std::set<int32_t> tPrekeys { second.GetPreKeys() };
60     std::set<int32_t>::const_iterator sIter = sPrekeys.cbegin();
61     std::set<int32_t>::const_iterator tIter = tPrekeys.cbegin();
62     for (; sIter != sPrekeys.cend() && tIter != tPrekeys.cend(); ++sIter, ++tIter) {
63         if (*sIter != *tIter) {
64             return (*sIter < *tIter);
65         }
66     }
67     if (sIter != sPrekeys.cend() || tIter != tPrekeys.cend()) {
68         return (tIter != tPrekeys.cend());
69     }
70     if (first.IsFinalKeyDown()) {
71         if (!second.IsFinalKeyDown()) {
72             return false;
73         }
74     } else {
75         if (second.IsFinalKeyDown()) {
76             return true;
77         }
78     }
79     return (first.GetFinalKeyDownDuration() < second.GetFinalKeyDownDuration());
80 }
81 
operator <(const SubscribeKeyEventInfo & other) const82 bool KeyEventInputSubscribeManager::SubscribeKeyEventInfo::operator<(const SubscribeKeyEventInfo &other) const
83 {
84     if (keyOption_ == nullptr) {
85         return (other.keyOption_ != nullptr);
86     } else if (other.keyOption_ == nullptr) {
87         return false;
88     }
89     return (*keyOption_ < *other.keyOption_);
90 }
91 
SubscribeKeyEvent(std::shared_ptr<KeyOption> keyOption,std::function<void (std::shared_ptr<KeyEvent>)> callback)92 int32_t KeyEventInputSubscribeManager::SubscribeKeyEvent(std::shared_ptr<KeyOption> keyOption,
93     std::function<void(std::shared_ptr<KeyEvent>)> callback)
94 {
95     CALL_DEBUG_ENTER;
96     CHKPR(keyOption, INVALID_SUBSCRIBE_ID);
97     CHKPR(callback, INVALID_SUBSCRIBE_ID);
98     std::set<int32_t> preKeys = keyOption->GetPreKeys();
99     if (preKeys.size() > PRE_KEYS_NUM) {
100         MMI_HILOGE("PreKeys number invalid");
101         return INVALID_SUBSCRIBE_ID;
102     }
103 
104     if (!MMIEventHdl.InitClient()) {
105         MMI_HILOGE("Client init failed");
106         return INVALID_SUBSCRIBE_ID;
107     }
108 
109     std::lock_guard<std::mutex> guard(mtx_);
110     auto [tIter, isOk] = subscribeInfos_.emplace(keyOption, callback);
111     if (!isOk) {
112         MMI_HILOGW("Subscription is duplicated");
113         return tIter->GetSubscribeId();
114     }
115     if (MMIEventHdl.SubscribeKeyEvent(*tIter) != RET_OK) {
116         MMI_HILOGE("Subscribing key event failed");
117         subscribeInfos_.erase(tIter);
118         return INVALID_SUBSCRIBE_ID;
119     }
120 
121     MMI_HILOGD("subscribeId:%{public}d, keyOption->finalKey:%{private}d,"
122         "keyOption->isFinalKeyDown:%{public}s, keyOption->finalKeyDownDuration:%{public}d",
123         tIter->GetSubscribeId(), keyOption->GetFinalKey(),
124         keyOption->IsFinalKeyDown() ? "true" : "false",
125         keyOption->GetFinalKeyDownDuration());
126     for (const auto &preKey : preKeys) {
127         MMI_HILOGD("prekey:%{private}d", preKey);
128     }
129     return tIter->GetSubscribeId();
130 }
131 
UnsubscribeKeyEvent(int32_t subscribeId)132 int32_t KeyEventInputSubscribeManager::UnsubscribeKeyEvent(int32_t subscribeId)
133 {
134     CALL_INFO_TRACE;
135     if (subscribeId < 0) {
136         MMI_HILOGE("The subscribe id is less than 0");
137         return RET_ERR;
138     }
139 
140     std::lock_guard<std::mutex> guard(mtx_);
141     if (!MMIEventHdl.InitClient()) {
142         MMI_HILOGE("Client init failed");
143         return INVALID_SUBSCRIBE_ID;
144     }
145     if (subscribeInfos_.empty()) {
146         MMI_HILOGE("The subscribeInfos is empty");
147         return RET_ERR;
148     }
149 
150     for (auto it = subscribeInfos_.begin(); it != subscribeInfos_.end(); ++it) {
151         if (it->GetSubscribeId() == subscribeId) {
152             if (MMIEventHdl.UnsubscribeKeyEvent(subscribeId) != RET_OK) {
153                 MMI_HILOGE("Leave, unsubscribe key event failed");
154                 return RET_ERR;
155             }
156             subscribeInfos_.erase(it);
157             return RET_OK;
158         }
159     }
160     return RET_ERR;
161 }
162 
OnSubscribeKeyEventCallback(std::shared_ptr<KeyEvent> event,int32_t subscribeId)163 int32_t KeyEventInputSubscribeManager::OnSubscribeKeyEventCallback(std::shared_ptr<KeyEvent> event,
164     int32_t subscribeId)
165 {
166     CHK_PID_AND_TID();
167     CHKPR(event, ERROR_NULL_POINTER);
168     if (subscribeId < 0) {
169         MMI_HILOGE("Leave, the subscribe id is less than 0");
170         return RET_ERR;
171     }
172 
173     BytraceAdapter::StartBytrace(event, BytraceAdapter::TRACE_STOP, BytraceAdapter::KEY_SUBSCRIBE_EVENT);
174     auto info = GetSubscribeKeyEvent(subscribeId);
175     CHKPR(info, ERROR_NULL_POINTER);
176     auto callback = info->GetCallback();
177     if (!callback) {
178         MMI_HILOGE("Callback is null");
179         return RET_ERR;
180     }
181     callback(event);
182     MMI_HILOGD("Key event id:%{public}d, keyCode:%{private}d", subscribeId, event->GetKeyCode());
183     return RET_OK;
184 }
185 
OnConnected()186 void KeyEventInputSubscribeManager::OnConnected()
187 {
188     CALL_DEBUG_ENTER;
189     std::lock_guard<std::mutex> guard(mtx_);
190     if (subscribeInfos_.empty()) {
191         MMI_HILOGD("Leave, subscribeInfos_ is empty");
192         return;
193     }
194     for (const auto& subscriberInfo : subscribeInfos_) {
195         if (MMIEventHdl.SubscribeKeyEvent(subscriberInfo) != RET_OK) {
196             MMI_HILOGE("Subscribe key event failed");
197         }
198     }
199 }
200 
GetSubscribeKeyEvent(int32_t id)201 const KeyEventInputSubscribeManager::SubscribeKeyEventInfo* KeyEventInputSubscribeManager::GetSubscribeKeyEvent(
202     int32_t id)
203 {
204     if (id < 0) {
205         MMI_HILOGE("Invalid input param id:%{public}d", id);
206         return nullptr;
207     }
208     std::lock_guard<std::mutex> guard(mtx_);
209     for (const auto &subscriber : subscribeInfos_) {
210         if (subscriber.GetSubscribeId() == id) {
211             return &subscriber;
212         }
213     }
214     return nullptr;
215 }
216 } // namespace MMI
217 } // namespace OHOS
218