diff --git a/BUILD.gn b/BUILD.gn index cec8cbbda9c3d93cc07376466d4b9a9c10930af6..b6c53b4ddbca16b808437e6ead9860211d7c7a3a 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -169,6 +169,7 @@ ohos_shared_library("usagestatservice") { "services/common/src/bundle_active_app_state_obsever.cpp", "services/common/src/bundle_active_binary_search.cpp", "services/common/src/bundle_active_bundle_mgr_helper.cpp", + "services/common/src/bundle_active_config_reader.cpp", "services/common/src/bundle_active_continuous_task_observer.cpp", "services/common/src/bundle_active_core.cpp", "services/common/src/bundle_active_debug_mode.cpp", @@ -206,6 +207,7 @@ ohos_shared_library("usagestatservice") { "bundle_framework:appexecfwk_core", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", "eventhandler:libeventhandler", "ffrt:libffrt", "hicollie:libhicollie", @@ -218,6 +220,8 @@ ohos_shared_library("usagestatservice") { "time_service:time_client", ] + public_external_deps = [ "jsoncpp:jsoncpp" ] + if (os_account_part_enabled) { cflags_cc += [ "-DOS_ACCOUNT_PART_ENABLED" ] external_deps += [ "os_account:os_account_innerkits" ] @@ -251,6 +255,7 @@ ohos_static_library("usagestatservice_static") { "services/common/src/bundle_active_app_state_obsever.cpp", "services/common/src/bundle_active_binary_search.cpp", "services/common/src/bundle_active_bundle_mgr_helper.cpp", + "services/common/src/bundle_active_config_reader.cpp", "services/common/src/bundle_active_continuous_task_observer.cpp", "services/common/src/bundle_active_core.cpp", "services/common/src/bundle_active_debug_mode.cpp", @@ -288,6 +293,7 @@ ohos_static_library("usagestatservice_static") { "bundle_framework:appexecfwk_core", "c_utils:utils", "common_event_service:cesfwk_innerkits", + "config_policy:configpolicy_util", "eventhandler:libeventhandler", "ffrt:libffrt", "hicollie:libhicollie", @@ -300,6 +306,8 @@ ohos_static_library("usagestatservice_static") { "time_service:time_client", ] + public_external_deps = [ "jsoncpp:jsoncpp" ] + if (os_account_part_enabled) { cflags_cc += [ "-DOS_ACCOUNT_PART_ENABLED" ] external_deps += [ "os_account:os_account_innerkits" ] diff --git a/bundle.json b/bundle.json index a655197da8bb4ad71d74ea8e1ded4898d462c837..5f7bf3504b64503e5e8d125cd437c82ce610dd60 100644 --- a/bundle.json +++ b/bundle.json @@ -27,6 +27,7 @@ "relational_store", "safwk", "common_event_service", + "config_policy", "os_account", "ipc", "access_token", @@ -44,6 +45,7 @@ "selinux_adapter", "time_service", "init", + "jsoncpp", "ffrt" ], "third_party": [] diff --git a/services/common/include/bundle_active_config_reader.h b/services/common/include/bundle_active_config_reader.h new file mode 100644 index 0000000000000000000000000000000000000000..1400e4efe278cf8dc51634d6ef75a507e5226024 --- /dev/null +++ b/services/common/include/bundle_active_config_reader.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BUNDLE_ACTIVE_CONFIG_READER_H +#define BUNDLE_ACTIVE_CONFIG_READER_H +#include +#include "json/json.h" + +namespace OHOS { +namespace DeviceUsageStats { +struct AppUsePeriodicallyConfig { + int32_t minUseTimes; + int32_t maxUseTimes; + int32_t minUseDays; +}; +class BundleActiveConfigReader { +public: + void LoadConfig(); + AppUsePeriodicallyConfig GetApplicationUsePeriodicallyConfig(); +private: + void LoadApplicationUsePeriodically(const char* path); + bool GetJsonFromFile(const char* filePath, Json::Value& root); + bool ConvertFullPath(const std::string& partialPath, std::string& fullPath); + AppUsePeriodicallyConfig appUsePeriodicallyConfig_; +}; + +} // namespace DeviceUsageStats +} // namespace OHOS +#endif // BUNDLE_ACTIVE_CONFIG_READER_H + diff --git a/services/common/include/bundle_active_core.h b/services/common/include/bundle_active_core.h index 6c1911bc2eb241f77e7ecc7d86f934a66cacebd9..ca02dab5e53e268d03a5422a08e8222eebbe10ca 100644 --- a/services/common/include/bundle_active_core.h +++ b/services/common/include/bundle_active_core.h @@ -42,6 +42,7 @@ #include "bundle_active_group_handler.h" #include "bundle_active_common_event_subscriber.h" #include "bundle_active_constant.h" +#include "bundle_active_config_reader.h" namespace OHOS { namespace DeviceUsageStats { @@ -282,9 +283,7 @@ private: bool debugCore_; ffrt::mutex bundleUninstalledMutex_; std::set bundleUninstalledSet_; - uint32_t minUseDays_ = 3; - uint32_t minUseTimes_ = 1; - uint32_t maxUseTimes_ = 10; + std::shared_ptr bundleActiveConfigReader_; }; } // namespace DeviceUsageStats } // namespace OHOS diff --git a/services/common/src/bundle_active_config_reader.cpp b/services/common/src/bundle_active_config_reader.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a7df1d9bdf69d3b721054d5b9ed3700b7aa20737 --- /dev/null +++ b/services/common/src/bundle_active_config_reader.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "bundle_active_config_reader.h" +#include "config_policy_utils.h" +#include "bundle_active_log.h" +#include +#include + +using namespace std; +namespace OHOS { +namespace DeviceUsageStats { +const char* CONFIG_PATH = "etc/device_usage_statistics/device_usage_statistics_config.json"; +const std::string APPLICATION_USE_PERIODICALLY_KEY = "application_use_periodically"; +const std::string MIN_USE_TIMES = "MinUseTimes"; +const std::string MAX_USE_TIMES = "MaxUseTimes"; +const std::string MIN_USE_DAYS = "MinUseDays"; +const int32_t DEFAULT_MIN_USE_TIMES = 1; +const int32_t DEFAULT_MAX_USE_TIMES = 10; +const int32_t DEFAULT_MIN_USE_DAYS = 3; +const int32_t MAX_BUFFER = 2048; + + +void BundleActiveConfigReader::LoadConfig() +{ + appUsePeriodicallyConfig_ = { DEFAULT_MIN_USE_TIMES, DEFAULT_MAX_USE_TIMES, DEFAULT_MIN_USE_DAYS}; + auto cfgFiles = GetCfgFiles(CONFIG_PATH); + if (!cfgFiles) { + BUNDLE_ACTIVE_LOGE("GetCfgFiles failed"); + return; + } + for (const auto& filePath : cfgFiles->paths) { + LoadApplicationUsePeriodically(filePath); + } + BUNDLE_ACTIVE_LOGI("appUsePeriodicallyConfig minUseTimes:%{public}d, maxUseTimes:%{public}d," + "minUseDays:%{public}d", appUsePeriodicallyConfig_.minUseTimes, + appUsePeriodicallyConfig_.maxUseTimes, appUsePeriodicallyConfig_.minUseDays); +}; + +void BundleActiveConfigReader::LoadApplicationUsePeriodically(const char *filePath) +{ + if (!filePath) { + return; + } + Json::Value root; + if (!GetJsonFromFile(filePath, root) || root.empty()) { + BUNDLE_ACTIVE_LOGE("file is empty %{private}s", filePath); + return; + } + if (!root.isMember(APPLICATION_USE_PERIODICALLY_KEY)) { + BUNDLE_ACTIVE_LOGE("not have application_use_periodically key"); + return; + } + Json::Value appUsePeriodicallyRoot = root[APPLICATION_USE_PERIODICALLY_KEY]; + if (appUsePeriodicallyRoot.empty() || !appUsePeriodicallyRoot.isObject()) { + BUNDLE_ACTIVE_LOGE("application_use_periodically content is empty"); + return; + } + if (appUsePeriodicallyRoot[MIN_USE_TIMES].empty() || !appUsePeriodicallyRoot[MIN_USE_TIMES].isInt()) { + BUNDLE_ACTIVE_LOGE("not have MinUseTimes key"); + return; + } + int32_t minUseTimes = appUsePeriodicallyRoot[MIN_USE_TIMES].asInt(); + if (appUsePeriodicallyRoot[MAX_USE_TIMES].empty() || !appUsePeriodicallyRoot[MAX_USE_TIMES].isInt()) { + BUNDLE_ACTIVE_LOGE("not have MaxUseTimes key"); + return; + } + int32_t maxUseTimes = appUsePeriodicallyRoot[MAX_USE_TIMES].asInt(); + if (appUsePeriodicallyRoot[MIN_USE_DAYS].empty() || !appUsePeriodicallyRoot[MIN_USE_DAYS].isInt()) { + BUNDLE_ACTIVE_LOGE("not have MinUseDays key"); + return; + } + int32_t minUseDays = appUsePeriodicallyRoot[MIN_USE_DAYS].asInt(); + appUsePeriodicallyConfig_ = { minUseTimes, maxUseTimes, minUseDays}; +}; + +bool BundleActiveConfigReader::GetJsonFromFile(const char *filePath, Json::Value &root) +{ + ifstream fin; + std::string realPath; + if (!BundleActiveConfigReader::ConvertFullPath(filePath, realPath)) { + BUNDLE_ACTIVE_LOGE("Get real path failed %{private}s", filePath); + return false; + } + BUNDLE_ACTIVE_LOGD("Read from %{private}s", realPath.c_str()); + fin.open(realPath, ios::in); + if (!fin.is_open()) { + BUNDLE_ACTIVE_LOGE("cannot open file %{private}s", realPath.c_str()); + return false; + } + char buffer[MAX_BUFFER]; + ostringstream os; + while (fin.getline(buffer, MAX_BUFFER)) { + os << buffer; + } + string data = os.str(); + JSONCPP_STRING errs; + Json::CharReaderBuilder readerBuilder; + const unique_ptr jsonReader(readerBuilder.newCharReader()); + bool res = jsonReader->parse(data.c_str(), data.c_str() + data.length(), &root, &errs); + fin.close(); + if (!res || !errs.empty()) { + BUNDLE_ACTIVE_LOGE("parse %{private}s json error", realPath.c_str()); + return false; + } + return true; +} + +bool BundleActiveConfigReader::ConvertFullPath(const std::string& partialPath, std::string& fullPath) +{ + if (partialPath.empty() || partialPath.length() >= PATH_MAX) { + return false; + } + char tmpPath[PATH_MAX] = {0}; + if (realpath(partialPath.c_str(), tmpPath) == nullptr) { + return false; + } + fullPath = tmpPath; + return true; +} + +AppUsePeriodicallyConfig BundleActiveConfigReader::GetApplicationUsePeriodicallyConfig() +{ + return appUsePeriodicallyConfig_; +}; + +} // namespace DeviceUsageStats +} // namespace OHOS + diff --git a/services/common/src/bundle_active_core.cpp b/services/common/src/bundle_active_core.cpp index 8a17258cedb3bfc159341843f25c63d964faad61..6ec93c247545a5e49eda5e89e2202615a1a79d23 100644 --- a/services/common/src/bundle_active_core.cpp +++ b/services/common/src/bundle_active_core.cpp @@ -256,6 +256,8 @@ void BundleActiveCore::Init() systemTimeShot_ = GetSystemTimeMs(); bundleGroupController_ = std::make_shared(debugCore_); BUNDLE_ACTIVE_LOGD("system time shot is %{public}lld", (long long)systemTimeShot_); + bundleActiveConfigReader_ = std::make_shared(); + bundleActiveConfigReader_->LoadConfig(); } void BundleActiveCore::InitBundleGroupController() @@ -790,11 +792,12 @@ bool BundleActiveCore::IsBundleUsePeriod(const std::string& bundleName, const in currentSystemTime, bundleName); int32_t useDayPeriod = 0; for (auto& item : packageStats) { - if (item.startCount_ >= minUseTimes_ && item.startCount_ <= maxUseTimes_) { + if (item.startCount_ >= bundleActiveConfigReader_->GetApplicationUsePeriodicallyConfig().minUseTimes + && item.startCount_ <= bundleActiveConfigReader_->GetApplicationUsePeriodicallyConfig().maxUseTimes) { useDayPeriod ++; } } - return useDayPeriod >= minUseDays_; + return useDayPeriod >= bundleActiveConfigReader_->GetApplicationUsePeriodicallyConfig().minUseDays; } void BundleActiveCore::GetAllActiveUser(std::vector& activatedOsAccountIds) diff --git a/services/common/src/bundle_active_service.cpp b/services/common/src/bundle_active_service.cpp index 5cc1af27f94ca1547682e5a3f2121f6c4021cda5..d187bea37c0502c50ff05cae31d321a1494afee3 100644 --- a/services/common/src/bundle_active_service.cpp +++ b/services/common/src/bundle_active_service.cpp @@ -329,6 +329,7 @@ ErrCode BundleActiveService::IsBundleUsePeriod(bool& IsUsePeriod, const std::str } } IsUsePeriod = bundleActiveCore_->IsBundleUsePeriod(bundleName, userId); + BUNDLE_ACTIVE_LOGI("IsBundleUsePeriod %{public}d", IsUsePeriod); return ERR_OK; } diff --git a/test/unittest/device_usage_statistics_service_test.cpp b/test/unittest/device_usage_statistics_service_test.cpp index 3edd8b79ad1242ed13e2a7e472144b48bb35b204..134203bdb6b5c3b4a3f3056664877f35f3dc9776 100644 --- a/test/unittest/device_usage_statistics_service_test.cpp +++ b/test/unittest/device_usage_statistics_service_test.cpp @@ -28,6 +28,7 @@ #include "bundle_active_user_history.h" #include "bundle_active_group_controller.h" #include "bundle_active_log.h" +#include "bundle_active_config_reader.h" using namespace testing::ext; @@ -1437,5 +1438,70 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_Dele userService->DeleteUninstalledBundleStats("test", 100, appIndex); } +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ConfigReader_001 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: issuesIBCE1G + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ConfigReader_001, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + bundleActiveConfigReader->LoadConfig(); + EXPECT_NE(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ConfigReader_002 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: issuesIBCE1G + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ConfigReader_002, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + const char *path = "test"; + bundleActiveConfigReader->LoadApplicationUsePeriodically(path); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ConfigReader_003 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: issuesIBCE1G + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ConfigReader_003, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + const char *path = "test"; + Json::Value root; + bool result = bundleActiveConfigReader->GetJsonFromFile(path, root); + EXPECT_EQ(result, false); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ConfigReader_004 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: issuesIBCE1G + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ConfigReader_004, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + std::string partialPath = "test"; + std::string fullPath = ""; + bool result = bundleActiveConfigReader->ConvertFullPath(partialPath, fullPath); + EXPECT_EQ(result, false); +} + } // namespace DeviceUsageStats } // namespace OHOS \ No newline at end of file