• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
HandleUnInstallApp(const std::list<int32_t> & sessions)106 void SessionListenerController::HandleUnInstallApp(const std::list<int32_t>& sessions)
107 {
108     for (auto id : sessions) {
109         CallListeners(&ISessionListener::OnMissionDestroyed, id);
110     }
111 }
112 
NotifySessionSnapshotChanged(int32_t persistentId)113 void SessionListenerController::NotifySessionSnapshotChanged(int32_t persistentId)
114 {
115     if (persistentId == -1) {
116         return;
117     }
118     WLOGFI("Id:%{public}d", persistentId);
119     CallListeners(&ISessionListener::OnMissionSnapshotChanged, persistentId);
120 }
121 
NotifySessionMovedToFront(int32_t persistentId)122 void SessionListenerController::NotifySessionMovedToFront(int32_t persistentId)
123 {
124     if (persistentId == -1) {
125         return;
126     }
127     WLOGFI("Id:%{public}d", persistentId);
128     CallListeners(&ISessionListener::OnMissionMovedToFront, persistentId);
129 }
130 
NotifySessionFocused(int32_t persistentId)131 void SessionListenerController::NotifySessionFocused(int32_t persistentId)
132 {
133     if (persistentId == -1) {
134         return;
135     }
136     TLOGI(WmsLogTag::WMS_FOCUS, "Id:%{public}d", persistentId);
137     CallListeners(&ISessionListener::OnMissionFocused, persistentId);
138 }
139 
NotifySessionUnfocused(int32_t persistentId)140 void SessionListenerController::NotifySessionUnfocused(int32_t persistentId)
141 {
142     if (persistentId == -1) {
143         return;
144     }
145     TLOGI(WmsLogTag::WMS_FOCUS, "Id:%{public}d", persistentId);
146     CallListeners(&ISessionListener::OnMissionUnfocused, persistentId);
147 }
148 
NotifySessionIconChanged(int32_t persistentId,const std::shared_ptr<OHOS::Media::PixelMap> & icon)149 void SessionListenerController::NotifySessionIconChanged(int32_t persistentId,
150                                                          const std::shared_ptr<OHOS::Media::PixelMap>& icon)
151 {
152     if (persistentId == -1) {
153         return;
154     }
155     WLOGFI("Id:%{public}d", persistentId);
156     CallListeners(&ISessionListener::OnMissionIconUpdated, persistentId, icon);
157 }
158 
NotifySessionClosed(const SessionInfo & sessionInfo)159 void SessionListenerController::NotifySessionClosed(const SessionInfo& sessionInfo)
160 {
161     int32_t persistentId = sessionInfo.persistentId_;
162     if (persistentId == -1) {
163         return;
164     }
165     WLOGFI("Id:%{public}d", persistentId);
166     CallListeners(&ISessionListener::OnMissionClosed, persistentId);
167     NotifySessionLifecycleEvent(ISessionLifecycleListener::SessionLifecycleEvent::DESTROYED, sessionInfo);
168 }
169 
NotifySessionLabelUpdated(int32_t persistentId)170 void SessionListenerController::NotifySessionLabelUpdated(int32_t persistentId)
171 {
172     if (persistentId == -1) {
173         return;
174     }
175     WLOGFI("Id:%{public}d", persistentId);
176     CallListeners(&ISessionListener::OnMissionLabelUpdated, persistentId);
177 }
178 
OnListenerDied(const wptr<IRemoteObject> & remote)179 void SessionListenerController::OnListenerDied(const wptr<IRemoteObject>& remote)
180 {
181     WLOGFD("in");
182     auto remoteObj = remote.promote();
183     if (!remoteObj) {
184         WLOGFD("invalid remote object");
185         return;
186     }
187     remoteObj->RemoveDeathRecipient(listenerDeathRecipient_);
188 
189     std::lock_guard guard(listenerLock_);
190     auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
191                            [&remoteObj](const sptr<ISessionListener>& item) {
192                                return item && item->AsObject() == remoteObj;
193                            });
194     if (it != sessionListeners_.end()) {
195         WLOGFI("SessionListener removed on died");
196         sessionListeners_.erase(it);
197     }
198 }
199 
OnSessionLifecycleListenerDied(const wptr<IRemoteObject> & remote)200 void SessionListenerController::OnSessionLifecycleListenerDied(const wptr<IRemoteObject>& remote)
201 {
202     TLOGD(WmsLogTag::WMS_LIFE, "in");
203     auto remoteObj = remote.promote();
204     if (!remoteObj) {
205         TLOGD(WmsLogTag::WMS_LIFE, "invalid remote object");
206         return;
207     }
208     taskScheduler_->PostAsyncTask([this, remoteObj, where = __func__] {
209         remoteObj->RemoveDeathRecipient(lifecycleListenerDeathRecipient_);
210         TLOGI(WmsLogTag::WMS_LIFE, "SessionLifecycleListener removed on died.");
211         RemoveSessionLifecycleListener(remoteObj);
212     }, __func__);
213 }
214 
215 template<typename F, typename... Args>
CallListeners(F func,Args &&...args)216 void SessionListenerController::CallListeners(F func, Args&&... args)
217 {
218     std::vector<sptr<ISessionListener>> sessionListenersTemp;
219     {
220         std::lock_guard guard(listenerLock_);
221         WLOGFD("size:%{public}d", static_cast<int32_t>(sessionListeners_.size()));
222         sessionListenersTemp = sessionListeners_;
223     }
224     for (auto listener : sessionListenersTemp) {
225         if (listener) {
226             (listener->*func)(std::forward<Args>(args)...);
227         }
228     }
229 }
230 
ConstructPayload(ISessionLifecycleListener::LifecycleEventPayload & payload,const SessionInfo & sessionInfo)231 void SessionListenerController::ConstructPayload(
232     ISessionLifecycleListener::LifecycleEventPayload& payload, const SessionInfo& sessionInfo)
233 {
234     payload.bundleName_ = sessionInfo.bundleName_;
235     payload.moduleName_ = sessionInfo.moduleName_;
236     payload.abilityName_ = sessionInfo.abilityName_;
237     payload.appIndex_ = sessionInfo.appIndex_;
238     payload.persistentId_ = sessionInfo.persistentId_;
239 }
240 
RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener> & listener,const std::vector<int32_t> & persistentIdList)241 WMError SessionListenerController::RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener>& listener,
242     const std::vector<int32_t>& persistentIdList)
243 {
244     if (!listener) {
245         TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
246         return WMError::WM_ERROR_INVALID_PARAM;
247     }
248     if (listenerMapById_.size() > MAX_LISTEN_TARGET_LIMIT) {
249         TLOGW(WmsLogTag::WMS_LIFE, "The number of listeners has reached the upper limit.");
250         return WMError::WM_ERROR_INVALID_OPERATION;
251     }
252     if (!lifecycleListenerDeathRecipient_) {
253         auto task = [weakThis = weak_from_this()](const wptr<IRemoteObject>& remote) {
254             if (auto controller = weakThis.lock()) {
255                 controller->OnSessionLifecycleListenerDied(remote);
256             }
257         };
258         lifecycleListenerDeathRecipient_ = sptr<ListenerDeathRecipient>::MakeSptr(task);
259     }
260     auto listenerObject = listener->AsObject();
261     if (listenerObject) {
262         listenerObject->AddDeathRecipient(lifecycleListenerDeathRecipient_);
263     }
264     for (const int32_t id : persistentIdList) {
265         if (!SceneSessionManager::GetInstance().IsMainWindowByPersistentId(id)) {
266             TLOGW(WmsLogTag::WMS_LIFE, "invalid persistentId");
267             continue;
268         }
269         auto it = listenerMapById_.find(id);
270         if (it != listenerMapById_.end()) {
271             if (it->second.size() >= MAX_LIFECYCLE_LISTENER_LIMIT) {
272                 TLOGE(WmsLogTag::WMS_LIFE, "The number of listen target has reached the upper limit.");
273                 return WMError::WM_ERROR_INVALID_OPERATION;
274             }
275             it->second.emplace_back(listener);
276         } else {
277             std::vector<sptr<ISessionLifecycleListener>> newListenerList;
278             newListenerList.emplace_back(listener);
279             listenerMapById_.emplace(id, newListenerList);
280         }
281     }
282     TLOGI(WmsLogTag::WMS_LIFE, "Register SessionLifecycleListener By Id Finished.");
283     return WMError::WM_OK;
284 }
285 
RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener> & listener,const std::vector<std::string> & bundleNameList)286 WMError SessionListenerController::RegisterSessionLifecycleListener(const sptr<ISessionLifecycleListener>& listener,
287     const std::vector<std::string>& bundleNameList)
288 {
289     if (!listener) {
290         TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
291         return WMError::WM_ERROR_INVALID_PARAM;
292     }
293     if (listenerMapById_.size() > MAX_LISTEN_TARGET_LIMIT) {
294         TLOGW(WmsLogTag::WMS_LIFE, "The number of listen target has reached the upper limit.");
295         return WMError::WM_ERROR_INVALID_OPERATION;
296     }
297     if (!lifecycleListenerDeathRecipient_) {
298         auto task = [weakThis = weak_from_this()](const wptr<IRemoteObject>& remote) {
299             if (auto controller = weakThis.lock()) {
300                 controller->OnSessionLifecycleListenerDied(remote);
301             }
302         };
303         lifecycleListenerDeathRecipient_ = sptr<ListenerDeathRecipient>::MakeSptr(task);
304     }
305     auto listenerObject = listener->AsObject();
306     if (listenerObject) {
307         listenerObject->AddDeathRecipient(lifecycleListenerDeathRecipient_);
308     }
309     if (bundleNameList.empty()) {
310         listenersOfAllBundles_.emplace_back(listener);
311         return WMError::WM_OK;
312     }
313     for (const std::string& bundleName : bundleNameList) {
314         if (bundleName.empty() || bundleName.size() > MAX_BUNDLE_NAME_LEN) {
315             TLOGW(WmsLogTag::WMS_LIFE, "invalid bundleName");
316             continue;
317         }
318         auto it = listenerMapByBundle_.find(bundleName);
319         if (it != listenerMapByBundle_.end()) {
320             if (it->second.size() >= MAX_LIFECYCLE_LISTENER_LIMIT) {
321                 TLOGE(WmsLogTag::WMS_LIFE, "The number of listeners has reached the upper limit.");
322                 return WMError::WM_ERROR_INVALID_OPERATION;
323             }
324             it->second.emplace_back(listener);
325         } else {
326             std::vector<sptr<ISessionLifecycleListener>> newListenerList;
327             newListenerList.emplace_back(listener);
328             listenerMapByBundle_.emplace(bundleName, newListenerList);
329         }
330     }
331     TLOGI(WmsLogTag::WMS_LIFE, "Register SessionLifecycleListener By Bundle Finished.");
332     return WMError::WM_OK;
333 }
334 
UnregisterSessionLifecycleListener(const sptr<ISessionLifecycleListener> & listener)335 WMError SessionListenerController::UnregisterSessionLifecycleListener(const sptr<ISessionLifecycleListener>& listener)
336 {
337     if (!listener) {
338         TLOGE(WmsLogTag::WMS_LIFE, "listener is invalid.");
339         return WMError::WM_ERROR_INVALID_PARAM;
340     }
341     const sptr<IRemoteObject> target = listener->AsObject();
342     if (!target) {
343         TLOGE(WmsLogTag::WMS_LIFE, "remote listener is invalid.");
344         return WMError::WM_ERROR_INVALID_PARAM;
345     }
346     RemoveSessionLifecycleListener(target);
347     TLOGI(WmsLogTag::WMS_LIFE, "Session Lifecycle Listener Unregister Finished.");
348     return WMError::WM_OK;
349 }
350 
RemoveSessionLifecycleListener(const sptr<IRemoteObject> & target)351 void SessionListenerController::RemoveSessionLifecycleListener(const sptr<IRemoteObject>& target)
352 {
353     auto compareByAsObject = [&target](const sptr<ISessionLifecycleListener>& item) {
354         return (item != nullptr) && (item->AsObject() == target);
355     };
356 
357     for (auto it = listenerMapById_.begin(); it != listenerMapById_.end();) {
358         auto& listeners = it->second;
359         listeners.erase(std::remove_if(listeners.begin(), listeners.end(), compareByAsObject), listeners.end());
360         if (listeners.empty()) {
361             it = listenerMapById_.erase(it);
362         } else {
363             ++it;
364         }
365     }
366 
367     for (auto it = listenerMapByBundle_.begin(); it != listenerMapByBundle_.end();) {
368         auto& listeners = it->second;
369         listeners.erase(std::remove_if(listeners.begin(), listeners.end(), compareByAsObject), listeners.end());
370         if (listeners.empty()) {
371             it = listenerMapByBundle_.erase(it);
372         } else {
373             ++it;
374         }
375     }
376 
377     auto iter = std::remove_if(listenersOfAllBundles_.begin(), listenersOfAllBundles_.end(), compareByAsObject);
378     listenersOfAllBundles_.erase(iter, listenersOfAllBundles_.end());
379     TLOGI(WmsLogTag::WMS_LIFE, "Remove listeners from map success.");
380 }
381 
NotifySessionLifecycleEvent(ISessionLifecycleListener::SessionLifecycleEvent event,const SessionInfo & sessionInfo)382 void SessionListenerController::NotifySessionLifecycleEvent(
383     ISessionLifecycleListener::SessionLifecycleEvent event, const SessionInfo& sessionInfo)
384 {
385     std::string bundleName = sessionInfo.bundleName_;
386     int32_t persistentId = sessionInfo.persistentId_;
387     if (persistentId <= INVALID_SESSION_ID) {
388         TLOGE(WmsLogTag::WMS_LIFE, "invalid persistentId!");
389         return;
390     }
391     ISessionLifecycleListener::LifecycleEventPayload payload;
392     ConstructPayload(payload, sessionInfo);
393     NotifyMissionEvent(event, persistentId);
394     TLOGI(WmsLogTag::WMS_LIFE, "start notify listeners, bundleName:%{public}s, Id:%{public}d, state:%{public}d",
395         bundleName.c_str(), persistentId, event);
396 
397     NotifyListeners(listenerMapById_, persistentId, event, payload);
398     NotifyListeners(listenerMapByBundle_, bundleName, event, payload);
399 
400     for (const auto& listener : listenersOfAllBundles_) {
401         if (listener != nullptr) {
402             listener->OnLifecycleEvent(event, payload);
403         }
404     }
405 }
406 
407 template <typename KeyType, typename MapType>
NotifyListeners(const MapType & listenerMap,const KeyType & key,const ISessionLifecycleListener::SessionLifecycleEvent event,ISessionLifecycleListener::LifecycleEventPayload & payload)408 void SessionListenerController::NotifyListeners(const MapType& listenerMap, const KeyType& key,
409     const ISessionLifecycleListener::SessionLifecycleEvent event,
410     ISessionLifecycleListener::LifecycleEventPayload& payload)
411 {
412     auto it = listenerMap.find(key);
413     if (it != listenerMap.end()) {
414         const auto& listeners = it->second;
415         for (const auto& listener : listeners) {
416             if (listener != nullptr) {
417                 listener->OnLifecycleEvent(event, payload);
418             }
419         }
420     }
421 }
422 
NotifyMissionEvent(ISessionLifecycleListener::SessionLifecycleEvent event,int32_t persistentId)423 void SessionListenerController::NotifyMissionEvent(
424     ISessionLifecycleListener::SessionLifecycleEvent event, int32_t persistentId)
425 {
426     switch (event) {
427         case ISessionLifecycleListener::SessionLifecycleEvent::CREATED:
428             NotifySessionCreated(persistentId);
429             break;
430         case ISessionLifecycleListener::SessionLifecycleEvent::DESTROYED:
431             NotifySessionDestroyed(persistentId);
432             break;
433         default:
434             break;
435     }
436 }
437 } // namespace Rosen
438 } // namespace OHOS
439