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