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