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