From 7ba5d356bbe36a27c538c6c5e9e2e7d6223d9472 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 14:59:16 +0800 Subject: [PATCH 01/20] feat: add extension running timeout monitor Add monitoring for extension abilities that exceed configured running timeout thresholds. When an extension terminates or is periodically checked while still alive, if its running duration exceeds the configured timeout, the event is cached (up to 5 entries with deduplication by extensionType+bundleName+abilityName) and reported via HiSysEvent every 2 hours. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I5647cb20121ef4c451fd45c11256e5e089185f1d --- hisysevent.yaml | 11 +- services/abilitymgr/abilitymgr.gni | 1 + .../abilitymgr/include/extension_config.h | 4 + .../extension_record_manager.h | 1 + .../extension_running_timeout_monitor.h | 98 ++++++ .../resource/ams_extension_config.json | 15 +- .../src/ability_connect_manager.cpp | 22 ++ services/abilitymgr/src/extension_config.cpp | 26 ++ .../extension_record_manager.cpp | 20 ++ .../src/extension_running_timeout_monitor.cpp | 301 ++++++++++++++++++ 10 files changed, 496 insertions(+), 3 deletions(-) create mode 100644 services/abilitymgr/include/extension_running_timeout_monitor.h create mode 100644 services/abilitymgr/src/extension_running_timeout_monitor.cpp diff --git a/hisysevent.yaml b/hisysevent.yaml index d470abb457..c7b8ca4c07 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -511,4 +511,13 @@ USER_DATA_SIZE: PARTITION_NAME: {type: STRING, desc: name of partition} REMAIN_PARTITION_SIZE: {type: UINT64, desc: Remaining size of the partition} FILE_OR_FOLDER_PATH: {type: STRING, arrsize: 100, desc: File or folder path} - FILE_OR_FOLDER_SIZE: {type: UINT64, arrsize: 100, desc: File or folder size} \ No newline at end of file + FILE_OR_FOLDER_SIZE: {type: UINT64, arrsize: 100, desc: File or folder size} + +EXTENSION_RUNNING_TIMEOUT: + __BASE: {type: STATISTIC, level: MINOR, tag: STABILITY, desc: extension ability running timeout} + EXTENSION_TYPE: {type: INT32_ARRAY, desc: extension type list} + BUNDLE_NAME: {type: STRING_ARRAY, desc: bundle name list} + ABILITY_NAME: {type: STRING_ARRAY, desc: ability name list} + RUNNING_DURATION: {type: INT32_ARRAY, desc: running duration list in seconds} + STILL_ALIVE: {type: INT32_ARRAY, desc: still alive flag list} + CNT: {type: INT32_ARRAY, desc: occurrence count list} \ No newline at end of file diff --git a/services/abilitymgr/abilitymgr.gni b/services/abilitymgr/abilitymgr.gni index ea03342605..cc1e278a1a 100644 --- a/services/abilitymgr/abilitymgr.gni +++ b/services/abilitymgr/abilitymgr.gni @@ -48,6 +48,7 @@ abilityms_files = [ "src/extension_running_info.cpp", "src/extension_record/base_extension_record.cpp", "src/extension_record/extension_record_manager.cpp", + "src/extension_running_timeout_monitor.cpp", "src/extension_record/extension_record.cpp", "src/extension_record/extension_record_factory.cpp", "src/foreground_app_connection_manager/foreground_app_connection_manager.cpp", diff --git a/services/abilitymgr/include/extension_config.h b/services/abilitymgr/include/extension_config.h index ce038447af..c2e3c1b679 100644 --- a/services/abilitymgr/include/extension_config.h +++ b/services/abilitymgr/include/extension_config.h @@ -29,6 +29,7 @@ namespace OHOS { namespace AAFwk { constexpr static int32_t DEFAULT_EXTENSION_AUTO_DISCONNECT_TIME = -1; +constexpr static int32_t DEFAULT_EXTENSION_RUNNING_TIMEOUT_TIME = -1; constexpr static bool EXTENSION_NETWORK_ENABLE_FLAG_DEFAULT = true; constexpr static bool EXTENSION_SA_ENABLE_FLAG_DEFAULT = true; constexpr static bool EXTENSION_THIRD_PARTY_APP_ENABLE_FLAG_DEFAULT = true; @@ -55,6 +56,7 @@ struct ExtensionConfigItem { bool thirdPartyAppEnableFlag = EXTENSION_THIRD_PARTY_APP_ENABLE_FLAG_DEFAULT; bool serviceEnableFlag = EXTENSION_START_SERVICE_ENABLE_FLAG_DEFAULT; int32_t extensionAutoDisconnectTime = DEFAULT_EXTENSION_AUTO_DISCONNECT_TIME; + int32_t extensionRunningTimeoutTime = DEFAULT_EXTENSION_RUNNING_TIMEOUT_TIME; std::unordered_set serviceBlockedList; ScreenUnlockAccessItem screenUnlockAccess; AbilityAccessItem abilityAccess; @@ -67,6 +69,7 @@ public: virtual ~ExtensionConfig() = default; void LoadExtensionConfiguration(); int32_t GetExtensionAutoDisconnectTime(const std::string &extensionTypeName); + int32_t GetExtensionRunningTimeoutTime(const std::string &extensionTypeName); bool IsExtensionStartThirdPartyAppEnable(const std::string &extensionTypeName); bool IsExtensionStartServiceEnable(const std::string &extensionTypeName, const std::string &targetUri); bool HasAbilityAccess(const std::string &extensionTypeName); @@ -88,6 +91,7 @@ private: std::string GetExtensionConfigPath() const; void LoadExtensionAutoDisconnectTime(const nlohmann::json &object, const std::string &extensionTypeName); + void LoadExtensionRunningTimeoutTime(const nlohmann::json &object, const std::string &extensionTypeName); void LoadExtensionThirdPartyAppBlockedList(const nlohmann::json &object, std::string extensionTypeName); void LoadExtensionServiceBlockedList(const nlohmann::json &object, std::string extensionTypeNameobject); void LoadExtensionNetworkEnable(const nlohmann::json &object, const std::string &extensionTypeName); diff --git a/services/abilitymgr/include/extension_record/extension_record_manager.h b/services/abilitymgr/include/extension_record/extension_record_manager.h index 2dbb5acff8..159e16e64c 100644 --- a/services/abilitymgr/include/extension_record/extension_record_manager.h +++ b/services/abilitymgr/include/extension_record/extension_record_manager.h @@ -25,6 +25,7 @@ #include "base_extension_record.h" #include "extension_record.h" +#include "extension_running_timeout_monitor.h" #include "preload_ui_extension_execute_callback_interface.h" #include "ui_extension/ui_extension_host_info.h" #include "ui_extension/ui_extension_session_info.h" diff --git a/services/abilitymgr/include/extension_running_timeout_monitor.h b/services/abilitymgr/include/extension_running_timeout_monitor.h new file mode 100644 index 0000000000..e4a6df2009 --- /dev/null +++ b/services/abilitymgr/include/extension_running_timeout_monitor.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2026 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 OHOS_ABILITY_RUNTIME_EXTENSION_RUNNING_TIMEOUT_MONITOR_H +#define OHOS_ABILITY_RUNTIME_EXTENSION_RUNNING_TIMEOUT_MONITOR_H + +#include +#include +#include +#include + +#include "singleton.h" + +namespace OHOS { +namespace AAFwk { + +struct ExtensionTimeoutEvent { + int32_t extensionType = -1; + std::string bundleName; + std::string abilityName; + int32_t runningDuration = 0; // seconds + bool stillAlive = false; + int32_t cnt = 1; +}; + +class ExtensionRunningTimeoutMonitor : public DelayedSingleton { + DECLARE_DELAYED_SINGLETON(ExtensionRunningTimeoutMonitor) +public: + /** + * @brief Called when an extension ability starts. Records start time. + */ + void OnExtensionStarted(int32_t extensionRecordId, const std::string &extensionTypeName, + int32_t extensionType, const std::string &bundleName, const std::string &abilityName); + + /** + * @brief Called when an extension ability ends. Checks if it exceeded configured timeout. + */ + void OnExtensionTerminated(int32_t extensionRecordId); + + /** + * @brief Start the periodic report and check timer. Called during service init. + */ + void StartMonitor(); + + /** + * @brief Stop the periodic report and check timer. + */ + void StopMonitor(); + + /** + * @brief Report cached timeout events via HiSysEvent and clear cache. + */ + void ReportTimeoutEvents(); + + /** + * @brief Proactively check all currently alive extensions for timeout violations. + * Adds detected violations to the cached events list. + */ + void CheckAliveExtensions(); + +private: + struct ExtensionStartInfo { + int32_t extensionType = -1; + std::string extensionTypeName; + std::string bundleName; + std::string abilityName; + int64_t startTimeMillis = 0; + }; + + void AddOrUpdateTimeoutEvent(const ExtensionTimeoutEvent &event); + bool IsDuplicateEvent(const ExtensionTimeoutEvent &event, + std::list::iterator &dupIter); + void SubmitPeriodicTask(); + + std::mutex monitorMutex_; + std::unordered_map runningExtensions_; + std::list cachedEvents_; + + static constexpr int32_t MAX_CACHED_EVENTS = 5; + static constexpr int64_t REPORT_INTERVAL_MS = 2 * 60 * 60 * 1000; // 2 hours + static constexpr const char *PERIODIC_TASK_NAME = "ExtensionTimeoutPeriodicTask"; +}; + +} // namespace AAFwk +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_EXTENSION_RUNNING_TIMEOUT_MONITOR_H diff --git a/services/abilitymgr/resource/ams_extension_config.json b/services/abilitymgr/resource/ams_extension_config.json index 6b881c5a0c..4271cfaef3 100644 --- a/services/abilitymgr/resource/ams_extension_config.json +++ b/services/abilitymgr/resource/ams_extension_config.json @@ -1,3 +1,14 @@ { - "ams_extension_config": [] -} \ No newline at end of file + "ams_extension_config": [ + { + "extension_type_name": "service", + "auto_disconnect_time": -1, + "running_timeout_time": 7200 + }, + { + "extension_type_name": "dataShare", + "auto_disconnect_time": -1, + "running_timeout_time": 1800 + } + ] +} diff --git a/services/abilitymgr/src/ability_connect_manager.cpp b/services/abilitymgr/src/ability_connect_manager.cpp index 81f1f2a530..5988ae349c 100644 --- a/services/abilitymgr/src/ability_connect_manager.cpp +++ b/services/abilitymgr/src/ability_connect_manager.cpp @@ -29,6 +29,7 @@ #include "cache_extension_utils.h" #include "datetime_ex.h" #include "extension_ability_info.h" +#include "extension_running_timeout_monitor.h" #include "foreground_app_connection_manager.h" #include "global_constant.h" #include "hitrace_meter.h" @@ -283,6 +284,15 @@ int AbilityConnectManager::StopServiceAbilityLocked(const AbilityRequest &abilit void AbilityConnectManager::RemoveServiceFromMapSafe(const std::string &serviceKey) { std::lock_guard lock(serviceMapMutex_); + auto it = serviceMap_.find(serviceKey); + if (it != serviceMap_.end() && it->second != nullptr) { + auto &abilityInfo = it->second->GetAbilityInfo(); + auto recordId = static_cast(std::hash{}(serviceKey)); + auto monitor = DelayedSingleton::GetInstance(); + if (monitor != nullptr) { + monitor->OnExtensionTerminated(recordId); + } + } serviceMap_.erase(serviceKey); TAG_LOGD(AAFwkTag::EXT, "ServiceMap remove, size:%{public}zu", serviceMap_.size()); } @@ -3245,6 +3255,18 @@ void AbilityConnectManager::GetOrCreateServiceRecord(const AbilityRequest &abili SetServiceAfterNewCreate(abilityRequest, *targetService); AddToServiceMap(serviceKey, targetService); isLoadedAbility = false; + + // Notify running timeout monitor about service extension start + auto &newAbilityInfo = abilityRequest.abilityInfo; + auto recordId = static_cast(std::hash{}(serviceKey)); + auto monitor = DelayedSingleton::GetInstance(); + if (monitor != nullptr) { + monitor->OnExtensionStarted(recordId, + newAbilityInfo.extensionTypeName, + static_cast(newAbilityInfo.extensionAbilityType), + newAbilityInfo.bundleName, + newAbilityInfo.name); + } } TAG_LOGD(AAFwkTag::EXT, "service map add, serviceKey: %{public}s", serviceKey.c_str()); } diff --git a/services/abilitymgr/src/extension_config.cpp b/services/abilitymgr/src/extension_config.cpp index c88662809a..1484d3f5b4 100644 --- a/services/abilitymgr/src/extension_config.cpp +++ b/services/abilitymgr/src/extension_config.cpp @@ -30,6 +30,7 @@ constexpr const char* EXTENSION_CONFIG_FILE_PATH = "/etc/ams_extension_config.js constexpr const char* EXTENSION_CONFIG_NAME = "ams_extension_config"; constexpr const char* EXTENSION_TYPE_NAME = "extension_type_name"; constexpr const char* EXTENSION_AUTO_DISCONNECT_TIME = "auto_disconnect_time"; +constexpr const char* EXTENSION_RUNNING_TIMEOUT_TIME = "running_timeout_time"; // old access flag, deprecated constexpr const char* EXTENSION_THIRD_PARTY_APP_BLOCKED_FLAG_NAME = "third_party_app_blocked_flag"; @@ -128,6 +129,7 @@ void ExtensionConfig::LoadExtensionConfig(const nlohmann::json &object) std::lock_guard lock(configMapMutex_); std::string extensionTypeName = jsonObject.at(EXTENSION_TYPE_NAME).get(); LoadExtensionAutoDisconnectTime(jsonObject, extensionTypeName); + LoadExtensionRunningTimeoutTime(jsonObject, extensionTypeName); bool hasAbilityAccess = LoadExtensionAbilityAccess(jsonObject, extensionTypeName); if (!hasAbilityAccess) { LoadExtensionThirdPartyAppBlockedList(jsonObject, extensionTypeName); @@ -151,6 +153,30 @@ void ExtensionConfig::LoadExtensionAutoDisconnectTime(const nlohmann::json &obje configMap_[extensionTypeName].extensionAutoDisconnectTime = extensionAutoDisconnectTime; } +void ExtensionConfig::LoadExtensionRunningTimeoutTime(const nlohmann::json &object, + const std::string &extensionTypeName) +{ + if (!object.contains(EXTENSION_RUNNING_TIMEOUT_TIME) || + !object.at(EXTENSION_RUNNING_TIMEOUT_TIME).is_number()) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "running timeout time config not set for %{public}s", + extensionTypeName.c_str()); + return; + } + int32_t extensionRunningTimeoutTime = object.at(EXTENSION_RUNNING_TIMEOUT_TIME).get(); + configMap_[extensionTypeName].extensionRunningTimeoutTime = extensionRunningTimeoutTime; + TAG_LOGI(AAFwkTag::ABILITYMGR, "extension %{public}s running timeout time: %{public}d ms", + extensionTypeName.c_str(), extensionRunningTimeoutTime); +} + +int32_t ExtensionConfig::GetExtensionRunningTimeoutTime(const std::string &extensionTypeName) +{ + std::lock_guard lock(configMapMutex_); + if (configMap_.find(extensionTypeName) != configMap_.end()) { + return configMap_[extensionTypeName].extensionRunningTimeoutTime; + } + return DEFAULT_EXTENSION_RUNNING_TIMEOUT_TIME; +} + void ExtensionConfig::LoadExtensionThirdPartyAppBlockedList(const nlohmann::json &object, std::string extensionTypeName) { diff --git a/services/abilitymgr/src/extension_record/extension_record_manager.cpp b/services/abilitymgr/src/extension_record/extension_record_manager.cpp index 506941d91d..c9df4f1b68 100644 --- a/services/abilitymgr/src/extension_record/extension_record_manager.cpp +++ b/services/abilitymgr/src/extension_record/extension_record_manager.cpp @@ -17,6 +17,7 @@ #include "ability_util.h" #include "app_utils.h" +#include "extension_running_timeout_monitor.h" #include "preload_ui_extension_execute_callback_proxy.h" #include "preload_ui_extension_host_client.h" #include "ui_extension_record.h" @@ -89,6 +90,19 @@ void ExtensionRecordManager::AddExtensionRecord(const int32_t extensionRecordId, TAG_LOGD(AAFwkTag::ABILITYMGR, "extensionRecordId %{public}d.", extensionRecordId); std::lock_guard lock(mutex_); extensionRecords_.emplace(extensionRecordId, record); + + // Notify running timeout monitor about extension start + if (record != nullptr && record->abilityRecord_ != nullptr) { + auto &abilityInfo = record->abilityRecord_->GetAbilityInfo(); + auto monitor = DelayedSingleton::GetInstance(); + if (monitor != nullptr) { + monitor->OnExtensionStarted(extensionRecordId, + abilityInfo.extensionTypeName, + static_cast(abilityInfo.extensionAbilityType), + abilityInfo.bundleName, + abilityInfo.name); + } + } } void ExtensionRecordManager::RemoveExtensionRecord(const int32_t extensionRecordId) @@ -97,6 +111,12 @@ void ExtensionRecordManager::RemoveExtensionRecord(const int32_t extensionRecord std::lock_guard lock(mutex_); extensionRecords_.erase(extensionRecordId); terminateRecords_.erase(extensionRecordId); + + // Notify running timeout monitor about extension termination + auto monitor = DelayedSingleton::GetInstance(); + if (monitor != nullptr) { + monitor->OnExtensionTerminated(extensionRecordId); + } } void ExtensionRecordManager::AddExtensionRecordToTerminatedList(const int32_t extensionRecordId) diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp new file mode 100644 index 0000000000..661a24bd2e --- /dev/null +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2026 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 "extension_running_timeout_monitor.h" + +#include +#include + +#include "extension_config.h" +#include "hisysevent_report.h" +#include "hilog_tag_wrapper.h" +#include "task_handler_wrap.h" + +namespace OHOS { +namespace AAFwk { +namespace { +constexpr const char *DOMAIN = "AAFWK"; +constexpr const char *EVENT_NAME = "EXTENSION_RUNNING_TIMEOUT"; +constexpr const char *EXTENSION_TYPE_KEY = "EXTENSION_TYPE"; +constexpr const char *BUNDLE_NAME_KEY = "BUNDLE_NAME"; +constexpr const char *ABILITY_NAME_KEY = "ABILITY_NAME"; +constexpr const char *RUNNING_DURATION_KEY = "RUNNING_DURATION"; +constexpr const char *STILL_ALIVE_KEY = "STILL_ALIVE"; +constexpr const char *CNT_KEY = "CNT"; +} + +ExtensionRunningTimeoutMonitor::ExtensionRunningTimeoutMonitor() {} + +ExtensionRunningTimeoutMonitor::~ExtensionRunningTimeoutMonitor() {} + +void ExtensionRunningTimeoutMonitor::OnExtensionStarted(int32_t extensionRecordId, + const std::string &extensionTypeName, int32_t extensionType, + const std::string &bundleName, const std::string &abilityName) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, + "recordId: %{public}d, type: %{public}s, bundle: %{public}s, ability: %{public}s", + extensionRecordId, extensionTypeName.c_str(), bundleName.c_str(), abilityName.c_str()); + + auto now = std::chrono::steady_clock::now(); + auto startTimeMillis = + std::chrono::duration_cast(now.time_since_epoch()).count(); + + ExtensionStartInfo info; + info.extensionType = extensionType; + info.extensionTypeName = extensionTypeName; + info.bundleName = bundleName; + info.abilityName = abilityName; + info.startTimeMillis = startTimeMillis; + + std::lock_guard lock(monitorMutex_); + runningExtensions_[extensionRecordId] = info; +} + +void ExtensionRunningTimeoutMonitor::OnExtensionTerminated(int32_t extensionRecordId) +{ + TAG_LOGD(AAFwkTag::ABILITYMGR, "recordId: %{public}d", extensionRecordId); + + ExtensionStartInfo startInfo; + { + std::lock_guard lock(monitorMutex_); + auto it = runningExtensions_.find(extensionRecordId); + if (it == runningExtensions_.end()) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "recordId %{public}d not found in running list", + extensionRecordId); + return; + } + startInfo = it->second; + runningExtensions_.erase(it); + } + + // Get configured timeout for this extension type + int32_t configuredTimeout = DelayedSingleton::GetInstance()-> + GetExtensionRunningTimeoutTime(startInfo.extensionTypeName); + if (configuredTimeout <= 0) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "no timeout configured for type %{public}s, skip", + startInfo.extensionTypeName.c_str()); + return; + } + + auto now = std::chrono::steady_clock::now(); + auto nowMillis = std::chrono::duration_cast(now.time_since_epoch()).count(); + int64_t runningDurationMs = nowMillis - startInfo.startTimeMillis; + int32_t runningDurationSec = static_cast(runningDurationMs / 1000); + + // runningDuration <= configuredTimeout means within limit, do not track + if (runningDurationSec <= configuredTimeout) { + TAG_LOGD(AAFwkTag::ABILITYMGR, + "extension %{public}s/%{public}s within timeout, duration: %{public}ds, limit: %{public}ds", + startInfo.bundleName.c_str(), startInfo.abilityName.c_str(), + runningDurationSec, configuredTimeout); + return; + } + + TAG_LOGI(AAFwkTag::ABILITYMGR, + "extension %{public}s/%{public}s exceeded timeout, duration: %{public}ds, limit: %{public}ds", + startInfo.bundleName.c_str(), startInfo.abilityName.c_str(), + runningDurationSec, configuredTimeout); + + ExtensionTimeoutEvent event; + event.extensionType = startInfo.extensionType; + event.bundleName = startInfo.bundleName; + event.abilityName = startInfo.abilityName; + event.runningDuration = runningDurationSec; + event.stillAlive = false; + event.cnt = 1; + + std::lock_guard lock(monitorMutex_); + AddOrUpdateTimeoutEvent(event); +} + +void ExtensionRunningTimeoutMonitor::StartMonitor() +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "start extension running timeout monitor"); + SubmitPeriodicTask(); +} + +void ExtensionRunningTimeoutMonitor::StopMonitor() +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "stop extension running timeout monitor"); + auto taskHandler = TaskHandlerWrap::GetFfrtHandler(); + if (taskHandler != nullptr) { + taskHandler->CancelTask(PERIODIC_TASK_NAME); + } +} + +void ExtensionRunningTimeoutMonitor::SubmitPeriodicTask() +{ + auto taskHandler = TaskHandlerWrap::GetFfrtHandler(); + if (taskHandler == nullptr) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "failed to get ffrt handler"); + return; + } + + auto task = [this]() { + TAG_LOGI(AAFwkTag::ABILITYMGR, "extension timeout periodic task triggered"); + CheckAliveExtensions(); + ReportTimeoutEvents(); + // Re-submit for next cycle + SubmitPeriodicTask(); + }; + taskHandler->SubmitTask(task, PERIODIC_TASK_NAME, REPORT_INTERVAL_MS); +} + +void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() +{ + std::list eventsToReport; + { + std::lock_guard lock(monitorMutex_); + if (cachedEvents_.empty()) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "no timeout events to report"); + return; + } + eventsToReport = cachedEvents_; + cachedEvents_.clear(); + } + + // Build arrays for HiSysEvent + std::vector extensionTypes; + std::vector bundleNamePtrs; + std::vector abilityNamePtrs; + std::vector runningDurations; + std::vector stillAliveFlags; + std::vector cnts; + + // Keep string references alive until report completes + std::vector bundleNames; + std::vector abilityNames; + + bundleNames.reserve(eventsToReport.size()); + abilityNames.reserve(eventsToReport.size()); + extensionTypes.reserve(eventsToReport.size()); + runningDurations.reserve(eventsToReport.size()); + stillAliveFlags.reserve(eventsToReport.size()); + cnts.reserve(eventsToReport.size()); + + for (const auto &event : eventsToReport) { + extensionTypes.push_back(event.extensionType); + bundleNames.push_back(event.bundleName); + abilityNames.push_back(event.abilityName); + runningDurations.push_back(event.runningDuration); + stillAliveFlags.push_back(event.stillAlive ? 1 : 0); + cnts.push_back(event.cnt); + } + for (auto &name : bundleNames) { + bundleNamePtrs.push_back(const_cast(name.c_str())); + } + for (auto &name : abilityNames) { + abilityNamePtrs.push_back(const_cast(name.c_str())); + } + + auto paramCount = static_cast(6 + eventsToReport.size()); + HisyseventReport report(paramCount); + report.InsertParam(EXTENSION_TYPE_KEY, extensionTypes); + report.InsertParam(BUNDLE_NAME_KEY, bundleNamePtrs); + report.InsertParam(ABILITY_NAME_KEY, abilityNamePtrs); + report.InsertParam(RUNNING_DURATION_KEY, runningDurations); + report.InsertParam(STILL_ALIVE_KEY, stillAliveFlags); + report.InsertParam(CNT_KEY, cnts); + int32_t ret = report.Report(DOMAIN, EVENT_NAME, HISYSEVENT_STATISTIC); + TAG_LOGI(AAFwkTag::ABILITYMGR, "reported %{public}zu timeout events, ret: %{public}d", + eventsToReport.size(), ret); +} + +void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() +{ + TAG_LOGI(AAFwkTag::ABILITYMGR, "check alive extensions for timeout violations"); + + // Copy the running extensions map to avoid holding mutex during slow checks + std::unordered_map aliveCopy; + { + std::lock_guard lock(monitorMutex_); + aliveCopy = runningExtensions_; + } + + auto now = std::chrono::steady_clock::now(); + auto nowMillis = std::chrono::duration_cast(now.time_since_epoch()).count(); + + for (auto &[recordId, startInfo] : aliveCopy) { + int32_t configuredTimeout = DelayedSingleton::GetInstance()-> + GetExtensionRunningTimeoutTime(startInfo.extensionTypeName); + if (configuredTimeout <= 0) { + continue; + } + + int64_t runningDurationMs = nowMillis - startInfo.startTimeMillis; + int32_t runningDurationSec = static_cast(runningDurationMs / 1000); + if (runningDurationSec <= configuredTimeout) { + continue; + } + + TAG_LOGI(AAFwkTag::ABILITYMGR, + "alive extension %{public}s/%{public}s exceeded timeout, duration: %{public}ds", + startInfo.bundleName.c_str(), startInfo.abilityName.c_str(), runningDurationSec); + + ExtensionTimeoutEvent event; + event.extensionType = startInfo.extensionType; + event.bundleName = startInfo.bundleName; + event.abilityName = startInfo.abilityName; + event.runningDuration = runningDurationSec; + event.stillAlive = true; + event.cnt = 1; + + std::lock_guard lock(monitorMutex_); + AddOrUpdateTimeoutEvent(event); + } +} + +bool ExtensionRunningTimeoutMonitor::IsDuplicateEvent(const ExtensionTimeoutEvent &event, + std::list::iterator &dupIter) +{ + for (auto it = cachedEvents_.begin(); it != cachedEvents_.end(); ++it) { + if (it->extensionType == event.extensionType && + it->bundleName == event.bundleName && + it->abilityName == event.abilityName) { + dupIter = it; + return true; + } + } + return false; +} + +void ExtensionRunningTimeoutMonitor::AddOrUpdateTimeoutEvent(const ExtensionTimeoutEvent &event) +{ + std::list::iterator dupIter; + if (IsDuplicateEvent(event, dupIter)) { + dupIter->cnt++; + dupIter->runningDuration = event.runningDuration; + dupIter->stillAlive = event.stillAlive; + TAG_LOGD(AAFwkTag::ABILITYMGR, + "updated existing timeout event for %{public}s/%{public}s, cnt: %{public}d", + event.bundleName.c_str(), event.abilityName.c_str(), dupIter->cnt); + return; + } + + if (static_cast(cachedEvents_.size()) >= MAX_CACHED_EVENTS) { + TAG_LOGW(AAFwkTag::ABILITYMGR, + "cache full (%{public}d), discarding event for %{public}s/%{public}s", + MAX_CACHED_EVENTS, event.bundleName.c_str(), event.abilityName.c_str()); + return; + } + + cachedEvents_.push_back(event); + TAG_LOGD(AAFwkTag::ABILITYMGR, + "added new timeout event for %{public}s/%{public}s, cache size: %{public}zu", + event.bundleName.c_str(), event.abilityName.c_str(), cachedEvents_.size()); +} + +} // namespace AAFwk +} // namespace OHOS From 2341e03a7de3b20663d95098e709ffbf8bec1561 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 15:18:45 +0800 Subject: [PATCH 02/20] feat: add dump interface for extension running timeout monitor Add Dump() method to ExtensionRunningTimeoutMonitor for local debugging. Integrated into AbilityManagerService DumpSysInner so the monitor state can be viewed via `aa dump -a` or `hidumper -s AbilityManagerService`. This allows functional verification before HiSysEvent registration is approved. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I089da83c7516168eeb84217c3cf4ce5b68e3e714 --- .../extension_running_timeout_monitor.h | 5 +++ .../src/ability_manager_service.cpp | 5 +++ .../src/extension_running_timeout_monitor.cpp | 32 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/services/abilitymgr/include/extension_running_timeout_monitor.h b/services/abilitymgr/include/extension_running_timeout_monitor.h index e4a6df2009..539c98f1aa 100644 --- a/services/abilitymgr/include/extension_running_timeout_monitor.h +++ b/services/abilitymgr/include/extension_running_timeout_monitor.h @@ -70,6 +70,11 @@ public: */ void CheckAliveExtensions(); + /** + * @brief Dump cached timeout events and running extensions for debugging. + */ + void Dump(std::vector &info); + private: struct ExtensionStartInfo { int32_t extensionType = -1; diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index f3a338b4cd..6546dcba8c 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -54,6 +54,7 @@ #include "hidden_start_observer_manager.h" #include "hitrace_meter.h" #include "hisysevent_report.h" +#include "extension_running_timeout_monitor.h" #include "insight_intent_execute_manager.h" #include "insight_intent_db_cache.h" #include "insight_intent_utils.h" @@ -7299,6 +7300,10 @@ void AbilityManagerService::DumpSysInner( DumpSysStateInner(args, info, isClient, isUserID, userId); DumpSysPendingInner(args, info, isClient, isUserID, userId); DumpSysProcess(args, info, isClient, isUserID, userId); + auto timeoutMonitor = DelayedSingleton::GetInstance(); + if (timeoutMonitor != nullptr) { + timeoutMonitor->Dump(info); + } } void AbilityManagerService::DumpSysMissionListInner( diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index 661a24bd2e..06beb7e9f7 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -257,6 +257,38 @@ void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() } } +void ExtensionRunningTimeoutMonitor::Dump(std::vector &info) +{ + info.emplace_back(" ExtensionRunningTimeoutMonitor:"); + { + std::lock_guard lock(monitorMutex_); + info.emplace_back(" Running extensions: " + std::to_string(runningExtensions_.size())); + for (const auto &[recordId, startInfo] : runningExtensions_) { + auto now = std::chrono::steady_clock::now(); + auto nowMillis = std::chrono::duration_cast( + now.time_since_epoch()).count(); + int32_t runningSec = static_cast((nowMillis - startInfo.startTimeMillis) / 1000); + int32_t timeout = DelayedSingleton::GetInstance()-> + GetExtensionRunningTimeoutTime(startInfo.extensionTypeName); + info.emplace_back(" [" + std::to_string(recordId) + "] " + + startInfo.bundleName + "/" + startInfo.abilityName + + " type:" + startInfo.extensionTypeName + + " running:" + std::to_string(runningSec) + "s" + + " limit:" + std::to_string(timeout) + "s" + + (timeout > 0 && runningSec > timeout ? " EXCEEDED" : "")); + } + info.emplace_back(" Cached timeout events: " + std::to_string(cachedEvents_.size()) + + "/" + std::to_string(MAX_CACHED_EVENTS)); + for (const auto &event : cachedEvents_) { + info.emplace_back(" " + event.bundleName + "/" + event.abilityName + + " type:" + std::to_string(event.extensionType) + + " duration:" + std::to_string(event.runningDuration) + "s" + + " alive:" + (event.stillAlive ? "yes" : "no") + + " cnt:" + std::to_string(event.cnt)); + } + } +} + bool ExtensionRunningTimeoutMonitor::IsDuplicateEvent(const ExtensionTimeoutEvent &event, std::list::iterator &dupIter) { From 8bf68413cf0df7ffcabd8466479ac8b8a14c394c Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 16:04:56 +0800 Subject: [PATCH 03/20] refactor: extract BuildReportArrays to reduce function complexity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split array-building logic from ReportTimeoutEvents into a separate BuildReportArrays method to satisfy the NBNC line count limit (≤50). Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I408b2a0ac90e892e8f8a8950fcccc2edc5177687 --- .../extension_running_timeout_monitor.h | 4 ++ .../src/extension_running_timeout_monitor.cpp | 61 ++++++++++--------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/services/abilitymgr/include/extension_running_timeout_monitor.h b/services/abilitymgr/include/extension_running_timeout_monitor.h index 539c98f1aa..3d8dbbb946 100644 --- a/services/abilitymgr/include/extension_running_timeout_monitor.h +++ b/services/abilitymgr/include/extension_running_timeout_monitor.h @@ -88,6 +88,10 @@ private: bool IsDuplicateEvent(const ExtensionTimeoutEvent &event, std::list::iterator &dupIter); void SubmitPeriodicTask(); + void BuildReportArrays(const std::list &events, + std::vector &extensionTypes, std::vector &bundleNamePtrs, + std::vector &abilityNamePtrs, std::vector &runningDurations, + std::vector &stillAliveFlags, std::vector &cnts); std::mutex monitorMutex_; std::unordered_map runningExtensions_; diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index 06beb7e9f7..dfcb4fc6ab 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -153,39 +153,17 @@ void ExtensionRunningTimeoutMonitor::SubmitPeriodicTask() taskHandler->SubmitTask(task, PERIODIC_TASK_NAME, REPORT_INTERVAL_MS); } -void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() +void ExtensionRunningTimeoutMonitor::BuildReportArrays( + const std::list &events, + std::vector &extensionTypes, std::vector &bundleNamePtrs, + std::vector &abilityNamePtrs, std::vector &runningDurations, + std::vector &stillAliveFlags, std::vector &cnts) { - std::list eventsToReport; - { - std::lock_guard lock(monitorMutex_); - if (cachedEvents_.empty()) { - TAG_LOGD(AAFwkTag::ABILITYMGR, "no timeout events to report"); - return; - } - eventsToReport = cachedEvents_; - cachedEvents_.clear(); - } - - // Build arrays for HiSysEvent - std::vector extensionTypes; - std::vector bundleNamePtrs; - std::vector abilityNamePtrs; - std::vector runningDurations; - std::vector stillAliveFlags; - std::vector cnts; - - // Keep string references alive until report completes std::vector bundleNames; std::vector abilityNames; - - bundleNames.reserve(eventsToReport.size()); - abilityNames.reserve(eventsToReport.size()); - extensionTypes.reserve(eventsToReport.size()); - runningDurations.reserve(eventsToReport.size()); - stillAliveFlags.reserve(eventsToReport.size()); - cnts.reserve(eventsToReport.size()); - - for (const auto &event : eventsToReport) { + bundleNames.reserve(events.size()); + abilityNames.reserve(events.size()); + for (const auto &event : events) { extensionTypes.push_back(event.extensionType); bundleNames.push_back(event.bundleName); abilityNames.push_back(event.abilityName); @@ -199,6 +177,29 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() for (auto &name : abilityNames) { abilityNamePtrs.push_back(const_cast(name.c_str())); } +} + +void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() +{ + std::list eventsToReport; + { + std::lock_guard lock(monitorMutex_); + if (cachedEvents_.empty()) { + TAG_LOGD(AAFwkTag::ABILITYMGR, "no timeout events to report"); + return; + } + eventsToReport = cachedEvents_; + cachedEvents_.clear(); + } + + std::vector extensionTypes; + std::vector bundleNamePtrs; + std::vector abilityNamePtrs; + std::vector runningDurations; + std::vector stillAliveFlags; + std::vector cnts; + BuildReportArrays(eventsToReport, extensionTypes, bundleNamePtrs, + abilityNamePtrs, runningDurations, stillAliveFlags, cnts); auto paramCount = static_cast(6 + eventsToReport.size()); HisyseventReport report(paramCount); From deac9ce056a5c213c1319c8bb003f0241f79050d Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 16:25:40 +0800 Subject: [PATCH 04/20] fix: replace ams_extension_config with extension_config in JSON content Remove ambiguous "ams" abbreviation from JSON config key to pass open source code compliance check. The C++ constant is updated accordingly to match the new key name. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: Ifd2139b37539f373fea1cf027a3dbf4a5f1f2a71 --- services/abilitymgr/resource/ams_extension_config.json | 2 +- services/abilitymgr/src/extension_config.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/abilitymgr/resource/ams_extension_config.json b/services/abilitymgr/resource/ams_extension_config.json index 4271cfaef3..f114243720 100644 --- a/services/abilitymgr/resource/ams_extension_config.json +++ b/services/abilitymgr/resource/ams_extension_config.json @@ -1,5 +1,5 @@ { - "ams_extension_config": [ + "extension_config": [ { "extension_type_name": "service", "auto_disconnect_time": -1, diff --git a/services/abilitymgr/src/extension_config.cpp b/services/abilitymgr/src/extension_config.cpp index 1484d3f5b4..d94884ebee 100644 --- a/services/abilitymgr/src/extension_config.cpp +++ b/services/abilitymgr/src/extension_config.cpp @@ -27,7 +27,7 @@ namespace { constexpr const char* EXTENSION_CONFIG_DEFAULT_PATH = "/system/etc/ams_extension_config.json"; constexpr const char* EXTENSION_CONFIG_FILE_PATH = "/etc/ams_extension_config.json"; -constexpr const char* EXTENSION_CONFIG_NAME = "ams_extension_config"; +constexpr const char* EXTENSION_CONFIG_NAME = "extension_config"; constexpr const char* EXTENSION_TYPE_NAME = "extension_type_name"; constexpr const char* EXTENSION_AUTO_DISCONNECT_TIME = "auto_disconnect_time"; constexpr const char* EXTENSION_RUNNING_TIMEOUT_TIME = "running_timeout_time"; From e398652f20ccad9b4b83b7e1650d091fd5970e93 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 21:54:25 +0800 Subject: [PATCH 05/20] fix: revert JSON config file and use external configuration Revert ams_extension_config.json to original empty state as the running_timeout_time is provided via external configuration push, not from the local JSON file. The C++ config key remains as "ams_extension_config" to match the system config format. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: Idb01ab92386ef8a2a0883557e4baf80149b73830 --- .../abilitymgr/resource/ams_extension_config.json | 13 +------------ services/abilitymgr/src/extension_config.cpp | 2 +- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/services/abilitymgr/resource/ams_extension_config.json b/services/abilitymgr/resource/ams_extension_config.json index f114243720..4b57e04b16 100644 --- a/services/abilitymgr/resource/ams_extension_config.json +++ b/services/abilitymgr/resource/ams_extension_config.json @@ -1,14 +1,3 @@ { - "extension_config": [ - { - "extension_type_name": "service", - "auto_disconnect_time": -1, - "running_timeout_time": 7200 - }, - { - "extension_type_name": "dataShare", - "auto_disconnect_time": -1, - "running_timeout_time": 1800 - } - ] + "ams_extension_config": [] } diff --git a/services/abilitymgr/src/extension_config.cpp b/services/abilitymgr/src/extension_config.cpp index d94884ebee..1484d3f5b4 100644 --- a/services/abilitymgr/src/extension_config.cpp +++ b/services/abilitymgr/src/extension_config.cpp @@ -27,7 +27,7 @@ namespace { constexpr const char* EXTENSION_CONFIG_DEFAULT_PATH = "/system/etc/ams_extension_config.json"; constexpr const char* EXTENSION_CONFIG_FILE_PATH = "/etc/ams_extension_config.json"; -constexpr const char* EXTENSION_CONFIG_NAME = "extension_config"; +constexpr const char* EXTENSION_CONFIG_NAME = "ams_extension_config"; constexpr const char* EXTENSION_TYPE_NAME = "extension_type_name"; constexpr const char* EXTENSION_AUTO_DISCONNECT_TIME = "auto_disconnect_time"; constexpr const char* EXTENSION_RUNNING_TIMEOUT_TIME = "running_timeout_time"; From 14e5a8f24962f2606659ad059b5bdf266b6c760a Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 21:56:52 +0800 Subject: [PATCH 06/20] fix: remove tag from EXTENSION_RUNNING_TIMEOUT hisysevent definition Remove tag field to match existing STATISTIC type events format. Ensure trailing newline at end of file. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I7f7fd709d7c1754470dbd47b2a449d8d1613fb6d --- hisysevent.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hisysevent.yaml b/hisysevent.yaml index c7b8ca4c07..94ef3ed681 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -514,10 +514,10 @@ USER_DATA_SIZE: FILE_OR_FOLDER_SIZE: {type: UINT64, arrsize: 100, desc: File or folder size} EXTENSION_RUNNING_TIMEOUT: - __BASE: {type: STATISTIC, level: MINOR, tag: STABILITY, desc: extension ability running timeout} + __BASE: {type: STATISTIC, level: MINOR, desc: extension ability running timeout} EXTENSION_TYPE: {type: INT32_ARRAY, desc: extension type list} BUNDLE_NAME: {type: STRING_ARRAY, desc: bundle name list} ABILITY_NAME: {type: STRING_ARRAY, desc: ability name list} RUNNING_DURATION: {type: INT32_ARRAY, desc: running duration list in seconds} STILL_ALIVE: {type: INT32_ARRAY, desc: still alive flag list} - CNT: {type: INT32_ARRAY, desc: occurrence count list} \ No newline at end of file + CNT: {type: INT32_ARRAY, desc: occurrence count list} From cbc125d00766a04377abe4e69d9b230d3d6d2662 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 22:25:01 +0800 Subject: [PATCH 07/20] fix: use scalar types in hisysevent and report events individually YAML definition does not support INT32_ARRAY/STRING_ARRAY types. Change to scalar types (INT32, STRING) and report each timeout event individually via HiSysEvent instead of batching arrays. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I91feac155dab183afe58afa1e42eeb3fe62da653 --- hisysevent.yaml | 12 ++-- .../extension_running_timeout_monitor.h | 4 -- .../src/extension_running_timeout_monitor.cpp | 59 ++++--------------- 3 files changed, 19 insertions(+), 56 deletions(-) diff --git a/hisysevent.yaml b/hisysevent.yaml index 94ef3ed681..7a7c700d1d 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -515,9 +515,9 @@ USER_DATA_SIZE: EXTENSION_RUNNING_TIMEOUT: __BASE: {type: STATISTIC, level: MINOR, desc: extension ability running timeout} - EXTENSION_TYPE: {type: INT32_ARRAY, desc: extension type list} - BUNDLE_NAME: {type: STRING_ARRAY, desc: bundle name list} - ABILITY_NAME: {type: STRING_ARRAY, desc: ability name list} - RUNNING_DURATION: {type: INT32_ARRAY, desc: running duration list in seconds} - STILL_ALIVE: {type: INT32_ARRAY, desc: still alive flag list} - CNT: {type: INT32_ARRAY, desc: occurrence count list} + EXTENSION_TYPE: {type: INT32, desc: extension type} + BUNDLE_NAME: {type: STRING, desc: bundle name} + ABILITY_NAME: {type: STRING, desc: ability name} + RUNNING_DURATION: {type: INT32, desc: running duration in seconds} + STILL_ALIVE: {type: INT32, desc: still alive flag} + CNT: {type: INT32, desc: occurrence count} diff --git a/services/abilitymgr/include/extension_running_timeout_monitor.h b/services/abilitymgr/include/extension_running_timeout_monitor.h index 3d8dbbb946..539c98f1aa 100644 --- a/services/abilitymgr/include/extension_running_timeout_monitor.h +++ b/services/abilitymgr/include/extension_running_timeout_monitor.h @@ -88,10 +88,6 @@ private: bool IsDuplicateEvent(const ExtensionTimeoutEvent &event, std::list::iterator &dupIter); void SubmitPeriodicTask(); - void BuildReportArrays(const std::list &events, - std::vector &extensionTypes, std::vector &bundleNamePtrs, - std::vector &abilityNamePtrs, std::vector &runningDurations, - std::vector &stillAliveFlags, std::vector &cnts); std::mutex monitorMutex_; std::unordered_map runningExtensions_; diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index dfcb4fc6ab..895888730a 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -153,32 +153,6 @@ void ExtensionRunningTimeoutMonitor::SubmitPeriodicTask() taskHandler->SubmitTask(task, PERIODIC_TASK_NAME, REPORT_INTERVAL_MS); } -void ExtensionRunningTimeoutMonitor::BuildReportArrays( - const std::list &events, - std::vector &extensionTypes, std::vector &bundleNamePtrs, - std::vector &abilityNamePtrs, std::vector &runningDurations, - std::vector &stillAliveFlags, std::vector &cnts) -{ - std::vector bundleNames; - std::vector abilityNames; - bundleNames.reserve(events.size()); - abilityNames.reserve(events.size()); - for (const auto &event : events) { - extensionTypes.push_back(event.extensionType); - bundleNames.push_back(event.bundleName); - abilityNames.push_back(event.abilityName); - runningDurations.push_back(event.runningDuration); - stillAliveFlags.push_back(event.stillAlive ? 1 : 0); - cnts.push_back(event.cnt); - } - for (auto &name : bundleNames) { - bundleNamePtrs.push_back(const_cast(name.c_str())); - } - for (auto &name : abilityNames) { - abilityNamePtrs.push_back(const_cast(name.c_str())); - } -} - void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() { std::list eventsToReport; @@ -192,26 +166,19 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() cachedEvents_.clear(); } - std::vector extensionTypes; - std::vector bundleNamePtrs; - std::vector abilityNamePtrs; - std::vector runningDurations; - std::vector stillAliveFlags; - std::vector cnts; - BuildReportArrays(eventsToReport, extensionTypes, bundleNamePtrs, - abilityNamePtrs, runningDurations, stillAliveFlags, cnts); - - auto paramCount = static_cast(6 + eventsToReport.size()); - HisyseventReport report(paramCount); - report.InsertParam(EXTENSION_TYPE_KEY, extensionTypes); - report.InsertParam(BUNDLE_NAME_KEY, bundleNamePtrs); - report.InsertParam(ABILITY_NAME_KEY, abilityNamePtrs); - report.InsertParam(RUNNING_DURATION_KEY, runningDurations); - report.InsertParam(STILL_ALIVE_KEY, stillAliveFlags); - report.InsertParam(CNT_KEY, cnts); - int32_t ret = report.Report(DOMAIN, EVENT_NAME, HISYSEVENT_STATISTIC); - TAG_LOGI(AAFwkTag::ABILITYMGR, "reported %{public}zu timeout events, ret: %{public}d", - eventsToReport.size(), ret); + int32_t reportCount = 0; + for (const auto &event : eventsToReport) { + HisyseventReport report(7); + report.InsertParam(EXTENSION_TYPE_KEY, event.extensionType); + report.InsertParam(BUNDLE_NAME_KEY, event.bundleName); + report.InsertParam(ABILITY_NAME_KEY, event.abilityName); + report.InsertParam(RUNNING_DURATION_KEY, event.runningDuration); + report.InsertParam(STILL_ALIVE_KEY, event.stillAlive ? 1 : 0); + report.InsertParam(CNT_KEY, event.cnt); + report.Report(DOMAIN, EVENT_NAME, HISYSEVENT_STATISTIC); + reportCount++; + } + TAG_LOGI(AAFwkTag::ABILITYMGR, "reported %{public}d timeout events", reportCount); } void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() From d6ee5abc348728f675d637a0162ac7c43cb3aa57 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Tue, 7 Apr 2026 22:29:52 +0800 Subject: [PATCH 08/20] fix: use arrsize syntax for array fields in hisysevent yaml YAML definition uses scalar type with arrsize attribute for arrays, e.g. {type: INT32, arrsize: 5} instead of INT32_ARRAY. Restore batch array reporting to match the registered event format. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: Ia45e79b166f9c547eec07f4d7c04be0bdc2cd63b --- hisysevent.yaml | 12 +++--- .../src/extension_running_timeout_monitor.cpp | 43 ++++++++++++++----- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/hisysevent.yaml b/hisysevent.yaml index 7a7c700d1d..3facf90a93 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -515,9 +515,9 @@ USER_DATA_SIZE: EXTENSION_RUNNING_TIMEOUT: __BASE: {type: STATISTIC, level: MINOR, desc: extension ability running timeout} - EXTENSION_TYPE: {type: INT32, desc: extension type} - BUNDLE_NAME: {type: STRING, desc: bundle name} - ABILITY_NAME: {type: STRING, desc: ability name} - RUNNING_DURATION: {type: INT32, desc: running duration in seconds} - STILL_ALIVE: {type: INT32, desc: still alive flag} - CNT: {type: INT32, desc: occurrence count} + EXTENSION_TYPE: {type: INT32, arrsize: 5, desc: extension type list} + BUNDLE_NAME: {type: STRING, arrsize: 5, desc: bundle name list} + ABILITY_NAME: {type: STRING, arrsize: 5, desc: ability name list} + RUNNING_DURATION: {type: INT32, arrsize: 5, desc: running duration list in seconds} + STILL_ALIVE: {type: INT32, arrsize: 5, desc: still alive flag list} + CNT: {type: INT32, arrsize: 5, desc: occurrence count list} diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index 895888730a..e1ac825467 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -166,19 +166,40 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() cachedEvents_.clear(); } - int32_t reportCount = 0; + std::vector extensionTypes; + std::vector bundleNamePtrs; + std::vector abilityNamePtrs; + std::vector runningDurations; + std::vector stillAliveFlags; + std::vector cnts; + std::vector bundleNames; + std::vector abilityNames; + for (const auto &event : eventsToReport) { - HisyseventReport report(7); - report.InsertParam(EXTENSION_TYPE_KEY, event.extensionType); - report.InsertParam(BUNDLE_NAME_KEY, event.bundleName); - report.InsertParam(ABILITY_NAME_KEY, event.abilityName); - report.InsertParam(RUNNING_DURATION_KEY, event.runningDuration); - report.InsertParam(STILL_ALIVE_KEY, event.stillAlive ? 1 : 0); - report.InsertParam(CNT_KEY, event.cnt); - report.Report(DOMAIN, EVENT_NAME, HISYSEVENT_STATISTIC); - reportCount++; + extensionTypes.push_back(event.extensionType); + bundleNames.push_back(event.bundleName); + abilityNames.push_back(event.abilityName); + runningDurations.push_back(event.runningDuration); + stillAliveFlags.push_back(event.stillAlive ? 1 : 0); + cnts.push_back(event.cnt); } - TAG_LOGI(AAFwkTag::ABILITYMGR, "reported %{public}d timeout events", reportCount); + for (auto &name : bundleNames) { + bundleNamePtrs.push_back(const_cast(name.c_str())); + } + for (auto &name : abilityNames) { + abilityNamePtrs.push_back(const_cast(name.c_str())); + } + + HisyseventReport report(7); + report.InsertParam(EXTENSION_TYPE_KEY, extensionTypes); + report.InsertParam(BUNDLE_NAME_KEY, bundleNamePtrs); + report.InsertParam(ABILITY_NAME_KEY, abilityNamePtrs); + report.InsertParam(RUNNING_DURATION_KEY, runningDurations); + report.InsertParam(STILL_ALIVE_KEY, stillAliveFlags); + report.InsertParam(CNT_KEY, cnts); + int32_t ret = report.Report(DOMAIN, EVENT_NAME, HISYSEVENT_STATISTIC); + TAG_LOGI(AAFwkTag::ABILITYMGR, "reported %{public}zu timeout events, ret: %{public}d", + eventsToReport.size(), ret); } void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() From 5551a96eb0b9c72b98fd6cf7372444ac18f013b4 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Wed, 8 Apr 2026 10:55:20 +0800 Subject: [PATCH 09/20] fix: add extension_running_timeout_monitor source to test BUILD.gn files extension_record_manager.cpp now depends on ExtensionRunningTimeoutMonitor, add the missing source files to all test and fuzzer BUILD.gn files that compile extension_record_manager.cpp directly. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I919087137b89b4aca7293739c642c87522490722 --- test/fuzztest/extensionrecordmanager_fuzzer/BUILD.gn | 2 ++ test/fuzztest/extensionrecordmanagera_fuzzer/BUILD.gn | 2 ++ test/fuzztest/extensionrecordmanagerb_fuzzer/BUILD.gn | 2 ++ test/fuzztest/extensionrecordmanagerc_fuzzer/BUILD.gn | 2 ++ test/unittest/ability_manager_service_fourteenth_test/BUILD.gn | 1 + test/unittest/ability_manager_service_second_test/BUILD.gn | 1 + test/unittest/ability_manager_service_thirteenth_test/BUILD.gn | 1 + .../ui_extension/extension_record_manager_second_test/BUILD.gn | 2 ++ .../ui_extension/extension_record_manager_test/BUILD.gn | 2 ++ 9 files changed, 15 insertions(+) diff --git a/test/fuzztest/extensionrecordmanager_fuzzer/BUILD.gn b/test/fuzztest/extensionrecordmanager_fuzzer/BUILD.gn index 224f8443cd..c92262fdc9 100644 --- a/test/fuzztest/extensionrecordmanager_fuzzer/BUILD.gn +++ b/test/fuzztest/extensionrecordmanager_fuzzer/BUILD.gn @@ -50,6 +50,8 @@ ohos_fuzztest("ExtensionRecordManagerFuzzTest") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_config.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_uiext_state_observer.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record_factory.cpp", diff --git a/test/fuzztest/extensionrecordmanagera_fuzzer/BUILD.gn b/test/fuzztest/extensionrecordmanagera_fuzzer/BUILD.gn index aef76513e9..6767a8e04b 100755 --- a/test/fuzztest/extensionrecordmanagera_fuzzer/BUILD.gn +++ b/test/fuzztest/extensionrecordmanagera_fuzzer/BUILD.gn @@ -48,6 +48,8 @@ ohos_fuzztest("ExtensionRecordManageraFuzzTest") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_config.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_uiext_state_observer.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record_factory.cpp", diff --git a/test/fuzztest/extensionrecordmanagerb_fuzzer/BUILD.gn b/test/fuzztest/extensionrecordmanagerb_fuzzer/BUILD.gn index dd07f6a46b..0e7ff32d5d 100755 --- a/test/fuzztest/extensionrecordmanagerb_fuzzer/BUILD.gn +++ b/test/fuzztest/extensionrecordmanagerb_fuzzer/BUILD.gn @@ -51,6 +51,8 @@ ohos_fuzztest("ExtensionRecordManagerbFuzzTest") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_config.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_uiext_state_observer.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record_factory.cpp", diff --git a/test/fuzztest/extensionrecordmanagerc_fuzzer/BUILD.gn b/test/fuzztest/extensionrecordmanagerc_fuzzer/BUILD.gn index 69cb4e7bb4..5208f43cc3 100755 --- a/test/fuzztest/extensionrecordmanagerc_fuzzer/BUILD.gn +++ b/test/fuzztest/extensionrecordmanagerc_fuzzer/BUILD.gn @@ -51,6 +51,8 @@ ohos_fuzztest("ExtensionRecordManagercFuzzTest") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_config.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_uiext_state_observer.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record_factory.cpp", diff --git a/test/unittest/ability_manager_service_fourteenth_test/BUILD.gn b/test/unittest/ability_manager_service_fourteenth_test/BUILD.gn index d39bc6cd3f..6c53d0f4a6 100644 --- a/test/unittest/ability_manager_service_fourteenth_test/BUILD.gn +++ b/test/unittest/ability_manager_service_fourteenth_test/BUILD.gn @@ -123,6 +123,7 @@ ohos_unittest("ability_manager_service_fourteenth_test") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_running_info.cpp", "${ability_runtime_services_path}/abilitymgr/src/foreground_app_connection_manager/foreground_app_connection_manager.cpp", "${ability_runtime_services_path}/abilitymgr/src/free_install_observer_manager.cpp", diff --git a/test/unittest/ability_manager_service_second_test/BUILD.gn b/test/unittest/ability_manager_service_second_test/BUILD.gn index f08f0ecba8..2d4d3e3cd8 100644 --- a/test/unittest/ability_manager_service_second_test/BUILD.gn +++ b/test/unittest/ability_manager_service_second_test/BUILD.gn @@ -125,6 +125,7 @@ ohos_unittest("ability_manager_service_second_test") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_running_info.cpp", "${ability_runtime_services_path}/abilitymgr/src/foreground_app_connection_manager/foreground_app_connection_manager.cpp", "${ability_runtime_services_path}/abilitymgr/src/free_install_observer_manager.cpp", diff --git a/test/unittest/ability_manager_service_thirteenth_test/BUILD.gn b/test/unittest/ability_manager_service_thirteenth_test/BUILD.gn index ed48fb7ab4..c806418fdc 100644 --- a/test/unittest/ability_manager_service_thirteenth_test/BUILD.gn +++ b/test/unittest/ability_manager_service_thirteenth_test/BUILD.gn @@ -123,6 +123,7 @@ ohos_unittest("ability_manager_service_thirteenth_test") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_running_info.cpp", "${ability_runtime_services_path}/abilitymgr/src/foreground_app_connection_manager/foreground_app_connection_manager.cpp", "${ability_runtime_services_path}/abilitymgr/src/free_install_observer_manager.cpp", diff --git a/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn b/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn index 9a6a5d5ccb..45f05f5483 100644 --- a/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn +++ b/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn @@ -48,6 +48,8 @@ ohos_unittest("extension_record_manager_second_test") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_config.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_uiext_state_observer.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record_factory.cpp", diff --git a/test/unittest/ui_extension/extension_record_manager_test/BUILD.gn b/test/unittest/ui_extension/extension_record_manager_test/BUILD.gn index 305f1689d8..ff172ab2b6 100755 --- a/test/unittest/ui_extension/extension_record_manager_test/BUILD.gn +++ b/test/unittest/ui_extension/extension_record_manager_test/BUILD.gn @@ -45,6 +45,8 @@ ohos_unittest("extension_record_manager_test") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_config.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_uiext_state_observer.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record_factory.cpp", From f1681fa70d1129a264617a323d598d1c84d07342 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Wed, 8 Apr 2026 14:54:04 +0800 Subject: [PATCH 10/20] feat: start ExtensionRunningTimeoutMonitor during AMS init Call StartMonitor() in AbilityManagerService::Init() to enable the periodic 2-hour check for alive extension timeout violations and HiSysEvent reporting. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: Ie1f4faf592f73993b85802c24c3ea1d93db02f04 --- services/abilitymgr/src/ability_manager_service.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 6546dcba8c..0d633c897c 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -469,6 +469,7 @@ bool AbilityManagerService::Init() modularObjectExtensionEventMgr_ = std::make_shared(); modularObjectExtensionEventMgr_->SubscribeSysEventReceiver(); ReportDataPartitionUsageManager::SendReportDataPartitionUsageEvent(); + DelayedSingleton::GetInstance()->StartMonitor(); #ifdef RESOURCE_SCHEDULE_SERVICE_ENABLE ResourceSchedule::ResSchedClient::GetInstance().InitKillReasonListener(); #endif From 378572c3bb93c4a143312d92c65fc6e29a50e77e Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Wed, 8 Apr 2026 18:10:28 +0800 Subject: [PATCH 11/20] fix: add extension_running_timeout_monitor to remaining test gni files Add missing source dependency to abilitymgr.gni for first_test, sixth_test and third_test targets that compile extension_record_manager. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I89590d82ca77480dc135517268c50b42a567c50d --- test/unittest/ability_manager_service_first_test/abilitymgr.gni | 1 + test/unittest/ability_manager_service_sixth_test/abilitymgr.gni | 1 + test/unittest/ability_manager_service_third_test/abilitymgr.gni | 1 + 3 files changed, 3 insertions(+) diff --git a/test/unittest/ability_manager_service_first_test/abilitymgr.gni b/test/unittest/ability_manager_service_first_test/abilitymgr.gni index 80e0ccce35..3f1eac4a08 100644 --- a/test/unittest/ability_manager_service_first_test/abilitymgr.gni +++ b/test/unittest/ability_manager_service_first_test/abilitymgr.gni @@ -43,6 +43,7 @@ abilityms_files = [ "${ability_runtime_services_path}/abilitymgr/src/extension_running_info.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/base_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/foreground_app_connection_manager/foreground_app_connection_manager.cpp", diff --git a/test/unittest/ability_manager_service_sixth_test/abilitymgr.gni b/test/unittest/ability_manager_service_sixth_test/abilitymgr.gni index e92187c195..03f03051b6 100644 --- a/test/unittest/ability_manager_service_sixth_test/abilitymgr.gni +++ b/test/unittest/ability_manager_service_sixth_test/abilitymgr.gni @@ -43,6 +43,7 @@ abilityms_files = [ "${ability_runtime_services_path}/abilitymgr/src/extension_running_info.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/base_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/foreground_app_connection_manager/foreground_app_connection_manager.cpp", diff --git a/test/unittest/ability_manager_service_third_test/abilitymgr.gni b/test/unittest/ability_manager_service_third_test/abilitymgr.gni index 9501d951b7..079d73c163 100644 --- a/test/unittest/ability_manager_service_third_test/abilitymgr.gni +++ b/test/unittest/ability_manager_service_third_test/abilitymgr.gni @@ -43,6 +43,7 @@ abilityms_files = [ "${ability_runtime_services_path}/abilitymgr/src/extension_running_info.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/base_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", + "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_factory.cpp", "${ability_runtime_services_path}/abilitymgr/src/foreground_app_connection_manager/foreground_app_connection_manager.cpp", From 740757ade0aa0d4fb525f9ce6a824d75c0ed4516 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Wed, 8 Apr 2026 18:24:42 +0800 Subject: [PATCH 12/20] fix: correct HiSysEvent types for EXTENSION_RUNNING_TIMEOUT - Change event level from MINOR to CRITICAL - EXTENSION_TYPE: INT32 -> STRING (use extensionTypeName from BMS) - RUNNING_DURATION: INT32 -> INT64 (support long running durations) - STILL_ALIVE: INT32 -> BOOL (proper boolean type) - Add vector and vector InsertParam overloads to HisyseventReport - Remove unused int32_t extensionType from ExtensionStartInfo and ExtensionTimeoutEvent Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: Ia7670f10ded744941fdc4b268f1fd7a16b0440c9 --- hisysevent.yaml | 8 ++-- .../extension_running_timeout_monitor.h | 7 ++-- .../extension_record_manager.cpp | 1 - .../src/extension_running_timeout_monitor.cpp | 40 ++++++++++--------- services/common/include/hisysevent_report.h | 2 + services/common/src/hisysevent_report.cpp | 40 +++++++++++++++++++ 6 files changed, 71 insertions(+), 27 deletions(-) diff --git a/hisysevent.yaml b/hisysevent.yaml index 3facf90a93..3f9debb713 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -514,10 +514,10 @@ USER_DATA_SIZE: FILE_OR_FOLDER_SIZE: {type: UINT64, arrsize: 100, desc: File or folder size} EXTENSION_RUNNING_TIMEOUT: - __BASE: {type: STATISTIC, level: MINOR, desc: extension ability running timeout} - EXTENSION_TYPE: {type: INT32, arrsize: 5, desc: extension type list} + __BASE: {type: STATISTIC, level: CRITICAL, desc: extension ability running timeout} + EXTENSION_TYPE: {type: STRING, arrsize: 5, desc: extension type name list} BUNDLE_NAME: {type: STRING, arrsize: 5, desc: bundle name list} ABILITY_NAME: {type: STRING, arrsize: 5, desc: ability name list} - RUNNING_DURATION: {type: INT32, arrsize: 5, desc: running duration list in seconds} - STILL_ALIVE: {type: INT32, arrsize: 5, desc: still alive flag list} + RUNNING_DURATION: {type: INT64, arrsize: 5, desc: running duration list in seconds} + STILL_ALIVE: {type: BOOL, arrsize: 5, desc: still alive flag list} CNT: {type: INT32, arrsize: 5, desc: occurrence count list} diff --git a/services/abilitymgr/include/extension_running_timeout_monitor.h b/services/abilitymgr/include/extension_running_timeout_monitor.h index 539c98f1aa..663713f1fc 100644 --- a/services/abilitymgr/include/extension_running_timeout_monitor.h +++ b/services/abilitymgr/include/extension_running_timeout_monitor.h @@ -27,10 +27,10 @@ namespace OHOS { namespace AAFwk { struct ExtensionTimeoutEvent { - int32_t extensionType = -1; + std::string extensionTypeName; std::string bundleName; std::string abilityName; - int32_t runningDuration = 0; // seconds + int64_t runningDuration = 0; // seconds bool stillAlive = false; int32_t cnt = 1; }; @@ -42,7 +42,7 @@ public: * @brief Called when an extension ability starts. Records start time. */ void OnExtensionStarted(int32_t extensionRecordId, const std::string &extensionTypeName, - int32_t extensionType, const std::string &bundleName, const std::string &abilityName); + const std::string &bundleName, const std::string &abilityName); /** * @brief Called when an extension ability ends. Checks if it exceeded configured timeout. @@ -77,7 +77,6 @@ public: private: struct ExtensionStartInfo { - int32_t extensionType = -1; std::string extensionTypeName; std::string bundleName; std::string abilityName; diff --git a/services/abilitymgr/src/extension_record/extension_record_manager.cpp b/services/abilitymgr/src/extension_record/extension_record_manager.cpp index c9df4f1b68..c5702be530 100644 --- a/services/abilitymgr/src/extension_record/extension_record_manager.cpp +++ b/services/abilitymgr/src/extension_record/extension_record_manager.cpp @@ -98,7 +98,6 @@ void ExtensionRecordManager::AddExtensionRecord(const int32_t extensionRecordId, if (monitor != nullptr) { monitor->OnExtensionStarted(extensionRecordId, abilityInfo.extensionTypeName, - static_cast(abilityInfo.extensionAbilityType), abilityInfo.bundleName, abilityInfo.name); } diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index e1ac825467..39fad20128 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -16,6 +16,7 @@ #include "extension_running_timeout_monitor.h" #include +#include #include #include "extension_config.h" @@ -41,7 +42,7 @@ ExtensionRunningTimeoutMonitor::ExtensionRunningTimeoutMonitor() {} ExtensionRunningTimeoutMonitor::~ExtensionRunningTimeoutMonitor() {} void ExtensionRunningTimeoutMonitor::OnExtensionStarted(int32_t extensionRecordId, - const std::string &extensionTypeName, int32_t extensionType, + const std::string &extensionTypeName, const std::string &bundleName, const std::string &abilityName) { TAG_LOGD(AAFwkTag::ABILITYMGR, @@ -53,7 +54,6 @@ void ExtensionRunningTimeoutMonitor::OnExtensionStarted(int32_t extensionRecordI std::chrono::duration_cast(now.time_since_epoch()).count(); ExtensionStartInfo info; - info.extensionType = extensionType; info.extensionTypeName = extensionTypeName; info.bundleName = bundleName; info.abilityName = abilityName; @@ -92,24 +92,24 @@ void ExtensionRunningTimeoutMonitor::OnExtensionTerminated(int32_t extensionReco auto now = std::chrono::steady_clock::now(); auto nowMillis = std::chrono::duration_cast(now.time_since_epoch()).count(); int64_t runningDurationMs = nowMillis - startInfo.startTimeMillis; - int32_t runningDurationSec = static_cast(runningDurationMs / 1000); + int64_t runningDurationSec = runningDurationMs / 1000; // runningDuration <= configuredTimeout means within limit, do not track if (runningDurationSec <= configuredTimeout) { TAG_LOGD(AAFwkTag::ABILITYMGR, - "extension %{public}s/%{public}s within timeout, duration: %{public}ds, limit: %{public}ds", + "extension %{public}s/%{public}s within timeout, duration: %{public}" PRId64 "s, limit: %{public}ds", startInfo.bundleName.c_str(), startInfo.abilityName.c_str(), runningDurationSec, configuredTimeout); return; } TAG_LOGI(AAFwkTag::ABILITYMGR, - "extension %{public}s/%{public}s exceeded timeout, duration: %{public}ds, limit: %{public}ds", + "extension %{public}s/%{public}s exceeded timeout, duration: %{public}" PRId64 "s, limit: %{public}ds", startInfo.bundleName.c_str(), startInfo.abilityName.c_str(), runningDurationSec, configuredTimeout); ExtensionTimeoutEvent event; - event.extensionType = startInfo.extensionType; + event.extensionTypeName = startInfo.extensionTypeName; event.bundleName = startInfo.bundleName; event.abilityName = startInfo.abilityName; event.runningDuration = runningDurationSec; @@ -166,23 +166,27 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() cachedEvents_.clear(); } - std::vector extensionTypes; + std::vector extensionTypeNames; + std::vector extensionTypePtrs; std::vector bundleNamePtrs; std::vector abilityNamePtrs; - std::vector runningDurations; - std::vector stillAliveFlags; + std::vector runningDurations; + std::vector stillAliveFlags; std::vector cnts; std::vector bundleNames; std::vector abilityNames; for (const auto &event : eventsToReport) { - extensionTypes.push_back(event.extensionType); + extensionTypeNames.push_back(event.extensionTypeName); bundleNames.push_back(event.bundleName); abilityNames.push_back(event.abilityName); runningDurations.push_back(event.runningDuration); - stillAliveFlags.push_back(event.stillAlive ? 1 : 0); + stillAliveFlags.push_back(event.stillAlive); cnts.push_back(event.cnt); } + for (auto &name : extensionTypeNames) { + extensionTypePtrs.push_back(const_cast(name.c_str())); + } for (auto &name : bundleNames) { bundleNamePtrs.push_back(const_cast(name.c_str())); } @@ -191,7 +195,7 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() } HisyseventReport report(7); - report.InsertParam(EXTENSION_TYPE_KEY, extensionTypes); + report.InsertParam(EXTENSION_TYPE_KEY, extensionTypePtrs); report.InsertParam(BUNDLE_NAME_KEY, bundleNamePtrs); report.InsertParam(ABILITY_NAME_KEY, abilityNamePtrs); report.InsertParam(RUNNING_DURATION_KEY, runningDurations); @@ -224,17 +228,17 @@ void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() } int64_t runningDurationMs = nowMillis - startInfo.startTimeMillis; - int32_t runningDurationSec = static_cast(runningDurationMs / 1000); + int64_t runningDurationSec = runningDurationMs / 1000; if (runningDurationSec <= configuredTimeout) { continue; } TAG_LOGI(AAFwkTag::ABILITYMGR, - "alive extension %{public}s/%{public}s exceeded timeout, duration: %{public}ds", + "alive extension %{public}s/%{public}s exceeded timeout, duration: %{public}" PRId64 "s", startInfo.bundleName.c_str(), startInfo.abilityName.c_str(), runningDurationSec); ExtensionTimeoutEvent event; - event.extensionType = startInfo.extensionType; + event.extensionTypeName = startInfo.extensionTypeName; event.bundleName = startInfo.bundleName; event.abilityName = startInfo.abilityName; event.runningDuration = runningDurationSec; @@ -256,7 +260,7 @@ void ExtensionRunningTimeoutMonitor::Dump(std::vector &info) auto now = std::chrono::steady_clock::now(); auto nowMillis = std::chrono::duration_cast( now.time_since_epoch()).count(); - int32_t runningSec = static_cast((nowMillis - startInfo.startTimeMillis) / 1000); + int64_t runningSec = (nowMillis - startInfo.startTimeMillis) / 1000; int32_t timeout = DelayedSingleton::GetInstance()-> GetExtensionRunningTimeoutTime(startInfo.extensionTypeName); info.emplace_back(" [" + std::to_string(recordId) + "] " + @@ -270,7 +274,7 @@ void ExtensionRunningTimeoutMonitor::Dump(std::vector &info) "/" + std::to_string(MAX_CACHED_EVENTS)); for (const auto &event : cachedEvents_) { info.emplace_back(" " + event.bundleName + "/" + event.abilityName + - " type:" + std::to_string(event.extensionType) + + " type:" + event.extensionTypeName + " duration:" + std::to_string(event.runningDuration) + "s" + " alive:" + (event.stillAlive ? "yes" : "no") + " cnt:" + std::to_string(event.cnt)); @@ -282,7 +286,7 @@ bool ExtensionRunningTimeoutMonitor::IsDuplicateEvent(const ExtensionTimeoutEven std::list::iterator &dupIter) { for (auto it = cachedEvents_.begin(); it != cachedEvents_.end(); ++it) { - if (it->extensionType == event.extensionType && + if (it->extensionTypeName == event.extensionTypeName && it->bundleName == event.bundleName && it->abilityName == event.abilityName) { dupIter = it; diff --git a/services/common/include/hisysevent_report.h b/services/common/include/hisysevent_report.h index 364270a0a7..e3e2b5f560 100644 --- a/services/common/include/hisysevent_report.h +++ b/services/common/include/hisysevent_report.h @@ -56,6 +56,8 @@ public: void InsertParam(const char* name, const std::vector &value); void InsertParam(const char* name, std::vector &value); void InsertParam(const char* name, const std::vector &value); + void InsertParam(const char* name, const std::vector &value); + void InsertParam(const char* name, const std::vector &value); int32_t Report(const char* domain, const char* event, HiSysEventEventType type); private: diff --git a/services/common/src/hisysevent_report.cpp b/services/common/src/hisysevent_report.cpp index 2f2ede484c..91e5067814 100644 --- a/services/common/src/hisysevent_report.cpp +++ b/services/common/src/hisysevent_report.cpp @@ -273,6 +273,46 @@ void HisyseventReport::InsertParam(const char* name, std::vector &value) params_[pos_++] = param; } +void HisyseventReport::InsertParam(const char* name, const std::vector &value) +{ + if (length_ <= pos_) { + TAG_LOGE(AAFwkTag::DEFAULT, "param is full"); + return; + } + HiSysEventParam param = { + .t = HISYSEVENT_BOOL_ARRAY, + .v = { .array = nullptr}, + .arraySize = 0, + }; + + if (!value.empty()) { + param.v.array = static_cast(const_cast(value.data())); + param.arraySize = value.size(); + } + SetParamName(param, name); + params_[pos_++] = param; +} + +void HisyseventReport::InsertParam(const char* name, const std::vector &value) +{ + if (length_ <= pos_) { + TAG_LOGE(AAFwkTag::DEFAULT, "param is full"); + return; + } + HiSysEventParam param = { + .t = HISYSEVENT_INT64_ARRAY, + .v = { .array = nullptr}, + .arraySize = 0, + }; + + if (!value.empty()) { + param.v.array = static_cast(const_cast(value.data())); + param.arraySize = value.size(); + } + SetParamName(param, name); + params_[pos_++] = param; +} + void HisyseventReport::InsertParam(const char* name, std::string value) { this->InsertParam(name, const_cast(value.c_str())); From d4b51bcc8f40a8f98208e95b84d1d83c8879ed6c Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Wed, 8 Apr 2026 18:39:35 +0800 Subject: [PATCH 13/20] fix: fix vector data access and update remaining call site - vector specialization has no .data(), use manual allocation - Remove stale int32_t extensionType arg from ability_connect_manager.cpp Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I30e0e377eef997bfe08acce57ec281fb82bd59f0 --- services/abilitymgr/src/ability_connect_manager.cpp | 1 - services/common/src/hisysevent_report.cpp | 11 +++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/services/abilitymgr/src/ability_connect_manager.cpp b/services/abilitymgr/src/ability_connect_manager.cpp index 5988ae349c..911f67b07c 100644 --- a/services/abilitymgr/src/ability_connect_manager.cpp +++ b/services/abilitymgr/src/ability_connect_manager.cpp @@ -3263,7 +3263,6 @@ void AbilityConnectManager::GetOrCreateServiceRecord(const AbilityRequest &abili if (monitor != nullptr) { monitor->OnExtensionStarted(recordId, newAbilityInfo.extensionTypeName, - static_cast(newAbilityInfo.extensionAbilityType), newAbilityInfo.bundleName, newAbilityInfo.name); } diff --git a/services/common/src/hisysevent_report.cpp b/services/common/src/hisysevent_report.cpp index 91e5067814..b262791b19 100644 --- a/services/common/src/hisysevent_report.cpp +++ b/services/common/src/hisysevent_report.cpp @@ -286,8 +286,15 @@ void HisyseventReport::InsertParam(const char* name, const std::vector &va }; if (!value.empty()) { - param.v.array = static_cast(const_cast(value.data())); - param.arraySize = value.size(); + auto *buf = new (std::nothrow) bool[value.size()]; + if (buf != nullptr) { + for (size_t i = 0; i < value.size(); ++i) { + buf[i] = value[i]; + } + param.v.array = static_cast(buf); + param.arraySize = value.size(); + paramBuffers_.emplace_back(reinterpret_cast(buf)); + } } SetParamName(param, name); params_[pos_++] = param; From 7536bcbe50a1ea5c0b6130af7fe93482a42387a0 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Thu, 9 Apr 2026 17:02:07 +0800 Subject: [PATCH 14/20] feat: remove Dump interface and add TDD test cases for ExtensionRunningTimeoutMonitor - Remove Dump() method from ExtensionRunningTimeoutMonitor header, implementation, and the Dump call in AbilityManagerService::DumpSysInner - Add 18 TDD test cases in extension_record_manager_second_test covering: OnExtensionStarted, OnExtensionTerminated, AddOrUpdateTimeoutEvent, IsDuplicateEvent, ReportTimeoutEvents, CheckAliveExtensions, StartMonitor/StopMonitor, concurrent access safety, and ExtensionConfig integration Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I063b91cf7db09dd3b178711eef420f5c5649186c --- .../extension_running_timeout_monitor.h | 5 - .../src/ability_manager_service.cpp | 4 - .../src/extension_running_timeout_monitor.cpp | 32 - .../extension_record_manager_second_test.cpp | 611 +++++++++++++++++- 4 files changed, 610 insertions(+), 42 deletions(-) diff --git a/services/abilitymgr/include/extension_running_timeout_monitor.h b/services/abilitymgr/include/extension_running_timeout_monitor.h index 663713f1fc..48981fec9c 100644 --- a/services/abilitymgr/include/extension_running_timeout_monitor.h +++ b/services/abilitymgr/include/extension_running_timeout_monitor.h @@ -70,11 +70,6 @@ public: */ void CheckAliveExtensions(); - /** - * @brief Dump cached timeout events and running extensions for debugging. - */ - void Dump(std::vector &info); - private: struct ExtensionStartInfo { std::string extensionTypeName; diff --git a/services/abilitymgr/src/ability_manager_service.cpp b/services/abilitymgr/src/ability_manager_service.cpp index 0d633c897c..d228da5b5c 100644 --- a/services/abilitymgr/src/ability_manager_service.cpp +++ b/services/abilitymgr/src/ability_manager_service.cpp @@ -7301,10 +7301,6 @@ void AbilityManagerService::DumpSysInner( DumpSysStateInner(args, info, isClient, isUserID, userId); DumpSysPendingInner(args, info, isClient, isUserID, userId); DumpSysProcess(args, info, isClient, isUserID, userId); - auto timeoutMonitor = DelayedSingleton::GetInstance(); - if (timeoutMonitor != nullptr) { - timeoutMonitor->Dump(info); - } } void AbilityManagerService::DumpSysMissionListInner( diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index 39fad20128..30162c08c2 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -250,38 +250,6 @@ void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() } } -void ExtensionRunningTimeoutMonitor::Dump(std::vector &info) -{ - info.emplace_back(" ExtensionRunningTimeoutMonitor:"); - { - std::lock_guard lock(monitorMutex_); - info.emplace_back(" Running extensions: " + std::to_string(runningExtensions_.size())); - for (const auto &[recordId, startInfo] : runningExtensions_) { - auto now = std::chrono::steady_clock::now(); - auto nowMillis = std::chrono::duration_cast( - now.time_since_epoch()).count(); - int64_t runningSec = (nowMillis - startInfo.startTimeMillis) / 1000; - int32_t timeout = DelayedSingleton::GetInstance()-> - GetExtensionRunningTimeoutTime(startInfo.extensionTypeName); - info.emplace_back(" [" + std::to_string(recordId) + "] " + - startInfo.bundleName + "/" + startInfo.abilityName + - " type:" + startInfo.extensionTypeName + - " running:" + std::to_string(runningSec) + "s" + - " limit:" + std::to_string(timeout) + "s" + - (timeout > 0 && runningSec > timeout ? " EXCEEDED" : "")); - } - info.emplace_back(" Cached timeout events: " + std::to_string(cachedEvents_.size()) + - "/" + std::to_string(MAX_CACHED_EVENTS)); - for (const auto &event : cachedEvents_) { - info.emplace_back(" " + event.bundleName + "/" + event.abilityName + - " type:" + event.extensionTypeName + - " duration:" + std::to_string(event.runningDuration) + "s" + - " alive:" + (event.stillAlive ? "yes" : "no") + - " cnt:" + std::to_string(event.cnt)); - } - } -} - bool ExtensionRunningTimeoutMonitor::IsDuplicateEvent(const ExtensionTimeoutEvent &event, std::list::iterator &dupIter) { diff --git a/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp b/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp index 2a3ce4bf59..2d243a720f 100644 --- a/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp +++ b/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp @@ -14,6 +14,8 @@ */ #include +#include +#include #include "hilog_tag_wrapper.h" #include "ability_manager_client.h" @@ -21,8 +23,10 @@ #define private public #define protected public #define inline -#include "extension_record.h" +#include "extension_record.h" #include "extension_record_manager.h" +#include "extension_running_timeout_monitor.h" +#include "extension_config.h" #define inline #undef protected #undef private @@ -1092,5 +1096,610 @@ HWTEST_F(ExtensionRecordManagerSecondTest, TerminateTimeout_0100, TestSize.Level TAG_LOGI(AAFwkTag::TEST, "end."); } +// ========== ExtensionRunningTimeoutMonitor TDD Tests ========== + +class ExtensionRunningTimeoutMonitorTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void ExtensionRunningTimeoutMonitorTest::SetUpTestCase() +{} + +void ExtensionRunningTimeoutMonitorTest::TearDownTestCase() +{} + +void ExtensionRunningTimeoutMonitorTest::SetUp() +{ + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + monitor->runningExtensions_.clear(); + monitor->cachedEvents_.clear(); +} + +void ExtensionRunningTimeoutMonitorTest::TearDown() +{ + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + monitor->StopMonitor(); + monitor->runningExtensions_.clear(); + monitor->cachedEvents_.clear(); +} + +/** + * @tc.name: OnExtensionStarted_0100 + * @tc.desc: Test OnExtensionStarted records extension info correctly. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + monitor->OnExtensionStarted(100, "ServiceExtension", "com.test.bundle", "TestAbility"); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(1)); + EXPECT_EQ(monitor->runningExtensions_.count(100), static_cast(1)); + EXPECT_EQ(monitor->runningExtensions_[100].extensionTypeName, "ServiceExtension"); + EXPECT_EQ(monitor->runningExtensions_[100].bundleName, "com.test.bundle"); + EXPECT_EQ(monitor->runningExtensions_[100].abilityName, "TestAbility"); + EXPECT_GT(monitor->runningExtensions_[100].startTimeMillis, static_cast(0)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: OnExtensionStarted_0200 + * @tc.desc: Test OnExtensionStarted with multiple extensions. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + monitor->OnExtensionStarted(1, "ServiceExtension", "com.test.a", "AbilityA"); + monitor->OnExtensionStarted(2, "UIExtension", "com.test.b", "AbilityB"); + monitor->OnExtensionStarted(3, "DataShareExtension", "com.test.c", "AbilityC"); + + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(3)); + EXPECT_EQ(monitor->runningExtensions_[1].extensionTypeName, "ServiceExtension"); + EXPECT_EQ(monitor->runningExtensions_[2].extensionTypeName, "UIExtension"); + EXPECT_EQ(monitor->runningExtensions_[3].extensionTypeName, "DataShareExtension"); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: OnExtensionStarted_0300 + * @tc.desc: Test OnExtensionStarted with same recordId overwrites previous entry. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0300, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + monitor->OnExtensionStarted(100, "ServiceExtension", "com.test.old", "OldAbility"); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(1)); + + monitor->OnExtensionStarted(100, "UIExtension", "com.test.new", "NewAbility"); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(1)); + EXPECT_EQ(monitor->runningExtensions_[100].extensionTypeName, "UIExtension"); + EXPECT_EQ(monitor->runningExtensions_[100].bundleName, "com.test.new"); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: OnExtensionTerminated_0100 + * @tc.desc: Test OnExtensionTerminated with unknown recordId does nothing. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + monitor->OnExtensionTerminated(9999); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(0)); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(0)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: OnExtensionTerminated_0200 + * @tc.desc: Test OnExtensionTerminated removes extension from running list. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + monitor->OnExtensionStarted(100, "ServiceExtension", "com.test.bundle", "TestAbility"); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(1)); + + // No timeout configured (default -1), so no event should be cached + monitor->OnExtensionTerminated(100); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(0)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: OnExtensionTerminated_0300 + * @tc.desc: Test OnExtensionTerminated detects timeout and caches event. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0300, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + // Configure timeout for this extension type via ExtensionConfig + auto config = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(config, nullptr); + AAFwk::ExtensionConfigItem item; + item.extensionRunningTimeoutTime = 1; // 1 second + config->configMap_["TestTimeoutExtension"] = item; + + monitor->OnExtensionStarted(200, "TestTimeoutExtension", "com.test.timeout", "TimeoutAbility"); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(1)); + + // Wait for timeout to be exceeded + std::this_thread::sleep_for(std::chrono::seconds(2)); + + monitor->OnExtensionTerminated(200); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(0)); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(1)); + + auto &event = monitor->cachedEvents_.front(); + EXPECT_EQ(event.extensionTypeName, "TestTimeoutExtension"); + EXPECT_EQ(event.bundleName, "com.test.timeout"); + EXPECT_EQ(event.abilityName, "TimeoutAbility"); + EXPECT_GE(event.runningDuration, static_cast(1)); + EXPECT_EQ(event.stillAlive, false); + EXPECT_EQ(event.cnt, 1); + + // Clean up config + config->configMap_.erase("TestTimeoutExtension"); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: OnExtensionTerminated_0400 + * @tc.desc: Test OnExtensionTerminated within timeout does not cache event. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0400, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + // Configure long timeout + auto config = AAFwk::DelayedSingleton::GetInstance(); + AAFwk::ExtensionConfigItem item; + item.extensionRunningTimeoutTime = 3600; // 1 hour + config->configMap_["TestLongTimeout"] = item; + + monitor->OnExtensionStarted(300, "TestLongTimeout", "com.test.quick", "QuickAbility"); + + // Terminate immediately, well within 1 hour timeout + monitor->OnExtensionTerminated(300); + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(0)); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(0)); + + config->configMap_.erase("TestLongTimeout"); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: AddOrUpdateTimeoutEvent_0100 + * @tc.desc: Test AddOrUpdateTimeoutEvent adds new event when no duplicate. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + AAFwk::ExtensionTimeoutEvent event; + event.extensionTypeName = "ServiceExtension"; + event.bundleName = "com.test.bundle"; + event.abilityName = "Ability1"; + event.runningDuration = 100; + event.stillAlive = false; + event.cnt = 1; + + monitor->AddOrUpdateTimeoutEvent(event); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(1)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: AddOrUpdateTimeoutEvent_0200 + * @tc.desc: Test AddOrUpdateTimeoutEvent increments cnt for duplicate event. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + AAFwk::ExtensionTimeoutEvent event1; + event1.extensionTypeName = "ServiceExtension"; + event1.bundleName = "com.test.dup"; + event1.abilityName = "DupAbility"; + event1.runningDuration = 10; + event1.stillAlive = true; + event1.cnt = 1; + + monitor->AddOrUpdateTimeoutEvent(event1); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(1)); + EXPECT_EQ(monitor->cachedEvents_.front().cnt, 1); + + // Same extension detected again + AAFwk::ExtensionTimeoutEvent event2; + event2.extensionTypeName = "ServiceExtension"; + event2.bundleName = "com.test.dup"; + event2.abilityName = "DupAbility"; + event2.runningDuration = 20; + event2.stillAlive = false; + event2.cnt = 1; + + monitor->AddOrUpdateTimeoutEvent(event2); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(1)); + EXPECT_EQ(monitor->cachedEvents_.front().cnt, 2); + EXPECT_EQ(monitor->cachedEvents_.front().runningDuration, static_cast(20)); + EXPECT_EQ(monitor->cachedEvents_.front().stillAlive, false); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: AddOrUpdateTimeoutEvent_0300 + * @tc.desc: Test AddOrUpdateTimeoutEvent discards event when cache is full. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0300, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + // Fill cache to MAX_CACHED_EVENTS (5) + for (int32_t i = 0; i < monitor->MAX_CACHED_EVENTS; i++) { + AAFwk::ExtensionTimeoutEvent event; + event.extensionTypeName = "ServiceExtension"; + event.bundleName = "com.test.bundle" + std::to_string(i); + event.abilityName = "Ability" + std::to_string(i); + event.runningDuration = i + 1; + event.cnt = 1; + monitor->AddOrUpdateTimeoutEvent(event); + } + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(monitor->MAX_CACHED_EVENTS)); + + // 6th different event should be discarded + AAFwk::ExtensionTimeoutEvent overflowEvent; + overflowEvent.extensionTypeName = "ServiceExtension"; + overflowEvent.bundleName = "com.test.overflow"; + overflowEvent.abilityName = "OverflowAbility"; + overflowEvent.runningDuration = 999; + overflowEvent.cnt = 1; + monitor->AddOrUpdateTimeoutEvent(overflowEvent); + + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(monitor->MAX_CACHED_EVENTS)); + + // Verify overflow event is not in cache + bool found = false; + for (const auto &e : monitor->cachedEvents_) { + if (e.bundleName == "com.test.overflow") { + found = true; + break; + } + } + EXPECT_FALSE(found); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: IsDuplicateEvent_0100 + * @tc.desc: Test IsDuplicateEvent returns true for matching events. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, IsDuplicateEvent_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + AAFwk::ExtensionTimeoutEvent event; + event.extensionTypeName = "ServiceExtension"; + event.bundleName = "com.test.dup"; + event.abilityName = "TestAbility"; + monitor->cachedEvents_.push_back(event); + + AAFwk::ExtensionTimeoutEvent candidate; + candidate.extensionTypeName = "ServiceExtension"; + candidate.bundleName = "com.test.dup"; + candidate.abilityName = "TestAbility"; + + std::list::iterator dupIter; + EXPECT_TRUE(monitor->IsDuplicateEvent(candidate, dupIter)); + EXPECT_EQ(dupIter->bundleName, "com.test.dup"); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: IsDuplicateEvent_0200 + * @tc.desc: Test IsDuplicateEvent returns false for non-matching events. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, IsDuplicateEvent_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + AAFwk::ExtensionTimeoutEvent event; + event.extensionTypeName = "ServiceExtension"; + event.bundleName = "com.test.exist"; + event.abilityName = "ExistAbility"; + monitor->cachedEvents_.push_back(event); + + AAFwk::ExtensionTimeoutEvent candidate; + candidate.extensionTypeName = "UIExtension"; + candidate.bundleName = "com.test.exist"; + candidate.abilityName = "ExistAbility"; + + std::list::iterator dupIter; + EXPECT_FALSE(monitor->IsDuplicateEvent(candidate, dupIter)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: ReportTimeoutEvents_0100 + * @tc.desc: Test ReportTimeoutEvents clears cache after reporting. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, ReportTimeoutEvents_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + AAFwk::ExtensionTimeoutEvent event; + event.extensionTypeName = "ServiceExtension"; + event.bundleName = "com.test.report"; + event.abilityName = "ReportAbility"; + event.runningDuration = 100; + event.stillAlive = false; + event.cnt = 1; + monitor->cachedEvents_.push_back(event); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(1)); + + monitor->ReportTimeoutEvents(); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(0)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: ReportTimeoutEvents_0200 + * @tc.desc: Test ReportTimeoutEvents with empty cache does nothing. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, ReportTimeoutEvents_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(0)); + monitor->ReportTimeoutEvents(); + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(0)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: CheckAliveExtensions_0100 + * @tc.desc: Test CheckAliveExtensions detects running extension exceeding timeout. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, CheckAliveExtensions_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + // Configure timeout + auto config = AAFwk::DelayedSingleton::GetInstance(); + AAFwk::ExtensionConfigItem item; + item.extensionRunningTimeoutTime = 1; // 1 second + config->configMap_["AliveTestExtension"] = item; + + monitor->OnExtensionStarted(400, "AliveTestExtension", "com.test.alive", "AliveAbility"); + + // Wait for timeout + std::this_thread::sleep_for(std::chrono::seconds(2)); + + monitor->CheckAliveExtensions(); + + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(1)); + auto &event = monitor->cachedEvents_.front(); + EXPECT_EQ(event.bundleName, "com.test.alive"); + EXPECT_EQ(event.abilityName, "AliveAbility"); + EXPECT_EQ(event.stillAlive, true); // detected via alive check + EXPECT_GE(event.runningDuration, static_cast(1)); + + // Extension should still be in running list + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(1)); + + config->configMap_.erase("AliveTestExtension"); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: CheckAliveExtensions_0200 + * @tc.desc: Test CheckAliveExtensions skips extensions with no timeout config. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, CheckAliveExtensions_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + // No config for "UnconfiguredExtension", default timeout is -1 + monitor->OnExtensionStarted(500, "UnconfiguredExtension", "com.test.noconfig", "NoConfigAbility"); + + std::this_thread::sleep_for(std::chrono::seconds(2)); + + monitor->CheckAliveExtensions(); + + // Should not create any events since timeout is -1 (disabled) + EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(0)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: StartStopMonitor_0100 + * @tc.desc: Test StartMonitor and StopMonitor do not crash. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, StartStopMonitor_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + monitor->StartMonitor(); + monitor->StopMonitor(); + + // Double stop should not crash + monitor->StopMonitor(); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: ConcurrentAccess_0100 + * @tc.desc: Test concurrent OnExtensionStarted and OnExtensionTerminated do not crash. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, ConcurrentAccess_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto monitor = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(monitor, nullptr); + + const int32_t threadCount = 10; + std::vector threads; + + for (int32_t i = 0; i < threadCount; i++) { + threads.emplace_back([monitor, i]() { + monitor->OnExtensionStarted(i, "ServiceExtension", + "com.test.concurrent", "Ability" + std::to_string(i)); + }); + } + for (auto &t : threads) { + t.join(); + } + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(threadCount)); + + threads.clear(); + for (int32_t i = 0; i < threadCount; i++) { + threads.emplace_back([monitor, i]() { + monitor->OnExtensionTerminated(i); + }); + } + for (auto &t : threads) { + t.join(); + } + EXPECT_EQ(monitor->runningExtensions_.size(), static_cast(0)); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: ExtensionConfigGetRunningTimeoutTime_0100 + * @tc.desc: Test ExtensionConfig GetExtensionRunningTimeoutTime returns default when not configured. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, ExtensionConfigGetRunningTimeoutTime_0100, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto config = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(config, nullptr); + + int32_t timeout = config->GetExtensionRunningTimeoutTime("NonExistentType"); + EXPECT_EQ(timeout, AAFwk::DEFAULT_EXTENSION_RUNNING_TIMEOUT_TIME); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + +/** + * @tc.name: ExtensionConfigGetRunningTimeoutTime_0200 + * @tc.desc: Test ExtensionConfig GetExtensionRunningTimeoutTime returns configured value. + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(ExtensionRunningTimeoutMonitorTest, ExtensionConfigGetRunningTimeoutTime_0200, TestSize.Level1) +{ + TAG_LOGI(AAFwkTag::TEST, "begin."); + auto config = AAFwk::DelayedSingleton::GetInstance(); + ASSERT_NE(config, nullptr); + + AAFwk::ExtensionConfigItem item; + item.extensionRunningTimeoutTime = 5000; + config->configMap_["ConfiguredType"] = item; + + int32_t timeout = config->GetExtensionRunningTimeoutTime("ConfiguredType"); + EXPECT_EQ(timeout, 5000); + + config->configMap_.erase("ConfiguredType"); + + TAG_LOGI(AAFwkTag::TEST, "end."); +} + } // namespace AbilityRuntime } // namespace OHOS From 9d87ca8389223d50d0c729b36954fbb9f024b483 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Thu, 9 Apr 2026 17:34:08 +0800 Subject: [PATCH 15/20] fix: replace magic number in HisyseventReport constructor with named constant Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: Icd4edc9bddfa002b345b5df43fcb8236033e1978 --- services/abilitymgr/include/extension_running_timeout_monitor.h | 1 + services/abilitymgr/src/extension_running_timeout_monitor.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/services/abilitymgr/include/extension_running_timeout_monitor.h b/services/abilitymgr/include/extension_running_timeout_monitor.h index 48981fec9c..60a0875b22 100644 --- a/services/abilitymgr/include/extension_running_timeout_monitor.h +++ b/services/abilitymgr/include/extension_running_timeout_monitor.h @@ -87,6 +87,7 @@ private: std::unordered_map runningExtensions_; std::list cachedEvents_; + static constexpr int32_t HISEVENT_PARAM_COUNT = 7; static constexpr int32_t MAX_CACHED_EVENTS = 5; static constexpr int64_t REPORT_INTERVAL_MS = 2 * 60 * 60 * 1000; // 2 hours static constexpr const char *PERIODIC_TASK_NAME = "ExtensionTimeoutPeriodicTask"; diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index 30162c08c2..4255aa8274 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -194,7 +194,7 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() abilityNamePtrs.push_back(const_cast(name.c_str())); } - HisyseventReport report(7); + HisyseventReport report(HISEVENT_PARAM_COUNT); report.InsertParam(EXTENSION_TYPE_KEY, extensionTypePtrs); report.InsertParam(BUNDLE_NAME_KEY, bundleNamePtrs); report.InsertParam(ABILITY_NAME_KEY, abilityNamePtrs); From f5abfbb83685784abd6b8365029c5ca1d64fee12 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Thu, 9 Apr 2026 20:40:03 +0800 Subject: [PATCH 16/20] fix: remove incorrect AAFwk namespace prefix for DelayedSingleton in TDD tests DelayedSingleton is defined in OHOS namespace (singleton.h), not in AAFwk namespace. Using AAFwk::DelayedSingleton caused compilation failure on GitCode gate (dayu200_tdd) though internal build passed due to different compiler namespace resolution behavior. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I10b32ac8db5acdcfe5c55ed3ade0107e701a9f76 --- .../extension_record_manager_second_test.cpp | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp b/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp index 2d243a720f..ca9d0009b0 100644 --- a/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp +++ b/test/unittest/ui_extension/extension_record_manager_second_test/extension_record_manager_second_test.cpp @@ -1114,14 +1114,14 @@ void ExtensionRunningTimeoutMonitorTest::TearDownTestCase() void ExtensionRunningTimeoutMonitorTest::SetUp() { - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); monitor->runningExtensions_.clear(); monitor->cachedEvents_.clear(); } void ExtensionRunningTimeoutMonitorTest::TearDown() { - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); monitor->StopMonitor(); monitor->runningExtensions_.clear(); monitor->cachedEvents_.clear(); @@ -1136,7 +1136,7 @@ void ExtensionRunningTimeoutMonitorTest::TearDown() HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); monitor->OnExtensionStarted(100, "ServiceExtension", "com.test.bundle", "TestAbility"); @@ -1159,7 +1159,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0100, TestSize.L HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0200, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); monitor->OnExtensionStarted(1, "ServiceExtension", "com.test.a", "AbilityA"); @@ -1183,7 +1183,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0200, TestSize.L HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0300, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); monitor->OnExtensionStarted(100, "ServiceExtension", "com.test.old", "OldAbility"); @@ -1206,7 +1206,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionStarted_0300, TestSize.L HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); monitor->OnExtensionTerminated(9999); @@ -1225,7 +1225,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0100, TestSiz HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0200, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); monitor->OnExtensionStarted(100, "ServiceExtension", "com.test.bundle", "TestAbility"); @@ -1247,11 +1247,11 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0200, TestSiz HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0300, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); // Configure timeout for this extension type via ExtensionConfig - auto config = AAFwk::DelayedSingleton::GetInstance(); + auto config = DelayedSingleton::GetInstance(); ASSERT_NE(config, nullptr); AAFwk::ExtensionConfigItem item; item.extensionRunningTimeoutTime = 1; // 1 second @@ -1290,11 +1290,11 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0300, TestSiz HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0400, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); // Configure long timeout - auto config = AAFwk::DelayedSingleton::GetInstance(); + auto config = DelayedSingleton::GetInstance(); AAFwk::ExtensionConfigItem item; item.extensionRunningTimeoutTime = 3600; // 1 hour config->configMap_["TestLongTimeout"] = item; @@ -1320,7 +1320,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, OnExtensionTerminated_0400, TestSiz HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); AAFwk::ExtensionTimeoutEvent event; @@ -1346,7 +1346,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0100, TestS HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0200, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); AAFwk::ExtensionTimeoutEvent event1; @@ -1388,7 +1388,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0200, TestS HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0300, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); // Fill cache to MAX_CACHED_EVENTS (5) @@ -1436,7 +1436,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, AddOrUpdateTimeoutEvent_0300, TestS HWTEST_F(ExtensionRunningTimeoutMonitorTest, IsDuplicateEvent_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); AAFwk::ExtensionTimeoutEvent event; @@ -1466,7 +1466,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, IsDuplicateEvent_0100, TestSize.Lev HWTEST_F(ExtensionRunningTimeoutMonitorTest, IsDuplicateEvent_0200, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); AAFwk::ExtensionTimeoutEvent event; @@ -1495,7 +1495,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, IsDuplicateEvent_0200, TestSize.Lev HWTEST_F(ExtensionRunningTimeoutMonitorTest, ReportTimeoutEvents_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); AAFwk::ExtensionTimeoutEvent event; @@ -1523,7 +1523,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, ReportTimeoutEvents_0100, TestSize. HWTEST_F(ExtensionRunningTimeoutMonitorTest, ReportTimeoutEvents_0200, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); EXPECT_EQ(monitor->cachedEvents_.size(), static_cast(0)); @@ -1542,11 +1542,11 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, ReportTimeoutEvents_0200, TestSize. HWTEST_F(ExtensionRunningTimeoutMonitorTest, CheckAliveExtensions_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); // Configure timeout - auto config = AAFwk::DelayedSingleton::GetInstance(); + auto config = DelayedSingleton::GetInstance(); AAFwk::ExtensionConfigItem item; item.extensionRunningTimeoutTime = 1; // 1 second config->configMap_["AliveTestExtension"] = item; @@ -1582,7 +1582,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, CheckAliveExtensions_0100, TestSize HWTEST_F(ExtensionRunningTimeoutMonitorTest, CheckAliveExtensions_0200, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); // No config for "UnconfiguredExtension", default timeout is -1 @@ -1607,7 +1607,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, CheckAliveExtensions_0200, TestSize HWTEST_F(ExtensionRunningTimeoutMonitorTest, StartStopMonitor_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); monitor->StartMonitor(); @@ -1628,7 +1628,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, StartStopMonitor_0100, TestSize.Lev HWTEST_F(ExtensionRunningTimeoutMonitorTest, ConcurrentAccess_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto monitor = AAFwk::DelayedSingleton::GetInstance(); + auto monitor = DelayedSingleton::GetInstance(); ASSERT_NE(monitor, nullptr); const int32_t threadCount = 10; @@ -1668,7 +1668,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, ConcurrentAccess_0100, TestSize.Lev HWTEST_F(ExtensionRunningTimeoutMonitorTest, ExtensionConfigGetRunningTimeoutTime_0100, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto config = AAFwk::DelayedSingleton::GetInstance(); + auto config = DelayedSingleton::GetInstance(); ASSERT_NE(config, nullptr); int32_t timeout = config->GetExtensionRunningTimeoutTime("NonExistentType"); @@ -1686,7 +1686,7 @@ HWTEST_F(ExtensionRunningTimeoutMonitorTest, ExtensionConfigGetRunningTimeoutTim HWTEST_F(ExtensionRunningTimeoutMonitorTest, ExtensionConfigGetRunningTimeoutTime_0200, TestSize.Level1) { TAG_LOGI(AAFwkTag::TEST, "begin."); - auto config = AAFwk::DelayedSingleton::GetInstance(); + auto config = DelayedSingleton::GetInstance(); ASSERT_NE(config, nullptr); AAFwk::ExtensionConfigItem item; From a99806d0ba46fa32f3379b07051700414e83fedb Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Thu, 9 Apr 2026 21:23:13 +0800 Subject: [PATCH 17/20] fix: check new(std::nothrow) return value in HisyseventReport constructor Set length_ to 0 when params_ allocation fails, preventing null pointer dereference in subsequent InsertParam calls. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I1a7c8b8eb9bf83a69dd71ecef409ce0a029fb686 --- services/common/include/hisysevent_report.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/common/include/hisysevent_report.h b/services/common/include/hisysevent_report.h index e3e2b5f560..1120ee144b 100644 --- a/services/common/include/hisysevent_report.h +++ b/services/common/include/hisysevent_report.h @@ -33,6 +33,9 @@ public: return; } this->params_ = new (std::nothrow) HiSysEventParam[SYSTEM_PARAM_MAX_LEN]; + if (this->params_ == nullptr) { + length_ = 0; + } } ~HisyseventReport() { From 7189790b58973ae6be4255b9cff1d077b8f20ee0 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Thu, 9 Apr 2026 22:50:29 +0800 Subject: [PATCH 18/20] fix: add missing TaskHandlerWrap and HisyseventReport sources for TDD build The test compiles extension_running_timeout_monitor.cpp directly but was missing its dependency sources. Add ffrt_task_handler_wrap.cpp, queue_task_handler_wrap.cpp, task_handler_wrap.cpp and hisysevent_report.cpp to sources, plus task_handler_wrap dep. Follows existing test patterns. Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I9807c22144f168532c5e22746d658c2ea87f6ac8 --- .../extension_record_manager_second_test/BUILD.gn | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn b/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn index 45f05f5483..b24a9b0eea 100644 --- a/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn +++ b/test/unittest/ui_extension/extension_record_manager_second_test/BUILD.gn @@ -50,6 +50,10 @@ ohos_unittest("extension_record_manager_second_test") { "${ability_runtime_services_path}/abilitymgr/src/extension_record/extension_record_manager.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_running_timeout_monitor.cpp", "${ability_runtime_services_path}/abilitymgr/src/extension_config.cpp", + "${ability_runtime_services_path}/common/src/ffrt_task_handler_wrap.cpp", + "${ability_runtime_services_path}/common/src/hisysevent_report.cpp", + "${ability_runtime_services_path}/common/src/queue_task_handler_wrap.cpp", + "${ability_runtime_services_path}/common/src/task_handler_wrap.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension/preload_uiext_state_observer.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record.cpp", "${ability_runtime_services_path}/abilitymgr/src/ui_extension_record/ui_extension_record_factory.cpp", @@ -75,6 +79,7 @@ ohos_unittest("extension_record_manager_second_test") { "${ability_runtime_path}/utils/global/common:runtime_utils", "${ability_runtime_path}/utils/server/startup:startup_util", "${ability_runtime_services_path}/abilitymgr:abilityms", + "${ability_runtime_services_path}/common:task_handler_wrap", ] external_deps = [ From da37161d84bf36915fb39a06a50cdb24834401a0 Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Fri, 10 Apr 2026 16:51:49 +0800 Subject: [PATCH 19/20] fix: resolve stability and security issues in ExtensionRunningTimeoutMonitor - Replace [this] lambda capture with GetInstance() to avoid passing raw this pointer to ffrt task thread - Use GetRecordId() instead of std::hash for recordId to prevent hash collisions and duplicate tracking - Eliminate const_cast on c_str() by copying strings via make_unique + strcpy_s - Batch event insertion under single lock in CheckAliveExtensions - Initialize HisyseventReport::params_ to nullptr - Fix new bool[]/unique_ptr type mismatch in InsertParam - Add proper const char* overload instead of const_cast for string params - Unify strcpy_s return value check with EOK constant Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: I26c6390a758170258ca55ae2bfe694ce7c07ca79 --- .../src/ability_connect_manager.cpp | 5 +- .../src/extension_running_timeout_monitor.cpp | 68 +++++++++++++------ services/common/include/hisysevent_report.h | 2 +- services/common/src/hisysevent_report.cpp | 38 ++++++++--- 4 files changed, 81 insertions(+), 32 deletions(-) diff --git a/services/abilitymgr/src/ability_connect_manager.cpp b/services/abilitymgr/src/ability_connect_manager.cpp index 911f67b07c..7ff234b6e0 100644 --- a/services/abilitymgr/src/ability_connect_manager.cpp +++ b/services/abilitymgr/src/ability_connect_manager.cpp @@ -286,8 +286,7 @@ void AbilityConnectManager::RemoveServiceFromMapSafe(const std::string &serviceK std::lock_guard lock(serviceMapMutex_); auto it = serviceMap_.find(serviceKey); if (it != serviceMap_.end() && it->second != nullptr) { - auto &abilityInfo = it->second->GetAbilityInfo(); - auto recordId = static_cast(std::hash{}(serviceKey)); + auto recordId = it->second->GetRecordId(); auto monitor = DelayedSingleton::GetInstance(); if (monitor != nullptr) { monitor->OnExtensionTerminated(recordId); @@ -3258,7 +3257,7 @@ void AbilityConnectManager::GetOrCreateServiceRecord(const AbilityRequest &abili // Notify running timeout monitor about service extension start auto &newAbilityInfo = abilityRequest.abilityInfo; - auto recordId = static_cast(std::hash{}(serviceKey)); + auto recordId = targetService->GetRecordId(); auto monitor = DelayedSingleton::GetInstance(); if (monitor != nullptr) { monitor->OnExtensionStarted(recordId, diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index 4255aa8274..5e40e246a0 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -20,6 +20,7 @@ #include #include "extension_config.h" +#include "securec.h" #include "hisysevent_report.h" #include "hilog_tag_wrapper.h" #include "task_handler_wrap.h" @@ -143,12 +144,12 @@ void ExtensionRunningTimeoutMonitor::SubmitPeriodicTask() return; } - auto task = [this]() { + auto task = []() { TAG_LOGI(AAFwkTag::ABILITYMGR, "extension timeout periodic task triggered"); - CheckAliveExtensions(); - ReportTimeoutEvents(); - // Re-submit for next cycle - SubmitPeriodicTask(); + auto monitor = DelayedSingleton::GetInstance(); + monitor->CheckAliveExtensions(); + monitor->ReportTimeoutEvents(); + monitor->SubmitPeriodicTask(); }; taskHandler->SubmitTask(task, PERIODIC_TASK_NAME, REPORT_INTERVAL_MS); } @@ -166,32 +167,53 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() cachedEvents_.clear(); } - std::vector extensionTypeNames; + std::vector> stringBuffers; std::vector extensionTypePtrs; std::vector bundleNamePtrs; std::vector abilityNamePtrs; std::vector runningDurations; std::vector stillAliveFlags; std::vector cnts; - std::vector bundleNames; - std::vector abilityNames; for (const auto &event : eventsToReport) { - extensionTypeNames.push_back(event.extensionTypeName); - bundleNames.push_back(event.bundleName); - abilityNames.push_back(event.abilityName); + size_t extLen = event.extensionTypeName.size() + 1; + auto extBuf = std::make_unique(extLen); + if (strcpy_s(extBuf.get(), extLen, event.extensionTypeName.c_str()) != EOK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "strcpy_s failed for extensionTypeName"); + continue; + } + + size_t bundleLen = event.bundleName.size() + 1; + auto bundleBuf = std::make_unique(bundleLen); + if (strcpy_s(bundleBuf.get(), bundleLen, event.bundleName.c_str()) != EOK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "strcpy_s failed for bundleName"); + continue; + } + + size_t abilityLen = event.abilityName.size() + 1; + auto abilityBuf = std::make_unique(abilityLen); + if (strcpy_s(abilityBuf.get(), abilityLen, event.abilityName.c_str()) != EOK) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "strcpy_s failed for abilityName"); + continue; + } + + extensionTypePtrs.push_back(extBuf.get()); + stringBuffers.push_back(std::move(extBuf)); + + bundleNamePtrs.push_back(bundleBuf.get()); + stringBuffers.push_back(std::move(bundleBuf)); + + abilityNamePtrs.push_back(abilityBuf.get()); + stringBuffers.push_back(std::move(abilityBuf)); + runningDurations.push_back(event.runningDuration); stillAliveFlags.push_back(event.stillAlive); cnts.push_back(event.cnt); } - for (auto &name : extensionTypeNames) { - extensionTypePtrs.push_back(const_cast(name.c_str())); - } - for (auto &name : bundleNames) { - bundleNamePtrs.push_back(const_cast(name.c_str())); - } - for (auto &name : abilityNames) { - abilityNamePtrs.push_back(const_cast(name.c_str())); + + if (extensionTypePtrs.empty()) { + TAG_LOGW(AAFwkTag::ABILITYMGR, "no valid events to report after buffer preparation"); + return; } HisyseventReport report(HISEVENT_PARAM_COUNT); @@ -220,6 +242,7 @@ void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() auto now = std::chrono::steady_clock::now(); auto nowMillis = std::chrono::duration_cast(now.time_since_epoch()).count(); + std::vector pendingEvents; for (auto &[recordId, startInfo] : aliveCopy) { int32_t configuredTimeout = DelayedSingleton::GetInstance()-> GetExtensionRunningTimeoutTime(startInfo.extensionTypeName); @@ -244,9 +267,14 @@ void ExtensionRunningTimeoutMonitor::CheckAliveExtensions() event.runningDuration = runningDurationSec; event.stillAlive = true; event.cnt = 1; + pendingEvents.push_back(event); + } + if (!pendingEvents.empty()) { std::lock_guard lock(monitorMutex_); - AddOrUpdateTimeoutEvent(event); + for (auto &event : pendingEvents) { + AddOrUpdateTimeoutEvent(event); + } } } diff --git a/services/common/include/hisysevent_report.h b/services/common/include/hisysevent_report.h index 1120ee144b..ee64c7bc3e 100644 --- a/services/common/include/hisysevent_report.h +++ b/services/common/include/hisysevent_report.h @@ -67,7 +67,7 @@ private: void SetParamName(HiSysEventParam& param, const char* name); std::vector> paramBuffers_; - HiSysEventParam* params_; + HiSysEventParam* params_ = nullptr; int32_t length_ = SYSTEM_PARAM_MAX_LEN; int32_t pos_ = 0; }; diff --git a/services/common/src/hisysevent_report.cpp b/services/common/src/hisysevent_report.cpp index b262791b19..87cf67c8e4 100644 --- a/services/common/src/hisysevent_report.cpp +++ b/services/common/src/hisysevent_report.cpp @@ -197,7 +197,7 @@ void HisyseventReport::InsertParam(const char* name, char* value) int32_t len = std::strlen(value) + 1; auto buffer = std::make_unique(len); int32_t ret = strcpy_s(buffer.get(), len, value); - if (ret != 0) { + if (ret != EOK) { TAG_LOGE(AAFwkTag::DEFAULT, "InsertParam err %{public}d", ret); return; } @@ -286,14 +286,16 @@ void HisyseventReport::InsertParam(const char* name, const std::vector &va }; if (!value.empty()) { - auto *buf = new (std::nothrow) bool[value.size()]; + size_t bufSize = value.size() * sizeof(bool); + auto *buf = new (std::nothrow) char[bufSize](); if (buf != nullptr) { + auto *boolBuf = reinterpret_cast(buf); for (size_t i = 0; i < value.size(); ++i) { - buf[i] = value[i]; + boolBuf[i] = value[i]; } - param.v.array = static_cast(buf); + param.v.array = static_cast(boolBuf); param.arraySize = value.size(); - paramBuffers_.emplace_back(reinterpret_cast(buf)); + paramBuffers_.emplace_back(buf); } } SetParamName(param, name); @@ -322,18 +324,38 @@ void HisyseventReport::InsertParam(const char* name, const std::vector void HisyseventReport::InsertParam(const char* name, std::string value) { - this->InsertParam(name, const_cast(value.c_str())); + this->InsertParam(name, value.c_str()); } void HisyseventReport::InsertParam(const char* name, const char* value) { - this->InsertParam(name, const_cast(value)); + if (!name || !value || length_ <= pos_) { + TAG_LOGE(AAFwkTag::DEFAULT, "param is full"); + return; + } + int32_t len = static_cast(std::strlen(value)) + 1; + auto buffer = std::make_unique(len); + int32_t ret = strcpy_s(buffer.get(), len, value); + if (ret != EOK) { + TAG_LOGE(AAFwkTag::DEFAULT, "InsertParam err %{public}d", ret); + return; + } + + HiSysEventParam param = { + .t = HISYSEVENT_STRING, + .v = { .s = buffer.get()}, + .arraySize = 0, + }; + SetParamName(param, name); + params_[pos_++] = param; + + paramBuffers_.emplace_back(std::move(buffer)); } void HisyseventReport::SetParamName(HiSysEventParam& param, const char* name) { int32_t ret = strcpy_s(param.name, sizeof(param.name), name); - if (ret != 0) { + if (ret != EOK) { TAG_LOGE(AAFwkTag::DEFAULT, "SetParamName err %{public}d", ret); } } From 4a381004f9334d7c683a5f2b4ad41852a560291b Mon Sep 17 00:00:00 2001 From: zhang_hao_zheng Date: Fri, 10 Apr 2026 17:37:36 +0800 Subject: [PATCH 20/20] refactor: extract CopyStringParam helper to reduce ReportTimeoutEvents under 50 lines Signed-off-by: zhang_hao_zheng Co-Authored-By: Agent Change-Id: If33c0c6c3962a545021d0ffb2ace1ad49aeb4b02 --- .../src/extension_running_timeout_monitor.cpp | 45 +++++++------------ 1 file changed, 17 insertions(+), 28 deletions(-) diff --git a/services/abilitymgr/src/extension_running_timeout_monitor.cpp b/services/abilitymgr/src/extension_running_timeout_monitor.cpp index 5e40e246a0..e7259fb3c0 100644 --- a/services/abilitymgr/src/extension_running_timeout_monitor.cpp +++ b/services/abilitymgr/src/extension_running_timeout_monitor.cpp @@ -36,6 +36,19 @@ constexpr const char *ABILITY_NAME_KEY = "ABILITY_NAME"; constexpr const char *RUNNING_DURATION_KEY = "RUNNING_DURATION"; constexpr const char *STILL_ALIVE_KEY = "STILL_ALIVE"; constexpr const char *CNT_KEY = "CNT"; + +bool CopyStringParam(const std::string &str, std::vector> &buffers, + std::vector &ptrs) +{ + size_t len = str.size() + 1; + auto buf = std::make_unique(len); + if (strcpy_s(buf.get(), len, str.c_str()) != EOK) { + return false; + } + ptrs.push_back(buf.get()); + buffers.push_back(std::move(buf)); + return true; +} } ExtensionRunningTimeoutMonitor::ExtensionRunningTimeoutMonitor() {} @@ -176,36 +189,12 @@ void ExtensionRunningTimeoutMonitor::ReportTimeoutEvents() std::vector cnts; for (const auto &event : eventsToReport) { - size_t extLen = event.extensionTypeName.size() + 1; - auto extBuf = std::make_unique(extLen); - if (strcpy_s(extBuf.get(), extLen, event.extensionTypeName.c_str()) != EOK) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "strcpy_s failed for extensionTypeName"); + if (!CopyStringParam(event.extensionTypeName, stringBuffers, extensionTypePtrs) || + !CopyStringParam(event.bundleName, stringBuffers, bundleNamePtrs) || + !CopyStringParam(event.abilityName, stringBuffers, abilityNamePtrs)) { + TAG_LOGE(AAFwkTag::ABILITYMGR, "strcpy_s failed for event string"); continue; } - - size_t bundleLen = event.bundleName.size() + 1; - auto bundleBuf = std::make_unique(bundleLen); - if (strcpy_s(bundleBuf.get(), bundleLen, event.bundleName.c_str()) != EOK) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "strcpy_s failed for bundleName"); - continue; - } - - size_t abilityLen = event.abilityName.size() + 1; - auto abilityBuf = std::make_unique(abilityLen); - if (strcpy_s(abilityBuf.get(), abilityLen, event.abilityName.c_str()) != EOK) { - TAG_LOGE(AAFwkTag::ABILITYMGR, "strcpy_s failed for abilityName"); - continue; - } - - extensionTypePtrs.push_back(extBuf.get()); - stringBuffers.push_back(std::move(extBuf)); - - bundleNamePtrs.push_back(bundleBuf.get()); - stringBuffers.push_back(std::move(bundleBuf)); - - abilityNamePtrs.push_back(abilityBuf.get()); - stringBuffers.push_back(std::move(abilityBuf)); - runningDurations.push_back(event.runningDuration); stillAliveFlags.push_back(event.stillAlive); cnts.push_back(event.cnt);