diff --git a/services/abilitymgr/include/extension_config.h b/services/abilitymgr/include/extension_config.h index 2dc28c50fc..d1520f4024 100644 --- a/services/abilitymgr/include/extension_config.h +++ b/services/abilitymgr/include/extension_config.h @@ -16,6 +16,7 @@ #ifndef OHOS_ABILITY_RUNTIME_EXTENSION_CONFIG_H #define OHOS_ABILITY_RUNTIME_EXTENSION_CONFIG_H +#include #include #include #include @@ -96,6 +97,7 @@ public: bool HasScreenUnlockAccessConfig(const std::string &extensionTypeName); bool HasScreenUnlockAccessAllowList(const std::string &extensionTypeName); bool HasScreenUnlockAccessBlockList(const std::string &extensionTypeName); + bool IsConfigLoaded() const; private: void LoadExtensionConfig(const nlohmann::json &object); bool ReadFileInfoJson(const std::string &filePath, nlohmann::json &jsonBuf); @@ -124,6 +126,7 @@ private: std::unordered_map configMap_; std::mutex configMapMutex_; + std::atomic isConfigLoaded_ = false; }; } // OHOS } // AAFwk diff --git a/services/abilitymgr/src/extension_config.cpp b/services/abilitymgr/src/extension_config.cpp index fdd0cf7160..17e378364a 100644 --- a/services/abilitymgr/src/extension_config.cpp +++ b/services/abilitymgr/src/extension_config.cpp @@ -143,6 +143,7 @@ void ExtensionConfig::LoadExtensionConfig(const nlohmann::json &object) LoadExtensionSAEnable(jsonObject, extensionTypeName); LoadScreenUnlockAccess(jsonObject, extensionTypeName); } + isConfigLoaded_.store(true); } void ExtensionConfig::LoadExtensionAutoDisconnectTime(const nlohmann::json &object, @@ -667,6 +668,11 @@ bool ExtensionConfig::ReadFileInfoJson(const std::string &filePath, nlohmann::js return true; } +bool ExtensionConfig::IsConfigLoaded() const +{ + return isConfigLoaded_.load(); +} + bool ExtensionConfig::CheckExtensionUriValid(const std::string &uri) { const size_t memberNum = 4; diff --git a/services/abilitymgr/src/interceptor/screen_unlock_interceptor.cpp b/services/abilitymgr/src/interceptor/screen_unlock_interceptor.cpp index ab2f2f7677..f0b1906f6b 100644 --- a/services/abilitymgr/src/interceptor/screen_unlock_interceptor.cpp +++ b/services/abilitymgr/src/interceptor/screen_unlock_interceptor.cpp @@ -150,6 +150,10 @@ ErrCode ScreenUnlockInterceptor::CheckExtensionInterception(const std::string &e const std::string &bundleName, bool isSystemApp) { auto extensionConfig = DelayedSingleton::GetInstance(); + if (!extensionConfig->IsConfigLoaded()) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "extension config not loaded, allow all extensions"); + return ERR_OK; + } if (!extensionConfig->HasScreenUnlockAccessConfig(extensionTypeName)) { TAG_LOGD(AAFwkTag::ABILITYMGR, "no screen_unlock_access config for extension: %{public}s", extensionTypeName.c_str()); diff --git a/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_coverage_test.cpp b/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_coverage_test.cpp index d157a5a52a..44fa89b8b0 100644 --- a/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_coverage_test.cpp +++ b/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_coverage_test.cpp @@ -64,10 +64,14 @@ void ScreenUnlockInterceptorCoverageTest::TearDownTestCase() void ScreenUnlockInterceptorCoverageTest::SetUp() { extensionConfig_->configMap_.clear(); + extensionConfig_->isConfigLoaded_.store(false); } void ScreenUnlockInterceptorCoverageTest::TearDown() -{} +{ + extensionConfig_->configMap_.clear(); + extensionConfig_->isConfigLoaded_.store(false); +} void ScreenUnlockInterceptorCoverageTest::LoadTestConfig(const std::string &configStr) { diff --git a/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_test.cpp b/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_test.cpp index 261a91b9f1..c5fee9de4b 100644 --- a/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_test.cpp +++ b/test/unittest/screen_unlock_interceptor_test/screen_unlock_interceptor_test.cpp @@ -63,10 +63,14 @@ void ScreenUnlockInterceptorTest::TearDownTestCase() void ScreenUnlockInterceptorTest::SetUp() { extensionConfig_->configMap_.clear(); + extensionConfig_->isConfigLoaded_.store(false); } void ScreenUnlockInterceptorTest::TearDown() -{} +{ + extensionConfig_->configMap_.clear(); + extensionConfig_->isConfigLoaded_.store(false); +} void ScreenUnlockInterceptorTest::LoadTestConfig(const std::string &configStr) { @@ -202,12 +206,20 @@ HWTEST_F(ScreenUnlockInterceptorTest, DoProcess_ScreenUnlocked, TestSize.Level1) /** * @tc.name: CheckExtensionInterception_NoConfig_ShouldBlock - * @tc.desc: Test CheckExtensionInterception when no screen_unlock_access config exists + * @tc.desc: Test CheckExtensionInterception when config is loaded but no screen_unlock_access config for this type * @tc.type: FUNC */ HWTEST_F(ScreenUnlockInterceptorTest, CheckExtensionInterception_NoConfig_ShouldBlock, TestSize.Level1) { GTEST_LOG_(INFO) << "CheckExtensionInterception_NoConfig_ShouldBlock start"; + // Load a dummy config so isConfigLoaded_ is true, simulating successful file read + const std::string configStr = R"({ + "ams_extension_config": [{ + "extension_type_name": "other_type", + "screen_unlock_access": { "defaultInterception": false } + }] + })"; + LoadTestConfig(configStr); ScreenUnlockInterceptor screenUnlockInterceptor; auto ret = screenUnlockInterceptor.CheckExtensionInterception("form", "com.test.bundle", true); EXPECT_EQ(ret, ERR_BLOCK_START_FIRST_BOOT_SCREEN_UNLOCK); @@ -580,5 +592,103 @@ HWTEST_F(ScreenUnlockInterceptorTest, CheckExtensionInterception_SystemApp_NoInt EXPECT_EQ(ret, ERR_BLOCK_START_FIRST_BOOT_SCREEN_UNLOCK); GTEST_LOG_(INFO) << "CheckExtensionInterception_SystemApp_NoInterceptionConfig end"; } + +/** + * @tc.name: CheckExtensionInterception_ConfigNotLoaded_ShouldAllow + * @tc.desc: Test CheckExtensionInterception when config file failed to load, should allow all + * @tc.type: FUNC + */ +HWTEST_F(ScreenUnlockInterceptorTest, CheckExtensionInterception_ConfigNotLoaded_ShouldAllow, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "CheckExtensionInterception_ConfigNotLoaded_ShouldAllow start"; + // isConfigLoaded_ is false by default (SetUp resets it), simulating config file read failure + EXPECT_FALSE(extensionConfig_->IsConfigLoaded()); + ScreenUnlockInterceptor screenUnlockInterceptor; + // system app extension + auto ret = screenUnlockInterceptor.CheckExtensionInterception("form", "com.test.bundle", true); + EXPECT_EQ(ret, ERR_OK); + // third-party extension + ret = screenUnlockInterceptor.CheckExtensionInterception("service", "com.test.bundle", false); + EXPECT_EQ(ret, ERR_OK); + GTEST_LOG_(INFO) << "CheckExtensionInterception_ConfigNotLoaded_ShouldAllow end"; +} + +/** + * @tc.name: IsConfigLoaded_AfterLoadConfig_ShouldReturnTrue + * @tc.desc: Test IsConfigLoaded returns true after config loaded, false after reset + * @tc.type: FUNC + */ +HWTEST_F(ScreenUnlockInterceptorTest, IsConfigLoaded_AfterLoadConfig_ShouldReturnTrue, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "IsConfigLoaded_AfterLoadConfig_ShouldReturnTrue start"; + EXPECT_FALSE(extensionConfig_->IsConfigLoaded()); + const std::string configStr = R"({ + "ams_extension_config": [{ + "extension_type_name": "form", + "screen_unlock_access": { "defaultInterception": false } + }] + })"; + LoadTestConfig(configStr); + EXPECT_TRUE(extensionConfig_->IsConfigLoaded()); + GTEST_LOG_(INFO) << "IsConfigLoaded_AfterLoadConfig_ShouldReturnTrue end"; +} + +/** + * @tc.name: DoProcess_SystemAppExtension_ConfigNotLoaded_ShouldAllow + * @tc.desc: Test DoProcess full chain: system app extension with config not loaded should allow + * @tc.type: FUNC + */ +HWTEST_F(ScreenUnlockInterceptorTest, DoProcess_SystemAppExtension_ConfigNotLoaded_ShouldAllow, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DoProcess_SystemAppExtension_ConfigNotLoaded_ShouldAllow start"; + EXPECT_FALSE(extensionConfig_->IsConfigLoaded()); + ScreenUnlockInterceptor screenUnlockInterceptor; + StartAbilityUtils::startAbilityInfo = std::make_shared(); + StartAbilityUtils::startAbilityInfo->abilityInfo.type = AbilityType::EXTENSION; + StartAbilityUtils::startAbilityInfo->abilityInfo.extensionTypeName = "form"; + StartAbilityUtils::startAbilityInfo->abilityInfo.applicationInfo.isSystemApp = true; + StartAbilityUtils::startAbilityInfo->abilityInfo.applicationInfo.allowAppRunWhenDeviceFirstLocked = true; + StartAbilityUtils::startAbilityInfo->abilityInfo.applicationInfo.bundleName = "com.test.bundle"; + + Want want; + AbilityInterceptorParam param(want, 0, 100, true, nullptr, []() { return false; }); + + auto screenLockManager = OHOS::ScreenLock::ScreenLockManager::GetInstance(); + EXPECT_NE(screenLockManager, nullptr); + screenLockManager->SetScreenLockedState(true); + + auto ret = screenUnlockInterceptor.DoProcess(param); + EXPECT_EQ(ret, ERR_OK); + GTEST_LOG_(INFO) << "DoProcess_SystemAppExtension_ConfigNotLoaded_ShouldAllow end"; +} + +/** + * @tc.name: DoProcess_ThirdPartyExtension_ConfigNotLoaded_ShouldAllow + * @tc.desc: Test DoProcess full chain: third-party extension with config not loaded should allow + * @tc.type: FUNC + */ +HWTEST_F(ScreenUnlockInterceptorTest, DoProcess_ThirdPartyExtension_ConfigNotLoaded_ShouldAllow, TestSize.Level1) +{ + GTEST_LOG_(INFO) << "DoProcess_ThirdPartyExtension_ConfigNotLoaded_ShouldAllow start"; + EXPECT_FALSE(extensionConfig_->IsConfigLoaded()); + ScreenUnlockInterceptor screenUnlockInterceptor; + StartAbilityUtils::startAbilityInfo = std::make_shared(); + StartAbilityUtils::startAbilityInfo->abilityInfo.type = AbilityType::EXTENSION; + StartAbilityUtils::startAbilityInfo->abilityInfo.extensionTypeName = "service"; + StartAbilityUtils::startAbilityInfo->abilityInfo.applicationInfo.isSystemApp = false; + StartAbilityUtils::startAbilityInfo->abilityInfo.applicationInfo.allowAppRunWhenDeviceFirstLocked = false; + StartAbilityUtils::startAbilityInfo->abilityInfo.applicationInfo.bundleName = "com.test.thirdparty"; + + Want want; + AbilityInterceptorParam param(want, 0, 100, true, nullptr, []() { return false; }); + + auto screenLockManager = OHOS::ScreenLock::ScreenLockManager::GetInstance(); + EXPECT_NE(screenLockManager, nullptr); + screenLockManager->SetScreenLockedState(true); + + auto ret = screenUnlockInterceptor.DoProcess(param); + EXPECT_EQ(ret, ERR_OK); + GTEST_LOG_(INFO) << "DoProcess_ThirdPartyExtension_ConfigNotLoaded_ShouldAllow end"; +} } // namespace AAFwk } // namespace OHOS