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