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_lite.h"
17 #include <ipc_skeleton.h>
18 #include <iremote_stub.h>
19 #include <iservice_registry.h>
20 #include <system_ability_definition.h>
21
22 #include "session_manager_service_recover_interface.h"
23 #include "scene_session_manager_lite_proxy.h"
24 #include "window_manager_hilog.h"
25
26 namespace OHOS::Rosen {
27 namespace {
28 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_DISPLAY, "SessionManagerLite" };
29 }
30
31 class SessionManagerServiceLiteRecoverListener : public IRemoteStub<ISessionManagerServiceRecoverListener> {
32 public:
33 explicit SessionManagerServiceLiteRecoverListener() = default;
34
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)35 virtual int32_t OnRemoteRequest(
36 uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override
37 {
38 if (data.ReadInterfaceToken() != GetDescriptor()) {
39 TLOGE(WmsLogTag::WMS_RECOVER, "InterfaceToken check failed");
40 return ERR_TRANSACTION_FAILED;
41 }
42 auto msgId = static_cast<SessionManagerServiceRecoverMessage>(code);
43 switch (msgId) {
44 case SessionManagerServiceRecoverMessage::TRANS_ID_ON_SESSION_MANAGER_SERVICE_RECOVER: {
45 auto sessionManagerService = data.ReadRemoteObject();
46 OnSessionManagerServiceRecover(sessionManagerService);
47 break;
48 }
49 case SessionManagerServiceRecoverMessage::TRANS_ID_ON_WMS_CONNECTION_CHANGED: {
50 int32_t userId = data.ReadInt32();
51 int32_t screenId = data.ReadInt32();
52 bool isConnected = data.ReadBool();
53 if (isConnected) {
54 OnWMSConnectionChanged(userId, screenId, isConnected, data.ReadRemoteObject());
55 } else {
56 OnWMSConnectionChanged(userId, screenId, isConnected, nullptr);
57 }
58 break;
59 }
60 default:
61 TLOGW(WmsLogTag::WMS_RECOVER, "unknown transaction code %{public}d", code);
62 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
63 }
64 return ERR_NONE;
65 }
66
OnSessionManagerServiceRecover(const sptr<IRemoteObject> & sessionManagerService)67 void OnSessionManagerServiceRecover(const sptr<IRemoteObject>& sessionManagerService) override
68 {
69 SessionManagerLite::GetInstance().Clear();
70 SessionManagerLite::GetInstance().ClearSessionManagerProxy();
71
72 auto sms = iface_cast<ISessionManagerService>(sessionManagerService);
73 SessionManagerLite::GetInstance().RecoverSessionManagerService(sms);
74 }
75
OnWMSConnectionChanged(int32_t userId,int32_t screenId,bool isConnected,const sptr<IRemoteObject> & sessionManagerService)76 void OnWMSConnectionChanged(
77 int32_t userId, int32_t screenId, bool isConnected, const sptr<IRemoteObject>& sessionManagerService) override
78 {
79 auto sms = iface_cast<ISessionManagerService>(sessionManagerService);
80 SessionManagerLite::GetInstance().OnWMSConnectionChanged(userId, screenId, isConnected, sms);
81 }
82 };
83
84 class SceneSessionManagerLiteProxyMock : public SceneSessionManagerLiteProxy {
85 public:
SceneSessionManagerLiteProxyMock(const sptr<IRemoteObject> & impl)86 explicit SceneSessionManagerLiteProxyMock(const sptr<IRemoteObject>& impl)
87 : SceneSessionManagerLiteProxy(impl) {}
88 virtual ~SceneSessionManagerLiteProxyMock() = default;
89
RegisterSessionListener(const sptr<ISessionListener> & listener)90 WSError RegisterSessionListener(const sptr<ISessionListener>& listener) override
91 {
92 TLOGI(WmsLogTag::DEFAULT, "called");
93 auto ret = SceneSessionManagerLiteProxy::RegisterSessionListener(listener);
94 if (ret != WSError::WS_OK) {
95 return ret;
96 }
97 SessionManagerLite::GetInstance().SaveSessionListener(listener);
98 return WSError::WS_OK;
99 }
UnRegisterSessionListener(const sptr<ISessionListener> & listener)100 WSError UnRegisterSessionListener(const sptr<ISessionListener>& listener) override
101 {
102 TLOGI(WmsLogTag::DEFAULT, "called");
103 auto ret = SceneSessionManagerLiteProxy::UnRegisterSessionListener(listener);
104 SessionManagerLite::GetInstance().DeleteSessionListener(listener);
105 return ret;
106 }
107 private:
108 static inline BrokerDelegator<SceneSessionManagerLiteProxyMock> delegator_;
109 };
110
WM_IMPLEMENT_SINGLE_INSTANCE(SessionManagerLite)111 WM_IMPLEMENT_SINGLE_INSTANCE(SessionManagerLite)
112
113 SessionManagerLite::~SessionManagerLite()
114 {
115 TLOGI(WmsLogTag::WMS_LIFE, "destroyed");
116 }
117
ClearSessionManagerProxy()118 void SessionManagerLite::ClearSessionManagerProxy()
119 {
120 WLOGFI("enter");
121 std::lock_guard<std::recursive_mutex> lock(mutex_);
122 sessionManagerServiceProxy_ = nullptr;
123 sceneSessionManagerLiteProxy_ = nullptr;
124 screenSessionManagerLiteProxy_ = nullptr;
125 }
126
GetSceneSessionManagerLiteProxy()127 sptr<ISceneSessionManagerLite> SessionManagerLite::GetSceneSessionManagerLiteProxy()
128 {
129 std::lock_guard<std::recursive_mutex> lock(mutex_);
130 InitSessionManagerServiceProxy();
131 InitSceneSessionManagerLiteProxy();
132 return sceneSessionManagerLiteProxy_;
133 }
134
GetScreenSessionManagerLiteProxy()135 sptr<IScreenSessionManagerLite> SessionManagerLite::GetScreenSessionManagerLiteProxy()
136 {
137 std::lock_guard<std::recursive_mutex> lock(mutex_);
138 InitSessionManagerServiceProxy();
139 InitScreenSessionManagerLiteProxy();
140 return screenSessionManagerLiteProxy_;
141 }
142
GetSessionManagerServiceProxy()143 sptr<ISessionManagerService> SessionManagerLite::GetSessionManagerServiceProxy()
144 {
145 std::lock_guard<std::recursive_mutex> lock(mutex_);
146 InitSessionManagerServiceProxy();
147 InitSceneSessionManagerLiteProxy();
148 return sessionManagerServiceProxy_;
149 }
150
SaveSessionListener(const sptr<ISessionListener> & listener)151 void SessionManagerLite::SaveSessionListener(const sptr<ISessionListener>& listener)
152 {
153 std::lock_guard<std::recursive_mutex> guard(listenerLock_);
154 auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
155 [&listener](const sptr<ISessionListener>& item) {
156 return (item && item->AsObject() == listener->AsObject());
157 });
158 if (it != sessionListeners_.end()) {
159 TLOGW(WmsLogTag::DEFAULT, "listener was already added, do not add again");
160 return;
161 }
162 sessionListeners_.emplace_back(listener);
163 }
164
DeleteSessionListener(const sptr<ISessionListener> & listener)165 void SessionManagerLite::DeleteSessionListener(const sptr<ISessionListener>& listener)
166 {
167 std::lock_guard<std::recursive_mutex> guard(listenerLock_);
168 auto it = std::find_if(sessionListeners_.begin(), sessionListeners_.end(),
169 [&listener](const sptr<ISessionListener>& item) {
170 return (item && item->AsObject() == listener->AsObject());
171 });
172 if (it != sessionListeners_.end()) {
173 sessionListeners_.erase(it);
174 }
175 }
176
DeleteAllSessionListeners()177 void SessionManagerLite::DeleteAllSessionListeners()
178 {
179 std::lock_guard<std::recursive_mutex> guard(listenerLock_);
180 sessionListeners_.clear();
181 }
182
RecoverSessionManagerService(const sptr<ISessionManagerService> & sessionManagerService)183 void SessionManagerLite::RecoverSessionManagerService(const sptr<ISessionManagerService>& sessionManagerService)
184 {
185 {
186 std::lock_guard<std::recursive_mutex> lock(mutex_);
187 sessionManagerServiceProxy_ = sessionManagerService;
188 }
189 GetSceneSessionManagerLiteProxy();
190 ReregisterSessionListener();
191 if (userSwitchCallbackFunc_) {
192 TLOGI(WmsLogTag::WMS_RECOVER, "user switch");
193 userSwitchCallbackFunc_();
194 }
195 }
196
ReregisterSessionListener() const197 void SessionManagerLite::ReregisterSessionListener() const
198 {
199 if (sceneSessionManagerLiteProxy_ == nullptr) {
200 TLOGE(WmsLogTag::WMS_RECOVER, "sceneSessionManagerLiteProxy is null");
201 return;
202 }
203
204 TLOGI(WmsLogTag::WMS_RECOVER, "listener count = %{public}" PRIu64,
205 static_cast<int64_t>(sessionListeners_.size()));
206 for (const auto& listener : sessionListeners_) {
207 auto ret = sceneSessionManagerLiteProxy_->RegisterSessionListener(listener);
208 if (ret != WSError::WS_OK) {
209 TLOGW(WmsLogTag::WMS_RECOVER, "failed, ret = %{public}" PRId32, ret);
210 }
211 }
212 }
213
RegisterUserSwitchListener(const UserSwitchCallbackFunc & callbackFunc)214 void SessionManagerLite::RegisterUserSwitchListener(const UserSwitchCallbackFunc& callbackFunc)
215 {
216 TLOGI(WmsLogTag::WMS_MULTI_USER, "enter");
217 userSwitchCallbackFunc_ = callbackFunc;
218 }
219
OnWMSConnectionChanged(int32_t userId,int32_t screenId,bool isConnected,const sptr<ISessionManagerService> & sessionManagerService)220 void SessionManagerLite::OnWMSConnectionChanged(
221 int32_t userId, int32_t screenId, bool isConnected, const sptr<ISessionManagerService>& sessionManagerService)
222 {
223 bool isCallbackRegistered = false;
224 int32_t lastUserId = INVALID_USER_ID;
225 int32_t lastScreenId = DEFAULT_SCREEN_ID;
226 {
227 // The mutex ensures the timing of the following variable states in multiple threads
228 std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
229 lastUserId = currentWMSUserId_;
230 lastScreenId = currentScreenId_;
231 isWMSConnected_ = isConnected;
232 isCallbackRegistered = wmsConnectionChangedFunc_ != nullptr;
233 if (isConnected) {
234 currentWMSUserId_ = userId;
235 currentScreenId_ = screenId;
236 }
237 }
238 TLOGI(WmsLogTag::WMS_MULTI_USER,
239 "Lite: curUserId=%{public}d, oldUserId=%{public}d, screenId=%{public}d, isConnected=%{public}d", userId,
240 lastUserId, screenId, isConnected);
241 if (isConnected && lastUserId > INVALID_UID && lastUserId != userId) {
242 // Notify the user that the old wms has been disconnected.
243 OnWMSConnectionChangedCallback(lastUserId, lastScreenId, false, isCallbackRegistered);
244 OnUserSwitch(sessionManagerService);
245 }
246 // Notify the user that the current wms connection has changed.
247 OnWMSConnectionChangedCallback(userId, screenId, isConnected, isCallbackRegistered);
248 }
249
OnUserSwitch(const sptr<ISessionManagerService> & sessionManagerService)250 void SessionManagerLite::OnUserSwitch(const sptr<ISessionManagerService> &sessionManagerService)
251 {
252 TLOGI(WmsLogTag::WMS_MULTI_USER, "User switched Lite");
253 {
254 Clear();
255 std::lock_guard<std::recursive_mutex> lock(mutex_);
256 sessionManagerServiceProxy_ = sessionManagerService;
257 sceneSessionManagerLiteProxy_ = nullptr;
258 InitSceneSessionManagerLiteProxy();
259 if (!sceneSessionManagerLiteProxy_) {
260 TLOGE(WmsLogTag::WMS_MULTI_USER, "sceneSessionManagerLiteProxy is null");
261 return;
262 }
263 }
264 ReregisterSessionListener();
265 if (userSwitchCallbackFunc_) {
266 TLOGI(WmsLogTag::WMS_MULTI_USER, "User switch Lite callback.");
267 userSwitchCallbackFunc_();
268 }
269 }
270
InitSessionManagerServiceProxy()271 void SessionManagerLite::InitSessionManagerServiceProxy()
272 {
273 if (sessionManagerServiceProxy_) {
274 return;
275 }
276 auto ret = InitMockSMSProxy();
277 if (ret != WMError::WM_OK) {
278 TLOGE(WmsLogTag::DEFAULT, "Init mock session manager service failed in Lite");
279 return;
280 }
281 RegisterSMSRecoverListener();
282 sptr<IRemoteObject> remoteObject = mockSessionManagerServiceProxy_->GetSessionManagerService();
283 if (!remoteObject) {
284 WLOGFE("Remote object is nullptr");
285 return;
286 }
287 sessionManagerServiceProxy_ = iface_cast<ISessionManagerService>(remoteObject);
288 if (!sessionManagerServiceProxy_) {
289 WLOGFE("sessionManagerServiceProxy is nullptr");
290 }
291 }
292
InitScreenSessionManagerLiteProxy()293 void SessionManagerLite::InitScreenSessionManagerLiteProxy()
294 {
295 if (screenSessionManagerLiteProxy_) {
296 return;
297 }
298 if (!mockSessionManagerServiceProxy_) {
299 WLOGFE("mockSessionManagerServiceProxy is nullptr");
300 return;
301 }
302
303 sptr<IRemoteObject> remoteObject = mockSessionManagerServiceProxy_->GetScreenSessionManagerLite();
304 if (!remoteObject) {
305 WLOGFW("Get screen session manager lite proxy failed, null");
306 return;
307 }
308 screenSessionManagerLiteProxy_ = iface_cast<IScreenSessionManagerLite>(remoteObject);
309 if (!screenSessionManagerLiteProxy_) {
310 WLOGFW("Get screen session manager lite proxy failed, iface_cast null");
311 }
312 }
313
InitSceneSessionManagerLiteProxy()314 void SessionManagerLite::InitSceneSessionManagerLiteProxy()
315 {
316 if (sceneSessionManagerLiteProxy_) {
317 return;
318 }
319 if (!sessionManagerServiceProxy_) {
320 WLOGFE("sessionManagerServiceProxy is nullptr");
321 return;
322 }
323
324 sptr<IRemoteObject> remoteObject = sessionManagerServiceProxy_->GetSceneSessionManagerLite();
325 if (!remoteObject) {
326 WLOGFW("Get scene session manager proxy failed, null");
327 return;
328 }
329 sceneSessionManagerLiteProxy_ = iface_cast<ISceneSessionManagerLite>(remoteObject);
330 if (sceneSessionManagerLiteProxy_) {
331 ssmDeath_ = new SSMDeathRecipientLite();
332 if (!ssmDeath_) {
333 WLOGFE("Failed to create death Recipient ptr WMSDeathRecipient");
334 return;
335 }
336 if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(ssmDeath_)) {
337 WLOGFE("Failed to add death recipient");
338 return;
339 }
340 } else {
341 WLOGFW("Get scene session manager proxy failed, iface_cast null");
342 }
343 }
344
Clear()345 void SessionManagerLite::Clear()
346 {
347 std::lock_guard<std::recursive_mutex> lock(mutex_);
348 if ((sceneSessionManagerLiteProxy_ != nullptr) && (sceneSessionManagerLiteProxy_->AsObject() != nullptr)) {
349 sceneSessionManagerLiteProxy_->AsObject()->RemoveDeathRecipient(ssmDeath_);
350 }
351 }
352
OnRemoteDied(const wptr<IRemoteObject> & wptrDeath)353 void SSMDeathRecipientLite::OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)
354 {
355 WLOGI("ssm OnRemoteDied");
356 SessionManagerLite::GetInstance().Clear();
357 SessionManagerLite::GetInstance().ClearSessionManagerProxy();
358 }
359
RegisterWMSConnectionChangedListener(const WMSConnectionChangedCallbackFunc & callbackFunc)360 WMError SessionManagerLite::RegisterWMSConnectionChangedListener(const WMSConnectionChangedCallbackFunc& callbackFunc)
361 {
362 TLOGI(WmsLogTag::WMS_MULTI_USER, "Lite in");
363 if (callbackFunc == nullptr) {
364 TLOGE(WmsLogTag::WMS_MULTI_USER, "Lite callbackFunc is null");
365 return WMError::WM_ERROR_NULLPTR;
366 }
367 bool isWMSAlreadyConnected = false;
368 int32_t userId = INVALID_USER_ID;
369 int32_t screenId = DEFAULT_SCREEN_ID;
370 {
371 // The mutex ensures the timing of the following variable states in multiple threads
372 std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
373 wmsConnectionChangedFunc_ = callbackFunc;
374 isWMSAlreadyConnected = isWMSConnected_ && (currentWMSUserId_ > INVALID_USER_ID);
375 userId = currentWMSUserId_;
376 screenId = currentScreenId_;
377 }
378 if (isWMSAlreadyConnected) {
379 TLOGI(WmsLogTag::WMS_MULTI_USER, "Lite WMS already connected, notify immediately");
380 OnWMSConnectionChangedCallback(userId, screenId, true, true);
381 }
382 {
383 std::lock_guard<std::recursive_mutex> lock(mutex_);
384 auto ret = InitMockSMSProxy();
385 if (ret != WMError::WM_OK) {
386 TLOGE(WmsLogTag::WMS_MULTI_USER, "Init mock session manager service failed");
387 return ret;
388 }
389 RegisterSMSRecoverListener();
390 }
391 return WMError::WM_OK;
392 }
393
InitMockSMSProxy()394 WMError SessionManagerLite::InitMockSMSProxy()
395 {
396 sptr<ISystemAbilityManager> systemAbilityManager =
397 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
398 if (!systemAbilityManager) {
399 TLOGE(WmsLogTag::WMS_MULTI_USER, "Failed to get system ability mgr.");
400 return WMError::WM_ERROR_NULLPTR;
401 }
402 sptr<IRemoteObject> remoteObject = systemAbilityManager->GetSystemAbility(WINDOW_MANAGER_SERVICE_ID);
403 if (!remoteObject) {
404 TLOGE(WmsLogTag::WMS_MULTI_USER, "Remote object is nullptr");
405 return WMError::WM_ERROR_NULLPTR;
406 }
407 mockSessionManagerServiceProxy_ = iface_cast<IMockSessionManagerInterface>(remoteObject);
408 if (!mockSessionManagerServiceProxy_) {
409 TLOGE(WmsLogTag::WMS_MULTI_USER, "Get mock session manager service proxy failed, nullptr");
410 return WMError::WM_ERROR_NULLPTR;
411 }
412
413 if (GetUserIdByUid(getuid()) != SYSTEM_USERID || isFoundationListenerRegistered_) {
414 return WMError::WM_OK;
415 }
416 if (!foundationDeath_) {
417 foundationDeath_ = sptr<FoundationDeathRecipientLite>::MakeSptr();
418 if (!foundationDeath_) {
419 TLOGE(WmsLogTag::WMS_MULTI_USER, "Failed to create death Recipient ptr");
420 return WMError::WM_ERROR_NO_MEM;
421 }
422 }
423 if (remoteObject->IsProxyObject() && !remoteObject->AddDeathRecipient(foundationDeath_)) {
424 TLOGE(WmsLogTag::WMS_MULTI_USER, "Failed to add death recipient");
425 return WMError::WM_ERROR_IPC_FAILED;
426 }
427 isFoundationListenerRegistered_ = true;
428 return WMError::WM_OK;
429 }
430
RegisterSMSRecoverListener()431 void SessionManagerLite::RegisterSMSRecoverListener()
432 {
433 if (!recoverListenerRegistered_) {
434 if (!mockSessionManagerServiceProxy_) {
435 TLOGE(WmsLogTag::WMS_RECOVER, "mockSessionManagerServiceProxy is null");
436 return;
437 }
438 recoverListenerRegistered_ = true;
439 TLOGI(WmsLogTag::WMS_RECOVER, "Register recover listener");
440 smsRecoverListener_ = new SessionManagerServiceLiteRecoverListener();
441 std::string identity = IPCSkeleton::ResetCallingIdentity();
442 mockSessionManagerServiceProxy_->RegisterSMSLiteRecoverListener(smsRecoverListener_);
443 IPCSkeleton::SetCallingIdentity(identity);
444 }
445 }
446
OnWMSConnectionChangedCallback(int32_t userId,int32_t screenId,bool isConnected,bool isCallbackRegistered)447 void SessionManagerLite::OnWMSConnectionChangedCallback(
448 int32_t userId, int32_t screenId, bool isConnected, bool isCallbackRegistered)
449 {
450 if (isCallbackRegistered) {
451 TLOGI(WmsLogTag::WMS_MULTI_USER,
452 "WMS connection changed with userId=%{public}d, screenId=%{public}d, isConnected=%{public}d", userId,
453 screenId, isConnected);
454 wmsConnectionChangedFunc_(userId, screenId, isConnected);
455 } else {
456 TLOGE(WmsLogTag::WMS_MULTI_USER, "Lite WMS CallbackFunc is null.");
457 }
458 }
459
OnRemoteDied(const wptr<IRemoteObject> & wptrDeath)460 void FoundationDeathRecipientLite::OnRemoteDied(const wptr<IRemoteObject>& wptrDeath)
461 {
462 TLOGI(WmsLogTag::WMS_RECOVER, "Foundation died");
463 SessionManagerLite::GetInstance().OnFoundationDied();
464 }
465
OnFoundationDied()466 void SessionManagerLite::OnFoundationDied()
467 {
468 TLOGI(WmsLogTag::WMS_RECOVER, "enter");
469 {
470 std::lock_guard<std::mutex> lock(wmsConnectionMutex_);
471 isWMSConnected_ = false;
472 }
473 std::lock_guard<std::recursive_mutex> lock(mutex_);
474 isFoundationListenerRegistered_ = false;
475 recoverListenerRegistered_ = false;
476 mockSessionManagerServiceProxy_ = nullptr;
477 sessionManagerServiceProxy_ = nullptr;
478 sceneSessionManagerLiteProxy_ = nullptr;
479 }
480 } // namespace OHOS::Rosen
481