• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "long_press_subscriber_handler.h"
16 
17 #include "app_mgr_client.h"
18 #include "key_command_handler_util.h"
19 
20 #undef MMI_LOG_DOMAIN
21 #define MMI_LOG_DOMAIN MMI_LOG_HANDLER
22 #undef MMI_LOG_TAG
23 #define MMI_LOG_TAG "LongPressSubscriberHandler"
24 
25 namespace OHOS {
26 namespace MMI {
27 namespace {
28 constexpr int32_t ONE_FINGER { 1 };
29 constexpr int32_t TWO_FINGER { 2 };
30 constexpr int32_t DEFAULT_USER_ID { 100 };
31 constexpr int32_t PX_BASE { 160 };
32 constexpr int32_t MS_TO_US { 1000 };
33 
34 }
Compare(const std::shared_ptr<Subscriber> & a,const std::shared_ptr<Subscriber> & b)35 bool Compare(const std::shared_ptr<Subscriber> &a, const std::shared_ptr<Subscriber> &b)
36 {
37     return a->duration_ < b->duration_;
38 }
39 
LongPressSubscriberHandler()40 LongPressSubscriberHandler::LongPressSubscriberHandler() {}
41 
~LongPressSubscriberHandler()42 LongPressSubscriberHandler::~LongPressSubscriberHandler() {}
43 
SubscribeLongPressEvent(SessionPtr sess,int32_t subscribeId,const LongPressRequest & longPressRequest)44 int32_t LongPressSubscriberHandler::SubscribeLongPressEvent(SessionPtr sess, int32_t subscribeId,
45     const LongPressRequest &longPressRequest)
46 {
47     CALL_DEBUG_ENTER;
48     CHKPR(sess, ERROR_NULL_POINTER);
49     MMI_HILOGD("SubscribeId:%{public}d, fingerCount:%{public}d, duration:%{public}d",
50         subscribeId, longPressRequest.fingerCount, longPressRequest.duration);
51     if (subscribeId < 0) {
52         MMI_HILOGE("Invalid subscribeId");
53         return RET_ERR;
54     }
55 
56     AddDurationTimer(longPressRequest.duration);
57     auto subscriber = std::make_shared<Subscriber>(subscribeId, sess, longPressRequest.fingerCount,
58         longPressRequest.duration);
59 
60     AddSessSubscriber(subscriber);
61     InsertSubScriber(std::move(subscriber));
62     InitSessionDeleteCallback();
63     return RET_OK;
64 }
65 
UnsubscribeLongPressEvent(SessionPtr sess,int32_t subscribeId)66 int32_t LongPressSubscriberHandler::UnsubscribeLongPressEvent(SessionPtr sess, int32_t subscribeId)
67 {
68     CALL_INFO_TRACE;
69     CHKPR(sess, ERROR_NULL_POINTER);
70     if (subscribeId < 0) {
71         MMI_HILOGE("Invalid subscribeId:%{public}d", subscribeId);
72         return RET_ERR;
73     }
74 
75     for (auto it = subscriberInfos_.begin(); it != subscriberInfos_.end(); ++it) {
76         std::vector<std::shared_ptr<Subscriber>> &subscribers = it->second;
77         for (auto iter = subscribers.begin(); iter != subscribers.end(); ++iter) {
78             if ((*iter)->sess_ == sess && (*iter)->id_ == subscribeId) {
79                 subscribers.erase(iter);
80                 auto fingerCount = it->first.first;
81                 auto duration = it->first.second;
82                 if (subscribers.empty()) {
83                     subscriberInfos_.erase(it);
84                 }
85                 RemoveDurationTimer(fingerCount, duration);
86                 RemoveSessSubscriber(sess, subscribeId);
87                 MMI_HILOGD("UnsubscribeLongPressEvent successed with %{public}d", subscribeId);
88                 return RET_OK;
89             }
90         }
91     }
92     MMI_HILOGE("UnsubscribeLongPressEvent failed with %{public}d", subscribeId);
93     return RET_ERR;
94 }
95 
AddDurationTimer(int32_t duration)96 void LongPressSubscriberHandler::AddDurationTimer(int32_t duration)
97 {
98     CALL_DEBUG_ENTER;
99     bool isExist = false;
100     for (auto &durationTimer : durationTimers_) {
101         if (durationTimer.duration == duration) {
102             isExist = true;
103             break;
104         }
105     }
106     if (!isExist) {
107         DurationTimer durationTimer = {
108             .duration = duration,
109         };
110         durationTimers_.push_back(durationTimer);
111     }
112 }
113 
RemoveDurationTimer(int32_t fingerCount,int32_t duration)114 void LongPressSubscriberHandler::RemoveDurationTimer(int32_t fingerCount, int32_t duration)
115 {
116     CALL_DEBUG_ENTER;
117     for (auto it = subscriberInfos_.begin(); it != subscriberInfos_.end(); ++it) {
118         if (it->first.second == duration && !it->second.empty()) {
119             return;
120         }
121     }
122     for (auto timer = durationTimers_.begin(); timer != durationTimers_.end(); ++timer) {
123         if (timer->duration == duration) {
124             durationTimers_.erase(timer);
125             return;
126         }
127     }
128 }
129 
AddSessSubscriber(const std::shared_ptr<Subscriber> subscriber)130 void LongPressSubscriberHandler::AddSessSubscriber(const std::shared_ptr<Subscriber> subscriber)
131 {
132     CALL_DEBUG_ENTER;
133     CHKPV(subscriber);
134     std::vector<std::shared_ptr<Subscriber>> &subscribers = sessManager_[subscriber->sess_];
135     subscribers.insert(std::lower_bound(subscribers.begin(), subscribers.end(), subscriber, Compare), subscriber);
136 }
137 
RemoveSessSubscriber(SessionPtr sess,int32_t subscribeId)138 void LongPressSubscriberHandler::RemoveSessSubscriber(SessionPtr sess, int32_t subscribeId)
139 {
140     CALL_DEBUG_ENTER;
141     CHKPV(sess);
142     auto it = sessManager_.find(sess);
143     if (it == sessManager_.end()) {
144         MMI_HILOGE("Not found the sess");
145         return;
146     }
147     std::vector<std::shared_ptr<Subscriber>> &subscribers = it->second;
148     for (auto iter = subscribers.begin(); iter != subscribers.end(); ++iter) {
149         if ((*iter)->id_ == subscribeId) {
150             subscribers.erase(iter);
151             if (subscribers.empty()) {
152                 sessManager_.erase(it);
153             }
154             return;
155         }
156     }
157 }
158 
OnSubscribeLongPressEvent(int32_t fingerCount,int32_t duration)159 void LongPressSubscriberHandler::OnSubscribeLongPressEvent(int32_t fingerCount, int32_t duration)
160 {
161     CALL_DEBUG_ENTER;
162     MMI_HILOGD("FingerCount:%{public}d, duration:%{public}d", fingerCount, duration);
163     auto pair = std::make_pair(fingerCount, duration);
164     auto it = subscriberInfos_.find(pair);
165     if (subscriberInfos_.find(pair) == subscriberInfos_.end()) {
166         MMI_HILOGE("Not found the subscriber, fingerCount:%{public}d, duration:%{public}d",
167             fingerCount, duration);
168         return;
169     }
170     std::vector<std::shared_ptr<Subscriber>> &subscribers = it->second;
171     for (const auto &subscriber : subscribers) {
172         NotifySubscriber(subscriber, RET_OK);
173     }
174 }
175 
InsertSubScriber(const std::shared_ptr<Subscriber> subscriber)176 void LongPressSubscriberHandler::InsertSubScriber(const std::shared_ptr<Subscriber> subscriber)
177 {
178     CALL_DEBUG_ENTER;
179     CHKPV(subscriber);
180     auto pair = std::make_pair(subscriber->fingerCount_, subscriber->duration_);
181     auto it = subscriberInfos_.find(pair);
182     if (it != subscriberInfos_.end()) {
183         std::vector<std::shared_ptr<Subscriber>> &subscribers = it->second;
184         for (const auto &sub : subscribers) {
185             if (subscriber->sess_ != nullptr && sub->id_ == subscriber->id_ && sub->sess_ == subscriber->sess_) {
186                 MMI_HILOGW("Repeat registration id:%{public}d, desc:%{public}s",
187                     subscriber->id_, subscriber->sess_->GetDescript().c_str());
188                 return;
189             }
190         }
191     }
192     subscriberInfos_[pair].push_back(subscriber);
193 }
194 
OnSessionDelete(SessionPtr sess)195 void LongPressSubscriberHandler::OnSessionDelete(SessionPtr sess)
196 {
197     CALL_DEBUG_ENTER;
198     CHKPV(sess);
199     for (auto it = subscriberInfos_.begin(); it != subscriberInfos_.end();) {
200         std::vector<std::shared_ptr<Subscriber>> &subscribers = it->second;
201         for (auto iter = subscribers.begin(); iter != subscribers.end();) {
202             if ((*iter)->sess_ == sess) {
203                 RemoveSessSubscriber(sess, (*iter)->id_);
204                 iter = subscribers.erase(iter);
205                 auto fingerCount = it->first.first;
206                 auto duration = it->first.second;
207                 RemoveDurationTimer(fingerCount, duration);
208                 continue;
209             }
210             ++iter;
211         }
212         if (subscribers.empty()) {
213             it = subscriberInfos_.erase(it);
214         } else {
215              ++it;
216         }
217     }
218 }
219 
HandleFingerGestureDownEvent(const std::shared_ptr<PointerEvent> touchEvent)220 void LongPressSubscriberHandler::HandleFingerGestureDownEvent(const std::shared_ptr<PointerEvent> touchEvent)
221 {
222     CALL_DEBUG_ENTER;
223     CHKPV(touchEvent);
224     auto fingerCount = touchEvent->GetPointerIds().size();
225     if (fingerCount > 0 && fingerCount <= TwoFingerGesture::MAX_TOUCH_NUM) {
226         touchEvent_ = touchEvent;
227         int32_t id = touchEvent->GetPointerId();
228         PointerEvent::PointerItem item;
229         touchEvent->GetPointerItem(id, item);
230         fingerGesture_.touches[fingerCount - 1].id = id;
231         fingerGesture_.touches[fingerCount - 1].x = item.GetDisplayX();
232         fingerGesture_.touches[fingerCount - 1].y = item.GetDisplayY();
233         fingerGesture_.touches[fingerCount - 1].downTime = item.GetDownTime();
234     } else {
235         MMI_HILOGD("The number of finger count is not 1 or 2");
236         return;
237     }
238     if (fingerCount == static_cast<size_t>(ONE_FINGER)) {
239         StartFingerGesture(ONE_FINGER);
240     } else if (fingerCount == static_cast<size_t>(TWO_FINGER)) {
241         StopFingerGesture();
242         auto firstFinger = fingerGesture_.touches[0];
243         auto secondFinger = fingerGesture_.touches[1];
244         auto pressTimeInterval = fabs(firstFinger.downTime - secondFinger.downTime);
245         if (pressTimeInterval > TWO_FINGERS_TIME_LIMIT) {
246             MMI_HILOGI("Two fingers time too long firstdownTime:%{public}" PRId64 ",seconddownTime:%{public}" PRId64,
247                 firstFinger.downTime, secondFinger.downTime);
248             return;
249         }
250         StartFingerGesture(TWO_FINGER);
251     } else {
252         MMI_HILOGW("The number of finger count is not 1 or 2");
253         StopFingerGesture();
254     }
255 }
256 
HandleFingerGestureMoveEvent(const std::shared_ptr<PointerEvent> touchEvent)257 void LongPressSubscriberHandler::HandleFingerGestureMoveEvent(const std::shared_ptr<PointerEvent> touchEvent)
258 {
259     CALL_DEBUG_ENTER;
260     CHKPV(touchEvent);
261     if (isAllTimerClosed) {
262         MMI_HILOGD("Finger gesture has stopped");
263         return;
264     }
265     auto fingerCount = touchEvent->GetPointerIds().size();
266     if (fingerCount > static_cast<size_t>(TWO_FINGER)) {
267         MMI_HILOGE("Not support more than two finger gesture");
268         return;
269     }
270     int32_t id = touchEvent->GetPointerId();
271     PointerEvent::PointerItem item;
272     touchEvent->GetPointerItem(id, item);
273     auto pos = std::find_if(std::begin(fingerGesture_.touches), std::end(fingerGesture_.touches),
274         [id](const auto& item) { return item.id == id; });
275     if (pos == std::end(fingerGesture_.touches)) {
276         MMI_HILOGE("Cant't find the pointer id");
277         return;
278     }
279     auto dx = std::abs(pos->x - item.GetDisplayX());
280     auto dy = std::abs(pos->y - item.GetDisplayY());
281     auto moveDistance = sqrt(pow(dx, TWO_FINGER) + pow(dy, TWO_FINGER));
282     if (moveDistance > TOUCH_MOVE_THRESHOLD) {
283         MMI_HILOGD("Finger movement distance greater than 15PX, defaultDistance:%{public}d, moveDistance:%{public}f",
284             TOUCH_MOVE_THRESHOLD, moveDistance);
285         CheckFingerGestureCancelEvent(touchEvent);
286         StopFingerGesture();
287     }
288 }
289 
HandleFingerGestureUpEvent(const std::shared_ptr<PointerEvent> touchEvent)290 void LongPressSubscriberHandler::HandleFingerGestureUpEvent(const std::shared_ptr<PointerEvent> touchEvent)
291 {
292     CALL_DEBUG_ENTER;
293     CHKPV(touchEvent);
294     if (isAllTimerClosed) {
295         MMI_HILOGD("Finger gesture has stopped");
296         return;
297     }
298     if (touchEvent->GetPointerIds().size() > static_cast<size_t>(TWO_FINGER)) {
299         MMI_HILOGE("Not support more than two finger gesture");
300         return;
301     }
302     CheckFingerGestureCancelEvent(touchEvent);
303     StopFingerGesture();
304 }
305 
CheckFingerGestureCancelEvent(const std::shared_ptr<PointerEvent> touchEvent) const306 void LongPressSubscriberHandler::CheckFingerGestureCancelEvent(const std::shared_ptr<PointerEvent> touchEvent) const
307 {
308     CALL_DEBUG_ENTER;
309     CHKPV(touchEvent);
310     auto fingerCount = touchEvent->GetPointerIds().size();
311     size_t index = fingerCount - 1;
312     if (index < 0 || index > static_cast<size_t>(ONE_FINGER)) {
313         MMI_HILOGE("Not support more than two finger gesture");
314         return;
315     }
316     int64_t currentTime = touchEvent->GetActionTime() - fingerGesture_.touches[index].downTime;
317     if (!durationTimers_.empty()) {
318         if (currentTime < durationTimers_[0].duration * MS_TO_US) {
319             MMI_HILOGD("The current time is earlier than the minimum delay, the cancel event does not need to be sent");
320             return;
321         }
322     }
323 
324     for (auto it = sessManager_.begin(); it != sessManager_.end(); ++it) {
325         const std::vector<std::shared_ptr<Subscriber>> &subscribers = it->second;
326         std::vector<std::shared_ptr<Subscriber>> tempSubs;
327         for (auto iter = subscribers.begin(); iter != subscribers.end(); ++iter) {
328             if (fingerCount == static_cast<size_t>((*iter)->fingerCount_)) {
329                 tempSubs.push_back(*iter);
330             }
331         }
332         if (tempSubs.size() < static_cast<size_t>(TWO_FINGER)) {
333             continue;
334         }
335         for (size_t i = 0; i + 1 < tempSubs.size(); ++i) {
336             if (currentTime < (tempSubs[i]->duration_ * MS_TO_US)) {
337                 break;
338             }
339             if ((currentTime > (tempSubs[i]->duration_ * MS_TO_US)) &&
340                 (currentTime < (tempSubs[i + 1]->duration_ * MS_TO_US))) {
341                 OnSubscribeLongPressCancelEvent(it->first, fingerCount, tempSubs[i + 1]->duration_);
342                 break;
343             }
344         }
345     }
346 }
347 
OnSubscribeLongPressCancelEvent(SessionPtr sess,int32_t fingerCount,int32_t duration) const348 void LongPressSubscriberHandler::OnSubscribeLongPressCancelEvent(SessionPtr sess, int32_t fingerCount,
349     int32_t duration) const
350 {
351     CALL_DEBUG_ENTER;
352     auto it = sessManager_.find(sess);
353     if (it == sessManager_.end()) {
354         MMI_HILOGE("Not found the sess");
355         return;
356     }
357     const std::vector<std::shared_ptr<Subscriber>> &subscribers = sessManager_.at(sess);
358     for (const auto &subscriber : subscribers) {
359         if (subscriber->fingerCount_ == fingerCount && subscriber->duration_ == duration) {
360             NotifySubscriber(subscriber, RET_ERR);
361         }
362     }
363 }
364 
StartFingerGesture(int32_t fingerCount)365 void LongPressSubscriberHandler::StartFingerGesture(int32_t fingerCount)
366 {
367     CALL_DEBUG_ENTER;
368     for (size_t i = 0; i < durationTimers_.size(); ++i) {
369         durationTimers_[i].timerId = TimerMgr->AddTimer(durationTimers_[i].duration, 1, [this, i, fingerCount]() {
370             durationTimers_[i].timerId = -1;
371             if (!CheckFingerGestureAction(fingerCount)) {
372                 return;
373             }
374             OnSubscribeLongPressEvent(fingerCount, durationTimers_[i].duration);
375         });
376     }
377     isAllTimerClosed = false;
378 }
379 
StopFingerGesture()380 void LongPressSubscriberHandler::StopFingerGesture()
381 {
382     CALL_DEBUG_ENTER;
383     for (auto &durationTimer : durationTimers_) {
384         if (durationTimer.timerId != -1) {
385             TimerMgr->RemoveTimer(durationTimer.timerId);
386             durationTimer.timerId = -1;
387         }
388     }
389     isAllTimerClosed = true;
390 }
391 
CheckFingerGestureAction(int32_t fingerCount) const392 bool LongPressSubscriberHandler::CheckFingerGestureAction(int32_t fingerCount) const
393 {
394     CALL_DEBUG_ENTER;
395     auto displayInfo = WIN_MGR->GetDefaultDisplayInfo();
396     CHKPR(displayInfo, false);
397     auto leftLimit = ConvertVPToPX(TOUCH_LIFT_LIMIT);
398     auto rightLimit = displayInfo->width - ConvertVPToPX(TOUCH_RIGHT_LIMIT);
399     auto topLimit = ConvertVPToPX(TOUCH_TOP_LIMIT);
400     auto bottomLimit = displayInfo->height - ConvertVPToPX(TOUCH_BOTTOM_LIMIT);
401 
402     auto firstFinger = fingerGesture_.touches[0];
403     if (firstFinger.x <= leftLimit || firstFinger.x >= rightLimit ||
404         firstFinger.y <= topLimit || firstFinger.y >= bottomLimit) {
405         MMI_HILOGI("Any finger out of region");
406         return false;
407     }
408     if (fingerCount == TWO_FINGER) {
409         auto secondFinger = fingerGesture_.touches[1];
410         if (secondFinger.x <= leftLimit || secondFinger.x >= rightLimit ||
411             secondFinger.y <= topLimit || secondFinger.y >= bottomLimit) {
412             MMI_HILOGI("Any finger out of region");
413             return false;
414         }
415         auto devX = firstFinger.x - secondFinger.x;
416         auto devY = firstFinger.y - secondFinger.y;
417         auto distance = sqrt(pow(devX, TWO_FINGER) + pow(devY, TWO_FINGER));
418         if (distance < ConvertVPToPX(TWO_FINGERS_DISTANCE_LIMIT)) {
419             MMI_HILOGI("Two fingers distance:%{public}f too small", distance);
420             return false;
421         }
422     }
423     return true;
424 }
425 
InitSessionDeleteCallback()426 bool LongPressSubscriberHandler::InitSessionDeleteCallback()
427 {
428     CALL_DEBUG_ENTER;
429     if (callbackInitialized_) {
430         MMI_HILOGD("Session delete callback has already been initialized");
431         return true;
432     }
433     auto udsServerPtr = InputHandler->GetUDSServer();
434     CHKPF(udsServerPtr);
435     std::function<void(SessionPtr)> callback =
436         [this] (SessionPtr sess) { return this->OnSessionDelete(sess); };
437     udsServerPtr->AddSessionDeletedCallback(callback);
438     callbackInitialized_ = true;
439     return true;
440 }
441 
ConvertVPToPX(int32_t vp) const442 int32_t LongPressSubscriberHandler::ConvertVPToPX(int32_t vp) const
443 {
444     if (vp <= 0) {
445         return 0;
446     }
447     auto displayInfo = WIN_MGR->GetDefaultDisplayInfo();
448     CHKPR(displayInfo, 0);
449     int32_t dpi = displayInfo->dpi;
450     if (dpi <= 0) {
451         return 0;
452     }
453     return vp * (dpi / PX_BASE);
454 }
455 
GetBundleName(std::string & bundleName,int32_t windowPid) const456 int32_t LongPressSubscriberHandler::GetBundleName(std::string &bundleName, int32_t windowPid) const
457 {
458     CALL_DEBUG_ENTER;
459     auto appMgrClient = DelayedSingleton<AppExecFwk::AppMgrClient>::GetInstance();
460     CHKPR(appMgrClient, ERROR_NULL_POINTER);
461     int32_t userid = WIN_MGR->GetCurrentUserId();
462     if (userid < 0) {
463         userid = DEFAULT_USER_ID;
464     }
465     auto udsServer = InputHandler->GetUDSServer();
466     CHKPR(udsServer, RET_ERR);
467     auto sess = udsServer->GetSessionByPid(windowPid);
468     if (sess != nullptr) {
469         bundleName = sess->GetProgramName();
470         return RET_OK;
471     }
472     return RET_ERR;
473 }
474 
NotifySubscriber(std::shared_ptr<Subscriber> subscriber,int32_t result) const475 void LongPressSubscriberHandler::NotifySubscriber(std::shared_ptr<Subscriber> subscriber, int32_t result) const
476 {
477     CALL_DEBUG_ENTER;
478     CHKPV(subscriber);
479     auto udsServerPtr = InputHandler->GetUDSServer();
480     CHKPV(udsServerPtr);
481     if (subscriber->sess_ == nullptr) {
482         MMI_HILOGE("Subscriber's sess is null");
483         return;
484     }
485     int32_t windowPid = WIN_MGR->GetWindowPid(touchEvent_->GetTargetWindowId());
486     if (windowPid == RET_ERR) {
487         MMI_HILOGE("Get window pid failed");
488         return;
489     }
490 
491     std::string bundleName;
492     if (GetBundleName(bundleName, windowPid) == RET_ERR) {
493         MMI_HILOGE("Failed to get bundle name, pid %{public}d", windowPid);
494     }
495     int32_t id = touchEvent_->GetPointerId();
496     PointerEvent::PointerItem item;
497     touchEvent_->GetPointerItem(id, item);
498     LongPressEvent longPressEvent = {
499         .fingerCount = subscriber->fingerCount_,
500         .duration = subscriber->duration_,
501         .pid = windowPid,
502         .displayId = touchEvent_->GetTargetDisplayId(),
503         .displayX = fingerGesture_.touches[0].x,
504         .displayY = fingerGesture_.touches[0].y,
505         .result = result,
506         .windowId = touchEvent_->GetTargetWindowId(),
507         .pointerId = touchEvent_->GetPointerId(),
508         .downTime = item.GetDownTime(),
509         .bundleName = bundleName,
510     };
511 
512     NetPacket pkt(MmiMessageId::ON_SUBSCRIBE_LONG_PRESS);
513     InputEventDataTransformation::LongPressEventToNetPacket(longPressEvent, pkt);
514     int32_t fd = subscriber->sess_->GetFd();
515     pkt << fd << subscriber->id_;
516     MMI_HILOGI("Notify subscriber id:%{public}d, pid:%{public}d", subscriber->id_, subscriber->sess_->GetPid());
517     if (pkt.ChkRWError()) {
518         MMI_HILOGE("Packet write dispatch subscriber failed");
519         return;
520     }
521     if (!udsServerPtr->SendMsg(fd, pkt)) {
522         MMI_HILOGE("Leave, server dispatch subscriber failed");
523     }
524 }
525 } // namespace MMI
526 } // namespace OHOS
527