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 "mock_session_manager_service.h"
17
18 #include <cstdint>
19 #include <fcntl.h>
20 #include <securec.h>
21 #include <unistd.h>
22
23 #include <bundle_mgr_interface.h>
24 #include <system_ability_definition.h>
25 #include <cinttypes>
26 #include <csignal>
27 #include <iomanip>
28 #include <ipc_skeleton.h>
29 #include <iservice_registry.h>
30 #include <map>
31 #include <sstream>
32
33 #include "window_manager_hilog.h"
34 #include "unique_fd.h"
35 #include "parameters.h"
36 #include "root_scene.h"
37 #include "string_ex.h"
38 #include "wm_common.h"
39 #include "ws_common.h"
40 #include "session_manager_service_interface.h"
41 #include "scene_session_manager_interface.h"
42 #include "screen_session_manager_lite.h"
43
44 #define PATH_LEN 1024
45 #define O_RDWR 02
46
47 namespace OHOS {
48 namespace Rosen {
49 namespace {
50 constexpr HiviewDFX::HiLogLabel LABEL = { LOG_CORE, HILOG_DOMAIN_WINDOW, "MockSessionManagerService" };
51
52 const std::u16string DEFAULT_USTRING = u"error";
53 const char DEFAULT_STRING[] = "error";
54 const std::string ARG_DUMP_HELP = "-h";
55 const std::string ARG_DUMP_ALL = "-a";
56 const std::string ARG_DUMP_WINDOW = "-w";
57 const std::string KEY_SCENE_BOARD_TEST_ENABLE = "persist.scb.testmode.enable";
58 const std::string SCENE_BOARD_BUNDLE_NAME = "com.ohos.sceneboard";
59 const std::string TEST_MODULE_NAME_SUFFIX = "_test";
60 } // namespace
61
62 class ClientListenerDeathRecipient : public IRemoteObject::DeathRecipient {
63 public:
ClientListenerDeathRecipient(int64_t pid,bool isLite)64 explicit ClientListenerDeathRecipient(int64_t pid, bool isLite)
65 : pid_(pid), isLite_(isLite) {}
66
OnRemoteDied(const wptr<IRemoteObject> & wptrDeath)67 void OnRemoteDied(const wptr<IRemoteObject> &wptrDeath) override
68 {
69 WLOGFD("[WMSRecover] OnRemoteDied, pid = %{public}" PRId64 ", isLite = %{public}" PRId32, pid_, isLite_);
70 if (isLite_) {
71 MockSessionManagerService::GetInstance().UnregisterSMSLiteRecoverListener(pid_);
72 } else {
73 MockSessionManagerService::GetInstance().UnregisterSMSRecoverListener(pid_);
74 }
75 }
76
77 private:
78 int64_t pid_ = -1;
79 bool isLite_ = false;
80 };
81
WM_IMPLEMENT_SINGLE_INSTANCE(MockSessionManagerService)82 WM_IMPLEMENT_SINGLE_INSTANCE(MockSessionManagerService)
83
84 void MockSessionManagerService::SMSDeathRecipient::OnRemoteDied(const wptr<IRemoteObject>& object)
85 {
86 WLOGFI("OnRemoteDied with userId_=%{public}d, screenId_=%{public}d", userId_, screenId_);
87 MockSessionManagerService::GetInstance().OnWMSConnectionChanged(userId_, screenId_, false);
88 auto sessionManagerService = object.promote();
89 if (!sessionManagerService) {
90 WLOGFE("sessionManagerService is null");
91 return;
92 }
93
94 if (IsSceneBoardTestMode()) {
95 WLOGFI("SceneBoard is testing, do not kill foundation.");
96 return;
97 }
98 WLOGFW("SessionManagerService died!");
99 }
100
SetId(int32_t userId,int32_t screenId)101 void MockSessionManagerService::SMSDeathRecipient::SetId(int32_t userId, int32_t screenId)
102 {
103 WLOGFI("SetId with userId=%{public}d, screenId=%{public}d", userId, screenId);
104 userId_ = userId;
105 screenId_ = screenId;
106 }
107
MockSessionManagerService()108 MockSessionManagerService::MockSessionManagerService() : SystemAbility(WINDOW_MANAGER_SERVICE_ID, true)
109 {
110 }
111
RegisterMockSessionManagerService()112 bool MockSessionManagerService::RegisterMockSessionManagerService()
113 {
114 bool res = SystemAbility::MakeAndRegisterAbility(this);
115 if (!res) {
116 WLOGFE("register failed");
117 }
118 if (!Publish(this)) {
119 WLOGFE("Publish failed");
120 }
121 WLOGFI("Publish mock session manager service success");
122 return true;
123 }
124
OnStart()125 void MockSessionManagerService::OnStart()
126 {
127 WLOGFD("OnStart begin");
128 }
129
Str16ToStr8(const std::u16string & str)130 static std::string Str16ToStr8(const std::u16string& str)
131 {
132 if (str == DEFAULT_USTRING) {
133 return DEFAULT_STRING;
134 }
135 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert(DEFAULT_STRING);
136 std::string result = convert.to_bytes(str);
137 return result == DEFAULT_STRING ? "" : result;
138 }
139
Dump(int fd,const std::vector<std::u16string> & args)140 int MockSessionManagerService::Dump(int fd, const std::vector<std::u16string> &args)
141 {
142 WLOGI("dump begin fd: %{public}d", fd);
143 if (fd < 0) {
144 return -1;
145 }
146 (void) signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE crash
147 UniqueFd ufd = UniqueFd(fd); // auto close
148 fd = ufd.Get();
149 std::vector<std::string> params;
150 for (auto& arg : args) {
151 params.emplace_back(Str16ToStr8(arg));
152 }
153
154 std::string dumpInfo;
155 if (params.empty()) {
156 ShowHelpInfo(dumpInfo);
157 } else if (params.size() == 1 && params[0] == ARG_DUMP_HELP) { // 1: params num
158 ShowHelpInfo(dumpInfo);
159 } else {
160 int errCode = DumpSessionInfo(params, dumpInfo);
161 if (errCode != 0) {
162 ShowIllegalArgsInfo(dumpInfo);
163 }
164 }
165 int ret = dprintf(fd, "%s\n", dumpInfo.c_str());
166 if (ret < 0) {
167 WLOGFE("dprintf error");
168 return -1; // WMError::WM_ERROR_INVALID_OPERATION;
169 }
170 WLOGI("dump end");
171 return 0;
172 }
173
SetSessionManagerService(const sptr<IRemoteObject> & sessionManagerService)174 bool MockSessionManagerService::SetSessionManagerService(const sptr<IRemoteObject>& sessionManagerService)
175 {
176 if (!sessionManagerService) {
177 WLOGFE("sessionManagerService is nullptr");
178 return false;
179 }
180 sessionManagerService_ = sessionManagerService;
181
182 smsDeathRecipient_ = new SMSDeathRecipient();
183 if (sessionManagerService_->IsProxyObject() && !sessionManagerService_->AddDeathRecipient(smsDeathRecipient_)) {
184 WLOGFE("Failed to add death recipient");
185 return false;
186 }
187
188 RegisterMockSessionManagerService();
189 WLOGFI("sessionManagerService set success!");
190
191 GetSceneSessionManager();
192
193 return true;
194 }
195
GetSessionManagerService()196 sptr<IRemoteObject> MockSessionManagerService::GetSessionManagerService()
197 {
198 if (!sessionManagerService_) {
199 WLOGFE("sessionManagerService is nullptr");
200 return nullptr;
201 }
202 WLOGFD("Get session manager service success");
203 return sessionManagerService_;
204 }
205
NotifySceneBoardAvailable()206 void MockSessionManagerService::NotifySceneBoardAvailable()
207 {
208 WLOGFI("[WMSRecover] scene board is available");
209 NotifySceneBoardAvailableToLiteClient();
210 NotifySceneBoardAvailableToClient();
211 }
212
RegisterSMSRecoverListener(const sptr<IRemoteObject> & listener)213 void MockSessionManagerService::RegisterSMSRecoverListener(const sptr<IRemoteObject>& listener)
214 {
215 if (listener == nullptr) {
216 WLOGFE("[WMSRecover] listener is nullptr");
217 return;
218 }
219
220 int64_t pid = IPCSkeleton::GetCallingPid();
221 WLOGFI("[WMSRecover] pid = %{public}" PRId64, pid);
222
223 std::lock_guard<std::recursive_mutex> lock(smsRecoverListenerLock_);
224
225 sptr<ClientListenerDeathRecipient> clientDeathLisntener = new ClientListenerDeathRecipient(pid, false);
226 listener->AddDeathRecipient(clientDeathLisntener);
227 auto smsListener = iface_cast<ISessionManagerServiceRecoverListener>(listener);
228 smsRecoverListenerMap_[pid] = smsListener;
229 if (smsListener && isWMSConnected_) {
230 smsListener->OnWMSConnectionChanged(currentUserId_, currentScreenId_, true);
231 }
232 }
233
UnregisterSMSRecoverListener()234 void MockSessionManagerService::UnregisterSMSRecoverListener()
235 {
236 int64_t pid = IPCSkeleton::GetCallingPid();
237 WLOGFD("[WMSRecover] pid = %{public}" PRId64, pid);
238 UnregisterSMSRecoverListener(pid);
239 }
240
UnregisterSMSRecoverListener(int64_t pid)241 void MockSessionManagerService::UnregisterSMSRecoverListener(int64_t pid)
242 {
243 WLOGFD("[WMSRecover] pid = %{public}" PRId64, pid);
244 std::lock_guard<std::recursive_mutex> lock(smsRecoverListenerLock_);
245 auto it = smsRecoverListenerMap_.find(pid);
246 if (it != smsRecoverListenerMap_.end()) {
247 smsRecoverListenerMap_.erase(it);
248 }
249 }
250
NotifySceneBoardAvailableToClient()251 void MockSessionManagerService::NotifySceneBoardAvailableToClient()
252 {
253 if (sessionManagerService_ == nullptr) {
254 WLOGFE("[WMSRecover] SessionManagerService is null");
255 return;
256 }
257
258 WLOGFI("[WMSRecover] Remote process count = %{public}" PRIu64,
259 static_cast<uint64_t>(smsRecoverListenerMap_.size()));
260
261 std::lock_guard<std::recursive_mutex> lock(smsRecoverListenerLock_);
262 for (auto& it: smsRecoverListenerMap_) {
263 if (it.second == nullptr) {
264 continue;
265 }
266
267 WLOGFI("[WMSRecover] Call OnSessionManagerServiceRecover pid = %{public}" PRId64
268 ", ref count = %{public}" PRId32, it.first, it.second->GetSptrRefCount());
269 it.second->OnSessionManagerServiceRecover(sessionManagerService_);
270 }
271 }
272
RegisterSMSLiteRecoverListener(const sptr<IRemoteObject> & listener)273 void MockSessionManagerService::RegisterSMSLiteRecoverListener(const sptr<IRemoteObject>& listener)
274 {
275 if (listener == nullptr) {
276 WLOGFE("[WMSRecover] listener is nullptr");
277 return;
278 }
279
280 int64_t pid = IPCSkeleton::GetCallingPid();
281 WLOGFI("[WMSRecover] pid = %{public}" PRId64, pid);
282
283 std::lock_guard<std::recursive_mutex> lock(smsLiteRecoverListenerLock_);
284
285 sptr<ClientListenerDeathRecipient> clientDeathLisntener = new ClientListenerDeathRecipient(pid, true);
286 listener->AddDeathRecipient(clientDeathLisntener);
287 smsLiteRecoverListenerMap_[pid] = iface_cast<ISessionManagerServiceRecoverListener>(listener);
288 }
289
UnregisterSMSLiteRecoverListener()290 void MockSessionManagerService::UnregisterSMSLiteRecoverListener()
291 {
292 int64_t pid = IPCSkeleton::GetCallingPid();
293 WLOGFD("[WMSRecover] pid = %{public}" PRId64, pid);
294 UnregisterSMSLiteRecoverListener(pid);
295 }
296
UnregisterSMSLiteRecoverListener(int64_t pid)297 void MockSessionManagerService::UnregisterSMSLiteRecoverListener(int64_t pid)
298 {
299 WLOGFD("[WMSRecover] pid = %{public}" PRId64, pid);
300 std::lock_guard<std::recursive_mutex> lock(smsLiteRecoverListenerLock_);
301 auto it = smsLiteRecoverListenerMap_.find(pid);
302 if (it != smsLiteRecoverListenerMap_.end()) {
303 smsLiteRecoverListenerMap_.erase(it);
304 }
305 }
306
NotifySceneBoardAvailableToLiteClient()307 void MockSessionManagerService::NotifySceneBoardAvailableToLiteClient()
308 {
309 if (sessionManagerService_ == nullptr) {
310 WLOGFE("[WMSRecover] SessionManagerService is null");
311 return;
312 }
313
314 WLOGFI("[WMSRecover] Remote lite process count = %{public}" PRIu64,
315 static_cast<uint64_t>(smsLiteRecoverListenerMap_.size()));
316
317 std::lock_guard<std::recursive_mutex> lock(smsLiteRecoverListenerLock_);
318 for (auto& it: smsLiteRecoverListenerMap_) {
319 if (it.second == nullptr) {
320 continue;
321 }
322
323 WLOGFI("[WMSRecover] Call OnSessionManagerServiceRecover Lite pid = %{public}" PRId64
324 ", ref count = %{public}" PRId32, it.first, it.second->GetSptrRefCount());
325 it.second->OnSessionManagerServiceRecover(sessionManagerService_);
326 }
327 }
328
NotifyWMSConnected(int32_t userId,int32_t screenId)329 void MockSessionManagerService::NotifyWMSConnected(int32_t userId, int32_t screenId)
330 {
331 WLOGFI("NotifyWMSConnected with userId = %{public}d, screenId = %{public}d", userId, screenId);
332 if (smsDeathRecipient_ == nullptr) {
333 WLOGFE("smsDeathRecipient_ is null, do nothing");
334 return;
335 }
336 currentUserId_ = userId;
337 currentScreenId_ = screenId;
338 smsDeathRecipient_->SetId(userId, screenId);
339 OnWMSConnectionChanged(userId, screenId, true);
340 }
341
OnWMSConnectionChanged(int32_t userId,int32_t screenId,bool isConnected)342 void MockSessionManagerService::OnWMSConnectionChanged(int32_t userId, int32_t screenId, bool isConnected)
343 {
344 isWMSConnected_ = isConnected;
345 std::lock_guard<std::recursive_mutex> lock(smsRecoverListenerLock_);
346 WLOGFD("Remote process count = %{public}" PRIu64, static_cast<uint64_t>(smsRecoverListenerMap_.size()));
347 for (auto& it : smsRecoverListenerMap_) {
348 if (it.second != nullptr) {
349 WLOGFI("Call OnWMSConnectionChanged pid = %{public}" PRId64, it.first);
350 it.second->OnWMSConnectionChanged(userId, screenId, isConnected);
351 }
352 }
353 }
354
GetScreenSessionManagerLite()355 sptr<IRemoteObject> MockSessionManagerService::GetScreenSessionManagerLite()
356 {
357 if (screenSessionManager_) {
358 return screenSessionManager_;
359 }
360 screenSessionManager_ = ScreenSessionManagerLite::GetInstance().AsObject();
361 return screenSessionManager_;
362 }
363
ShowIllegalArgsInfo(std::string & dumpInfo)364 void MockSessionManagerService::ShowIllegalArgsInfo(std::string& dumpInfo)
365 {
366 dumpInfo.append("The arguments are illegal and you can enter '-h' for help.");
367 }
368
GetSceneSessionManager()369 sptr<IRemoteObject> MockSessionManagerService::GetSceneSessionManager()
370 {
371 sptr<ISessionManagerService> sessionManagerServiceProxy =
372 iface_cast<ISessionManagerService>(sessionManagerService_);
373 if (!sessionManagerServiceProxy) {
374 WLOGFE("sessionManagerServiceProxy is nullptr");
375 return nullptr;
376 }
377 sptr<IRemoteObject> remoteObject = sessionManagerServiceProxy->GetSceneSessionManager();
378 if (!remoteObject) {
379 WLOGFW("Get scene session manager proxy failed, scene session manager service is null");
380 return sptr<IRemoteObject>(nullptr);
381 }
382 sceneSessionManager_ = remoteObject;
383 return sceneSessionManager_;
384 }
385
DumpSessionInfo(const std::vector<std::string> & args,std::string & dumpInfo)386 int MockSessionManagerService::DumpSessionInfo(const std::vector<std::string>& args, std::string& dumpInfo)
387 {
388 if (args.empty()) {
389 return -1; // WMError::WM_ERROR_INVALID_PARAM;
390 }
391 if (!sessionManagerService_) {
392 WLOGFE("sessionManagerService is nullptr");
393 return -1;
394 }
395 if (!sceneSessionManager_) {
396 WLOGFW("Get scene session manager ...");
397 GetSceneSessionManager();
398 if (!sceneSessionManager_) {
399 WLOGFW("Get scene session manager proxy failed, nullptr");
400 return -1;
401 }
402 }
403 sptr<ISceneSessionManager> sceneSessionManagerProxy = iface_cast<ISceneSessionManager>(sceneSessionManager_);
404 WSError ret = sceneSessionManagerProxy->GetSessionDumpInfo(args, dumpInfo);
405 if (ret != WSError::WS_OK) {
406 WLOGFD("sessionManagerService set success!");
407 return -1;
408 }
409 return 0; // WMError::WM_OK;
410 }
411
ShowHelpInfo(std::string & dumpInfo)412 void MockSessionManagerService::ShowHelpInfo(std::string& dumpInfo)
413 {
414 dumpInfo.append("Usage:\n")
415 .append(" -h ")
416 .append("|help text for the tool\n")
417 .append(" -a ")
418 .append("|dump all window information in the system\n")
419 .append(" -w {window id} [ArkUI Option] ")
420 .append("|dump specified window information\n")
421 .append(" ------------------------------------[ArkUI Option]------------------------------------ \n");
422 ShowAceDumpHelp(dumpInfo);
423 }
424
ShowAceDumpHelp(std::string & dumpInfo)425 void MockSessionManagerService::ShowAceDumpHelp(std::string& dumpInfo)
426 {
427 }
428
IsSceneBoardTestMode()429 bool MockSessionManagerService::SMSDeathRecipient::IsSceneBoardTestMode()
430 {
431 if (!OHOS::system::GetBoolParameter(KEY_SCENE_BOARD_TEST_ENABLE, false)) {
432 WLOGFD("SceneBoard testmode is disabled.");
433 return false;
434 }
435 auto systemAbilityMgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
436 if (systemAbilityMgr == nullptr) {
437 WLOGFE("Failed to get SystemAbilityManager.");
438 return false;
439 }
440
441 auto bmsObj = systemAbilityMgr->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
442 if (bmsObj == nullptr) {
443 WLOGFE("Failed to get BundleManagerService.");
444 return false;
445 }
446 sptr<AppExecFwk::IBundleMgr> bundleMgr_ = iface_cast<AppExecFwk::IBundleMgr>(bmsObj);
447 AppExecFwk::BundleInfo bundleInfo;
448 int uid = IPCSkeleton::GetCallingUid();
449 int userId = uid / 200000;
450 bool result = bundleMgr_->GetBundleInfo(SCENE_BOARD_BUNDLE_NAME,
451 AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, userId);
452 if (!result) {
453 WLOGFE("Failed to query bundleInfo, userId:%{public}d", userId);
454 return true;
455 }
456 auto hapModulesList = bundleInfo.hapModuleInfos;
457 if (hapModulesList.empty()) {
458 WLOGFE("hapModulesList is empty");
459 return false;
460 }
461 std::string suffix = TEST_MODULE_NAME_SUFFIX;
462 for (auto hapModule: hapModulesList) {
463 std::string moduleName = hapModule.moduleName;
464 if (moduleName.length() < suffix.length()) {
465 continue;
466 }
467 if (moduleName.compare(moduleName.length() - suffix.length(), suffix.length(), suffix) == 0) {
468 WLOGFI("Found test module name: %{public}s", moduleName.c_str());
469 return true;
470 }
471 }
472 return false;
473 }
474
WriteStringToFile(int32_t pid,const char * str)475 void MockSessionManagerService::WriteStringToFile(int32_t pid, const char* str)
476 {
477 char file[PATH_LEN] = {0};
478 if (snprintf_s(file, PATH_LEN, PATH_LEN - 1, "/proc/%d/unexpected_die_catch", pid) == -1) {
479 WLOGFI("failed to build path for %d.", pid);
480 }
481 int fd = open(file, O_RDWR);
482 if (fd == -1) {
483 return;
484 }
485 if (write(fd, str, strlen(str)) < 0) {
486 WLOGFI("failed to write 0 for %s", file);
487 close(fd);
488 return;
489 }
490 close(fd);
491 }
492 } // namespace Rosen
493 } // namespace OHOS