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_manager_lite.h"
17 #include <ipc_skeleton.h>
18 #include <iremote_stub.h>
19 #include <iservice_registry.h>
20 #include <system_ability_definition.h>
21 
22 #include "session_manager_service_recover_interface.h"
23 #include "scene_session_manager_lite_proxy.h"
24 #include "window_manager_hilog.h"
25 
26 namespace OHOS::Rosen {
27 namespace {
28 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "SessionManagerLite" };
29 }
30 
31 class SessionManagerServiceLiteRecoverListener : public IRemoteStub<ISessionManagerServiceRecoverListener> {
32 public:
33     SessionManagerServiceLiteRecoverListener() = default;
34 
35     int32_t OnRemoteRequest(
36         uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override
37     {
38         if (data.ReadInterfaceToken() != GetDescriptor()) {
39             TLOGE(WmsLogTag::WMS_RECOVER, "InterfaceToken check failed");
40             return ERR_TRANSACTION_FAILED;
41         }
42         auto msgId = static_cast<SessionManagerServiceRecoverMessage>(code);
43         switch (msgId) {
44             case SessionManagerServiceRecoverMessage::TRANS_ID_ON_SESSION_MANAGER_SERVICE_RECOVER: {
45                 auto sessionManagerService = data.ReadRemoteObject();
46                 // Even if sessionManagerService is null, the recovery process is still required.
47                 OnSessionManagerServiceRecover(sessionManagerService);
48                 break;
49             }
50             case SessionManagerServiceRecoverMessage::TRANS_ID_ON_WMS_CONNECTION_CHANGED: {
51                 int32_t userId = INVALID_USER_ID;
52                 int32_t screenId = DEFAULT_SCREEN_ID;
53                 bool isConnected = false;
54                 if (!data.ReadInt32(userId) || !data.ReadInt32(screenId) || !data.ReadBool(isConnected)) {
55                     TLOGE(WmsLogTag::WMS_MULTI_USER, "Read data failed in lite!");
56                     return ERR_TRANSACTION_FAILED;
57                 }
58                 if (isConnected) {
59                     // Even if data.ReadRemoteObject() is null, the WMS connection still needs to be notified.
60                     OnWMSConnectionChanged(userId, screenId, isConnected, data.ReadRemoteObject());
61                 } else {
62                     OnWMSConnectionChanged(userId, screenId, isConnected, nullptr);
63                 }
64                 break;
65             }
66             default:
67                 TLOGW(WmsLogTag::WMS_RECOVER, "unknown transaction code %{public}d", code);
68                 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
69         }
70         return ERR_NONE;
71     }
72 
73     void OnSessionManagerServiceRecover(const sptr<IRemoteObject>& sessionManagerService) override
74     {
75         SessionManagerLite::GetInstance().Clear();
76         SessionManagerLite::GetInstance().ClearSessionManagerProxy();
77 
78         auto sms = iface_cast<ISessionManagerService>(sessionManagerService);
79         SessionManagerLite::GetInstance().RecoverSessionManagerService(sms);
80     }
81 
82     void OnWMSConnectionChanged(
83         int32_t userId, int32_t screenId, bool isConnected, const sptr<IRemoteObject>& sessionManagerService) override
84     {
85         auto sms = iface_cast<ISessionManagerService>(sessionManagerService);
86         SessionManagerLite::GetInstance().OnWMSConnectionChanged(userId, screenId, isConnected, sms);
87     }
88 };
89 
90 class SceneSessionManagerLiteProxyMock : public SceneSessionManagerLiteProxy {
91 public:
SceneSessionManagerLiteProxyMock(const sptr<IRemoteObject>& impl)92     explicit SceneSessionManagerLiteProxyMock(const sptr<IRemoteObject>& impl)
93         : SceneSessionManagerLiteProxy(impl) {}
94     virtual ~SceneSessionManagerLiteProxyMock() = default;
95 
96     WSError RegisterSessionListener(const sptr<ISessionListener>& listener, bool isRecover = false) override
97     {
98         TLOGI(WmsLogTag::DEFAULT, "called");
99         auto ret = SceneSessionManagerLiteProxy::RegisterSessionListener(listener);
100         if (ret != WSError::WS_OK) {
101             return ret;
102         }
103         if (isRecover) {
104             TLOGI(WmsLogTag::DEFAULT, "Recover mode, no need to save listener");
105             return WSError::WS_OK;
106         }
107         SessionManagerLite::GetInstance().SaveSessionListener(listener);
108         return WSError::WS_OK;
109     }
110     WSError UnRegisterSessionListener(const sptr<ISessionListener>& listener) override
111     {
112         TLOGI(WmsLogTag::DEFAULT, "called");
113         auto ret = SceneSessionManagerLiteProxy::UnRegisterSessionListener(listener);
114         SessionManagerLite::GetInstance().DeleteSessionListener(listener);
115         return ret;
116     }
117 
118 private:
119     static inline BrokerDelegator<SceneSessionManagerLiteProxyMock> delegator_;
120 };
121 
122 WM_IMPLEMENT_SINGLE_INSTANCE(SessionManagerLite)
123 
~SessionManagerLite()124 SessionManagerLite::~SessionManagerLite()
125 {
126     TLOGI(WmsLogTag::WMS_LIFE, "destroyed");
127 }
128 
ClearSessionManagerProxy()129 void SessionManagerLite::ClearSessionManagerProxy()
130 {
131     WLOGFI("enter");
132     std::lock_guard<std::recursive_mutex> lock(mutex_);
133     sessionManagerServiceProxy_ = nullptr;
134     sceneSessionManagerLiteProxy_ = nullptr;
135     screenSessionManagerLiteProxy_ = nullptr;
136 }
137 
GetSceneSessionManagerLiteProxy()138 sptr<ISceneSessionManagerLite> SessionManagerLite::GetSceneSessionManagerLiteProxy()
139 {
140     std::lock_guard<std::recursive_mutex> lock(mutex_);
141     InitSessionManagerServiceProxy();
142     InitSceneSessionManagerLiteProxy();
143     return sceneSessionManagerLiteProxy_;
144 }
145 
GetScreenSessionManagerLiteProxy()146 sptr<IScreenSessionManagerLite> SessionManagerLite::GetScreenSessionManagerLiteProxy()
147 {
148     std::lock_guard<std::recursive_mutex> lock(mutex_);
149     InitSessionManagerServiceProxy();
150     InitScreenSessionManagerLiteProxy();
151     return screenSessionManagerLiteProxy_;
152 }
153 
GetSessionManagerServiceProxy()154 sptr<ISessionManagerService> SessionManagerLite::GetSessionManagerServiceProxy()
155 {
156     std::lock_guard<std::recursive_mutex> lock(mutex_);
157     InitSessionManagerServiceProxy();
158     InitSceneSessionManagerLiteProxy();
159     return sessionManagerServiceProxy_;
160 }
161 
SaveSessionListener(const sptr<ISessionListener>& listener)162 void SessionManagerLite::SaveSessionListener(const sptr<ISessionListener>& listener)
163 {
164     if (listener == nullptr) {
165         TLOGW(WmsLogTag::DEFAULT, "listener is nullptr");
166         return;
167     }
168     std::lock_guard<std::recursive_mutex> guard(listenerLock_);
169     auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
170         [&listener](const sptr<ISessionListener>& item) {
171             return (item && item->AsObject() == listener->AsObject());
172         });
173     if (it != sessionListeners_.end()) {
174         TLOGW(WmsLogTag::DEFAULT, "listener was already added, do not add again");
175         return;
176     }
177     sessionListeners_.emplace_back(listener);
178 }
179 
DeleteSessionListener(const sptr<ISessionListener>& listener)180 void SessionManagerLite::DeleteSessionListener(const sptr<ISessionListener>& listener)
181 {
182     TLOGI(WmsLogTag::DEFAULT, "called");
183     std::lock_guard<std::recursive_mutex> guard(listenerLock_);
184     auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
185         [&listener](const sptr<ISessionListener>& item) {
186             return (item && item->AsObject() == listener->AsObject());
187         });
188     if (it != sessionListeners_.end()) {
189         sessionListeners_.erase(it);
190     }
191 }
192 
DeleteAllSessionListeners()193 void SessionManagerLite::DeleteAllSessionListeners()
194 {
195     std::lock_guard<std::recursive_mutex> guard(listenerLock_);
196     sessionListeners_.clear();
197 }
198 
RecoverSessionManagerService(const sptr<ISessionManagerService>& sessionManagerService)199 void SessionManagerLite::RecoverSessionManagerService(const sptr<ISessionManagerService>& sessionManagerService)
200 {
201     {
202         std::lock_guard<std::recursive_mutex> lock(mutex_);
203         sessionManagerServiceProxy_ = sessionManagerService;
204     }
205     GetSceneSessionManagerLiteProxy();
206     ReregisterSessionListener();
207     if (userSwitchCallbackFunc_) {
208         TLOGI(WmsLogTag::WMS_RECOVER, "user switch");
209         userSwitchCallbackFunc_();
210     }
211 }
212 
ReregisterSessionListener()213 void SessionManagerLite::ReregisterSessionListener()
214 {
215     sptr<ISceneSessionManagerLite> sceneSessionManagerLiteProxy = nullptr;
216     {
217         std::lock_guard<std::recursive_mutex> lock(mutex_);
218         sceneSessionManagerLiteProxy = sceneSessionManagerLiteProxy_;
219     }
220     if (sceneSessionManagerLiteProxy == nullptr) {
221         TLOGE(WmsLogTag::WMS_RECOVER, "sceneSessionManagerLiteProxy is null");
222         return;
223     }
224 
225     std::lock_guard<std::recursive_mutex> guard(listenerLock_);
226     TLOGI(WmsLogTag::WMS_RECOVER, "listener count = %{public}" PRIu64,
227         static_cast<int64_t>(sessionListeners_.size()));
228     for (const auto& listener : sessionListeners_) {
229         auto ret = sceneSessionManagerLiteProxy->RegisterSessionListener(listener, true);
230         if (ret != WSError::WS_OK) {
231             TLOGW(WmsLogTag::WMS_RECOVER, "failed, ret = %{public}" PRId32, ret);
232         }
233     }
234 }
235 
RegisterUserSwitchListener(const UserSwitchCallbackFunc& callbackFunc)236 void SessionManagerLite::RegisterUserSwitchListener(const UserSwitchCallbackFunc& callbackFunc)
237 {
238     TLOGI(WmsLogTag::WMS_MULTI_USER, "enter");
239     userSwitchCallbackFunc_ = callbackFunc;
240 }
241 
OnWMSConnectionChanged( int32_t userId, int32_t screenId, bool isConnected, const sptr<ISessionManagerService>& sessionManagerService)242 void SessionManagerLite::OnWMSConnectionChanged(
243     int32_t userId, int32_t screenId, bool isConnected, const sptr<ISessionManagerService>& sessionManagerService)
244 {
245     bool isCallbackRegistered = false;
246     int32_t lastUserId = INVALID_USER_ID;
247     int32_t lastScreenId = DEFAULT_SCREEN_ID;
248     {
249         // The mutex ensures the timing of the following variable states in multiple threads
250         std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
251         lastUserId = currentWMSUserId_;
252         lastScreenId = currentScreenId_;
253         isCallbackRegistered = wmsConnectionChangedFunc_ != nullptr;
254         if (isConnected) {
255             currentWMSUserId_ = userId;
256             currentScreenId_ = screenId;
257         }
258         // isWMSConnected_ only represents the wms connection status of the active user
259         if (currentWMSUserId_ == userId) {
260             isWMSConnected_ = isConnected;
261         }
262     }
263     TLOGI(WmsLogTag::WMS_MULTI_USER,
264         "Lite: curUserId=%{public}d, oldUserId=%{public}d, screenId=%{public}d, isConnected=%{public}d", userId,
265         lastUserId, screenId, isConnected);
266     if (isConnected && lastUserId > INVALID_USER_ID && lastUserId != userId) {
267         // Notify the user that the old wms has been disconnected.
268         OnWMSConnectionChangedCallback(lastUserId, lastScreenId, false, isCallbackRegistered);
269         OnUserSwitch(sessionManagerService);
270     }
271     // Notify the user that the current wms connection has changed.
272     OnWMSConnectionChangedCallback(userId, screenId, isConnected, isCallbackRegistered);
273 }
274 
OnUserSwitch(const sptr<ISessionManagerService>& sessionManagerService)275 void SessionManagerLite::OnUserSwitch(const sptr<ISessionManagerService>& sessionManagerService)
276 {
277     TLOGI(WmsLogTag::WMS_MULTI_USER, "User switched Lite");
278     {
279         Clear();
280         std::lock_guard<std::recursive_mutex> lock(mutex_);
281         sessionManagerServiceProxy_ = sessionManagerService;
282         sceneSessionManagerLiteProxy_ = nullptr;
283         InitSceneSessionManagerLiteProxy();
284         if (!sceneSessionManagerLiteProxy_) {
285             TLOGE(WmsLogTag::WMS_MULTI_USER, "sceneSessionManagerLiteProxy is null");
286             return;
287         }
288     }
289     ReregisterSessionListener();
290     if (userSwitchCallbackFunc_) {
291         TLOGI(WmsLogTag::WMS_MULTI_USER, "User switch Lite callback.");
292         userSwitchCallbackFunc_();
293     }
294 }
295 
InitSessionManagerServiceProxy()296 void SessionManagerLite::InitSessionManagerServiceProxy()
297 {
298     if (sessionManagerServiceProxy_) {
299         return;
300     }
301     auto ret = InitMockSMSProxy();
302     if (ret != WMError::WM_OK) {
303         TLOGE(WmsLogTag::DEFAULT, "Init mock session manager service failed in Lite");
304         return;
305     }
306     RegisterSMSRecoverListener();
307     sptr<IRemoteObject> remoteObject = mockSessionManagerServiceProxy_->GetSessionManagerService();
308     if (!remoteObject) {
309         WLOGFE("Remote object is nullptr");
310         return;
311     }
312     sessionManagerServiceProxy_ = iface_cast<ISessionManagerService>(remoteObject);
313     if (!sessionManagerServiceProxy_) {
314         WLOGFE("sessionManagerServiceProxy is nullptr");
315     }
316 }
317 
InitScreenSessionManagerLiteProxy()318 void SessionManagerLite::InitScreenSessionManagerLiteProxy()
319 {
320     if (screenSessionManagerLiteProxy_) {
321         return;
322     }
323     if (!mockSessionManagerServiceProxy_) {
324         WLOGFE("mockSessionManagerServiceProxy is nullptr");
325         return;
326     }
327 
328     sptr<IRemoteObject> remoteObject = mockSessionManagerServiceProxy_->GetScreenSessionManagerLite();
329     if (!remoteObject) {
330         WLOGFW("Get screen session manager lite proxy failed, null");
331         return;
332     }
333     screenSessionManagerLiteProxy_ = iface_cast<IScreenSessionManagerLite>(remoteObject);
334     if (!screenSessionManagerLiteProxy_) {
335         WLOGFW("Get screen session manager lite proxy failed, iface_cast null");
336     }
337 }
338 
InitSceneSessionManagerLiteProxy()339 void SessionManagerLite::InitSceneSessionManagerLiteProxy()
340 {
341     if (sceneSessionManagerLiteProxy_) {
342         return;
343     }
344     if (!sessionManagerServiceProxy_) {
345         WLOGFE("sessionManagerServiceProxy is nullptr");
346         return;
347     }
348 
349     sptr<IRemoteObject> remoteObject = sessionManagerServiceProxy_->GetSceneSessionManagerLite();
350     if (!remoteObject) {
351         WLOGFW("Get scene session manager proxy failed, null");
352         return;
353     }
354     sceneSessionManagerLiteProxy_ = iface_cast<ISceneSessionManagerLite>(remoteObject);
355     if (sceneSessionManagerLiteProxy_) {
356         ssmDeath_ = sptr<SSMDeathRecipientLite>::MakeSptr();
357         if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(ssmDeath_)) {
358             WLOGFE("Failed to add death recipient");
359             return;
360         }
361     } else {
362         WLOGFW("Get scene session manager proxy failed, iface_cast null");
363     }
364 }
365 
Clear()366 void SessionManagerLite::Clear()
367 {
368     std::lock_guard<std::recursive_mutex> lock(mutex_);
369     if ((sceneSessionManagerLiteProxy_ != nullptr) && (sceneSessionManagerLiteProxy_->AsObject() != nullptr)) {
370         sceneSessionManagerLiteProxy_->AsObject()->RemoveDeathRecipient(ssmDeath_);
371     }
372 }
373 
OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)374 void SSMDeathRecipientLite::OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)
375 {
376     WLOGI("ssm OnRemoteDied");
377     SessionManagerLite::GetInstance().Clear();
378     SessionManagerLite::GetInstance().ClearSessionManagerProxy();
379 }
380 
RegisterWMSConnectionChangedListener(const WMSConnectionChangedCallbackFunc& callbackFunc)381 WMError SessionManagerLite::RegisterWMSConnectionChangedListener(const WMSConnectionChangedCallbackFunc& callbackFunc)
382 {
383     TLOGI(WmsLogTag::WMS_MULTI_USER, "Lite in");
384     if (callbackFunc == nullptr) {
385         TLOGE(WmsLogTag::WMS_MULTI_USER, "Lite callbackFunc is null");
386         return WMError::WM_ERROR_NULLPTR;
387     }
388     bool isWMSAlreadyConnected = false;
389     int32_t userId = INVALID_USER_ID;
390     int32_t screenId = DEFAULT_SCREEN_ID;
391     {
392         // The mutex ensures the timing of the following variable states in multiple threads
393         std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
394         wmsConnectionChangedFunc_ = callbackFunc;
395         isWMSAlreadyConnected = isWMSConnected_ && (currentWMSUserId_ > INVALID_USER_ID);
396         userId = currentWMSUserId_;
397         screenId = currentScreenId_;
398     }
399     if (isWMSAlreadyConnected) {
400         TLOGI(WmsLogTag::WMS_MULTI_USER, "Lite WMS already connected, notify immediately");
401         OnWMSConnectionChangedCallback(userId, screenId, true, true);
402     }
403     {
404         std::lock_guard<std::recursive_mutex> lock(mutex_);
405         auto ret = InitMockSMSProxy();
406         if (ret != WMError::WM_OK) {
407             TLOGE(WmsLogTag::WMS_MULTI_USER, "Init mock session manager service failed");
408             return ret;
409         }
410         RegisterSMSRecoverListener();
411     }
412     return WMError::WM_OK;
413 }
414 
InitMockSMSProxy()415 WMError SessionManagerLite::InitMockSMSProxy()
416 {
417     sptr<ISystemAbilityManager> systemAbilityManager =
418         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
419     if (!systemAbilityManager) {
420         TLOGE(WmsLogTag::WMS_MULTI_USER, "Failed to get system ability mgr.");
421         return WMError::WM_ERROR_NULLPTR;
422     }
423     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(WINDOW_MANAGER_SERVICE_ID);
424     if (!remoteObject) {
425         TLOGE(WmsLogTag::WMS_MULTI_USER, "Remote object is nullptr");
426         return WMError::WM_ERROR_NULLPTR;
427     }
428     mockSessionManagerServiceProxy_ = iface_cast<IMockSessionManagerInterface>(remoteObject);
429     if (!mockSessionManagerServiceProxy_) {
430         TLOGE(WmsLogTag::WMS_MULTI_USER, "Get mock session manager service proxy failed, nullptr");
431         return WMError::WM_ERROR_NULLPTR;
432     }
433 
434     if (GetUserIdByUid(getuid()) != SYSTEM_USERID || isFoundationListenerRegistered_) {
435         return WMError::WM_OK;
436     }
437     if (!foundationDeath_) {
438         foundationDeath_ = sptr<FoundationDeathRecipientLite>::MakeSptr();
439     }
440     if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(foundationDeath_)) {
441         TLOGE(WmsLogTag::WMS_MULTI_USER, "Failed to add death recipient");
442         return WMError::WM_ERROR_IPC_FAILED;
443     }
444     isFoundationListenerRegistered_ = true;
445     return WMError::WM_OK;
446 }
447 
RegisterSMSRecoverListener()448 void SessionManagerLite::RegisterSMSRecoverListener()
449 {
450     if (!recoverListenerRegistered_) {
451         if (!mockSessionManagerServiceProxy_) {
452             TLOGE(WmsLogTag::WMS_RECOVER, "mockSessionManagerServiceProxy is null");
453             return;
454         }
455         recoverListenerRegistered_ = true;
456         TLOGI(WmsLogTag::WMS_RECOVER, "Register recover listener");
457         smsRecoverListener_ = sptr<SessionManagerServiceLiteRecoverListener>::MakeSptr();
458         std::string identity = IPCSkeleton::ResetCallingIdentity();
459         mockSessionManagerServiceProxy_->RegisterSMSLiteRecoverListener(smsRecoverListener_);
460         IPCSkeleton::SetCallingIdentity(identity);
461     }
462 }
463 
OnWMSConnectionChangedCallback( int32_t userId, int32_t screenId, bool isConnected, bool isCallbackRegistered)464 void SessionManagerLite::OnWMSConnectionChangedCallback(
465     int32_t userId, int32_t screenId, bool isConnected, bool isCallbackRegistered)
466 {
467     if (isCallbackRegistered) {
468         TLOGI(WmsLogTag::WMS_MULTI_USER,
469             "WMS connection changed with userId=%{public}d, screenId=%{public}d, isConnected=%{public}d", userId,
470             screenId, isConnected);
471         wmsConnectionChangedFunc_(userId, screenId, isConnected);
472     } else {
473         TLOGD(WmsLogTag::WMS_MULTI_USER, "Lite WMS CallbackFunc is null.");
474     }
475 }
476 
OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)477 void FoundationDeathRecipientLite::OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)
478 {
479     TLOGI(WmsLogTag::WMS_RECOVER, "Foundation died");
480     SessionManagerLite::GetInstance().OnFoundationDied();
481 }
482 
OnFoundationDied()483 void SessionManagerLite::OnFoundationDied()
484 {
485     TLOGI(WmsLogTag::WMS_RECOVER, "enter");
486     {
487         std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
488         isWMSConnected_ = false;
489     }
490     std::lock_guard<std::recursive_mutex> lock(mutex_);
491     isFoundationListenerRegistered_ = false;
492     recoverListenerRegistered_ = false;
493     mockSessionManagerServiceProxy_ = nullptr;
494     sessionManagerServiceProxy_ = nullptr;
495     sceneSessionManagerLiteProxy_ = nullptr;
496 }
497 } // namespace OHOS::Rosen
498