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