1 /*
2  * Copyright (c) 2021-2024 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 "client_msg_handler.h"
17 
18 #include <cinttypes>
19 #include <iostream>
20 #include <sstream>
21 
22 #include "anr_handler.h"
23 #include "bytrace_adapter.h"
24 #include "event_log_helper.h"
25 #include "input_device.h"
26 #include "input_device_impl.h"
27 #include "input_event_data_transformation.h"
28 #include "input_handler_manager.h"
29 #include "input_manager_impl.h"
30 #ifdef OHOS_BUILD_ENABLE_MONITOR
31 #include "input_monitor_manager.h"
32 #endif // OHOS_BUILD_ENABLE_MONITOR
33 #include "mmi_client.h"
34 #include "multimodal_event_handler.h"
35 #include "multimodal_input_connect_manager.h"
36 #include "napi_constants.h"
37 #include "proto.h"
38 #include "time_cost_chk.h"
39 #include "util.h"
40 
41 #undef MMI_LOG_TAG
42 #define MMI_LOG_TAG "ClientMsgHandler"
43 
44 namespace OHOS {
45 namespace MMI {
46 namespace {
47 constexpr int32_t PRINT_INTERVAL_COUNT { 50 };
48 } // namespace
Init()49 void ClientMsgHandler::Init()
50 {
51     MsgCallback funs[] = {
52 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
53         { MmiMessageId::ON_KEY_EVENT, [this] (const UDSClient& client, NetPacket& pkt) {
54             return this->OnKeyEvent(client, pkt); }},
55         { MmiMessageId::ON_SUBSCRIBE_KEY, [this] (const UDSClient &client, NetPacket &pkt) {
56             return this->OnSubscribeKeyEventCallback(client, pkt); }},
57 #endif // OHOS_BUILD_ENABLE_KEYBOARD
58 #ifdef OHOS_BUILD_ENABLE_SWITCH
59         { MmiMessageId::ON_SUBSCRIBE_SWITCH, [this] (const UDSClient &client, NetPacket &pkt) {
60             return this->OnSubscribeSwitchEventCallback(client, pkt); }},
61 #endif // OHOS_BUILD_ENABLE_SWITCH
62 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
63         { MmiMessageId::ON_POINTER_EVENT, [this] (const UDSClient& client, NetPacket& pkt) {
64             return this->OnPointerEvent(client, pkt); }},
65 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
66         { MmiMessageId::ADD_INPUT_DEVICE_LISTENER, [this] (const UDSClient& client, NetPacket& pkt) {
67             return this->OnDevListener(client, pkt); }},
68         { MmiMessageId::NOTICE_ANR, [this] (const UDSClient& client, NetPacket& pkt) {
69             return this->OnAnr(client, pkt); }},
70 #if defined(OHOS_BUILD_ENABLE_KEYBOARD) && (defined(OHOS_BUILD_ENABLE_INTERCEPTOR) || \
71     defined(OHOS_BUILD_ENABLE_MONITOR))
72         { MmiMessageId::REPORT_KEY_EVENT, [this] (const UDSClient& client, NetPacket& pkt) {
73             return this->ReportKeyEvent(client, pkt); }},
74 #endif // OHOS_BUILD_ENABLE_KEYBOARD
75 #if (defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)) && \
76     (defined(OHOS_BUILD_ENABLE_INTERCEPTOR) || defined(OHOS_BUILD_ENABLE_MONITOR))
77         { MmiMessageId::REPORT_POINTER_EVENT, [this] (const UDSClient& client, NetPacket& pkt) {
78             return this->ReportPointerEvent(client, pkt); }},
79 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
80         { MmiMessageId::NOTIFY_BUNDLE_NAME, [this] (const UDSClient& client, NetPacket& pkt) {
81             return this->NotifyBundleName(client, pkt); }},
82         { MmiMessageId::WINDOW_STATE_ERROR_NOTIFY, [this] (const UDSClient& client, NetPacket& pkt) {
83             return this->NotifyWindowStateError(client, pkt); }},
84     };
85     for (auto &it : funs) {
86         if (!RegistrationEvent(it)) {
87             MMI_HILOGW("Failed to register event errCode:%{public}d", EVENT_REG_FAIL);
88             continue;
89         }
90     }
91 }
92 
InitProcessedCallback()93 void ClientMsgHandler::InitProcessedCallback()
94 {
95     CALL_DEBUG_ENTER;
96     int32_t tokenType = MULTIMODAL_INPUT_CONNECT_MGR->GetTokenType();
97     if (tokenType == TokenType::TOKEN_HAP || tokenType == TokenType::TOKEN_SYSTEM_HAP) {
98         MMI_HILOGD("Current session is hap");
99         dispatchCallback_ = [] (int32_t eventId, int64_t actionTime) {
100             return ClientMsgHandler::OnDispatchEventProcessed(eventId, actionTime);
101         };
102     } else if (tokenType == static_cast<int32_t>(TokenType::TOKEN_NATIVE)) {
103         MMI_HILOGD("Current session is native");
104     } else {
105         MMI_HILOGE("Current session is unknown tokenType:%{public}d", tokenType);
106     }
107 }
108 
OnMsgHandler(const UDSClient& client, NetPacket& pkt)109 void ClientMsgHandler::OnMsgHandler(const UDSClient& client, NetPacket& pkt)
110 {
111     auto id = pkt.GetMsgId();
112     TimeCostChk chk("ClientMsgHandler::OnMsgHandler", "overtime 300(us)", MAX_OVER_TIME, id);
113     auto callback = GetMsgCallback(id);
114     CHKPV(callback);
115     ResetLogTrace();
116     auto ret = (*callback)(client, pkt);
117     if (ret < 0) {
118         MMI_HILOGE("Msg handling failed. id:%{public}d, ret:%{public}d", id, ret);
119         return;
120     }
121 }
122 
123 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
OnKeyEvent(const UDSClient& client, NetPacket& pkt)124 int32_t ClientMsgHandler::OnKeyEvent(const UDSClient& client, NetPacket& pkt)
125 {
126     auto key = KeyEvent::Create();
127     CHKPR(key, ERROR_NULL_POINTER);
128     int32_t ret = InputEventDataTransformation::NetPacketToKeyEvent(pkt, key);
129     if (ret != RET_OK) {
130         MMI_HILOG_DISPATCHE("Read netPacket failed");
131         return RET_ERR;
132     }
133     LogTracer lt(key->GetId(), key->GetEventType(), key->GetKeyAction());
134     int32_t fd = 0;
135     pkt >> fd;
136 #ifdef OHOS_BUILD_ENABLE_SECURITY_COMPONENT
137     if (InputEventDataTransformation::UnmarshallingEnhanceData(pkt, key) != ERR_OK) {
138         MMI_HILOG_DISPATCHE("Failed to deserialize enhance data key event");
139         return RET_ERR;
140     }
141 #endif // OHOS_BUILD_ENABLE_SECURITY_COMPONENT
142     if (pkt.ChkRWError()) {
143         MMI_HILOG_DISPATCHE("Packet read fd failed");
144         return PACKET_READ_FAIL;
145     }
146     MMI_HILOG_DISPATCHD("Key event dispatcher of client, Fd:%{public}d", fd);
147     MMI_HILOG_DISPATCHI("InputTracking id:%{public}d KeyEvent ReceivedMsg", key->GetId());
148     EventLogHelper::PrintEventData(key, MMI_LOG_HEADER);
149     BytraceAdapter::StartBytrace(key, BytraceAdapter::TRACE_START, BytraceAdapter::KEY_DISPATCH_EVENT);
150     key->SetProcessedCallback(dispatchCallback_);
151     InputMgrImpl.OnKeyEvent(key);
152     key->MarkProcessed();
153     return RET_OK;
154 }
155 #endif // OHOS_BUILD_ENABLE_KEYBOARD
156 
NotifyBundleName(const UDSClient& client, NetPacket& pkt)157 int32_t ClientMsgHandler::NotifyBundleName(const UDSClient& client, NetPacket& pkt)
158 {
159     CALL_DEBUG_ENTER;
160     int32_t pid = 0;
161     int32_t uid = 0;
162     int32_t syncStatus = 0;
163     std::string bundleName;
164     pkt >> pid >> uid >> bundleName >> syncStatus;
165     InputMgrImpl.NotifyBundleName(pid, uid, bundleName, syncStatus);
166     MMI_HILOGD("NotifyBundleName pid:%{public}d, uid:%{public}d, bundleName:%{public}s, syncStatus:%{public}d",
167         pid, uid, bundleName.c_str(), syncStatus);
168     return RET_OK;
169 }
170 
171 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
OnPointerEvent(const UDSClient& client, NetPacket& pkt)172 int32_t ClientMsgHandler::OnPointerEvent(const UDSClient& client, NetPacket& pkt)
173 {
174     CALL_DEBUG_ENTER;
175     auto pointerEvent = PointerEvent::Create();
176     CHKPR(pointerEvent, ERROR_NULL_POINTER);
177     if (InputEventDataTransformation::Unmarshalling(pkt, pointerEvent) != ERR_OK) {
178         MMI_HILOG_DISPATCHE("Failed to deserialize pointer event");
179         return RET_ERR;
180     }
181 #ifdef OHOS_BUILD_ENABLE_SECURITY_COMPONENT
182     if (InputEventDataTransformation::UnmarshallingEnhanceData(pkt, pointerEvent) != ERR_OK) {
183         MMI_HILOG_DISPATCHE("Failed to deserialize enhance data pointer event");
184         return RET_ERR;
185     }
186 #endif // OHOS_BUILD_ENABLE_SECURITY_COMPONENT
187     LogTracer lt(pointerEvent->GetId(), pointerEvent->GetEventType(), pointerEvent->GetPointerAction());
188     MMI_HILOG_FREEZEI("id:%{public}d ac:%{public}d recv", pointerEvent->GetId(), pointerEvent->GetPointerAction());
189     if (pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_AXIS_UPDATE &&
190         pointerEvent->GetPointerAction() != PointerEvent::POINTER_ACTION_ROTATE_UPDATE) {
191         std::string logInfo = std::string("ac: ") + pointerEvent->DumpPointerAction();
192         aggregator_.Record({MMI_LOG_DISPATCH, INPUT_KEY_FLOW, __FUNCTION__, __LINE__}, logInfo.c_str(),
193             std::to_string(pointerEvent->GetId()));
194     }
195     EventLogHelper::PrintEventData(pointerEvent, {MMI_LOG_DISPATCH, INPUT_KEY_FLOW, __FUNCTION__, __LINE__});
196     if (PointerEvent::POINTER_ACTION_CANCEL == pointerEvent->GetPointerAction() ||
197         PointerEvent::POINTER_ACTION_HOVER_CANCEL == pointerEvent->GetPointerAction() ||
198         PointerEvent::POINTER_ACTION_FINGERPRINT_CANCEL == pointerEvent->GetPointerAction()) {
199         MMI_HILOG_DISPATCHI("Operation canceled");
200     }
201     pointerEvent->SetProcessedCallback(dispatchCallback_);
202     BytraceAdapter::StartBytrace(pointerEvent, BytraceAdapter::TRACE_START, BytraceAdapter::POINT_DISPATCH_EVENT);
203     processedCount_++;
204     if (processedCount_ == PRINT_INTERVAL_COUNT) {
205         MMI_HILOG_FREEZEI("Last eventId:%{public}d, current eventId:%{public}d", lastEventId_, pointerEvent->GetId());
206         processedCount_ = 0;
207         lastEventId_ = pointerEvent->GetId();
208     }
209     InputMgrImpl.OnPointerEvent(pointerEvent);
210     if (pointerEvent->GetSourceType() == PointerEvent::SOURCE_TYPE_JOYSTICK) {
211         pointerEvent->MarkProcessed();
212     }
213     return RET_OK;
214 }
215 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
216 
217 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
OnSubscribeKeyEventCallback(const UDSClient &client, NetPacket &pkt)218 int32_t ClientMsgHandler::OnSubscribeKeyEventCallback(const UDSClient &client, NetPacket &pkt)
219 {
220     std::shared_ptr<KeyEvent> keyEvent = KeyEvent::Create();
221     CHKPR(keyEvent, ERROR_NULL_POINTER);
222     int32_t ret = InputEventDataTransformation::NetPacketToKeyEvent(pkt, keyEvent);
223     if (ret != RET_OK) {
224         MMI_HILOGE("Read net packet failed");
225         return RET_ERR;
226     }
227     LogTracer lt(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
228     int32_t fd = -1;
229     int32_t subscribeId = -1;
230     pkt >> fd >> subscribeId;
231     if (pkt.ChkRWError()) {
232         MMI_HILOGE("Packet read fd failed");
233         return PACKET_READ_FAIL;
234     }
235     if (keyEvent->GetKeyCode() == KeyEvent::KEYCODE_POWER) {
236         if (!EventLogHelper::IsBetaVersion()) {
237             MMI_HILOGI("Subscribe:%{public}d,Fd:%{public}d,KeyEvent:%{public}d, "
238                 "Action:%{public}d, KeyAction:%{public}d, EventType:%{public}d,Flag:%{public}u",
239                 subscribeId, fd, keyEvent->GetId(), keyEvent->GetAction(), keyEvent->GetKeyAction(),
240                 keyEvent->GetEventType(), keyEvent->GetFlag());
241         } else {
242             MMI_HILOGI("Subscribe:%{public}d,Fd:%{public}d,KeyEvent:%{public}d,"
243                 "KeyCode:%{private}d,ActionTime:%{public}" PRId64 ",ActionStartTime:%{public}" PRId64 ","
244                 "Action:%{public}d,KeyAction:%{public}d,EventType:%{public}d,Flag:%{public}u",
245             subscribeId, fd, keyEvent->GetId(), keyEvent->GetKeyCode(), keyEvent->GetActionTime(),
246             keyEvent->GetActionStartTime(), keyEvent->GetAction(), keyEvent->GetKeyAction(),
247             keyEvent->GetEventType(), keyEvent->GetFlag());
248         }
249     } else {
250         MMI_HILOGD("Subscribe:%{public}d,Fd:%{public}d,KeyEvent:%{public}d,"
251             "KeyCode:%{private}d,ActionTime:%{public}" PRId64 ",ActionStartTime:%{public}" PRId64 ","
252             "Action:%{public}d,KeyAction:%{public}d,EventType:%{public}d,Flag:%{public}u",
253         subscribeId, fd, keyEvent->GetId(), keyEvent->GetKeyCode(), keyEvent->GetActionTime(),
254         keyEvent->GetActionStartTime(), keyEvent->GetAction(), keyEvent->GetKeyAction(),
255         keyEvent->GetEventType(), keyEvent->GetFlag());
256     }
257 
258     BytraceAdapter::StartBytrace(keyEvent, BytraceAdapter::TRACE_START, BytraceAdapter::KEY_SUBSCRIBE_EVENT);
259     return KeyEventInputSubscribeMgr.OnSubscribeKeyEventCallback(keyEvent, subscribeId);
260 }
261 #endif // OHOS_BUILD_ENABLE_KEYBOARD
262 
263 #ifdef OHOS_BUILD_ENABLE_SWITCH
OnSubscribeSwitchEventCallback(const UDSClient &client, NetPacket &pkt)264 int32_t ClientMsgHandler::OnSubscribeSwitchEventCallback(const UDSClient &client, NetPacket &pkt)
265 {
266     std::shared_ptr<SwitchEvent> switchEvent = std::make_shared<SwitchEvent>(0);
267     int32_t ret = InputEventDataTransformation::NetPacketToSwitchEvent(pkt, switchEvent);
268     if (ret != RET_OK) {
269         MMI_HILOGE("Read net packet failed");
270         return RET_ERR;
271     }
272     LogTracer lt(switchEvent->GetId(), switchEvent->GetEventType(), switchEvent->GetAction());
273     int32_t fd = -1;
274     int32_t subscribeId = -1;
275     pkt >> fd >> subscribeId;
276     if (pkt.ChkRWError()) {
277         MMI_HILOGE("Packet read fd failed");
278         return PACKET_READ_FAIL;
279     }
280     return SWITCH_EVENT_INPUT_SUBSCRIBE_MGR.OnSubscribeSwitchEventCallback(switchEvent, subscribeId);
281 }
282 #endif // OHOS_BUILD_ENABLE_SWITCH
283 
OnDevListener(const UDSClient& client, NetPacket& pkt)284 int32_t ClientMsgHandler::OnDevListener(const UDSClient& client, NetPacket& pkt)
285 {
286     CALL_DEBUG_ENTER;
287     std::string type;
288     int32_t deviceId = 0;
289     pkt >> type >> deviceId;
290     if (pkt.ChkRWError()) {
291         MMI_HILOGE("Packet read type failed");
292         return RET_ERR;
293     }
294     INPUT_DEVICE_IMPL.OnDevListener(deviceId, type);
295     return RET_OK;
296 }
297 
298 #if defined(OHOS_BUILD_ENABLE_KEYBOARD) && (defined(OHOS_BUILD_ENABLE_INTERCEPTOR) || \
299     defined(OHOS_BUILD_ENABLE_MONITOR))
ReportKeyEvent(const UDSClient& client, NetPacket& pkt)300 int32_t ClientMsgHandler::ReportKeyEvent(const UDSClient& client, NetPacket& pkt)
301 {
302     CALL_DEBUG_ENTER;
303     InputHandlerType handlerType;
304     uint32_t deviceTags = 0;
305     pkt >> handlerType >> deviceTags;
306     if (pkt.ChkRWError()) {
307         MMI_HILOG_DISPATCHE("Packet read handler failed");
308         return RET_ERR;
309     }
310     auto keyEvent = KeyEvent::Create();
311     CHKPR(keyEvent, ERROR_NULL_POINTER);
312     if (InputEventDataTransformation::NetPacketToKeyEvent(pkt, keyEvent) != ERR_OK) {
313         MMI_HILOG_DISPATCHE("Failed to deserialize key event");
314         return RET_ERR;
315     }
316     LogTracer lt(keyEvent->GetId(), keyEvent->GetEventType(), keyEvent->GetKeyAction());
317     BytraceAdapter::StartBytrace(keyEvent, BytraceAdapter::TRACE_START, BytraceAdapter::KEY_INTERCEPT_EVENT);
318     switch (handlerType) {
319         case INTERCEPTOR: {
320 #ifdef OHOS_BUILD_ENABLE_INTERCEPTOR
321             InputInterMgr->OnInputEvent(keyEvent, deviceTags);
322 #endif // OHOS_BUILD_ENABLE_INTERCEPTOR
323             break;
324         }
325         case MONITOR: {
326 #ifdef OHOS_BUILD_ENABLE_MONITOR
327             IMonitorMgr->OnInputEvent(keyEvent, deviceTags);
328 #endif // OHOS_BUILD_ENABLE_MONITOR
329             break;
330         }
331         default: {
332             MMI_HILOG_DISPATCHW("Failed to intercept or monitor on the event");
333             break;
334         }
335     }
336     return RET_OK;
337 }
338 #endif // OHOS_BUILD_ENABLE_KEYBOARD && OHOS_BUILD_ENABLE_INTERCEPTOR || OHOS_BUILD_ENABLE_MONITOR
339 
340 #if (defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)) && \
341     (defined(OHOS_BUILD_ENABLE_INTERCEPTOR) || defined(OHOS_BUILD_ENABLE_MONITOR))
ReportPointerEvent(const UDSClient& client, NetPacket& pkt)342 int32_t ClientMsgHandler::ReportPointerEvent(const UDSClient& client, NetPacket& pkt)
343 {
344     InputHandlerType handlerType;
345     uint32_t deviceTags = 0;
346     pkt >> handlerType >> deviceTags;
347     if (pkt.ChkRWError()) {
348         MMI_HILOG_DISPATCHE("Packet read Pointer data failed");
349         return RET_ERR;
350     }
351     MMI_HILOG_DISPATCHD("Client handlerType:%{public}d", handlerType);
352     auto pointerEvent = PointerEvent::Create();
353     CHKPR(pointerEvent, ERROR_NULL_POINTER);
354     if (InputEventDataTransformation::Unmarshalling(pkt, pointerEvent) != ERR_OK) {
355         MMI_HILOG_DISPATCHW("Failed to deserialize pointer event");
356         return RET_ERR;
357     }
358     LogTracer lt(pointerEvent->GetId(), pointerEvent->GetEventType(), pointerEvent->GetPointerAction());
359     BytraceAdapter::StartBytrace(pointerEvent, BytraceAdapter::TRACE_START, BytraceAdapter::POINT_INTERCEPT_EVENT);
360     switch (handlerType) {
361         case INTERCEPTOR: {
362 #ifdef OHOS_BUILD_ENABLE_INTERCEPTOR
363             InputInterMgr->OnInputEvent(pointerEvent, deviceTags);
364 #endif // OHOS_BUILD_ENABLE_INTERCEPTOR
365             break;
366         }
367         case MONITOR: {
368 #ifdef OHOS_BUILD_ENABLE_MONITOR
369             IMonitorMgr->OnInputEvent(pointerEvent, deviceTags);
370 #endif // OHOS_BUILD_ENABLE_MONITOR
371             break;
372         }
373         default: {
374             MMI_HILOG_DISPATCHW("Failed to intercept or monitor on the event");
375             break;
376         }
377     }
378     return RET_OK;
379 }
380 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
381 
OnDispatchEventProcessed(int32_t eventId, int64_t actionTime)382 void ClientMsgHandler::OnDispatchEventProcessed(int32_t eventId, int64_t actionTime)
383 {
384     CALL_DEBUG_ENTER;
385     ANRHDL->SetLastProcessedEventId(ANR_DISPATCH, eventId, actionTime);
386 }
387 
OnAnr(const UDSClient& client, NetPacket& pkt)388 int32_t ClientMsgHandler::OnAnr(const UDSClient& client, NetPacket& pkt)
389 {
390     CALL_DEBUG_ENTER;
391     int32_t pid = 0;
392     int32_t eventId = 0;
393     pkt >> pid;
394     pkt >> eventId;
395     if (pkt.ChkRWError()) {
396         MMI_HILOG_ANRDETECTE("Packet read data failed");
397         return RET_ERR;
398     }
399     MMI_HILOG_ANRDETECTI("Client pid:%{public}d eventId:%{public}d", pid, eventId);
400     InputMgrImpl.OnAnr(pid, eventId);
401     return RET_OK;
402 }
403 
NotifyWindowStateError(const UDSClient& client, NetPacket& pkt)404 int32_t ClientMsgHandler::NotifyWindowStateError(const UDSClient& client, NetPacket& pkt)
405 {
406     CALL_DEBUG_ENTER;
407     int32_t pid = 0;
408     int32_t windowId = 0;
409     pkt >> pid;
410     pkt >> windowId;
411     if (pkt.ChkRWError()) {
412         MMI_HILOG_ANRDETECTE("Packet read data failed");
413         return RET_ERR;
414     }
415     MMI_HILOG_ANRDETECTI("Client pid:%{public}d windowId:%{public}d", pid, windowId);
416     InputMgrImpl.OnWindowStateError(pid, windowId);
417     return RET_OK;
418 }
419 
420 } // namespace MMI
421 } // namespace OHOS
422