From 8a4e936db5d7004572efdeb217b19afdd3963dd5 Mon Sep 17 00:00:00 2001 From: QiangShaowei Date: Sat, 21 Jun 2025 17:45:32 +0800 Subject: [PATCH] =?UTF-8?q?add=20query=20high=20freq=20hour=20and=20latest?= =?UTF-8?q?=20use=20time=20Signed-off-by:=20=E7=BD=97=E4=B8=B9=E4=BA=91=20?= =?UTF-8?q??= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BUILD.gn | 1 + IBundleActiveService.idl | 3 + bundle.json | 3 +- .../innerkits/include/bundle_active_client.h | 24 +- .../bundle_active_high_frequency_period.h | 77 +++ .../innerkits/src/bundle_active_client.cpp | 24 + .../bundle_active_high_frequency_period.cpp | 99 ++++ libusagestatsinner.versionscript | 1 + .../include/bundle_active_config_reader.h | 23 +- .../common/include/bundle_active_constant.h | 4 + services/common/include/bundle_active_core.h | 25 +- .../common/include/bundle_active_service.h | 25 +- .../src/bundle_active_config_reader.cpp | 163 ++++-- services/common/src/bundle_active_core.cpp | 149 +++++- services/common/src/bundle_active_service.cpp | 79 ++- .../bundleactivecommon_fuzzer.cpp | 12 +- .../bundleactiveobserver_fuzzer.cpp | 6 +- ...leactivepowerstatecallbackproxy_fuzzer.cpp | 5 + .../device_usage_statistics_config.json | 6 + .../device_usage_statistics_config_test1.json | 6 + .../device_usage_statistics_config_test2.json | 6 + .../device_usage_statistics_mock_test.cpp | 44 ++ .../device_usage_statistics_service_test.cpp | 504 +++++++++++++++++- .../unittest/device_usage_statistics_test.cpp | 125 +++++ 24 files changed, 1329 insertions(+), 85 deletions(-) create mode 100644 interfaces/innerkits/include/bundle_active_high_frequency_period.h create mode 100644 interfaces/innerkits/src/bundle_active_high_frequency_period.cpp diff --git a/BUILD.gn b/BUILD.gn index 9615773..c7e3014 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -76,6 +76,7 @@ ohos_shared_library("usagestatsinner") { "interfaces/innerkits/src/bundle_active_form_record.cpp", "interfaces/innerkits/src/bundle_active_module_record.cpp", "interfaces/innerkits/src/bundle_active_package_stats.cpp", + "interfaces/innerkits/src/bundle_active_high_frequency_period.cpp", ] public_configs = [ ":usagestats_public_config" ] deps = [ diff --git a/IBundleActiveService.idl b/IBundleActiveService.idl index 6a654eb..d2b2893 100644 --- a/IBundleActiveService.idl +++ b/IBundleActiveService.idl @@ -14,6 +14,7 @@ */ sequenceable OHOS.DeviceUsageStats.BundleActiveEvent; +sequenceable OHOS.DeviceUsageStats.BundleActiveHighFrequencyPeriod; sequenceable OHOS.DeviceUsageStats.BundleActivePackageStats; sequenceable OHOS.DeviceUsageStats.BundleActiveModuleRecord; sequenceable OHOS.DeviceUsageStats.BundleActiveEventStats; @@ -39,4 +40,6 @@ interface OHOS.DeviceUsageStats.IBundleActiveService { [out]List eventStats, [in] int userId); void QueryNotificationEventStats([in] long beginTime, [in] long endTime, [out]List eventStats, [in] int userId); + void QueryHighFrequencyPeriodBundle([out] List bundleHighFreqPeriod, [in] int userId); + void QueryBundleTodayLatestUsedTime([out] long latestUsedTime, [in] String bundleName, [in] int userId); } \ No newline at end of file diff --git a/bundle.json b/bundle.json index 74fcdc4..79a289f 100644 --- a/bundle.json +++ b/bundle.json @@ -68,7 +68,8 @@ "bundle_active_form_record.h", "bundle_active_group_map.h", "bundle_active_module_record.h", - "bundle_active_package_stats.h" + "bundle_active_package_stats.h", + "bundle_active_high_frequency_period.h" ] }, "name": "//foundation/resourceschedule/device_usage_statistics:usagestatsinner" diff --git a/interfaces/innerkits/include/bundle_active_client.h b/interfaces/innerkits/include/bundle_active_client.h index 0ad98ae..bcce217 100644 --- a/interfaces/innerkits/include/bundle_active_client.h +++ b/interfaces/innerkits/include/bundle_active_client.h @@ -25,6 +25,7 @@ #include "bundle_active_package_stats.h" #include "bundle_active_module_record.h" #include "bundle_state_inner_errors.h" +#include "bundle_active_high_frequency_period.h" #include "system_ability_definition.h" #include "if_system_ability_manager.h" @@ -36,7 +37,7 @@ class BundleActiveClient { public: // max number of query modules result. const int32_t MAXNUM_UP_LIMIT = 1000; - + /** * @brief ReportEvent, used to report event. * @@ -184,6 +185,27 @@ public: */ ErrCode QueryNotificationEventStats(int64_t beginTime, int64_t endTime, std::vector& eventStats, int32_t userId = -1); + + /** + * @brief QueryHighFrequencyPeriodBundle, query the high-frequency usage period of the application in the past week. + * + * @param appFreqHours . + * @param userId default userId is -1 for JS API, if other SAs call this API, they should explicit define userId. + * @return errCode. + */ + ErrCode QueryHighFrequencyPeriodBundle( + std::vector& appFreqHours, int32_t userId = -1); + + /** + * @brief QueryBundleTodayLatestUsedTime, query the latest use time of the application on the current day. + * + * @param latestUsedTime . + * @param bundleName . + * @param userId default userId is -1 for JS API, if other SAs call this API, they should explicit define userId. + * @return errCode. + */ + ErrCode QueryBundleTodayLatestUsedTime(int64_t& latestUsedTime, const std::string& bundleName, int32_t userId = -1); + /* * function: GetInstance, get single instance of client. * return: object of BundleActiveClient. diff --git a/interfaces/innerkits/include/bundle_active_high_frequency_period.h b/interfaces/innerkits/include/bundle_active_high_frequency_period.h new file mode 100644 index 0000000..c1a5580 --- /dev/null +++ b/interfaces/innerkits/include/bundle_active_high_frequency_period.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025 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_HIGH_FREQUENCY_PERIOD_H +#define BUNDLE_ACTIVE_HIGH_FREQUENCY_PERIOD_H + +#include +#include +#include +#include "parcel.h" + +namespace OHOS { +namespace DeviceUsageStats { +class BundleActiveHighFrequencyPeriod : public Parcelable { +public: + std::string bundleName_; + std::vector highFreqHours_; + + /* + * function: BundleActiveHighFrequencyPeriod, default constructor. + */ + BundleActiveHighFrequencyPeriod(); + + /* + * function: BundleActiveHighFrequencyPeriod, copy constructor. + * parameters: orig + */ + BundleActiveHighFrequencyPeriod(const BundleActiveHighFrequencyPeriod& orig); + + /* + * function: BundleActiveHighFrequencyPeriod, use bundleName, highFreqHours to construct + * object. parameters: bundleName, highFreqHours + */ + BundleActiveHighFrequencyPeriod( + const std::string& bundleName, const std::vector& highFreqHours); + + /* + * function: ~BundleActiveHighFrequencyPeriod, default destructor. + */ + ~BundleActiveHighFrequencyPeriod() {} + + /* + * function: Marshalling, mashalling BundleActiveHighFrequencyPeriod object to parcel. + * parameters: parcel + * return: result of mashalling, true means successful, flase means failed. + */ + virtual bool Marshalling(Parcel &parcel) const override; + + /* + * function: Unmarshalling, Unmashalling BundleActiveHighFrequencyPeriod object from parcel. + * parameters: parcel + * return: point to a BundleActiveHighFrequencyPeriod. + */ + static BundleActiveHighFrequencyPeriod *Unmarshalling(Parcel &parcel); + + /* + * function: ToString, change app high-frequency info to string. + * return: string of from bundleName and highFreqHours + */ + std::string ToString() const; +}; +} // namespace DeviceUsageStats +} // namespace OHOS +#endif // BUNDLE_ACTIVE_HIGH_FREQUENCY_PERIOD_H + diff --git a/interfaces/innerkits/src/bundle_active_client.cpp b/interfaces/innerkits/src/bundle_active_client.cpp index e92722e..ac873cb 100644 --- a/interfaces/innerkits/src/bundle_active_client.cpp +++ b/interfaces/innerkits/src/bundle_active_client.cpp @@ -104,6 +104,30 @@ ErrCode BundleActiveClient::QueryBundleStatsInfoByInterval(std::vectorQueryBundleStatsInfoByInterval(PackageStats, intervalType, beginTime, endTime, userId); } +ErrCode BundleActiveClient::QueryBundleTodayLatestUsedTime( + int64_t& latestUsedTime, const std::string& bundleName, int32_t userId) +{ + std::lock_guard lock(mutex_); + ErrCode ret = GetBundleActiveProxy(); + if (ret != ERR_OK) { + return ret; + } + return bundleActiveProxy_->QueryBundleTodayLatestUsedTime(latestUsedTime, bundleName, userId); +} + +ErrCode BundleActiveClient::QueryHighFrequencyPeriodBundle( + std::vector& appFreqHours, int32_t userId) +{ + std::lock_guard lock(mutex_); + ErrCode ret = GetBundleActiveProxy(); + if (ret != ERR_OK) { + return ret; + } + auto err = bundleActiveProxy_->QueryHighFrequencyPeriodBundle(appFreqHours, userId); + BUNDLE_ACTIVE_LOGI("QueryHighFrequencyPeriodBundle appFreqHour is %{public}zu", appFreqHours.size()); + return err; +} + ErrCode BundleActiveClient::QueryBundleEvents(std::vector& bundleActiveEvents, const int64_t beginTime, const int64_t endTime, int32_t userId) { diff --git a/interfaces/innerkits/src/bundle_active_high_frequency_period.cpp b/interfaces/innerkits/src/bundle_active_high_frequency_period.cpp new file mode 100644 index 0000000..95a508b --- /dev/null +++ b/interfaces/innerkits/src/bundle_active_high_frequency_period.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2025 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 + +#include "bundle_active_high_frequency_period.h" + +namespace OHOS { +namespace DeviceUsageStats { +namespace { + static const int32_t MAX_HOUR_NUM = 24; +} +BundleActiveHighFrequencyPeriod::BundleActiveHighFrequencyPeriod() +{ + bundleName_ = ""; +} + +BundleActiveHighFrequencyPeriod::BundleActiveHighFrequencyPeriod( + const std::string& bundleName, const std::vector& highFreqHours) + : bundleName_(bundleName), highFreqHours_(highFreqHours) +{ +} + +BundleActiveHighFrequencyPeriod::BundleActiveHighFrequencyPeriod(const BundleActiveHighFrequencyPeriod& orig) +{ + bundleName_ = orig.bundleName_; + highFreqHours_ = orig.highFreqHours_; +} + +bool BundleActiveHighFrequencyPeriod::Marshalling(Parcel &parcel) const +{ + if (highFreqHours_.size() > MAX_HOUR_NUM) { + return false; + } + if (parcel.WriteString(bundleName_) && parcel.WriteUint32(highFreqHours_.size())) { + for (auto highFreqHour : highFreqHours_) { + if (!parcel.WriteInt32(highFreqHour)) { + return false; + } + } + return true; + } + return false; +} + +BundleActiveHighFrequencyPeriod *BundleActiveHighFrequencyPeriod::Unmarshalling(Parcel& parcel) +{ + BundleActiveHighFrequencyPeriod *result = new (std::nothrow) BundleActiveHighFrequencyPeriod(); + if (result == nullptr) { + return nullptr; + } + result->bundleName_ = parcel.ReadString(); + uint32_t size; + if (!parcel.ReadUint32(size) || size > MAX_HOUR_NUM) { + delete result; + return nullptr; + } + result->highFreqHours_.clear(); + for (uint32_t i = 0; i < size; i++) { + int32_t tmp; + if (!parcel.ReadInt32(tmp)) { + delete result; + return nullptr; + } + result->highFreqHours_.emplace_back(tmp); + } + return result; +} + +std::string BundleActiveHighFrequencyPeriod::ToString() const +{ + std::stringstream highFreqHoursToString; + highFreqHoursToString << "bundle name is "; + highFreqHoursToString << this->bundleName_; + highFreqHoursToString << ", highFreqHours_ is "; + for (size_t i = 0; i < highFreqHours_.size(); ++i) { + if (i != 0) { + highFreqHoursToString << ", "; + } + highFreqHoursToString << highFreqHours_[i]; + } + highFreqHoursToString << "\n"; + return highFreqHoursToString.str(); +} +} // namespace DeviceUsageStats +} // namespace OHOS + diff --git a/libusagestatsinner.versionscript b/libusagestatsinner.versionscript index 9823f6a..f28ce6e 100644 --- a/libusagestatsinner.versionscript +++ b/libusagestatsinner.versionscript @@ -25,6 +25,7 @@ *BundleActiveFormRecord*; *BundleActiveModuleRecord*; *BundleActivePackageStats*; + *BundleActiveHighFrequencyPeriod*; local: *; }; diff --git a/services/common/include/bundle_active_config_reader.h b/services/common/include/bundle_active_config_reader.h index 23dc226..a0e4dab 100644 --- a/services/common/include/bundle_active_config_reader.h +++ b/services/common/include/bundle_active_config_reader.h @@ -25,17 +25,34 @@ struct AppUsePeriodicallyConfig { int32_t maxUseTimes; int32_t minUseDays; }; + +struct AppHighFrequencyPeriodThresholdConfig { + int32_t minTotalUseDays; + int32_t minTopUseHoursLimit; + int32_t minHourUseDays; + int32_t maxHighFreqHourNum; +}; + class BundleActiveConfigReader { public: void LoadConfig(); AppUsePeriodicallyConfig GetApplicationUsePeriodicallyConfig(); + AppHighFrequencyPeriodThresholdConfig GetAppHighFrequencyPeriodThresholdConfig(); uint64_t GetMaxDataSize(); private: - void LoadApplicationUsePeriodically(const char* path); - bool GetJsonFromFile(const char* filePath, cJSON *&root); + void LoadConfigFile(const char* filePath); + void LoadApplicationUsePeriodically(cJSON* root); + void LoadAppHighFreqPeriodThresholdConfig(cJSON* root); + void LoadMaxDataSize(cJSON* root); + bool GetJsonFromFile(const char* filePath, cJSON*& root); bool ConvertFullPath(const std::string& partialPath, std::string& fullPath); - void LoadMaxDataSize(const char *filePath); + int32_t GetIntValue( + cJSON* root, const char* parameterName, int32_t minLimit, int32_t maxLimit, int32_t defaultValue); + bool IsValidObject(cJSON* item); + bool IsValidNumber(cJSON* item); + AppUsePeriodicallyConfig appUsePeriodicallyConfig_; + AppHighFrequencyPeriodThresholdConfig appHighFreqPeriodThresholdConfig_; uint64_t maxDataSize_ = 0; }; diff --git a/services/common/include/bundle_active_constant.h b/services/common/include/bundle_active_constant.h index b26848d..e1f6bf6 100644 --- a/services/common/include/bundle_active_constant.h +++ b/services/common/include/bundle_active_constant.h @@ -81,6 +81,10 @@ const int32_t FORM_UID_COLUMN_INDEX = 8; const int32_t QUERY_CONDITION_VALID = 0; const int32_t QUERY_CONDITION_INVALID = -1; const int32_t DEFAULT_DELETE_EVENT_DALIYS = 0; +const int32_t NUM_HOUR_ONE_DAY = 24; +const int32_t NUM_DAY_ONE_WEEK = 7; +const int32_t MINIMUM_LIMIT = 0; +const int32_t DEFAULT_INVALID_VALUE = 0; const uint32_t BUNDLE_ACTIVE_DB_NAME_MAX_LENGTH = 100; const int64_t TWO_SECONDS = 2 * 1000LL; const int64_t TEN_MINUTES = 10 * 60 * 1000LL; diff --git a/services/common/include/bundle_active_core.h b/services/common/include/bundle_active_core.h index 64bbe3d..341a389 100644 --- a/services/common/include/bundle_active_core.h +++ b/services/common/include/bundle_active_core.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 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 @@ -43,6 +43,7 @@ #include "bundle_active_common_event_subscriber.h" #include "bundle_active_constant.h" #include "bundle_active_config_reader.h" +#include "bundle_active_high_frequency_period.h" namespace OHOS { namespace DeviceUsageStats { @@ -188,6 +189,15 @@ public: ErrCode QueryNotificationEventStats(int64_t beginTime, int64_t endTime, std::vector& eventStats, int32_t userId); + /* + * function: QueryHighFrequencyPeriodBundle, query the high-frequency usage period of the app in the past week. + * parameters: appFreqHours, userId, default userId is -1 for JS API, + * if other SAs call this API, they should explicit define userId. + * return: errorcode. + */ + ErrCode QueryHighFrequencyPeriodBundle( + std::vector& appFreqHours, int32_t userId); + // get the wall time and check if the wall time is changed. int64_t CheckTimeChangeAndGetWallTime(int32_t userId = 0); @@ -242,6 +252,14 @@ public: void DeInit(); private: + // 用于应用使用时段信息统计 + struct AppUsage { + int32_t dayUsage[NUM_DAY_ONE_WEEK] = {}; + int32_t hourUsage[NUM_DAY_ONE_WEEK][NUM_HOUR_ONE_DAY] = {}; + int32_t hourTotalUse[NUM_HOUR_ONE_DAY] = {}; + int64_t startTime = DEFAULT_INVALID_VALUE; + }; + void NotifOberserverGroupChanged(const AppGroupCallbackInfo& callbackInfo, AccessToken::HapTokenInfo tokenInfo); void AddObserverDeathRecipient(const sptr &observer); void RemoveObserverDeathRecipient(const sptr &observer); @@ -253,6 +271,11 @@ private: void ProcessDataSize(); bool IsFolderSizeLimit(); void DeleteExcessiveTableData(); + void ProcessEvents(std::unordered_map& appUsages, std::vector& events); + void GetFreqBundleHours(std::vector& appFreqHours, + std::unordered_map& appUsages); + void GetTopHourUsage( + std::vector>& topHoursUsage, AppUsage& usage); int64_t flushInterval_; static const int64_t TIME_CHANGE_THRESHOLD_MILLIS = TEN_MINUTES; const int32_t DEFAULT_USER_ID = -1; diff --git a/services/common/include/bundle_active_service.h b/services/common/include/bundle_active_service.h index 5e86c33..47edb99 100644 --- a/services/common/include/bundle_active_service.h +++ b/services/common/include/bundle_active_service.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 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 @@ -30,6 +30,7 @@ #include "bundle_active_app_state_observer.h" #include "bundle_active_continuous_task_observer.h" #include "bundle_active_account_helper.h" +#include "bundle_active_high_frequency_period.h" #include "file_ex.h" #include "string_ex.h" #include "system_ability.h" @@ -185,6 +186,27 @@ public: ErrCode QueryNotificationEventStats(int64_t beginTime, int64_t endTime, std::vector& eventStats, int32_t userId) override; + /** + * @brief QueryHighFrequencyPeriodBundle, query the high-frequency usage period of the app in the past week. + * + * @param appFreqHours . + * @param userId default userId is -1 for JS API, if other SAs call this API, they should explicit define userId. + * @return errCode. + */ + ErrCode QueryHighFrequencyPeriodBundle( + std::vector& appFreqHours, int32_t userId) override; + + /** + * @brief QueryBundleTodayLatestUsedTime, query the latest use time of the application on the current day. + * + * @param latestUsedTime . + * @param bundleName . + * @param userId default userId is -1 for JS API, if other SAs call this API, they should explicit define userId. + * @return errCode. + */ + ErrCode QueryBundleTodayLatestUsedTime( + int64_t& latestUsedTime, const std::string& bundleName, int32_t userId) override; + /** * @brief BundleActiveService, default constructor. * @@ -254,6 +276,7 @@ private: int32_t DumpEvents(const std::vector &dumpOption, std::vector &dumpInfo); int32_t DumpPackageUsage(const std::vector &dumpOption, std::vector &dumpInfo); int32_t DumpModuleUsage(const std::vector &dumpOption, std::vector &dumpInfo); + int32_t DumpHighFreqHourUsage(const std::vector &dumpOption, std::vector &dumpInfo); int32_t GetNameAndIndexForUid(int32_t uid); std::vector MergePackageStats( const std::vector& packageStats); diff --git a/services/common/src/bundle_active_config_reader.cpp b/services/common/src/bundle_active_config_reader.cpp index de71976..c6238a4 100644 --- a/services/common/src/bundle_active_config_reader.cpp +++ b/services/common/src/bundle_active_config_reader.cpp @@ -15,6 +15,7 @@ #include "bundle_active_config_reader.h" #include "config_policy_utils.h" +#include "bundle_active_constant.h" #include "bundle_active_log.h" #include "file_ex.h" @@ -27,35 +28,56 @@ const static char* MIN_USE_TIMES = "MinUseTimes"; const static char* MAX_USE_TIMES = "MaxUseTimes"; const static char* MIN_USE_DAYS = "MinUseDays"; const static char* MAX_DATA_SIZE = "MaxDataSize"; +const static char* APPLICATION_USE_HIGH_FREQUENCY_JUDGE_THRESHOLD = + "application_use_high_frequency_judge_threshold"; +const static char* MIN_TOTAL_USE_DAYS = "MinTotalUseDays"; +const static char* MIN_TOP_USE_HOURS_LIMIT = "MinTopUseHoursLimit"; +const static char* MIN_HOUR_USE_DAYS = "MinHourUseDays"; +const static char* MAX_HIGH_FREQUENCY_HOUR_NUM = "MaxHighFrequencyHourNum"; 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 DEFAULT_MIN_TOTAL_USE_DAYS = 4; +const int32_t DEFAULT_TOP_USE_HOURS_LIMIT = 6; +const int32_t DEFAULT_MIN_HOUR_USE_DAYS = 4; +const int32_t DEFAULT_MAX_HIGH_FREQUENCY_HOUR_NUM = 3; const int32_t MAX_BUFFER = 2048; const uint64_t DEFAULT_MAX_DATA_SIZE = 5 * 1024 * 1024; void BundleActiveConfigReader::LoadConfig() { - appUsePeriodicallyConfig_ = { DEFAULT_MIN_USE_TIMES, DEFAULT_MAX_USE_TIMES, DEFAULT_MIN_USE_DAYS}; + appUsePeriodicallyConfig_ = {DEFAULT_MIN_USE_TIMES, DEFAULT_MAX_USE_TIMES, DEFAULT_MIN_USE_DAYS}; + appHighFreqPeriodThresholdConfig_ = {DEFAULT_MIN_TOTAL_USE_DAYS, + DEFAULT_TOP_USE_HOURS_LIMIT, + DEFAULT_MIN_HOUR_USE_DAYS, + DEFAULT_MAX_HIGH_FREQUENCY_HOUR_NUM}; auto cfgFiles = GetCfgFiles(CONFIG_PATH); if (!cfgFiles) { BUNDLE_ACTIVE_LOGE("GetCfgFiles failed"); return; } for (const auto& filePath : cfgFiles->paths) { - LoadApplicationUsePeriodically(filePath); - LoadMaxDataSize(filePath); + LoadConfigFile(filePath); } BUNDLE_ACTIVE_LOGI("appUsePeriodicallyConfig minUseTimes:%{public}d, maxUseTimes:%{public}d," "minUseDays:%{public}d maxDataSize:%{public}lu", appUsePeriodicallyConfig_.minUseTimes, appUsePeriodicallyConfig_.maxUseTimes, appUsePeriodicallyConfig_.minUseDays, static_cast(maxDataSize_)); + BUNDLE_ACTIVE_LOGI("appHighFreqPeriodThresholdConfig minTotalUseDays:%{public}d, minTopUseHoursLimit:%{public}d," + "minHourUseDays:%{public}d," + "maxHighFreqHourNum:%{public}d", + appHighFreqPeriodThresholdConfig_.minTotalUseDays, + appHighFreqPeriodThresholdConfig_.minTopUseHoursLimit, + appHighFreqPeriodThresholdConfig_.minHourUseDays, + appHighFreqPeriodThresholdConfig_.maxHighFreqHourNum); FreeCfgFiles(cfgFiles); -}; +} -void BundleActiveConfigReader::LoadApplicationUsePeriodically(const char *filePath) +void BundleActiveConfigReader::LoadConfigFile(const char *filePath) { if (!filePath) { + BUNDLE_ACTIVE_LOGE("file does no exit"); return; } cJSON *root = nullptr; @@ -63,36 +85,73 @@ void BundleActiveConfigReader::LoadApplicationUsePeriodically(const char *filePa BUNDLE_ACTIVE_LOGE("file is empty %{private}s", filePath); return; } + LoadApplicationUsePeriodically(root); + LoadAppHighFreqPeriodThresholdConfig(root); + LoadMaxDataSize(root); + cJSON_Delete(root); +} + + +void BundleActiveConfigReader::LoadApplicationUsePeriodically(cJSON* root) +{ cJSON *appUsePeriodicallyRoot = cJSON_GetObjectItem(root, APPLICATION_USE_PERIODICALLY_KEY); - if (!appUsePeriodicallyRoot || !cJSON_IsObject(appUsePeriodicallyRoot)) { + if (!IsValidObject(appUsePeriodicallyRoot)) { BUNDLE_ACTIVE_LOGE("application_use_periodically content is empty"); - cJSON_Delete(root); return; } - cJSON *minUseTimesItem = cJSON_GetObjectItem(appUsePeriodicallyRoot, MIN_USE_TIMES); - if (!minUseTimesItem || !cJSON_IsNumber(minUseTimesItem)) { - BUNDLE_ACTIVE_LOGE("not have MinUseTimes key"); - cJSON_Delete(root); - return; - } - int32_t minUseTimes = static_cast(minUseTimesItem->valueint); - cJSON *maxUseTimesItem = cJSON_GetObjectItem(appUsePeriodicallyRoot, MAX_USE_TIMES); - if (!maxUseTimesItem || !cJSON_IsNumber(maxUseTimesItem)) { - BUNDLE_ACTIVE_LOGE("not have MaxUseTimes key"); - cJSON_Delete(root); + + int32_t minUseTimes = + GetIntValue(appUsePeriodicallyRoot, MIN_USE_TIMES, MINIMUM_LIMIT, INT32_MAX, DEFAULT_MIN_USE_TIMES); + int32_t maxUseTimes = + GetIntValue(appUsePeriodicallyRoot, MAX_USE_TIMES, MINIMUM_LIMIT, INT32_MAX, DEFAULT_MAX_USE_TIMES); + int32_t minUseDays = + GetIntValue(appUsePeriodicallyRoot, MIN_USE_DAYS, MINIMUM_LIMIT, INT32_MAX, DEFAULT_MIN_USE_DAYS); + + appUsePeriodicallyConfig_ = {minUseTimes, maxUseTimes, minUseDays}; +} + +void BundleActiveConfigReader::LoadAppHighFreqPeriodThresholdConfig(cJSON* root) +{ + cJSON* appHighFreqPeriodThresholdConfigRoot = + cJSON_GetObjectItem(root, APPLICATION_USE_HIGH_FREQUENCY_JUDGE_THRESHOLD); + if (!IsValidObject(appHighFreqPeriodThresholdConfigRoot)) { + BUNDLE_ACTIVE_LOGE("application_use_high_frequency_judge_threshold content is empty"); return; } - int32_t maxUseTimes = static_cast(maxUseTimesItem->valueint); - cJSON *minUseDaysItem = cJSON_GetObjectItem(appUsePeriodicallyRoot, MIN_USE_DAYS); - if (!minUseDaysItem || !cJSON_IsNumber(minUseDaysItem)) { - BUNDLE_ACTIVE_LOGE("not have MinUseDays key"); - cJSON_Delete(root); + int32_t minTotalUseDays = GetIntValue(appHighFreqPeriodThresholdConfigRoot, + MIN_TOTAL_USE_DAYS, + MINIMUM_LIMIT, + NUM_DAY_ONE_WEEK, + DEFAULT_MIN_TOTAL_USE_DAYS); + + int32_t minTopUseHoursLimit = GetIntValue(appHighFreqPeriodThresholdConfigRoot, + MIN_TOP_USE_HOURS_LIMIT, + MINIMUM_LIMIT, + NUM_HOUR_ONE_DAY, + DEFAULT_TOP_USE_HOURS_LIMIT); + int32_t minHourUseDays = GetIntValue(appHighFreqPeriodThresholdConfigRoot, + MIN_HOUR_USE_DAYS, + MINIMUM_LIMIT, + NUM_DAY_ONE_WEEK, + DEFAULT_MIN_HOUR_USE_DAYS); + int32_t maxHighFreqHourNum = GetIntValue(appHighFreqPeriodThresholdConfigRoot, + MAX_HIGH_FREQUENCY_HOUR_NUM, + MINIMUM_LIMIT, + NUM_HOUR_ONE_DAY, + DEFAULT_MAX_HIGH_FREQUENCY_HOUR_NUM); + + appHighFreqPeriodThresholdConfig_ = {minTotalUseDays, minTopUseHoursLimit, minHourUseDays, maxHighFreqHourNum}; +} + +void BundleActiveConfigReader::LoadMaxDataSize(cJSON* root) +{ + cJSON *maxDataSizeItem = cJSON_GetObjectItem(root, MAX_DATA_SIZE); + if (!IsValidNumber(maxDataSizeItem)) { + BUNDLE_ACTIVE_LOGE("not have max data size key"); return; } - int32_t minUseDays = static_cast(minUseDaysItem->valueint); - appUsePeriodicallyConfig_ = { minUseTimes, maxUseTimes, minUseDays}; - cJSON_Delete(root); -}; + maxDataSize_ = static_cast(maxDataSizeItem->valueint); +} bool BundleActiveConfigReader::GetJsonFromFile(const char *filePath, cJSON *&root) { @@ -134,27 +193,12 @@ bool BundleActiveConfigReader::ConvertFullPath(const std::string& partialPath, s AppUsePeriodicallyConfig BundleActiveConfigReader::GetApplicationUsePeriodicallyConfig() { return appUsePeriodicallyConfig_; -}; +} -void BundleActiveConfigReader::LoadMaxDataSize(const char *filePath) +AppHighFrequencyPeriodThresholdConfig BundleActiveConfigReader::GetAppHighFrequencyPeriodThresholdConfig() { - if (!filePath) { - return; - } - cJSON *root = nullptr; - if (!GetJsonFromFile(filePath, root) || !root) { - BUNDLE_ACTIVE_LOGE("file is empty %{private}s", filePath); - return; - } - cJSON *maxDataSizeItem = cJSON_GetObjectItem(root, MAX_DATA_SIZE); - if (!maxDataSizeItem || !cJSON_IsNumber(maxDataSizeItem)) { - BUNDLE_ACTIVE_LOGE("not have max data size key"); - cJSON_Delete(root); - return; - } - maxDataSize_ = static_cast(maxDataSizeItem->valueint); - cJSON_Delete(root); -}; + return appHighFreqPeriodThresholdConfig_; +} uint64_t BundleActiveConfigReader::GetMaxDataSize() { @@ -162,7 +206,32 @@ uint64_t BundleActiveConfigReader::GetMaxDataSize() return DEFAULT_MAX_DATA_SIZE; } return maxDataSize_; -}; +} + +int32_t BundleActiveConfigReader::GetIntValue( + cJSON* root, const char* parameterName, int32_t minLimit, int32_t maxLimit, int32_t defaultValue) +{ + cJSON* item = cJSON_GetObjectItem(root, parameterName); + if (!IsValidNumber(item)) { + BUNDLE_ACTIVE_LOGE("Configuration parameter %{private}s error", parameterName); + return defaultValue; + } + int32_t value = static_cast(item->valueint); + if (value < minLimit || value > maxLimit) { + BUNDLE_ACTIVE_LOGE("Configuration parameter %{private}s is invalid value", parameterName); + return defaultValue; + } + return value; +} + +bool BundleActiveConfigReader::IsValidObject(cJSON* item) +{ + return item != nullptr && cJSON_IsObject(item); +} +bool BundleActiveConfigReader::IsValidNumber(cJSON* item) +{ + return item != nullptr && cJSON_IsNumber(item); +} } // namespace DeviceUsageStats } // namespace OHOS \ No newline at end of file diff --git a/services/common/src/bundle_active_core.cpp b/services/common/src/bundle_active_core.cpp index c1fb547..f869d2e 100644 --- a/services/common/src/bundle_active_core.cpp +++ b/services/common/src/bundle_active_core.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 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 @@ -27,6 +27,7 @@ #include "ffrt_inner.h" #include "bundle_constants.h" #include "hisysevent.h" +#include "bundle_active_high_frequency_period.h" #include "bundle_active_report_controller.h" #include "bundle_active_event_reporter.h" #include "os_account_constants.h" @@ -39,15 +40,23 @@ const int32_t DEFAULT_OS_ACCOUNT_ID = 0; // 0 is the default id when there is no constexpr int32_t BUNDLE_UNINSTALL_DELAY_TIME = 5 * 1000 * 1000; constexpr int32_t MIN_USER_ID = -1; constexpr int32_t MAX_DELETE_EVENT_DALIYS = 6; +constexpr int32_t INDEX_USE_TIME = 1; +constexpr int32_t INDEX_HOUR = 0; constexpr double DEFAULT_PERCENT_USER_SPACE_LIMIT = 0.1; static constexpr char RSS[] = "RSS"; static constexpr char FILEMANAGEMENT[] = "FILEMANAGEMENT"; static constexpr char DATA_PATH[] = "/data"; +// 用于根据使用次数对时段进行降序的数据结构 +struct ElementWithIndex { + int32_t useTimes; + int32_t originlIndex; +}; + BundleActiveReportHandlerObject::BundleActiveReportHandlerObject() { - userId_ = -1; - bundleName_ = ""; + userId_ = -1; + bundleName_ = ""; } BundleActiveReportHandlerObject::BundleActiveReportHandlerObject(const int32_t userId, const std::string bundleName) @@ -1027,6 +1036,140 @@ void BundleActiveCore::DeleteExcessiveTableData() } } } + +ErrCode BundleActiveCore::QueryHighFrequencyPeriodBundle( + std::vector& appFreqHours, int32_t userId) +{ + BUNDLE_ACTIVE_LOGD("QueryHighFrequencyPeriodBundle called"); + std::lock_guard lock(mutex_); + int64_t timeNow = CheckTimeChangeAndGetWallTime(userId); + if (timeNow == ERR_TIME_OPERATION_FAILED) { + return ERR_TIME_OPERATION_FAILED; + } + std::shared_ptr service = GetUserDataAndInitializeIfNeeded(userId, timeNow, debugCore_); + if (service == nullptr) { + return ERR_MEMORY_OPERATION_FAILED; + } + int64_t currentSystemTime = BundleActiveUtil::GetSystemTimeMs(); + int64_t aWeekAgo = currentSystemTime - ONE_WEEK_TIME; + std::vector bundleActiveEvents; + auto res = service->QueryBundleEvents(bundleActiveEvents, aWeekAgo, currentSystemTime, userId, ""); + if (res != ERR_OK) { + BUNDLE_ACTIVE_LOGE("QueryHighFrequencyPeriodBundle QueryBundleEvents fail"); + return res; + } + std::unordered_map appUsages; + // 解析前台事件,记录应用使用时段数据 + ProcessEvents(appUsages, bundleActiveEvents); + // 获取高频时段使用应用信息 + GetFreqBundleHours(appFreqHours, appUsages); + return res; +} + +void BundleActiveCore::GetFreqBundleHours(std::vector& appFreqHours, + std::unordered_map& appUsages) +{ + BUNDLE_ACTIVE_LOGD("BundleActiveCore GetFreqBundleHours appUsages size: %{public}zu", appUsages.size()); + for (auto& [appName, usage] : appUsages) { + // 统计应用一周内的使用天数 + int32_t totalDayUse = 0; + for (int32_t i = 0; i < NUM_DAY_ONE_WEEK; i++) { + if (usage.dayUsage[i] != 0) { + totalDayUse++; + } + } + // 若一周内的使用天数不满足阈值minTotalUseDays, 则判断为非周期性使用应用 + if (totalDayUse < bundleActiveConfigReader_->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays) { + continue; + } + // 统计应用每个时段 一周内的使用天数,只取满足使用天数限制的时段信息 + std::vector> topHoursUsage; + GetTopHourUsage(topHoursUsage, usage); + if (topHoursUsage.size() > 0) { + // 按使用天数降序排序 + std::sort(topHoursUsage.begin(), + topHoursUsage.end(), + [](const std::vector& hourUsageA, const std::vector &hourUsageB) { + return hourUsageA[INDEX_USE_TIME] > hourUsageB[INDEX_USE_TIME]; + }); + uint64_t maxHighFreqHourNum = static_cast( + bundleActiveConfigReader_->GetAppHighFrequencyPeriodThresholdConfig().maxHighFreqHourNum); + // 只取使用天数最多的前TOPN个时段 + if (topHoursUsage.size() > maxHighFreqHourNum) { + topHoursUsage.erase(topHoursUsage.begin() + maxHighFreqHourNum, topHoursUsage.end()); + } + std::vector hourColumn; + for (const auto& hourUsage : topHoursUsage) { + hourColumn.push_back(hourUsage[INDEX_HOUR]); + } + appFreqHours.emplace_back(appName, hourColumn); + } + } +} + +void BundleActiveCore::GetTopHourUsage( + std::vector>& topHoursUsage, BundleActiveCore::AppUsage& usage) +{ + std::vector elementsWithIndices(NUM_HOUR_ONE_DAY); + for (int32_t i = 0; i < NUM_HOUR_ONE_DAY; i++) { + elementsWithIndices[i] = {usage.hourTotalUse[i], i}; + } + sort(elementsWithIndices.begin(), + elementsWithIndices.end(), + [](const ElementWithIndex& hourUseTimeA, const ElementWithIndex& hourUseTimeB) { + return hourUseTimeA.useTimes > hourUseTimeB.useTimes; + }); + int32_t minTopUseHoursLimit = + bundleActiveConfigReader_->GetAppHighFrequencyPeriodThresholdConfig().minTopUseHoursLimit; + for (int32_t i = 0; i < minTopUseHoursLimit; i++) { + int32_t hour = elementsWithIndices[i].originlIndex; + int32_t hourUseDays = 0; + for (int32_t weekDay = 0; weekDay < NUM_DAY_ONE_WEEK; weekDay++) { + if (usage.hourUsage[weekDay][hour] > 0) { + hourUseDays++; + } + } + if (hourUseDays >= bundleActiveConfigReader_->GetAppHighFrequencyPeriodThresholdConfig().minHourUseDays) { + topHoursUsage.emplace_back(std::vector{hour, hourUseDays}); + } + } +} + +void BundleActiveCore::ProcessEvents( + std::unordered_map& appUsages, std::vector& events) +{ + BUNDLE_ACTIVE_LOGD("BundleActiveCore ProcessEvent events size: %{public}zu", events.size()); + for (size_t i = 0; i < events.size(); ++i) { + std::string bundleName = events[i].bundleName_; + if (events[i].eventId_ == BundleActiveEvent::ABILITY_FOREGROUND) { + auto [it, inserted] = appUsages.emplace(bundleName, BundleActiveCore::AppUsage()); + if (it->second.startTime == DEFAULT_INVALID_VALUE) { + it->second.startTime = events[i].timeStamp_; + } + } else if (events[i].eventId_ == BundleActiveEvent::ABILITY_BACKGROUND || + events[i].eventId_ == BundleActiveEvent::ABILITY_STOP) { + auto it = appUsages.find(bundleName); + if (it == appUsages.end() || it->second.startTime == DEFAULT_INVALID_VALUE) { + continue; + } + // 转换成以秒为单位 + const time_t timestampSeconds = it->second.startTime / 1000; + // 转换为tm结构体以获取详细信息 + std::tm* startTimeTm = std::localtime(×tampSeconds); + if (startTimeTm == nullptr) { + it->second.startTime = DEFAULT_INVALID_VALUE; + continue; + } + // 获取星期几(0=周日, 6=周六) + int32_t weekDay = startTimeTm->tm_wday; + int32_t hour = startTimeTm->tm_hour; + it->second.dayUsage[weekDay]++; + it->second.hourUsage[weekDay][hour]++; + it->second.hourTotalUse[hour]++; + it->second.startTime = DEFAULT_INVALID_VALUE; + } + } +} } // namespace DeviceUsageStats } // namespace OHOS diff --git a/services/common/src/bundle_active_service.cpp b/services/common/src/bundle_active_service.cpp index 134ffb4..a6da2d8 100644 --- a/services/common/src/bundle_active_service.cpp +++ b/services/common/src/bundle_active_service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2024 Huawei Device Co., Ltd. + * Copyright (c) 2022-2025 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 @@ -34,7 +34,6 @@ #include "xcollie/watchdog.h" #include "bundle_active_util.h" #include "bundle_active_report_controller.h" - #include "bundle_active_service.h" namespace OHOS { @@ -50,6 +49,7 @@ const int32_t EVENTS_PARAM = 5; static constexpr int32_t NO_DUMP_PARAM_NUMS = 0; const int32_t PACKAGE_USAGE_PARAM = 6; const int32_t MODULE_USAGE_PARAM = 4; +const int32_t HIGH_FREQUENCY_HOUR_USAGE_PARAM = 3; const std::string NEEDED_PERMISSION = "ohos.permission.BUNDLE_ACTIVE_INFO"; const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0); const bool REGISTER_RESULT = @@ -403,6 +403,60 @@ ErrCode BundleActiveService::QueryBundleEvents(std::vector& b return ret; } +ErrCode BundleActiveService::QueryHighFrequencyPeriodBundle( + std::vector& appFreqHours, int32_t userId) +{ + ErrCode ret = ERR_OK; + int32_t callingUid = OHOS::IPCSkeleton::GetCallingUid(); + AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + if (userId == -1) { + ret = BundleActiveAccountHelper::GetUserId(callingUid, userId); + if (ret != ERR_OK || userId == -1) { + return ret; + } + } + BUNDLE_ACTIVE_LOGI("QueryHighFrequencyPeriodBundle userid is %{public}d", userId); + ret = CheckSystemAppOrNativePermission(callingUid, tokenId); + if (ret == ERR_OK) { + ret = bundleActiveCore_->QueryHighFrequencyPeriodBundle(appFreqHours, userId); + BUNDLE_ACTIVE_LOGI("QueryHighFrequencyPeriodBundle result is %{public}zu", appFreqHours.size()); + } + return ret; +} + +ErrCode BundleActiveService::QueryBundleTodayLatestUsedTime( + int64_t& latestUsedTime, const std::string& bundleName, int32_t userId) +{ + ErrCode ret = ERR_OK; + int32_t callingUid = OHOS::IPCSkeleton::GetCallingUid(); + AccessToken::AccessTokenID tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); + if (userId == -1) { + ret = BundleActiveAccountHelper::GetUserId(callingUid, userId); + if (ret != ERR_OK || userId == -1) { + return ret; + } + } + BUNDLE_ACTIVE_LOGI("QueryBundleTodayLatestUsedTime userid is %{public}d", userId); + ret = CheckSystemAppOrNativePermission(callingUid, tokenId); + if (ret != ERR_OK) { + return ret; + } + int64_t currentSystemTime = BundleActiveUtil::GetSystemTimeMs(); + int64_t startTime = BundleActiveUtil::GetIntervalTypeStartTime(currentSystemTime, BundleActiveUtil::PERIOD_DAILY); + std::vector packageStats; + ret = bundleActiveCore_->QueryBundleStatsInfos( + packageStats, userId, BundleActiveUtil::PERIOD_DAILY, startTime, currentSystemTime, bundleName); + if (ret != ERR_OK) { + return ret; + } + auto bundleActivePackageStats = MergePackageStats(packageStats); + if (bundleActivePackageStats.empty() || bundleActivePackageStats[0].bundleName_ != bundleName) { + return ERR_NO_APP_GROUP_INFO_IN_DATABASE; + } + latestUsedTime = bundleActivePackageStats[0].lastTimeUsed_; + return ret; +} + ErrCode BundleActiveService::SetAppGroup(const std::string& bundleName, int32_t newGroup, int32_t userId) { ErrCode ret = ERR_OK; @@ -775,6 +829,8 @@ int32_t BundleActiveService::ShellDump(const std::vector &dumpOptio ret = DumpPackageUsage(dumpOption, dumpInfo); } else if (dumpOption[1] == "ModuleUsage") { ret = DumpModuleUsage(dumpOption, dumpInfo); + } else if (dumpOption[1] == "HighFreqHourUsage") { + ret = DumpHighFreqHourUsage(dumpOption, dumpInfo); } return ret; } @@ -842,6 +898,23 @@ int32_t BundleActiveService::DumpModuleUsage(const std::vector &dum return ret; } +int32_t BundleActiveService::DumpHighFreqHourUsage(const std::vector& dumpOption, + std::vector& dumpInfo) +{ + int32_t ret = -1; + if (static_cast(dumpOption.size()) != HIGH_FREQUENCY_HOUR_USAGE_PARAM) { + return ret; + } + int32_t userId = BundleActiveUtil::StringToInt64(dumpOption[2]); + std::vector appFreqHours; + ret = bundleActiveCore_->QueryHighFrequencyPeriodBundle(appFreqHours, userId); + dumpInfo.emplace_back("appFreqHour size " + std::to_string(appFreqHours.size()) + "\n"); + for (auto& appFreqHour : appFreqHours) { + dumpInfo.emplace_back(appFreqHour.ToString()); + } + return ret; +} + void BundleActiveService::DumpUsage(std::string &result) { std::string dumpHelpMsg = @@ -880,7 +953,7 @@ std::vector BundleActiveService::MergePackageStats( return tempPackageStats; } -void BundleActiveService::MergeSamePackageStats(BundleActivePackageStats &left, const BundleActivePackageStats &right) +void BundleActiveService::MergeSamePackageStats(BundleActivePackageStats& left, const BundleActivePackageStats& right) { if (left.bundleName_ != right.bundleName_) { BUNDLE_ACTIVE_LOGE("Merge package stats failed, existing packageName : %{public}s," diff --git a/test/fuzztest/bundleactivecommon_fuzzer/bundleactivecommon_fuzzer.cpp b/test/fuzztest/bundleactivecommon_fuzzer/bundleactivecommon_fuzzer.cpp index f8e3a53..b3314a5 100644 --- a/test/fuzztest/bundleactivecommon_fuzzer/bundleactivecommon_fuzzer.cpp +++ b/test/fuzztest/bundleactivecommon_fuzzer/bundleactivecommon_fuzzer.cpp @@ -43,12 +43,7 @@ namespace DeviceUsageStats { { auto bundleActiveConfigReader = std::make_shared(); std::string filePath = fdp->ConsumeRandomLengthString(); - bundleActiveConfigReader->LoadConfig(); - bundleActiveConfigReader->LoadApplicationUsePeriodically(filePath.c_str()); - bundleActiveConfigReader->LoadApplicationUsePeriodically(CONFIG_TEST1_PATH); - bundleActiveConfigReader->LoadApplicationUsePeriodically(CONFIG_TEST2_PATH); - bundleActiveConfigReader->LoadApplicationUsePeriodically(CONFIG_TEST3_PATH); - bundleActiveConfigReader->LoadApplicationUsePeriodically(CONFIG_TEST4_PATH); + bundleActiveConfigReader->LoadConfigFile(filePath.c_str()); cJSON *root = nullptr; bundleActiveConfigReader->GetJsonFromFile(filePath.c_str(), root); bundleActiveConfigReader->GetJsonFromFile(CONFIG_TEST_PATH, root); @@ -104,8 +99,9 @@ namespace DeviceUsageStats { fuzzData.RewindRead(0); MessageParcel fuzzReply; MessageOption fuzzOption; - bundleActiveService->OnRemoteRequest(fuzzCode % MAX_CODE, - fuzzData, fuzzReply, fuzzOption); + bundleActiveService->OnRemoteRequest(fuzzCode % MAX_CODE, fuzzData, fuzzReply, fuzzOption); + std::vector appFreqHours; + bundleActiveService->QueryHighFrequencyPeriodBundle(appFreqHours, userId); return true; } diff --git a/test/fuzztest/bundleactiveobserver_fuzzer/bundleactiveobserver_fuzzer.cpp b/test/fuzztest/bundleactiveobserver_fuzzer/bundleactiveobserver_fuzzer.cpp index f5aa379..187d437 100644 --- a/test/fuzztest/bundleactiveobserver_fuzzer/bundleactiveobserver_fuzzer.cpp +++ b/test/fuzztest/bundleactiveobserver_fuzzer/bundleactiveobserver_fuzzer.cpp @@ -55,8 +55,8 @@ namespace DeviceUsageStats { DelayedSingleton::GetInstance()->IsBundleIdle(result, inputBundlName, userId); DelayedSingleton::GetInstance()->IsBundleUsePeriod(result, inputBundlName, userId); DelayedSingleton::GetInstance()->GetApplicationUsePeriodicallyConfig(); - DelayedSingleton::GetInstance()->LoadApplicationUsePeriodically( - inputBundlName.c_str()); + DelayedSingleton::GetInstance()->GetAppHighFrequencyPeriodThresholdConfig(); + DelayedSingleton::GetInstance()->LoadConfigFile(inputBundlName.c_str()); return true; } @@ -80,6 +80,8 @@ namespace DeviceUsageStats { DelayedSingleton::GetInstance()->DumpPackageUsage(dumpOption, dumpInfo); dumpInfo.clear(); DelayedSingleton::GetInstance()->DumpModuleUsage(dumpOption, dumpInfo); + dumpInfo.clear(); + DelayedSingleton::GetInstance()->DumpHighFreqHourUsage(dumpOption, dumpInfo); std::string result; DelayedSingleton::GetInstance()->DumpUsage(result); return true; diff --git a/test/fuzztest/bundleactivepowerstatecallbackproxy_fuzzer/bundleactivepowerstatecallbackproxy_fuzzer.cpp b/test/fuzztest/bundleactivepowerstatecallbackproxy_fuzzer/bundleactivepowerstatecallbackproxy_fuzzer.cpp index 0a3488e..99310ef 100644 --- a/test/fuzztest/bundleactivepowerstatecallbackproxy_fuzzer/bundleactivepowerstatecallbackproxy_fuzzer.cpp +++ b/test/fuzztest/bundleactivepowerstatecallbackproxy_fuzzer/bundleactivepowerstatecallbackproxy_fuzzer.cpp @@ -133,6 +133,11 @@ namespace DeviceUsageStats { eventStats, userId); DelayedSingleton::GetInstance()->QueryNotificationEventStats(beginTime, endTime, eventStats, userId); + std::vector appFreqHours; + DelayedSingleton::GetInstance()->QueryHighFrequencyPeriodBundle(appFreqHours, userId); + int64_t latestUsedTime; + DelayedSingleton::GetInstance()->QueryBundleTodayLatestUsedTime(latestUsedTime, + bundleName, userId); return true; } diff --git a/test/resource/deviceUsage/parseconfig/device_usage_statistics_config.json b/test/resource/deviceUsage/parseconfig/device_usage_statistics_config.json index f50c21a..3acacf4 100644 --- a/test/resource/deviceUsage/parseconfig/device_usage_statistics_config.json +++ b/test/resource/deviceUsage/parseconfig/device_usage_statistics_config.json @@ -4,5 +4,11 @@ "MaxUseTimes" : 15, "MinUseDays" : 6 }, + "application_use_high_frequency_judge_threshold": { + "MinTotalUseDays" : 5, + "MinTopUseHoursLimit" : 5, + "MinHourUseDays" : 5, + "MaxHighFrequencyHourNum" : 3 + }, "MaxDataSize": 6 } \ No newline at end of file diff --git a/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test1.json b/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test1.json index a1f91f2..0cee628 100644 --- a/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test1.json +++ b/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test1.json @@ -4,5 +4,11 @@ "MaxUseTimes" : 15, "MinUseDays" : 6 }, + "application_use_high_frequency_judge_threshold": { + "MinTotalUseDays" : 8, + "MinTopUseHoursLimit" : 5, + "MinHourUseDays" : 4, + "MaxHighFrequencyHourNum" : 3 + }, "MaxDataSize": "abc" } \ No newline at end of file diff --git a/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test2.json b/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test2.json index 31145c3..37216e5 100644 --- a/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test2.json +++ b/test/resource/deviceUsage/parseconfig/device_usage_statistics_config_test2.json @@ -3,5 +3,11 @@ "MinUseTimes" : 5, "MaxUseTimes" : 15, "MinUseDays" : 6 + }, + "application_use_high_frequency_judge_threshold": { + "MinTotalUseDays" : 5, + "MinTopUseHoursLimit" : -1, + "MinHourUseDays" : 4, + "MaxHighFrequencyHourNum" : "a" } } \ No newline at end of file diff --git a/test/unittest/device_usage_statistics_mock_test.cpp b/test/unittest/device_usage_statistics_mock_test.cpp index 6f0f797..9d279cb 100644 --- a/test/unittest/device_usage_statistics_mock_test.cpp +++ b/test/unittest/device_usage_statistics_mock_test.cpp @@ -26,6 +26,7 @@ #include "bundle_active_constant.h" #include "bundle_active_usage_database.h" #include "bundle_active_test_util.h" +#include "bundle_active_high_frequency_period.h" using namespace testing::ext; @@ -114,6 +115,11 @@ HWTEST_F(DeviceUsageStatisticsMockTest, DeviceUsageStatisticsMockTest_GetBundleA std::vector moduleRecord; int32_t maxNum = 1000; EXPECT_NE(BundleActiveClient::GetInstance().QueryModuleUsageRecords(maxNum, moduleRecord, g_defaultUserId), ERR_OK); + std::vector appFreqHours; + EXPECT_NE(BundleActiveClient::GetInstance().QueryHighFrequencyPeriodBundle(appFreqHours, g_defaultUserId), ERR_OK); + int64_t latestUsedTime; + EXPECT_NE(BundleActiveClient::GetInstance().QueryBundleTodayLatestUsedTime( + latestUsedTime, g_defaultBundleName, g_commonUserid), ERR_OK); } /* @@ -461,6 +467,44 @@ HWTEST_F(DeviceUsageStatisticsMockTest, DeviceUsageStatisticsMockTest_GetBundleA std::string formName = "defaultFormName"; database->RemoveFormData(userId, bundleName, moduleName, formName, 0, 0, uid); } + +/* + * @tc.name: DeviceUsageStatisticsMockTest_QueryHighFrequencyPeriodBundle_001 + * @tc.desc: test QueryHighFrequencyPeriodBundle + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsMockTest, DeviceUsageStatisticsMockTest_QueryHighFrequencyPeriodBundle_001, + Function | MediumTest | Level0) +{ + std::vector appFreqHours; + ErrCode code = + DelayedSingleton::GetInstance()->QueryHighFrequencyPeriodBundle(appFreqHours, 0); + EXPECT_NE(code, ERR_OK); + + code = + DelayedSingleton::GetInstance()->QueryHighFrequencyPeriodBundle(appFreqHours, -1); + EXPECT_NE(code, ERR_OK); +} + +/* + * @tc.name: DeviceUsageStatisticsMockTest_QueryBundleTodayLatestUsedTime_001 + * @tc.desc: test QueryHighFrequencyPeriodBundle + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsMockTest, DeviceUsageStatisticsMockTest_QueryBundleTodayLatestUsedTime_001, + Function | MediumTest | Level0) +{ + int64_t latestUsedTime = 0; + ErrCode code = + DelayedSingleton::GetInstance()->QueryBundleTodayLatestUsedTime(latestUsedTime, "test", 0); + EXPECT_NE(code, ERR_OK); + EXPECT_EQ(latestUsedTime, 0); + code = DelayedSingleton::GetInstance()->QueryBundleTodayLatestUsedTime( + latestUsedTime, "test", -1); + EXPECT_NE(code, ERR_OK); +} } // namespace DeviceUsageStats } // namespace OHOS diff --git a/test/unittest/device_usage_statistics_service_test.cpp b/test/unittest/device_usage_statistics_service_test.cpp index f4b7655..7488493 100644 --- a/test/unittest/device_usage_statistics_service_test.cpp +++ b/test/unittest/device_usage_statistics_service_test.cpp @@ -187,6 +187,11 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_dump dumpOption = {"-A", "ModuleUsage", "1", "100"}; bundleActiveService->ShellDump(dumpOption, dumpInfo); + dumpOption.clear(); + dumpInfo.clear(); + dumpOption = {"-A", "HighFreqHourUsage", "100"}; + bundleActiveService->ShellDump(dumpOption, dumpInfo); + std::vector args; bundleActiveService->Dump(-1, args); @@ -1524,8 +1529,9 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_Conf { auto bundleActiveConfigReader = std::make_shared(); EXPECT_NE(bundleActiveConfigReader, nullptr); - const char *path = "test"; - bundleActiveConfigReader->LoadApplicationUsePeriodically(path); + cJSON* root = cJSON_CreateObject(); + bundleActiveConfigReader->LoadApplicationUsePeriodically(root); + cJSON_Delete(root); EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 0); } @@ -1643,6 +1649,77 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_GetF EXPECT_EQ(bundleUserHistory->GetFirstUseTime(bundleName, userId), 100); } +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadConfigFile_001 + * @tc.desc: LoadConfigFile + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadConfigFile_001, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + std::string path = "test"; + bundleActiveConfigReader->LoadConfigFile(path.c_str()); + EXPECT_EQ(bundleActiveConfigReader->GetMaxDataSize(), 5 * 1024 * 1024); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 0); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadConfigFile_002 + * @tc.desc: LoadConfigFile + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadConfigFile_002, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + bundleActiveConfigReader->maxDataSize_ = 1; + EXPECT_NE(bundleActiveConfigReader, nullptr); + bundleActiveConfigReader->LoadConfigFile(CONFIG_PATH); + EXPECT_EQ(bundleActiveConfigReader->GetMaxDataSize(), 6); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 5); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 5); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadConfigFile_003 + * @tc.desc: LoadConfigFile + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadConfigFile_003, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + bundleActiveConfigReader->maxDataSize_ = 1; + EXPECT_NE(bundleActiveConfigReader, nullptr); + bundleActiveConfigReader->LoadConfigFile(CONFIG_TEST1_PATH); + EXPECT_EQ(bundleActiveConfigReader->GetMaxDataSize(), 1); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 5); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 4); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadConfigFile_004 + * @tc.desc: LoadConfigFile + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadConfigFile_004, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + bundleActiveConfigReader->LoadConfigFile(nullptr); + EXPECT_EQ(bundleActiveConfigReader->GetMaxDataSize(), 5 * 1024 * 1024); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 0); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 0); +} + /* * @tc.name: DeviceUsageStatisticsServiceTest_LoadMaxDataSize_001 * @tc.desc: ConfigReader @@ -1653,11 +1730,16 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_Load Function | MediumTest | Level0) { auto bundleActiveConfigReader = std::make_shared(); - bundleActiveConfigReader->maxDataSize_ = 1; + bundleActiveConfigReader->maxDataSize_ = 0; EXPECT_NE(bundleActiveConfigReader, nullptr); - std::string path = "test"; - bundleActiveConfigReader->LoadMaxDataSize(path.c_str()); - EXPECT_EQ(bundleActiveConfigReader->maxDataSize_, 1); + cJSON* root = nullptr; + if (!bundleActiveConfigReader->GetJsonFromFile(CONFIG_PATH, root) || !root) { + cJSON_Delete(root); + FAIL() << "GetJsonFromFile failed"; + } + bundleActiveConfigReader->LoadMaxDataSize(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->maxDataSize_, 6); } /* @@ -1672,8 +1754,14 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_Load auto bundleActiveConfigReader = std::make_shared(); bundleActiveConfigReader->maxDataSize_ = 0; EXPECT_NE(bundleActiveConfigReader, nullptr); - bundleActiveConfigReader->LoadMaxDataSize(CONFIG_PATH); - EXPECT_EQ(bundleActiveConfigReader->maxDataSize_, 6); + cJSON* root = nullptr; + if (!bundleActiveConfigReader->GetJsonFromFile(CONFIG_TEST1_PATH, root) || !root) { + cJSON_Delete(root); + FAIL() << "GetJsonFromFile failed"; + } + bundleActiveConfigReader->LoadMaxDataSize(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->maxDataSize_, 0); } /* @@ -1688,24 +1776,148 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_Load auto bundleActiveConfigReader = std::make_shared(); bundleActiveConfigReader->maxDataSize_ = 0; EXPECT_NE(bundleActiveConfigReader, nullptr); - bundleActiveConfigReader->LoadMaxDataSize(CONFIG_TEST1_PATH); + cJSON* root = nullptr; + if (!bundleActiveConfigReader->GetJsonFromFile(CONFIG_TEST2_PATH, root) || !root) { + cJSON_Delete(root); + FAIL() << "GetJsonFromFile failed"; + } + bundleActiveConfigReader->LoadMaxDataSize(root); + cJSON_Delete(root); EXPECT_EQ(bundleActiveConfigReader->maxDataSize_, 0); } /* - * @tc.name: DeviceUsageStatisticsServiceTest_LoadMaxDataSize_004 + * @tc.name: DeviceUsageStatisticsServiceTest_LoadApplicationUsePeriodically_001 * @tc.desc: ConfigReader * @tc.type: FUNC - * @tc.require: issuesIC2FBU + * @tc.require: SR20250319441801 AR20250322520501 */ -HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadMaxDataSize_004, +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadApplicationUsePeriodically_001, Function | MediumTest | Level0) { auto bundleActiveConfigReader = std::make_shared(); - bundleActiveConfigReader->maxDataSize_ = 0; EXPECT_NE(bundleActiveConfigReader, nullptr); - bundleActiveConfigReader->LoadMaxDataSize(CONFIG_TEST2_PATH); - EXPECT_EQ(bundleActiveConfigReader->maxDataSize_, 0); + cJSON* root = cJSON_CreateObject(); + bundleActiveConfigReader->LoadApplicationUsePeriodically(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 0); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().maxUseTimes, 0); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseDays, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadApplicationUsePeriodically_002 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadApplicationUsePeriodically_002, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + cJSON* root = nullptr; + if (!bundleActiveConfigReader->GetJsonFromFile(CONFIG_PATH, root) || !root) { + cJSON_Delete(root); + FAIL() << "GetJsonFromFile failed"; + } + bundleActiveConfigReader->LoadApplicationUsePeriodically(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseTimes, 5); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().maxUseTimes, 15); + EXPECT_EQ(bundleActiveConfigReader->GetApplicationUsePeriodicallyConfig().minUseDays, 6); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_001 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_001, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + cJSON* root = cJSON_CreateObject(); + bundleActiveConfigReader->LoadAppHighFreqPeriodThresholdConfig(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 0); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTopUseHoursLimit, 0); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minHourUseDays, 0); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().maxHighFreqHourNum, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_002 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_002, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + cJSON* root = nullptr; + if (!bundleActiveConfigReader->GetJsonFromFile(CONFIG_PATH, root) || !root) { + cJSON_Delete(root); + FAIL() << "GetJsonFromFile failed"; + } + bundleActiveConfigReader->LoadAppHighFreqPeriodThresholdConfig(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 5); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTopUseHoursLimit, 5); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minHourUseDays, 5); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().maxHighFreqHourNum, 3); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_003 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_003, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + cJSON* root = nullptr; + if (!bundleActiveConfigReader->GetJsonFromFile(CONFIG_TEST1_PATH, root) || !root) { + cJSON_Delete(root); + FAIL() << "GetJsonFromFile failed"; + } + bundleActiveConfigReader->LoadAppHighFreqPeriodThresholdConfig(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 4); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTopUseHoursLimit, 5); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minHourUseDays, 4); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().maxHighFreqHourNum, 3); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_004 + * @tc.desc: ConfigReader + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_LoadAppHighFreqPeriodThresholdConfig_004, + Function | MediumTest | Level0) +{ + auto bundleActiveConfigReader = std::make_shared(); + EXPECT_NE(bundleActiveConfigReader, nullptr); + cJSON* root = nullptr; + if (!bundleActiveConfigReader->GetJsonFromFile(CONFIG_TEST2_PATH, root) || !root) { + cJSON_Delete(root); + FAIL() << "GetJsonFromFile failed"; + } + bundleActiveConfigReader->LoadAppHighFreqPeriodThresholdConfig(root); + cJSON_Delete(root); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTotalUseDays, 5); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minTopUseHoursLimit, 6); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().minHourUseDays, 4); + EXPECT_EQ(bundleActiveConfigReader->GetAppHighFrequencyPeriodThresholdConfig().maxHighFreqHourNum, 3); } /* @@ -1812,5 +2024,267 @@ HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_Dele EXPECT_NE(bundleActiveCore, nullptr); } +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ProcessEvents_001 + * @tc.desc: ProcessEvents + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ProcessEvents_001, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + std::vector events; + events.emplace_back(2, 1750349685948); + events.emplace_back(3, 1750349694953); + events.emplace_back(2, 1750349705944); + events.emplace_back(4, 1750349715942); + std::unordered_map appUsages; + bundleActiveCore->ProcessEvents(appUsages, events); + EXPECT_EQ(appUsages.size(), 1); + const time_t timestampSeconds = 1750349685948 / 1000; + std::tm* timeTm = std::localtime(×tampSeconds); + if (timeTm == nullptr) { + FAIL() << "localtime faild"; + } + EXPECT_EQ(appUsages[""].dayUsage[timeTm->tm_wday], 2); + EXPECT_EQ(appUsages[""].hourUsage[timeTm->tm_wday][timeTm->tm_hour], 2); + EXPECT_EQ(appUsages[""].hourTotalUse[timeTm->tm_hour], 2); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ProcessEvents_002 + * @tc.desc: ProcessEvents + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ProcessEvents_002, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + std::vector events; + events.emplace_back(1, 1750349685948); + events.emplace_back(2, 0); + events.emplace_back(1, 1750349705944); + events.emplace_back(1, 1750349715942); + std::unordered_map appUsages; + bundleActiveCore->ProcessEvents(appUsages, events); + EXPECT_EQ(appUsages.size(), 1); + const time_t timestampSeconds = 1750349685948 / 1000; + std::tm* timeTm = std::localtime(×tampSeconds); + if (timeTm == nullptr) { + FAIL() << "localtime faild"; + } + EXPECT_EQ(appUsages[""].dayUsage[timeTm->tm_wday], 0); + EXPECT_EQ(appUsages[""].hourUsage[timeTm->tm_wday][timeTm->tm_hour], 0); + EXPECT_EQ(appUsages[""].hourTotalUse[timeTm->tm_hour], 0); + EXPECT_EQ(appUsages[""].startTime, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ProcessEvents_003 + * @tc.desc: ProcessEvents + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ProcessEvents_003, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + std::vector events; + events.emplace_back(1, 1750349685948); + events.emplace_back(1, 1750349694953); + events.emplace_back(1, 1750349705944); + events.emplace_back(1, 1750349715942); + std::unordered_map appUsages; + bundleActiveCore->ProcessEvents(appUsages, events); + EXPECT_EQ(appUsages.size(), 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_ProcessEvents_004 + * @tc.desc: ProcessEvents + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_ProcessEvents_004, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + std::vector events; + events.emplace_back(1, 1750349685948); + events.emplace_back(1, 1750349694953); + events.emplace_back(1, 1750349705944); + events.emplace_back(3, 1750349715942); + std::unordered_map appUsages; + bundleActiveCore->ProcessEvents(appUsages, events); + EXPECT_EQ(appUsages.size(), 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_GetTopHourUsage_001 + * @tc.desc: GetTopHourUsage + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_GetTopHourUsage_001, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_ = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTotalUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTopUseHoursLimit = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minHourUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.maxHighFreqHourNum = 1; + std::vector> topHoursUsage; + BundleActiveCore::AppUsage appUsage = {{300, 300, 300, 300, 300, 300, 300}, + {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}}, + {7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98, 105, 112, 119, 126, 133, 140, 147, 154, 161, 168}, + 1750349685948}; + bundleActiveCore->GetTopHourUsage(topHoursUsage, appUsage); + EXPECT_EQ(topHoursUsage.size(), 1); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_GetTopHourUsage_002 + * @tc.desc: GetTopHourUsage + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_GetTopHourUsage_002, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_ = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTotalUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTopUseHoursLimit = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minHourUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.maxHighFreqHourNum = 1; + std::vector> topHoursUsage; + BundleActiveCore::AppUsage appUsage; + bundleActiveCore->GetTopHourUsage(topHoursUsage, appUsage); + EXPECT_EQ(topHoursUsage.size(), 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_GetFreqBundleHours_001 + * @tc.desc: GetFreqBundleHours + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_GetFreqBundleHours_001, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_ = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTotalUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTopUseHoursLimit = 6; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minHourUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.maxHighFreqHourNum = 1; + std::unordered_map appUsages; + BundleActiveCore::AppUsage appUsage = {{300, 300, 300, 300, 300, 300, 300}, + {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}}, + {7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98, 105, 112, 119, 126, 133, 140, 147, 154, 161, 168}, + 1750349685948}; + appUsages["bundleNameA"] = appUsage; + appUsages["bundleNameB"] = BundleActiveCore::AppUsage(); + std::vector appFreqHours; + bundleActiveCore->GetFreqBundleHours(appFreqHours, appUsages); + EXPECT_EQ(appFreqHours.size(), 1); + EXPECT_EQ(appFreqHours[0].bundleName_, "bundleNameA"); + EXPECT_EQ(appFreqHours[0].highFreqHours_.size(), 1); + EXPECT_EQ(appFreqHours[0].highFreqHours_[0], 23); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_GetFreqBundleHours_002 + * @tc.desc: GetFreqBundleHours + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_GetFreqBundleHours_002, + Function | MediumTest | Level0) +{ + auto bundleActiveCore = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_ = std::make_shared(); + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTotalUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minTopUseHoursLimit = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.minHourUseDays = 1; + bundleActiveCore->bundleActiveConfigReader_->appHighFreqPeriodThresholdConfig_.maxHighFreqHourNum = 1; + std::unordered_map appUsages; + appUsages["bundleNameA"] = BundleActiveCore::AppUsage(); + appUsages["bundleNameB"] = BundleActiveCore::AppUsage(); + std::vector appFreqHours; + bundleActiveCore->GetFreqBundleHours(appFreqHours, appUsages); + EXPECT_EQ(appFreqHours.size(), 0); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_DumpHighFreqHourUsage_001 + * @tc.desc: DumpHighFreqHourUsage + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_DumpHighFreqHourUsage_001, + Function | MediumTest | Level0) +{ + auto bundleActiveService = std::make_shared(); + std::vector dumpOption = {"option1", "option2"}; + std::vector dumpInfo; + int32_t result = bundleActiveService->DumpHighFreqHourUsage(dumpOption, dumpInfo); + EXPECT_EQ(result, -1); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_DumpHighFreqHourUsage_002 + * @tc.desc: DumpHighFreqHourUsage + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_DumpHighFreqHourUsage_002, + Function | MediumTest | Level0) +{ + auto bundleActiveService = std::make_shared(); + bundleActiveService->bundleActiveCore_ = std::make_shared(); + std::vector dumpOption = {"option1", "option2", "0"}; + std::vector dumpInfo; + + int32_t result = bundleActiveService->DumpHighFreqHourUsage(dumpOption, dumpInfo); + EXPECT_EQ(result, 0); + EXPECT_EQ(dumpInfo.size(), 1); + EXPECT_EQ(dumpInfo[0], "appFreqHour size 0\n"); +} + +/* + * @tc.name: DeviceUsageStatisticsServiceTest_QueryBundleTodayLatestUsedTime_001 + * @tc.desc: QueryBundleTodayLatestUsedTime + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsServiceTest, DeviceUsageStatisticsServiceTest_QueryBundleTodayLatestUsedTime_001, + Function | MediumTest | Level0) +{ + auto bundleActiveService = std::make_shared(); + bundleActiveService->bundleActiveCore_ = std::make_shared(); + int64_t latestUsedTime = 0; + ErrCode result = bundleActiveService->QueryBundleTodayLatestUsedTime(latestUsedTime, "testBundleName", -1); + EXPECT_NE(result, 0); + EXPECT_EQ(latestUsedTime, 0); + result = bundleActiveService->QueryBundleTodayLatestUsedTime(latestUsedTime, "testBundleName", 100); + EXPECT_NE(result, 0); + EXPECT_EQ(latestUsedTime, 0); +} } // namespace DeviceUsageStats } // namespace OHOS \ No newline at end of file diff --git a/test/unittest/device_usage_statistics_test.cpp b/test/unittest/device_usage_statistics_test.cpp index 62e03d4..1e1bc01 100644 --- a/test/unittest/device_usage_statistics_test.cpp +++ b/test/unittest/device_usage_statistics_test.cpp @@ -34,6 +34,7 @@ #include "token_setproc.h" #include "nativetoken_kit.h" #include "bundle_active_test_util.h" +#include "bundle_active_high_frequency_period.h" using namespace testing::ext; @@ -590,6 +591,130 @@ HWTEST_F(DeviceUsageStatisticsTest, DeviceUsageStatisticsTest_AppGroupCallbackSt data1.WriteInterfaceToken(AppGroupCallbackStub::GetDescriptor()); EXPECT_EQ(appGroupCallbackStub->OnRemoteRequest(1, data1, reply, option), 5); } + +/* + * @tc.name: DeviceUsageStatisticsTest_QueryHighFrequencyPeriodBundle_001 + * @tc.desc: QueryHighFrequencyPeriodBundle + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsTest, DeviceUsageStatisticsTest_QueryHighFrequencyPeriodBundle_001, + Function | MediumTest | Level0) +{ + std::vector appFreqHours; + ErrCode ret = BundleActiveClient::GetInstance().QueryHighFrequencyPeriodBundle( + appFreqHours, g_defaultFormId); + EXPECT_EQ(ret, 0); + EXPECT_EQ(appFreqHours.size(), 0); + ret = BundleActiveClient::GetInstance().QueryHighFrequencyPeriodBundle( + appFreqHours, g_commonUserid); + EXPECT_EQ(ret, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsTest__QueryBundleTodayLatestUsedTime_001 + * @tc.desc: _QueryBundleTodayLatestUsedTime + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsTest, DeviceUsageStatisticsTest_QueryBundleTodayLatestUsedTime_001, + Function | MediumTest | Level0) +{ + int64_t latestUsedTime = 0; + ErrCode ret = BundleActiveClient::GetInstance().QueryBundleTodayLatestUsedTime( + latestUsedTime, g_defaultFormName, g_commonUserid); + EXPECT_NE(ret, 0); + EXPECT_EQ(latestUsedTime, 0); +} + +/* + * @tc.name: DeviceUsageStatisticsTest__BundleActiveHighFrequencyPeriod_001 + * @tc.desc: BundleActiveHighFrequencyPeriod + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsTest, DeviceUsageStatisticsTest_BundleActiveHighFrequencyPeriod_001, + Function | MediumTest | Level0) +{ + BundleActiveHighFrequencyPeriod originalBundle; + std::vector highFreqHour; + highFreqHour.push_back(1); + originalBundle.bundleName_ = g_defaultFormName; + originalBundle.highFreqHours_ = highFreqHour; + EXPECT_EQ(originalBundle.bundleName_, g_defaultFormName); + + BundleActiveHighFrequencyPeriod copy(originalBundle); + EXPECT_EQ(copy.bundleName_, originalBundle.bundleName_); + + BundleActiveHighFrequencyPeriod withPara(g_defaultFormName, highFreqHour); + EXPECT_EQ(withPara.bundleName_, g_defaultFormName); +} + +/* + * @tc.name: DeviceUsageStatisticsTest__BundleActiveHighFrequencyPeriod_002 + * @tc.desc: BundleActiveHighFrequencyPeriod + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsTest, DeviceUsageStatisticsTest_BundleActiveHighFrequencyPeriod_002, + Function | MediumTest | Level0) +{ + BundleActiveHighFrequencyPeriod testShall; + MessageParcel parcel1; + EXPECT_TRUE(testShall.Marshalling(parcel1)); + EXPECT_NE(testShall.Unmarshalling(parcel1), nullptr); + + MessageParcel parcel2; + testShall.bundleName_ = g_defaultFormName; + testShall.highFreqHours_.push_back(1); + EXPECT_TRUE(testShall.Marshalling(parcel2)); + EXPECT_NE(testShall.Unmarshalling(parcel2), nullptr); + + MessageParcel parcel3; + parcel3.WriteString(g_defaultFormName); + parcel3.WriteUint32(3); + parcel3.WriteInt32(1); + parcel3.WriteInt32(2); + EXPECT_EQ(testShall.Unmarshalling(parcel3), nullptr); + + MessageParcel parcel4; + parcel4.WriteString(g_defaultFormName); + parcel4.WriteUint32(2); + parcel4.WriteInt32(1); + parcel4.WriteInt32(2); + EXPECT_NE(testShall.Unmarshalling(parcel4), nullptr); + + MessageParcel parcel5; + parcel5.WriteString(g_defaultFormName); + parcel5.WriteUint32(25); + parcel5.WriteInt32(1); + parcel5.WriteInt32(2); + EXPECT_EQ(testShall.Unmarshalling(parcel5), nullptr); + + MessageParcel parcel6; + testShall.highFreqHours_.resize(25); + EXPECT_FALSE(testShall.Marshalling(parcel6)); +} + +/* + * @tc.name: DeviceUsageStatisticsTest__BundleActiveHighFrequencyPeriod_003 + * @tc.desc: BundleActiveHighFrequencyPeriod + * @tc.type: FUNC + * @tc.require: SR20250319441801 AR20250322520501 + */ +HWTEST_F(DeviceUsageStatisticsTest, DeviceUsageStatisticsTest_BundleActiveHighFrequencyPeriod_003, + Function | MediumTest | Level0) +{ + BundleActiveHighFrequencyPeriod originalBundle; + EXPECT_EQ(originalBundle.ToString(), "bundle name is , highFreqHours_ is \n"); + + originalBundle.bundleName_ = "test"; + originalBundle.highFreqHours_.push_back(1); + EXPECT_EQ(originalBundle.ToString(), "bundle name is test, highFreqHours_ is 1\n"); + + originalBundle.highFreqHours_.push_back(2); + EXPECT_EQ(originalBundle.ToString(), "bundle name is test, highFreqHours_ is 1, 2\n"); +} } // namespace DeviceUsageStats } // namespace OHOS -- Gitee