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