已开启
补充execCmd接口的ccm管控 #20321
SKY2001创建于 3 天前
补充execCmd接口的ccm管控 #20321
已开启
共 9 个文件变更+172-1
| @@ -26,6 +26,7 @@ enum class CliManagerErrorCode { | |||
| 26 | ERROR_PERMISSION_DENIED = 201, | 26 | ERROR_PERMISSION_DENIED = 201, |
| 27 | ERROR_NOT_SYSTEM_APP = 202, | 27 | ERROR_NOT_SYSTEM_APP = 202, |
| 28 | ERROR_INVALID_PARAM = 401, | 28 | ERROR_INVALID_PARAM = 401, |
| 29 | + ERROR_NOT_SUPPORTED = 801, | ||
| 29 | 30 | ||
| 30 | ERROR_TOOL_NOT_FOUND = 35600030, | 31 | ERROR_TOOL_NOT_FOUND = 35600030, |
| 31 | ERROR_REACH_LIMIT = 35600031, | 32 | ERROR_REACH_LIMIT = 35600031, |
| @@ -22,6 +22,8 @@ | |||
| 22 | namespace OHOS { | 22 | namespace OHOS { |
| 23 | namespace CliTool { | 23 | namespace CliTool { |
| 24 | namespace { | 24 | namespace { |
| 25 | +constexpr const char* ERROR_MSG_NOT_SUPPORTED = | ||
| 26 | + "Capability not supported. Failed to call the API due to limited device capabilities."; | ||
| 25 | static const std::map<CliManagerErrorCode, std::string> ERROR_MSG_MAP = { | 27 | static const std::map<CliManagerErrorCode, std::string> ERROR_MSG_MAP = { |
| 26 | {CliManagerErrorCode::ERROR_PERMISSION_DENIED, "Permission denied."}, | 28 | {CliManagerErrorCode::ERROR_PERMISSION_DENIED, "Permission denied."}, |
| 27 | {CliManagerErrorCode::ERROR_NOT_SYSTEM_APP, "Not system application."}, | 29 | {CliManagerErrorCode::ERROR_NOT_SYSTEM_APP, "Not system application."}, |
| @@ -34,6 +36,7 @@ static const std::map<CliManagerErrorCode, std::string> ERROR_MSG_MAP = { | |||
| 34 | {CliManagerErrorCode::ERROR_FUNCTION_NOT_EXIST, "The function does not exist."}, | 36 | {CliManagerErrorCode::ERROR_FUNCTION_NOT_EXIST, "The function does not exist."}, |
| 35 | {CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_FAILED, "The function execute failed."}, | 37 | {CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_FAILED, "The function execute failed."}, |
| 36 | {CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_TIMEOUT, "The function execute timeout."}, | 38 | {CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_TIMEOUT, "The function execute timeout."}, |
| 39 | + {CliManagerErrorCode::ERROR_NOT_SUPPORTED, ERROR_MSG_NOT_SUPPORTED}, | ||
| 37 | }; | 40 | }; |
| 38 | 41 | ||
| 39 | static const std::map<int32_t, CliManagerErrorCode> NATIVE_TO_BUSINESS_ERROR_MAP = { | 42 | static const std::map<int32_t, CliManagerErrorCode> NATIVE_TO_BUSINESS_ERROR_MAP = { |
| @@ -49,6 +52,7 @@ static const std::map<int32_t, CliManagerErrorCode> NATIVE_TO_BUSINESS_ERROR_MAP | |||
| 49 | {ERR_FUNCTION_NOT_EXIST, CliManagerErrorCode::ERROR_FUNCTION_NOT_EXIST}, | 52 | {ERR_FUNCTION_NOT_EXIST, CliManagerErrorCode::ERROR_FUNCTION_NOT_EXIST}, |
| 50 | {ERR_FUNCTION_EXECUTE_FAILED, CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_FAILED}, | 53 | {ERR_FUNCTION_EXECUTE_FAILED, CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_FAILED}, |
| 51 | {ERR_FUNCTION_EXECUTE_TIMEOUT, CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_TIMEOUT}, | 54 | {ERR_FUNCTION_EXECUTE_TIMEOUT, CliManagerErrorCode::ERROR_FUNCTION_EXECUTE_TIMEOUT}, |
| 55 | + {AAFwk::ERR_CAPABILITY_NOT_SUPPORT, CliManagerErrorCode::ERROR_NOT_SUPPORTED}, | ||
| 52 | }; | 56 | }; |
| 53 | 57 | ||
| 54 | static const std::map<int32_t, std::string> INNER_ERROR_MSG_MAP = { | 58 | static const std::map<int32_t, std::string> INNER_ERROR_MSG_MAP = { |
| @@ -1088,6 +1088,10 @@ int32_t CliToolManagerService::ExecCmd(const ExecCmdParam ¶m, const std::str | |||
| 1088 | { | 1088 | { |
| 1089 | InterfaceCallCounter counter(interfaceCalledCount_); | 1089 | InterfaceCallCounter counter(interfaceCalledCount_); |
| 1090 | TAG_LOGI(AAFwkTag::CLI_TOOL, "ExecCmd called: cmd=%{public}s", param.cmd.c_str()); | 1090 | TAG_LOGI(AAFwkTag::CLI_TOOL, "ExecCmd called: cmd=%{public}s", param.cmd.c_str()); |
| 1091 | + if (!AAFwk::AppUtils::GetInstance().IsSupportExecCmd()) { | ||
| 1092 | + TAG_LOGE(AAFwkTag::CLI_TOOL, "Disabled ExecCmd"); | ||
| 1093 | + return AAFwk::ERR_CAPABILITY_NOT_SUPPORT; | ||
| 1094 | + } | ||
| 1091 | if (auto ret = ValidateExecToolPermissions(); ret != ERR_OK) { | 1095 | if (auto ret = ValidateExecToolPermissions(); ret != ERR_OK) { |
| 1092 | return ret; | 1096 | return ret; |
| 1093 | } | 1097 | } |
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 17 | 18 | ||
| 18 | 19 | ||
| 19 | 20 | ||
| @@ -461,6 +462,31 @@ HWTEST_F(CliToolMGRClientTest, ExecCmd_0200, TestSize.Level1) | |||
| 461 | EXPECT_EQ(callbackCode, ERR_OK); | 462 | EXPECT_EQ(callbackCode, ERR_OK); |
| 462 | } | 463 | } |
| 463 | 464 | ||
| 465 | +/** | ||
| 466 | + * @tc.name: ExecCmd_0300 | ||
| 467 | + * @tc.desc: Test ExecCmd success activates the provisional session subscription | ||
| 468 | + * @tc.type: FUNC | ||
| 469 | + */ | ||
| 470 | +HWTEST_F(CliToolMGRClientTest, ExecCmd_0300, TestSize.Level1) | ||
| 471 | +{ | ||
| 472 | + SetMockService(); | ||
| 473 | + ExecCmdParam param; | ||
| 474 | + param.cmd = "echo activate_subscription"; | ||
| 475 | + param.options.timeout = 30; | ||
| 476 | + auto sessionCallback = std::make_shared<MockSessionCallback>(); | ||
| 477 | + | ||
| 478 | + // Success path: the provisional subscription is activated, so a session event is delivered. | ||
| 479 | + CliToolMgrClientFlag::retExecCmd = ERR_OK; | ||
| 480 | + EXPECT_EQ(CliToolMGRClient::GetInstance().ExecCmd(param, nullptr, sessionCallback), ERR_OK); | ||
| 481 | + | ||
| 482 | + CliToolEvent event; | ||
| 483 | + event.type = "stdout"; | ||
| 484 | + EXPECT_EQ(CliSessionSubscriptionManager::GetInstance().HandleSessionEvent( | ||
| 485 | + "shell", CliToolMgrClientFlag::lastSubscriptionId, event), ERR_OK); | ||
| 486 | + EXPECT_EQ(sessionCallback->eventCount, 1); | ||
| 487 | + EXPECT_EQ(sessionCallback->lastEventType, "stdout"); | ||
| 488 | +} | ||
| 489 | + | ||
| 464 | /** | 490 | /** |
| 465 | * @tc.name: ExecCmd_0400 | 491 | * @tc.name: ExecCmd_0400 |
| 466 | * @tc.desc: Test ExecCmd with null session callback still succeeds | 492 | * @tc.desc: Test ExecCmd with null session callback still succeeds |
| @@ -533,6 +559,72 @@ HWTEST_F(CliToolMGRClientTest, ExecCmd_0600, TestSize.Level1) | |||
| 533 | // sessionInfo was not set, so receivedSession keeps default empty state | 559 | // sessionInfo was not set, so receivedSession keeps default empty state |
| 534 | EXPECT_TRUE(receivedSession.sessionId.empty()); | 560 | EXPECT_TRUE(receivedSession.sessionId.empty()); |
| 535 | } | 561 | } |
| 562 | + | ||
| 563 | +/** | ||
| 564 | + * @tc.name: ExecCmd_0700 | ||
| 565 | + * @tc.desc: Test ExecCmd propagates capability-not-supported verbatim and cleans up callback and subscription | ||
| 566 | + * @tc.type: FUNC | ||
| 567 | + */ | ||
| 568 | +HWTEST_F(CliToolMGRClientTest, ExecCmd_0700, TestSize.Level1) | ||
| 569 | +{ | ||
| 570 | + SetMockService(); | ||
| 571 | + ExecCmdParam param; | ||
| 572 | + param.cmd = "echo capability_disabled"; | ||
| 573 | + param.options.timeout = 30; | ||
| 574 | + int32_t callbackCode = -1; | ||
| 575 | + auto sessionCallback = std::make_shared<MockSessionCallback>(); | ||
| 576 | + | ||
| 577 | + // Simulate the service-side capability gate rejecting ExecCmd (device does not support exec cmd). | ||
| 578 | + CliToolMgrClientFlag::retExecCmd = AAFwk::ERR_CAPABILITY_NOT_SUPPORT; | ||
| 579 | + EXPECT_EQ(CliToolMGRClient::GetInstance().ExecCmd(param, | ||
| 580 | + [&callbackCode](int32_t code, const CliSessionInfo &) { callbackCode = code; }, | ||
| 581 | + sessionCallback), AAFwk::ERR_CAPABILITY_NOT_SUPPORT); | ||
| 582 | + | ||
| 583 | + // Error path: the reply callback is removed (stray reply dropped) and the subscription is removed. | ||
| 584 | + EXPECT_EQ(CliEventReplyManager::GetInstance().HandleEventReply( | ||
| 585 | + CliToolMgrClientFlag::lastEventId, CliEventReplyResult {}), -1); | ||
| 586 | + CliToolEvent event; | ||
| 587 | + event.type = "stdout"; | ||
| 588 | + EXPECT_NE(CliSessionSubscriptionManager::GetInstance().HandleSessionEvent( | ||
| 589 | + "shell", CliToolMgrClientFlag::lastSubscriptionId, event), ERR_OK); | ||
| 590 | + EXPECT_EQ(callbackCode, -1); | ||
| 591 | + EXPECT_EQ(sessionCallback->eventCount, 0); | ||
| 592 | +} | ||
| 593 | + | ||
| 594 | +/** | ||
| 595 | + * @tc.name: ExecCmd_0800 | ||
| 596 | + * @tc.desc: Test ExecCmd success delivers a non-OK reply code and sessionInfo to the reply callback | ||
| 597 | + * @tc.type: FUNC | ||
| 598 | + */ | ||
| 599 | +HWTEST_F(CliToolMGRClientTest, ExecCmd_0800, TestSize.Level1) | ||
| 600 | +{ | ||
| 601 | + SetMockService(); | ||
| 602 | + ExecCmdParam param; | ||
| 603 | + param.cmd = "echo reply_with_code"; | ||
| 604 | + param.options.timeout = 30; | ||
| 605 | + int32_t receivedCode = -1; | ||
| 606 | + CliSessionInfo receivedSession; | ||
| 607 | + receivedSession.sessionId = "unset"; | ||
| 608 | + | ||
| 609 | + CliToolMgrClientFlag::retExecCmd = ERR_OK; | ||
| 610 | + EXPECT_EQ(CliToolMGRClient::GetInstance().ExecCmd(param, | ||
| 611 | + [&receivedCode, &receivedSession](int32_t code, const CliSessionInfo &session) { | ||
| 612 | + receivedCode = code; | ||
| 613 | + receivedSession = session; | ||
| 614 | + }, nullptr), ERR_OK); | ||
| 615 | + | ||
| 616 | + // The service later reports a non-OK result with a populated session; both must reach the callback verbatim. | ||
| 617 | + CliSessionInfo session; | ||
| 618 | + session.sessionId = "shell_session"; | ||
| 619 | + CliEventReplyResult result; | ||
| 620 | + result.code = ERR_NO_INIT; | ||
| 621 | + result.sessionInfo = session; | ||
| 622 | + EXPECT_EQ(CliEventReplyManager::GetInstance().HandleEventReply( | ||
| 623 | + CliToolMgrClientFlag::lastEventId, result), ERR_OK); | ||
| 624 | + EXPECT_EQ(receivedCode, ERR_NO_INIT); | ||
| 625 | + EXPECT_EQ(receivedSession.sessionId, "shell_session"); | ||
| 626 | +} | ||
| 627 | + | ||
| 536 | /** | 628 | /** |
| 537 | * @tc.name: FunctionInterfaces_0100 | 629 | * @tc.name: FunctionInterfaces_0100 |
| 538 | * @tc.desc: Test function register/query/getAll success paths | 630 | * @tc.desc: Test function register/query/getAll success paths |
Mcli_tool_framework/test/unittest/cli_tool_mgr_client_test/mock/src/mock_cli_tool_mgr_service.cpp+2-1
| @@ -194,9 +194,10 @@ int32_t MockCliToolMgrService::ExecTool(const ExecToolParam &, const std::string | |||
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | int32_t MockCliToolMgrService::ExecCmd(const ExecCmdParam &, const std::string &eventId, | 196 | int32_t MockCliToolMgrService::ExecCmd(const ExecCmdParam &, const std::string &eventId, |
| 197 | - const sptr<ICliToolManagerScheduler> &, const std::string &) | 197 | + const sptr<ICliToolManagerScheduler> &, const std::string &subscriptionId) |
| 198 | { | 198 | { |
| 199 | CliToolMgrClientFlag::lastEventId = eventId; | 199 | CliToolMgrClientFlag::lastEventId = eventId; |
| 200 | + CliToolMgrClientFlag::lastSubscriptionId = subscriptionId; | ||
| 200 | return CliToolMgrClientFlag::retExecCmd; | 201 | return CliToolMgrClientFlag::retExecCmd; |
| 201 | } | 202 | } |
| 202 | 203 | ||
| @@ -27,6 +27,7 @@ ohos_unittest("cli_tool_mgr_service_test") { | |||
| 27 | module_out_path = module_output_path | 27 | module_out_path = module_output_path |
| 28 | 28 | ||
| 29 | include_dirs = [ | 29 | include_dirs = [ |
| 30 | + "${ability_runtime_innerkits_path}/ability_manager/include", | ||
| 30 | "${ability_runtime_innerkits_path}/app_manager/include/appmgr", | 31 | "${ability_runtime_innerkits_path}/app_manager/include/appmgr", |
| 31 | "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", | 32 | "${ability_runtime_path}/interfaces/kits/native/appkit/ability_bundle_manager_helper", |
| 32 | "${ability_runtime_path}/test/unittest/cli_tool_mgr/cli_tool_mgr_service_test", | 33 | "${ability_runtime_path}/test/unittest/cli_tool_mgr/cli_tool_mgr_service_test", |
| @@ -36,6 +36,7 @@ | |||
| 36 | 36 | ||
| 37 | 37 | ||
| 38 | 38 | ||
| 39 | + | ||
| 39 | 40 | ||
| 40 | 41 | ||
| 41 | 42 | ||
| @@ -80,6 +81,11 @@ bool IsPermissionGateResult(int32_t result) | |||
| 80 | { | 81 | { |
| 81 | return result == ERR_NOT_SYSTEM_APP || result == ERR_PERMISSION_DENIED; | 82 | return result == ERR_NOT_SYSTEM_APP || result == ERR_PERMISSION_DENIED; |
| 82 | } | 83 | } |
| 84 | + | ||
| 85 | +bool IsCapabilityGateResult(int32_t result) | ||
| 86 | +{ | ||
| 87 | + return result == AAFwk::ERR_CAPABILITY_NOT_SUPPORT; | ||
| 88 | +} | ||
| 83 | } // namespace { | 89 | } // namespace { |
| 84 | 90 | ||
| 85 | class TestScheduler : public CliToolManagerSchedulerStub { | 91 | class TestScheduler : public CliToolManagerSchedulerStub { |
| @@ -2398,6 +2404,52 @@ HWTEST_F(CliToolManagerServiceTest, ExecCmd_0700, TestSize.Level1) | |||
| 2398 | TAG_LOGI(AAFwkTag::TEST, "CliToolManagerService_ExecCmd_0700 end"); | 2404 | TAG_LOGI(AAFwkTag::TEST, "CliToolManagerService_ExecCmd_0700 end"); |
| 2399 | } | 2405 | } |
| 2400 | 2406 | ||
| 2407 | +/** | ||
| 2408 | + * @tc.name: CliToolManagerService_ExecCmd_0800 | ||
| 2409 | + * @tc.desc: Test ExecCmd capability gate rejects before session setup and creates no session record | ||
| 2410 | + * @tc.type: FUNC | ||
| 2411 | + */ | ||
| 2412 | +HWTEST_F(CliToolManagerServiceTest, ExecCmd_0800, TestSize.Level1) | ||
| 2413 | +{ | ||
| 2414 | + TAG_LOGI(AAFwkTag::TEST, "CliToolManagerService_ExecCmd_0800 start"); | ||
| 2415 | + | ||
| 2416 | + ExecCmdParam param; | ||
| 2417 | + param.cmd = "echo capability_gate"; | ||
| 2418 | + param.options.timeout = 30; | ||
| 2419 | + sptr<TestScheduler> scheduler = new TestScheduler(); | ||
| 2420 | + int32_t result = service_->ExecCmd(param, "event_exec_cmd_cap_gate", scheduler, "subscription_cap_gate"); | ||
| 2421 | + | ||
| 2422 | + // When exec cmd is not supported on the device, ExecCmd is rejected at the capability gate | ||
| 2423 | + // (before permission/scheduler/session setup); otherwise an early-rejection code is returned. | ||
| 2424 | + EXPECT_TRUE(IsCapabilityGateResult(result) || IsPermissionGateResult(result) || | ||
| 2425 | + result == ERR_NO_INIT || result == ERR_NOT_HAP || result == ERR_INVALID_PARAM); | ||
| 2426 | + // No session record is created on early rejection. | ||
| 2427 | + EXPECT_TRUE(service_->sessionRecords_.empty()); | ||
| 2428 | + | ||
| 2429 | + TAG_LOGI(AAFwkTag::TEST, "CliToolManagerService_ExecCmd_0800 end"); | ||
| 2430 | +} | ||
| 2431 | + | ||
| 2432 | +/** | ||
| 2433 | + * @tc.name: CliToolManagerService_ExecCmd_0900 | ||
| 2434 | + * @tc.desc: Test ExecCmd capability gate takes precedence over scheduler setup with null scheduler | ||
| 2435 | + * @tc.type: FUNC | ||
| 2436 | + */ | ||
| 2437 | +HWTEST_F(CliToolManagerServiceTest, ExecCmd_0900, TestSize.Level1) | ||
| 2438 | +{ | ||
| 2439 | + TAG_LOGI(AAFwkTag::TEST, "CliToolManagerService_ExecCmd_0900 start"); | ||
| 2440 | + | ||
| 2441 | + ExecCmdParam param; | ||
| 2442 | + param.cmd = "echo null_scheduler_gate"; | ||
| 2443 | + param.options.timeout = 30; | ||
| 2444 | + // A null scheduler would normally yield ERR_NO_INIT at SetScheduler; the capability gate rejects first. | ||
| 2445 | + int32_t result = service_->ExecCmd(param, "event_exec_cmd_null_sched_gate", nullptr, "subscription_ns_gate"); | ||
| 2446 | + | ||
| 2447 | + EXPECT_TRUE(IsCapabilityGateResult(result) || result == ERR_NO_INIT || IsPermissionGateResult(result)); | ||
| 2448 | + EXPECT_TRUE(service_->sessionRecords_.empty()); | ||
| 2449 | + | ||
| 2450 | + TAG_LOGI(AAFwkTag::TEST, "CliToolManagerService_ExecCmd_0900 end"); | ||
| 2451 | +} | ||
| 2452 | + | ||
| 2401 | /** | 2453 | /** |
| 2402 | * @tc.name: CliToolManagerService_RegisterFunction_0100 | 2454 | * @tc.name: CliToolManagerService_RegisterFunction_0100 |
| 2403 | * @tc.desc: Test RegisterFunction with valid function | 2455 | * @tc.desc: Test RegisterFunction with valid function |
| @@ -365,6 +365,8 @@ public: | |||
| 365 | 365 | ||
| 366 | bool IsAutoStartupSupported(); | 366 | bool IsAutoStartupSupported(); |
| 367 | 367 | ||
| 368 | + bool IsSupportExecCmd(); | ||
| 369 | + | ||
| 368 | bool IsProductAppbootSettingEnabled(); | 370 | bool IsProductAppbootSettingEnabled(); |
| 369 | 371 | ||
| 370 | void LoadAppTransferList(); | 372 | void LoadAppTransferList(); |
| @@ -479,6 +481,8 @@ private: | |||
| 479 | volatile DeviceConfiguration<bool> isSupportAllowDebugPermission_ = {false, false}; | 481 | volatile DeviceConfiguration<bool> isSupportAllowDebugPermission_ = {false, false}; |
| 480 | volatile DeviceConfiguration<bool> isStartUIAbilityInCurrentProcess_ = {false, false}; | 482 | volatile DeviceConfiguration<bool> isStartUIAbilityInCurrentProcess_ = {false, false}; |
| 481 | volatile DeviceConfiguration<bool> isSupportModularObjectExtension_ = {false, false}; | 483 | volatile DeviceConfiguration<bool> isSupportModularObjectExtension_ = {false, false}; |
| 484 | + volatile DeviceConfiguration<bool> isSupportExecCmd_ = {false, false}; | ||
| 485 | + std::mutex isSupportExecCmdMutex_; | ||
| 482 | volatile DeviceConfiguration<bool> isAutoStartupSupported_ = {false, false}; | 486 | volatile DeviceConfiguration<bool> isAutoStartupSupported_ = {false, false}; |
| 483 | volatile DeviceConfiguration<bool> isProductAppbootSettingEnabled_ = {false, false}; | 487 | volatile DeviceConfiguration<bool> isProductAppbootSettingEnabled_ = {false, false}; |
| 484 | volatile DeviceConfiguration<bool> isHybridSpawnUnified_ = {false, false}; | 488 | volatile DeviceConfiguration<bool> isHybridSpawnUnified_ = {false, false}; |
| @@ -90,6 +90,7 @@ constexpr const char* IS_ENTERPRISE_DEVICE_TYPE = "const.edm.is_enterprise_devic | |||
| 90 | constexpr const char* IS_EDM_ENABLE = "persist.edm.edm_enable"; | 90 | constexpr const char* IS_EDM_ENABLE = "persist.edm.edm_enable"; |
| 91 | constexpr const char* IS_DEVELOPER_MODE = "security.developermode.state"; | 91 | constexpr const char* IS_DEVELOPER_MODE = "security.developermode.state"; |
| 92 | constexpr const char* SUPPORT_AUTO_STARTUP = "const.abilityms.enable_auto_startup"; | 92 | constexpr const char* SUPPORT_AUTO_STARTUP = "const.abilityms.enable_auto_startup"; |
| 93 | +constexpr const char* SUPPORT_EXEC_CMD = "const.abilityms.support_exec_cmd"; | ||
| 93 | constexpr const char* SUPPORT_DELAYED_PROCESS_EXIT = "const.abilityms.support_delayed_process_exit"; | 94 | constexpr const char* SUPPORT_DELAYED_PROCESS_EXIT = "const.abilityms.support_delayed_process_exit"; |
| 94 | // Support prepare terminate | 95 | // Support prepare terminate |
| 95 | constexpr int32_t PREPARE_TERMINATE_ENABLE_SIZE = 6; | 96 | constexpr int32_t PREPARE_TERMINATE_ENABLE_SIZE = 6; |
| @@ -905,6 +906,17 @@ bool AppUtils::IsAutoStartupSupported() | |||
| 905 | return isAutoStartupSupported_.value; | 906 | return isAutoStartupSupported_.value; |
| 906 | } | 907 | } |
| 907 | 908 | ||
| 909 | +bool AppUtils::IsSupportExecCmd() | ||
A | |||
| 910 | +{ | ||
| 911 | + std::lock_guard lock(isSupportExecCmdMutex_); | ||
| 912 | + if (!isSupportExecCmd_.isLoaded) { | ||
| 913 | + isSupportExecCmd_.value = system::GetBoolParameter(SUPPORT_EXEC_CMD, false); | ||
| 914 | + isSupportExecCmd_.isLoaded = true; | ||
| 915 | + } | ||
| 916 | + TAG_LOGD(AAFwkTag::DEFAULT, "SupportExecCmd: %{public}d", isSupportExecCmd_.value); | ||
| 917 | + return isSupportExecCmd_.value; | ||
| 918 | +} | ||
| 919 | + | ||
| 908 | bool AppUtils::IsProductAppbootSettingEnabled() | 920 | bool AppUtils::IsProductAppbootSettingEnabled() |
| 909 | { | 921 | { |
| 910 | if (!isProductAppbootSettingEnabled_.isLoaded) { | 922 | if (!isProductAppbootSettingEnabled_.isLoaded) { |
🤖 AI 代码检视意见(回复本评论可解决检视意见,点击被检视代码行左侧的小头像可收起检视意见)
🟡 在互斥锁内进行日志打印可能引发死锁
位置:
L909-L918| 严重程度: Medium❓ 问题描述
在
IsSupportExecCmd方法中,TAG_LOGD被置于std::lock_guard保护的临界区内执行。HiLog 等日志系统内部通常会获取自身的锁来写入日志缓冲区。如果在持有业务锁(isSupportExecCmdMutex_)的状态下调用日志接口获取日志锁,而另一处代码以相反的顺序获取这两个锁,将导致锁顺序倒置并引发死锁。此外,在锁内执行耗时的I/O或日志操作会降低系统的并发性能。💡 修复建议
修改建议:将日志打印移出临界区。先将需要记录的值保存到局部变量中,释放互斥锁后再执行日志打印。
909: bool AppUtils::IsSupportExecCmd() 910: { 911: bool value = false; 912: { 913: std::lock_guard lock(isSupportExecCmdMutex_); 914: if (!isSupportExecCmd_.isLoaded) { 915: isSupportExecCmd_.value = system::GetBoolParameter(SUPPORT_EXEC_CMD, false); 916: isSupportExecCmd_.isLoaded = true; 917: } 918: value = isSupportExecCmd_.value; 919: } 920: TAG_LOGD(AAFwkTag::DEFAULT, "SupportExecCmd: %{public}d", value); 921: return value; 922: }