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.h"
17 
18 #include <iservice_registry.h>
19 #include <system_ability_definition.h>
20 #include <ipc_skeleton.h>
21 
22 #include "session_manager_service_recover_interface.h"
23 #include "singleton_delegator.h"
24 #include "window_manager_hilog.h"
25 #include "session_manager_lite.h"
26 
27 namespace OHOS::Rosen {
28 namespace {
29 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_DISPLAY, "SessionManager" };
30 }
31 
32 class SessionManagerServiceRecoverListener : public IRemoteStub<ISessionManagerServiceRecoverListener> {
33 public:
34     explicit SessionManagerServiceRecoverListener() = default;
35 
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)36     virtual int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply,
37         MessageOption& option) override
38     {
39         if (data.ReadInterfaceToken() != GetDescriptor()) {
40             WLOGFE("InterfaceToken check failed");
41             return ERR_TRANSACTION_FAILED;
42         }
43         auto msgId = static_cast<SessionManagerServiceRecoverMessage>(code);
44         switch (msgId) {
45             case SessionManagerServiceRecoverMessage::TRANS_ID_ON_SESSION_MANAGER_SERVICE_RECOVER: {
46                 auto sessionManagerService = data.ReadRemoteObject();
47                 OnSessionManagerServiceRecover(sessionManagerService);
48                 break;
49             }
50             case SessionManagerServiceRecoverMessage::TRANS_ID_ON_WMS_CONNECTION_CHANGED: {
51                 int32_t userId = data.ReadInt32();
52                 int32_t screenId = data.ReadInt32();
53                 bool isConnected = data.ReadBool();
54                 if (isConnected) {
55                     OnWMSConnectionChanged(userId, screenId, isConnected, data.ReadRemoteObject());
56                 } else {
57                     OnWMSConnectionChanged(userId, screenId, isConnected, nullptr);
58                 }
59                 break;
60             }
61             default:
62                 WLOGFW("unknown transaction code %{public}d", code);
63                 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
64         }
65         return ERR_NONE;
66     }
67 
OnSessionManagerServiceRecover(const sptr<IRemoteObject> & sessionManagerService)68     void OnSessionManagerServiceRecover(const sptr<IRemoteObject>& sessionManagerService) override
69     {
70         SessionManager::GetInstance().Clear();
71         SessionManager::GetInstance().ClearSessionManagerProxy();
72 
73         auto sms = iface_cast<ISessionManagerService>(sessionManagerService);
74         SessionManager::GetInstance().RecoverSessionManagerService(sms);
75     }
76 
OnWMSConnectionChanged(int32_t userId,int32_t screenId,bool isConnected,const sptr<IRemoteObject> & sessionManagerService)77     void OnWMSConnectionChanged(
78         int32_t userId, int32_t screenId, bool isConnected, const sptr<IRemoteObject>& sessionManagerService) override
79     {
80         auto sms = iface_cast<ISessionManagerService>(sessionManagerService);
81         SessionManager::GetInstance().OnWMSConnectionChanged(userId, screenId, isConnected, sms);
82     }
83 };
84 
WM_IMPLEMENT_SINGLE_INSTANCE(SessionManager)85 WM_IMPLEMENT_SINGLE_INSTANCE(SessionManager)
86 
87 SessionManager::~SessionManager()
88 {
89     WLOGFI("destroyed!");
90 }
91 
OnWMSConnectionChangedCallback(int32_t userId,int32_t screenId,bool isConnected,bool isCallbackRegistered)92 void SessionManager::OnWMSConnectionChangedCallback(
93     int32_t userId, int32_t screenId, bool isConnected, bool isCallbackRegistered)
94 {
95     if (isCallbackRegistered) {
96         TLOGI(WmsLogTag::WMS_MULTI_USER,
97             "WMS connection changed with userId=%{public}d, screenId=%{public}d, isConnected=%{public}d", userId,
98             screenId, isConnected);
99         wmsConnectionChangedFunc_(userId, screenId, isConnected);
100     } else {
101         TLOGE(WmsLogTag::WMS_MULTI_USER, "WMS CallbackFunc is null.");
102     }
103 }
104 
OnWMSConnectionChanged(int32_t userId,int32_t screenId,bool isConnected,const sptr<ISessionManagerService> & sessionManagerService)105 void SessionManager::OnWMSConnectionChanged(
106     int32_t userId, int32_t screenId, bool isConnected, const sptr<ISessionManagerService>& sessionManagerService)
107 {
108     bool isCallbackRegistered = false;
109     int32_t lastUserId = INVALID_USER_ID;
110     int32_t lastScreenId = DEFAULT_SCREEN_ID;
111     {
112         // The mutex ensures the timing of the following variable states in multiple threads
113         std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
114         lastUserId = currentWMSUserId_;
115         lastScreenId = currentScreenId_;
116         isWMSConnected_ = isConnected;
117         isCallbackRegistered = wmsConnectionChangedFunc_ != nullptr;
118         if (isConnected) {
119             currentWMSUserId_ = userId;
120             currentScreenId_ = screenId;
121         }
122     }
123     TLOGI(WmsLogTag::WMS_MULTI_USER,
124         "curUserId=%{public}d, oldUserId=%{public}d, screenId=%{public}d, isConnected=%{public}d", userId, lastUserId,
125         screenId, isConnected);
126     if (isConnected && lastUserId > INVALID_UID && lastUserId != userId) {
127         // Notify the user that the old wms has been disconnected.
128         OnWMSConnectionChangedCallback(lastUserId, lastScreenId, false, isCallbackRegistered);
129         OnUserSwitch(sessionManagerService);
130     }
131     // Notify the user that the current wms connection has changed.
132     OnWMSConnectionChangedCallback(userId, screenId, isConnected, isCallbackRegistered);
133 }
134 
ClearSessionManagerProxy()135 void SessionManager::ClearSessionManagerProxy()
136 {
137     WLOGFI("enter!");
138     std::lock_guard<std::recursive_mutex> lock(mutex_);
139     if (sessionManagerServiceProxy_ != nullptr) {
140         int refCount = sessionManagerServiceProxy_->GetSptrRefCount();
141         WLOGFI("sessionManagerServiceProxy GetSptrRefCount : %{public}d", refCount);
142         sessionManagerServiceProxy_ = nullptr;
143     }
144     sceneSessionManagerProxy_ = nullptr;
145 }
146 
GetSceneSessionManagerProxy()147 __attribute__((no_sanitize("cfi"))) sptr<ISceneSessionManager> SessionManager::GetSceneSessionManagerProxy()
148 {
149     std::lock_guard<std::recursive_mutex> lock(mutex_);
150     InitSessionManagerServiceProxy();
151     InitSceneSessionManagerProxy();
152     return sceneSessionManagerProxy_;
153 }
154 
InitSessionManagerServiceProxy()155 void SessionManager::InitSessionManagerServiceProxy()
156 {
157     if (sessionManagerServiceProxy_) {
158         return;
159     }
160     if (InitMockSMSProxy() != WMError::WM_OK) {
161         WLOGFE("Init mock session manager service proxy failed");
162         return;
163     }
164 
165     RegisterSMSRecoverListener();
166 
167     sessionManagerServiceProxy_ = SessionManagerLite::GetInstance().GetSessionManagerServiceProxy();
168     if (!sessionManagerServiceProxy_) {
169         WLOGFE("sessionManagerServiceProxy is nullptr");
170     }
171 }
172 
InitMockSMSProxy()173 WMError SessionManager::InitMockSMSProxy()
174 {
175     sptr<ISystemAbilityManager> systemAbilityManager =
176         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
177     if (!systemAbilityManager) {
178         WLOGFE("Failed to get system ability mgr.");
179         return WMError::WM_ERROR_NULLPTR;
180     }
181 
182     sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(WINDOW_MANAGER_SERVICE_ID);
183     if (!remoteObject) {
184         WLOGFE("Remote object is nullptr");
185         return WMError::WM_ERROR_NULLPTR;
186     }
187     mockSessionManagerServiceProxy_ = iface_cast<IMockSessionManagerInterface>(remoteObject);
188     if (!mockSessionManagerServiceProxy_) {
189         WLOGFW("Get mock session manager service proxy failed, nullptr");
190         return WMError::WM_ERROR_NULLPTR;
191     }
192 
193     if (GetUserIdByUid(getuid()) != SYSTEM_USERID || isFoundationListenerRegistered_) {
194         return WMError::WM_OK;
195     }
196     if (!foundationDeath_) {
197         foundationDeath_ = new FoundationDeathRecipient();
198         if (!foundationDeath_) {
199             WLOGFE("Failed to create death Recipient ptr FoundationDeathRecipient");
200             return WMError::WM_ERROR_NO_MEM;
201         }
202     }
203     if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(foundationDeath_)) {
204         WLOGFE("Failed to add death recipient");
205         return WMError::WM_ERROR_IPC_FAILED;
206     }
207     isFoundationListenerRegistered_ = true;
208     return WMError::WM_OK;
209 }
210 
InitSceneSessionManagerProxy()211 __attribute__((no_sanitize("cfi"))) void SessionManager::InitSceneSessionManagerProxy()
212 {
213     if (sceneSessionManagerProxy_) {
214         return;
215     }
216     if (!sessionManagerServiceProxy_) {
217         WLOGFE("sessionManagerServiceProxy is nullptr");
218         return;
219     }
220 
221     sptr<IRemoteObject> remoteObject = sessionManagerServiceProxy_->GetSceneSessionManager();
222     if (!remoteObject) {
223         WLOGFW("Get scene session manager proxy failed, null");
224         return;
225     }
226     sceneSessionManagerProxy_ = iface_cast<ISceneSessionManager>(remoteObject);
227     if (sceneSessionManagerProxy_) {
228         ssmDeath_ = new SSMDeathRecipient();
229         if (!ssmDeath_) {
230             WLOGFE("Failed to create death Recipient ptr WMSDeathRecipient");
231             return;
232         }
233         if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(ssmDeath_)) {
234             WLOGFE("Failed to add death recipient");
235             return;
236         }
237     } else {
238         WLOGFW("Get scene session manager proxy failed, iface_cast null");
239     }
240 }
241 
RegisterSMSRecoverListener()242 void SessionManager::RegisterSMSRecoverListener()
243 {
244     if (!isRecoverListenerRegistered_) {
245         if (!mockSessionManagerServiceProxy_) {
246             TLOGE(WmsLogTag::WMS_RECOVER, "mockSessionManagerServiceProxy is null");
247             return;
248         }
249         isRecoverListenerRegistered_ = true;
250         TLOGI(WmsLogTag::WMS_RECOVER, "Register recover listener");
251         smsRecoverListener_ = new SessionManagerServiceRecoverListener();
252         std::string identity = IPCSkeleton::ResetCallingIdentity();
253         mockSessionManagerServiceProxy_->RegisterSMSRecoverListener(smsRecoverListener_);
254         IPCSkeleton::SetCallingIdentity(identity);
255     }
256 }
257 
RegisterWindowManagerRecoverCallbackFunc(const WindowManagerRecoverCallbackFunc & callbackFunc)258 void SessionManager::RegisterWindowManagerRecoverCallbackFunc(const WindowManagerRecoverCallbackFunc& callbackFunc)
259 {
260     std::lock_guard<std::recursive_mutex> lock(recoverMutex_);
261     windowManagerRecoverFunc_ = callbackFunc;
262 }
263 
RecoverSessionManagerService(const sptr<ISessionManagerService> & sessionManagerService)264 void SessionManager::RecoverSessionManagerService(const sptr<ISessionManagerService>& sessionManagerService)
265 {
266     {
267         std::lock_guard<std::recursive_mutex> lock(mutex_);
268         sessionManagerServiceProxy_ = sessionManagerService;
269     }
270 
271     {
272         std::lock_guard<std::recursive_mutex> lock(recoverMutex_);
273         TLOGI(WmsLogTag::WMS_RECOVER, "Run recover");
274         if (windowManagerRecoverFunc_ != nullptr) {
275             TLOGD(WmsLogTag::WMS_RECOVER, "windowManagerRecover");
276             windowManagerRecoverFunc_();
277         }
278     }
279 }
280 
OnUserSwitch(const sptr<ISessionManagerService> & sessionManagerService)281 void SessionManager::OnUserSwitch(const sptr<ISessionManagerService>& sessionManagerService)
282 {
283     TLOGI(WmsLogTag::WMS_MULTI_USER, "User switched");
284     Clear();
285     ClearSessionManagerProxy();
286     {
287         std::lock_guard<std::recursive_mutex> lock(mutex_);
288         sessionManagerServiceProxy_ = sessionManagerService;
289         InitSceneSessionManagerProxy();
290         if (!sceneSessionManagerProxy_) {
291             TLOGE(WmsLogTag::WMS_MULTI_USER, "sceneSessionManagerProxy is null");
292             return;
293         }
294     }
295     if (userSwitchCallbackFunc_) {
296         TLOGI(WmsLogTag::WMS_MULTI_USER, "User switch callback");
297         userSwitchCallbackFunc_();
298     }
299 }
300 
Clear()301 void SessionManager::Clear()
302 {
303     std::lock_guard<std::recursive_mutex> lock(mutex_);
304     if ((sceneSessionManagerProxy_ != nullptr) && (sceneSessionManagerProxy_->AsObject() != nullptr)) {
305         sceneSessionManagerProxy_->AsObject()->RemoveDeathRecipient(ssmDeath_);
306     }
307 }
308 
RegisterWMSConnectionChangedListener(const WMSConnectionChangedCallbackFunc & callbackFunc)309 WMError SessionManager::RegisterWMSConnectionChangedListener(const WMSConnectionChangedCallbackFunc& callbackFunc)
310 {
311     TLOGI(WmsLogTag::WMS_MULTI_USER, "in");
312     if (callbackFunc == nullptr) {
313         TLOGE(WmsLogTag::WMS_MULTI_USER, "callbackFunc is null");
314         return WMError::WM_ERROR_NULLPTR;
315     }
316     bool isWMSAlreadyConnected = false;
317     int32_t userId = INVALID_USER_ID;
318     int32_t screenId = DEFAULT_SCREEN_ID;
319     {
320         // The mutex ensures the timing of the following variable states in multiple threads
321         std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
322         wmsConnectionChangedFunc_ = callbackFunc;
323         isWMSAlreadyConnected = isWMSConnected_ && (currentWMSUserId_ > INVALID_USER_ID);
324         userId = currentWMSUserId_;
325         screenId = currentScreenId_;
326     }
327     if (isWMSAlreadyConnected) {
328         TLOGI(WmsLogTag::WMS_MULTI_USER, "WMS already connected, notify immediately");
329         OnWMSConnectionChangedCallback(userId, screenId, true, true);
330     }
331     {
332         std::lock_guard<std::recursive_mutex> lock(mutex_);
333         auto ret = InitMockSMSProxy();
334         if (ret != WMError::WM_OK) {
335             TLOGE(WmsLogTag::WMS_MULTI_USER, "Init mock session manager service failed");
336             return ret;
337         }
338         RegisterSMSRecoverListener();
339     }
340     return WMError::WM_OK;
341 }
342 
RegisterUserSwitchListener(const UserSwitchCallbackFunc & callbackFunc)343 void SessionManager::RegisterUserSwitchListener(const UserSwitchCallbackFunc& callbackFunc)
344 {
345     TLOGI(WmsLogTag::WMS_MULTI_USER, "enter");
346     userSwitchCallbackFunc_ = callbackFunc;
347 }
348 
OnFoundationDied()349 void SessionManager::OnFoundationDied()
350 {
351     TLOGI(WmsLogTag::WMS_RECOVER, "enter");
352     {
353         std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
354         isWMSConnected_ = false;
355     }
356     std::lock_guard<std::recursive_mutex> lock(mutex_);
357     isFoundationListenerRegistered_ = false;
358     isRecoverListenerRegistered_ = false;
359     mockSessionManagerServiceProxy_ = nullptr;
360     sessionManagerServiceProxy_ = nullptr;
361     sceneSessionManagerProxy_ = nullptr;
362 }
363 
OnRemoteDied(const wptr<IRemoteObject> & wptrDeath)364 void FoundationDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)
365 {
366     TLOGI(WmsLogTag::WMS_RECOVER, "Foundation died");
367     SessionManager::GetInstance().OnFoundationDied();
368 }
369 
OnRemoteDied(const wptr<IRemoteObject> & wptrDeath)370 void SSMDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)
371 {
372     WLOGI("ssm OnRemoteDied");
373     SessionManager::GetInstance().Clear();
374     SessionManager::GetInstance().ClearSessionManagerProxy();
375 }
376 } // namespace OHOS::Rosen
377