1 /*
2 * Copyright (c) 2023 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 "session_listener_controller.h"
17 #include "scene_session_manager.h"
18 #include "window_manager_hilog.h"
19
20 namespace OHOS {
21 namespace Rosen {
22 namespace {
23 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SessionListenerController"};
24 }
25 constexpr int32_t MAX_LIFECYCLE_LISTENER_LIMIT = 32;
26 constexpr int32_t MAX_LISTEN_TARGET_LIMIT = 512;
27 constexpr int32_t MAX_BUNDLE_NAME_LEN = 128;
28
SessionListenerController(const std::shared_ptr<TaskScheduler> & taskScheduler)29 SessionListenerController::SessionListenerController(const std::shared_ptr<TaskScheduler>& taskScheduler)
30 {
31 taskScheduler_ = taskScheduler;
32 }
33
AddSessionListener(const sptr<ISessionListener> & listener)34 WSError SessionListenerController::AddSessionListener(const sptr<ISessionListener>& listener)
35 {
36 if (!listener) {
37 WLOGFE("listener is invalid");
38 return WSError::WS_ERROR_INVALID_PARAM;
39 }
40
41 std::lock_guard guard(listenerLock_);
42 auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
43 [&listener](const sptr<ISessionListener>& item) {
44 return item && item->AsObject() == listener->AsObject();
45 });
46 if (it != sessionListeners_.end()) {
47 WLOGFW("listener was already added");
48 return WSError::WS_OK;
49 }
50
51 if (!listenerDeathRecipient_) {
52 auto task = [weakThis = weak_from_this()](const wptr<IRemoteObject>& remote) {
53 if (auto controller = weakThis.lock()) {
54 controller->OnListenerDied(remote);
55 }
56 };
57 listenerDeathRecipient_ = sptr<ListenerDeathRecipient>::MakeSptr(task);
58 }
59 if (auto listenerObject = listener->AsObject(); listenerObject && listenerObject->IsProxyObject()) {
60 listenerObject->AddDeathRecipient(listenerDeathRecipient_);
61 }
62 sessionListeners_.emplace_back(listener);
63 WLOGFI("success");
64 return WSError::WS_OK;
65 }
66
DelSessionListener(const sptr<ISessionListener> & listener)67 void SessionListenerController::DelSessionListener(const sptr<ISessionListener>& listener)
68 {
69 if (!listener) {
70 WLOGFE("listener is invalid");
71 return;
72 }
73
74 std::lock_guard guard(listenerLock_);
75 auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
76 [&listener](const sptr<ISessionListener>& item) {
77 return item && item->AsObject() == listener->AsObject();
78 });
79 if (it != sessionListeners_.end()) {
80 WLOGFI("success");
81 if (auto listenerObject = listener->AsObject(); listenerObject && listenerObject->IsProxyObject()) {
82 listenerObject->RemoveDeathRecipient(listenerDeathRecipient_);
83 }
84 sessionListeners_.erase(it);
85 }
86 }
87
NotifySessionCreated(int32_t persistentId)88 void SessionListenerController::NotifySessionCreated(int32_t persistentId)
89 {
90 if (persistentId == -1) {
91 return;
92 }
93 WLOGFI("Id:%{public}d", persistentId);
94 CallListeners(&ISessionListener::OnMissionCreated, persistentId);
95 }
96
NotifySessionDestroyed(int32_t persistentId)97 void SessionListenerController::NotifySessionDestroyed(int32_t persistentId)
98 {
99 if (persistentId == -1) {
100 return;
101 }
102 WLOGFI("Id:%{public}d", persistentId);
103 CallListeners(&ISessionListener::OnMissionDestroyed, persistentId);
104 }
105
NotifySessionBackground(int32_t persistentId)106 void SessionListenerController::NotifySessionBackground(int32_t persistentId)
107 {
108 if (persistentId == -1) {
109 return;
110 }
111 TLOGI(WmsLogTag::WMS_LIFE, "Id:%{public}d", persistentId);
112 CallListeners(&ISessionListener::OnMissionMovedToBackground, persistentId);
113 }
114
HandleUnInstallApp(const std::list<int32_t> & sessions)115 void SessionListenerController::HandleUnInstallApp(const std::list<int32_t>& sessions)
116 {
117 for (auto id : sessions) {
118 CallListeners(&ISessionListener::OnMissionDestroyed, id);
119 }
120 }
121
NotifySessionSnapshotChanged(int32_t persistentId)122 void SessionListenerController::NotifySessionSnapshotChanged(int32_t persistentId)
123 {
124 if (persistentId == -1) {
125 return;
126 }
127 WLOGFI("Id:%{public}d", persistentId);
128 CallListeners(&ISessionListener::OnMissionSnapshotChanged, persistentId);
129 }
130
NotifySessionMovedToFront(int32_t persistentId)131 void SessionListenerController::NotifySessionMovedToFront(int32_t persistentId)
132 {
133 if (persistentId == -1) {
134 return;
135 }
136 WLOGFI("Id:%{public}d", persistentId);
137 CallListeners(&ISessionListener::OnMissionMovedToFront, persistentId);
138 }
139
NotifySessionFocused(int32_t persistentId)140 void SessionListenerController::NotifySessionFocused(int32_t persistentId)
141 {
142 if (persistentId == -1) {
143 return;
144 }
145 TLOGI(WmsLogTag::WMS_FOCUS, "Id:%{public}d", persistentId);
146 CallListeners(&ISessionListener::OnMissionFocused, persistentId);
147 }
148
NotifySessionUnfocused(int32_t persistentId)149 void SessionListenerController::NotifySessionUnfocused(int32_t persistentId)
150 {
151 if (persistentId == -1) {
152 return;
153 }
154 TLOGI(WmsLogTag::WMS_FOCUS, "Id:%{public}d", persistentId);
155 CallListeners(&ISessionListener::OnMissionUnfocused, persistentId);
156 }
157
NotifySessionIconChanged(int32_t persistentId,const std::shared_ptr<OHOS::Media::PixelMap> & icon)158 void SessionListenerController::NotifySessionIconChanged(int32_t persistentId,
159 const std::shared_ptr<OHOS::Media::PixelMap>& icon)
160 {
161 if (persistentId == -1) {
162 return;
163 }
164 WLOGFI("Id:%{public}d", persistentId);
165 CallListeners(&ISessionListener::OnMissionIconUpdated, persistentId, icon);
166 }
167
NotifySessionClosed(const SessionInfo & sessionInfo)168 void SessionListenerController::NotifySessionClosed(const SessionInfo& sessionInfo)
169 {
170 int32_t persistentId = sessionInfo.persistentId_;
171 if (persistentId == -1) {
172 return;
173 }
174 WLOGFI("Id:%{public}d", persistentId);
175 CallListeners(&ISessionListener::OnMissionClosed, persistentId);
176 NotifySessionLifecycleEvent(ISessionLifecycleListener::SessionLifecycleEvent::DESTROYED, sessionInfo);
177 }
178
NotifySessionLabelUpdated(int32_t persistentId)179 void SessionListenerController::NotifySessionLabelUpdated(int32_t persistentId)
180 {
181 if (persistentId == -1) {
182 return;
183 }
184 WLOGFI("Id:%{public}d", persistentId);
185 CallListeners(&ISessionListener::OnMissionLabelUpdated, persistentId);
186 }
187
OnListenerDied(const wptr<IRemoteObject> & remote)188 void SessionListenerController::OnListenerDied(const wptr<IRemoteObject>& remote)
189 {
190 WLOGFD("in");
191 auto remoteObj = remote.promote();
192 if (!remoteObj) {
193 WLOGFD("invalid remote object");
194 return;
195 }
196 remoteObj->RemoveDeathRecipient(listenerDeathRecipient_);
197
198 std::lock_guard guard(listenerLock_);
199 auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
200 [&remoteObj](const sptr<ISessionListener>& item) {
201 return item && item->AsObject() == remoteObj;
202 });
203 if (it != sessionListeners_.end()) {
204 WLOGFI("SessionListener removed on died");
205 sessionListeners_.erase(it);
206 }
207 }
208
OnSessionLifecycleListenerDied(const wptr<IRemoteObject> & remote)209 void SessionListenerController::OnSessionLifecycleListenerDied(const wptr<IRemoteObject>& remote)
210 {
211 TLOGD(WmsLogTag::WMS_LIFE, "in");
212 taskScheduler_->PostAsyncTask([weakThis = weak_from_this(), remote, where = __func__] {
213 auto controller = weakThis.lock();
214 if (controller == nullptr) {
215 TLOGNE(WmsLogTag::WMS_LIFE, "controller is null");
216 return;
217 }
218 auto remoteObj = remote.promote();
219 if (!remoteObj) {
220 TLOGND(WmsLogTag::WMS_LIFE, "invalid remote object");
221 return;
222 }
223 remoteObj->RemoveDeathRecipient(controller->lifecycleListenerDeathRecipient_);
224 TLOGNI(WmsLogTag::WMS_LIFE, "SessionLifecycleListener removed on died.");
225 controller->RemoveSessionLifecycleListener(remoteObj);
226 }, __func__);
227 }
228
229 template<typename F, typename... Args>
CallListeners(F func,Args &&...args)230 void SessionListenerController::CallListeners(F func, Args&&... args)
231 {
232 std::vector<sptr<ISessionListener>> sessionListenersTemp;
233 {
234 std::lock_guard guard(listenerLock_);
235 WLOGFD("size:%{public}d", static_cast<int32_t>(sessionListeners_.size()));
236 sessionListenersTemp = sessionListeners_;
237 }
238 for (auto listener : sessionListenersTemp) {
239 if (listener) {
240 (listener->*func)(std::forward<Args>(args)...);
241 }
242 }
243 }
244
ConstructPayload(ISessionLifecycleListener::LifecycleEventPayload & payload,const SessionInfo & sessionInfo,const uint32_t resultCode,const uint64_t fromScreenId,const uint64_t toScreenId)245 void SessionListenerController::ConstructPayload(ISessionLifecycleListener::LifecycleEventPayload& payload,
246 const SessionInfo& sessionInfo, const uint32_t resultCode, const uint64_t fromScreenId, const uint64_t toScreenId)
247 {
248 payload.bundleName_ = sessionInfo.bundleName_;
249 payload.moduleName_ = sessionInfo.moduleName_;
250 payload.abilityName_ = sessionInfo.abilityName_;
251 payload.appIndex_ = sessionInfo.appIndex_;
252 payload.persistentId_ = sessionInfo.persistentId_;
253 payload.resultCode_ = resultCode;
254 payload.fromScreenId_ = fromScreenId;
255 payload.toScreenId_ = toScreenId;
256 }
257
RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener> & listener,const std::vector<int32_t> & persistentIdList)258 WMError SessionListenerController::RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener>& listener,
259 const std::vector<int32_t>& persistentIdList)
260 {
261 if (!listener) {
262 TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
263 return WMError::WM_ERROR_INVALID_PARAM;
264 }
265 if (!lifecycleListenerDeathRecipient_) {
266 auto task = [weakThis = weak_from_this()](const wptr<IRemoteObject>& remote) {
267 if (auto controller = weakThis.lock()) {
268 controller->OnSessionLifecycleListenerDied(remote);
269 }
270 };
271 lifecycleListenerDeathRecipient_ = sptr<ListenerDeathRecipient>::MakeSptr(task);
272 }
273 auto listenerObject = listener->AsObject();
274 if (listenerObject) {
275 listenerObject->AddDeathRecipient(lifecycleListenerDeathRecipient_);
276 }
277 if (UnregisterSessionLifecycleListener(listener) != WMError::WM_OK) {
278 TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
279 return WMError::WM_ERROR_INVALID_PARAM;
280 }
281 bool hasValidId = false;
282 for (const int32_t id : persistentIdList) {
283 if (!SceneSessionManager::GetInstance().IsMainWindowByPersistentId(id)) {
284 TLOGW(WmsLogTag::WMS_LIFE, "invalid persistentId");
285 continue;
286 }
287 hasValidId = true;
288 auto it = listenerMapById_.find(id);
289 if (it != listenerMapById_.end()) {
290 if (it->second.size() >= MAX_LIFECYCLE_LISTENER_LIMIT) {
291 TLOGE(WmsLogTag::WMS_LIFE, "The number of listen target has reached the upper limit.");
292 return WMError::WM_ERROR_INVALID_OPERATION;
293 }
294 it->second.emplace_back(listener);
295 } else {
296 std::vector<sptr<ISessionLifecycleListener>> newListenerList;
297 newListenerList.emplace_back(listener);
298 listenerMapById_.emplace(id, newListenerList);
299 }
300 TLOGI(WmsLogTag::WMS_LIFE, "id:%{public}d", id);
301 }
302 return hasValidId ? WMError::WM_OK : WMError::WM_ERROR_INVALID_PARAM;
303 }
304
RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener> & listener,const std::vector<std::string> & bundleNameList)305 WMError SessionListenerController::RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener>& listener,
306 const std::vector<std::string>& bundleNameList)
307 {
308 if (!listener) {
309 TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
310 return WMError::WM_ERROR_INVALID_PARAM;
311 }
312 if (!lifecycleListenerDeathRecipient_) {
313 auto task = [weakThis = weak_from_this()](const wptr<IRemoteObject>& remote) {
314 if (auto controller = weakThis.lock()) {
315 controller->OnSessionLifecycleListenerDied(remote);
316 }
317 };
318 lifecycleListenerDeathRecipient_ = sptr<ListenerDeathRecipient>::MakeSptr(task);
319 }
320 auto listenerObject = listener->AsObject();
321 if (listenerObject) {
322 listenerObject->AddDeathRecipient(lifecycleListenerDeathRecipient_);
323 }
324 if (UnregisterSessionLifecycleListener(listener) != WMError::WM_OK) {
325 TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
326 return WMError::WM_ERROR_INVALID_PARAM;
327 }
328 if (bundleNameList.empty()) {
329 listenersOfAllBundles_.emplace_back(listener);
330 TLOGI(WmsLogTag::WMS_LIFE, "Register SessionLifecycleListener By All Bundles Finished.");
331 return WMError::WM_OK;
332 }
333 for (const std::string& bundleName : bundleNameList) {
334 if (bundleName.empty() || bundleName.size() > MAX_BUNDLE_NAME_LEN) {
335 TLOGW(WmsLogTag::WMS_LIFE, "invalid bundleName");
336 continue;
337 }
338 auto it = listenerMapByBundle_.find(bundleName);
339 if (it != listenerMapByBundle_.end()) {
340 if (it->second.size() >= MAX_LIFECYCLE_LISTENER_LIMIT) {
341 TLOGE(WmsLogTag::WMS_LIFE, "The number of listeners has reached the upper limit.");
342 return WMError::WM_ERROR_INVALID_OPERATION;
343 }
344 it->second.emplace_back(listener);
345 } else {
346 std::vector<sptr<ISessionLifecycleListener>> newListenerList;
347 newListenerList.emplace_back(listener);
348 listenerMapByBundle_.emplace(bundleName, newListenerList);
349 }
350 }
351 TLOGI(WmsLogTag::WMS_LIFE, "Register SessionLifecycleListener By Bundle Finished.");
352 return WMError::WM_OK;
353 }
354
UnregisterSessionLifecycleListener(const sptr<ISessionLifecycleListener> & listener)355 WMError SessionListenerController::UnregisterSessionLifecycleListener(const sptr<ISessionLifecycleListener>& listener)
356 {
357 if (!listener) {
358 TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
359 return WMError::WM_ERROR_INVALID_PARAM;
360 }
361 const sptr<IRemoteObject> target = listener->AsObject();
362 if (!target) {
363 TLOGE(WmsLogTag::WMS_LIFE, "remote listener is invalid.");
364 return WMError::WM_ERROR_INVALID_PARAM;
365 }
366 RemoveSessionLifecycleListener(target);
367 TLOGI(WmsLogTag::WMS_LIFE, "Session Lifecycle Listener Unregister Finished.");
368 return WMError::WM_OK;
369 }
370
RemoveSessionLifecycleListener(const sptr<IRemoteObject> & target)371 void SessionListenerController::RemoveSessionLifecycleListener(const sptr<IRemoteObject>& target)
372 {
373 auto compareByAsObject = [&target](const sptr<ISessionLifecycleListener>& item) {
374 return (item != nullptr) && (item->AsObject() == target);
375 };
376
377 for (auto it = listenerMapById_.begin(); it != listenerMapById_.end();) {
378 auto& listeners = it->second;
379 listeners.erase(std::remove_if(listeners.begin(), listeners.end(), compareByAsObject), listeners.end());
380 if (listeners.empty()) {
381 it = listenerMapById_.erase(it);
382 } else {
383 ++it;
384 }
385 }
386
387 for (auto it = listenerMapByBundle_.begin(); it != listenerMapByBundle_.end();) {
388 auto& listeners = it->second;
389 listeners.erase(std::remove_if(listeners.begin(), listeners.end(), compareByAsObject), listeners.end());
390 if (listeners.empty()) {
391 it = listenerMapByBundle_.erase(it);
392 } else {
393 ++it;
394 }
395 }
396
397 auto iter = std::remove_if(listenersOfAllBundles_.begin(), listenersOfAllBundles_.end(), compareByAsObject);
398 listenersOfAllBundles_.erase(iter, listenersOfAllBundles_.end());
399 TLOGI(WmsLogTag::WMS_LIFE, "Remove listeners from map success.");
400 }
401
NotifySessionLifecycleEvent(ISessionLifecycleListener::SessionLifecycleEvent event,const SessionInfo & sessionInfo)402 void SessionListenerController::NotifySessionLifecycleEvent(
403 ISessionLifecycleListener::SessionLifecycleEvent event, const SessionInfo& sessionInfo)
404 {
405 std::string bundleName = sessionInfo.bundleName_;
406 int32_t persistentId = sessionInfo.persistentId_;
407 if (persistentId <= INVALID_SESSION_ID) {
408 TLOGE(WmsLogTag::WMS_LIFE, "invalid persistentId!");
409 return;
410 }
411 ISessionLifecycleListener::LifecycleEventPayload payload;
412 ConstructPayload(payload, sessionInfo);
413 NotifyMissionEvent(event, persistentId);
414 taskScheduler_->PostAsyncTask(
415 [weakThis = weak_from_this(), event, payload, bundleName, persistentId, where = __func__] {
416 auto controller = weakThis.lock();
417 if (controller == nullptr) {
418 TLOGE(WmsLogTag::WMS_LIFE, "controller is null.");
419 return;
420 }
421 TLOGI(WmsLogTag::WMS_LIFE, "start notify listeners, bundleName:%{public}s, Id:%{public}d, state:%{public}d",
422 bundleName.c_str(), persistentId, event);
423
424 controller->NotifyListeners(controller->listenerMapById_, persistentId, event, payload);
425 controller->NotifyListeners(controller->listenerMapByBundle_, bundleName, event, payload);
426 for (const auto& listener : controller->listenersOfAllBundles_) {
427 if (listener != nullptr) {
428 listener->OnLifecycleEvent(event, payload);
429 }
430 }
431 }, __func__);
432 }
433
434 template <typename KeyType, typename MapType>
NotifyListeners(const MapType & listenerMap,const KeyType & key,const ISessionLifecycleListener::SessionLifecycleEvent event,const ISessionLifecycleListener::LifecycleEventPayload & payload)435 void SessionListenerController::NotifyListeners(const MapType& listenerMap, const KeyType& key,
436 const ISessionLifecycleListener::SessionLifecycleEvent event,
437 const ISessionLifecycleListener::LifecycleEventPayload& payload)
438 {
439 auto it = listenerMap.find(key);
440 if (it != listenerMap.end()) {
441 const auto& listeners = it->second;
442 for (const auto& listener : listeners) {
443 if (listener != nullptr) {
444 listener->OnLifecycleEvent(event, payload);
445 }
446 }
447 }
448 }
449
NotifyMissionEvent(ISessionLifecycleListener::SessionLifecycleEvent event,int32_t persistentId)450 void SessionListenerController::NotifyMissionEvent(
451 ISessionLifecycleListener::SessionLifecycleEvent event, int32_t persistentId)
452 {
453 switch (event) {
454 case ISessionLifecycleListener::SessionLifecycleEvent::CREATED:
455 NotifySessionCreated(persistentId);
456 break;
457 case ISessionLifecycleListener::SessionLifecycleEvent::DESTROYED:
458 NotifySessionDestroyed(persistentId);
459 break;
460 case ISessionLifecycleListener::SessionLifecycleEvent::BACKGROUND:
461 NotifySessionBackground(persistentId);
462 break;
463 default:
464 break;
465 }
466 }
467
NotifySessionTransferToTargetScreenEvent(const SessionInfo & sessionInfo,const uint32_t resultCode,const uint64_t fromScreenId,const uint64_t toScreenId)468 void SessionListenerController::NotifySessionTransferToTargetScreenEvent(const SessionInfo& sessionInfo,
469 const uint32_t resultCode, const uint64_t fromScreenId, const uint64_t toScreenId)
470 {
471 int32_t persistentId = sessionInfo.persistentId_;
472 if (persistentId <= INVALID_SESSION_ID) {
473 TLOGE(WmsLogTag::WMS_LIFE, "invalid persistentId!");
474 return;
475 }
476 std::string bundleName = sessionInfo.bundleName_;
477 auto event = ISessionLifecycleListener::SessionLifecycleEvent::TRANSFER_TO_TARGET_SCREEN;
478 ISessionLifecycleListener::LifecycleEventPayload payload;
479 ConstructPayload(payload, sessionInfo, resultCode, fromScreenId, toScreenId);
480 taskScheduler_->PostAsyncTask(
481 [weakThis = weak_from_this(), event, payload, bundleName, persistentId, where = __func__] {
482 auto controller = weakThis.lock();
483 if (controller == nullptr) {
484 TLOGNE(WmsLogTag::WMS_LIFE, "controller is null.");
485 return;
486 }
487 TLOGNI(WmsLogTag::WMS_LIFE,
488 "start notify listeners, bundleName:%{public}s, persistentId:%{public}d, event:%{public}d",
489 bundleName.c_str(), persistentId, event);
490 controller->NotifyListeners(controller->listenerMapById_, persistentId, event, payload);
491 controller->NotifyListeners(controller->listenerMapByBundle_, bundleName, event, payload);
492 for (const auto& listener : controller->listenersOfAllBundles_) {
493 if (listener != nullptr) {
494 listener->OnLifecycleEvent(event, payload);
495 }
496 }
497 }, __func__);
498 }
499
IsListenerMapByIdSizeReachLimit() const500 bool SessionListenerController::IsListenerMapByIdSizeReachLimit() const
501 {
502 return taskScheduler_->PostSyncTask([this] {
503 return listenerMapById_.size() >= MAX_LISTEN_TARGET_LIMIT;
504 }, __func__);
505 }
506
IsListenerMapByBundleSizeReachLimit(bool isBundleNameListEmpty) const507 bool SessionListenerController::IsListenerMapByBundleSizeReachLimit(bool isBundleNameListEmpty) const
508 {
509 return taskScheduler_->PostSyncTask([this, isBundleNameListEmpty] {
510 if (isBundleNameListEmpty) {
511 return listenersOfAllBundles_.size() >= MAX_LIFECYCLE_LISTENER_LIMIT;
512 }
513 return listenerMapByBundle_.size() >= MAX_LISTEN_TARGET_LIMIT;
514 }, __func__);
515 }
516 } // namespace Rosen
517 } // namespace OHOS
518