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