• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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