diff --git a/OAT.xml b/OAT.xml
index 8dca4dd1122389f3e550789ae95b3c5155cb40ee..4c5f051eabe86bbeaed58f72de142bdfb37be482 100644
--- a/OAT.xml
+++ b/OAT.xml
@@ -62,6 +62,7 @@ Note:If the text contains special characters, please escape them according to th
+
@@ -71,6 +72,7 @@ Note:If the text contains special characters, please escape them according to th
+
diff --git a/framework/native/unified_collection/process/include/process_status.h b/framework/native/unified_collection/process/include/process_status.h
index f0a95f81d53cadd57edbf8d4f58cb1cc51e8898b..af3ad60f39fd2e3e6cc2b4eed66b1ab176fab6e5 100644
--- a/framework/native/unified_collection/process/include/process_status.h
+++ b/framework/native/unified_collection/process/include/process_status.h
@@ -23,18 +23,37 @@
namespace OHOS {
namespace HiviewDFX {
namespace UCollectUtil {
+enum ProcessState {
+ INVALID = -1,
+ BACKGROUND = 0,
+ FOREGROUND,
+};
+
+struct ProcessInfo {
+ std::string name;
+ ProcessState state;
+ uint64_t lastForegroundTime;
+};
+
class ProcessStatus : public OHOS::DelayedRefSingleton {
public:
std::string GetProcessName(int32_t pid);
+ ProcessState GetProcessState(int32_t pid);
+ uint64_t GetProcessLastForegroundTime(int32_t pid);
+ void NotifyProcessState(int32_t pid, ProcessState procState);
private:
- bool NeedClearProcessNames();
- void ClearProcessNames();
+ bool UpdateProcessName(int32_t pid, const std::string& procName);
+ void UpdateProcessState(int32_t pid, ProcessState procState);
+ void UpdateProcessForegroundState(int32_t pid);
+ void UpdateProcessBackgroundState(int32_t pid);
+ bool NeedClearProcessInfos();
+ void ClearProcessInfos();
private:
std::mutex mutex_;
- /* map */
- std::unordered_map processNames_;
+ /* map */
+ std::unordered_map processInfos_;
};
} // namespace UCollectUtil
} // namespace HiviewDFX
diff --git a/framework/native/unified_collection/process/process_status.cpp b/framework/native/unified_collection/process/process_status.cpp
index b9140b784e906aca1211a80eb155e520462cdd4e..a18a9b14ae59d68292fb6c278ee05b7fb4265b3f 100644
--- a/framework/native/unified_collection/process/process_status.cpp
+++ b/framework/native/unified_collection/process/process_status.cpp
@@ -14,14 +14,19 @@
*/
#include "process_status.h"
+#include
+
#include "file_util.h"
#include "logger.h"
+#include "time_util.h"
namespace OHOS {
namespace HiviewDFX {
namespace UCollectUtil {
DEFINE_LOG_TAG("UCollectUtil-ProcessStatus");
namespace {
+constexpr uint64_t INVALID_LAST_FOREGROUND_TIME = 0;
+
bool IsValidProcessId(int32_t pid)
{
std::string procDir = "/proc/" + std::to_string(pid);
@@ -78,44 +83,129 @@ std::string ProcessStatus::GetProcessName(int32_t pid)
{
std::unique_lock lock(mutex_);
// the cleanup judgment is triggered each time
- if (NeedClearProcessNames()) {
- ClearProcessNames();
+ if (NeedClearProcessInfos()) {
+ ClearProcessInfos();
}
- if (processNames_.find(pid) != processNames_.end()) {
- return processNames_[pid];
+ if (processInfos_.find(pid) != processInfos_.end() && !processInfos_[pid].name.empty()) {
+ return processInfos_[pid].name;
}
std::string procName = GetProcessNameFromProcCmdline(pid);
- if (!procName.empty()) {
- processNames_[pid] = procName;
+ if (UpdateProcessName(pid, procName)) {
return procName;
}
procName = GetProcessNameFromProcStat(pid);
- if (!procName.empty()) {
- processNames_[pid] = procName;
+ if (UpdateProcessName(pid, procName)) {
return procName;
}
HIVIEW_LOGW("failed to get proc name from pid=%{public}d", pid);
return "";
}
-bool ProcessStatus::NeedClearProcessNames()
+bool ProcessStatus::NeedClearProcessInfos()
{
constexpr size_t maxSizeOfProcessNames = 1000;
- return processNames_.size() > maxSizeOfProcessNames;
+ return processInfos_.size() > maxSizeOfProcessNames;
}
-void ProcessStatus::ClearProcessNames()
+void ProcessStatus::ClearProcessInfos()
{
- HIVIEW_LOGI("start to clear process name, size=%{public}zu", processNames_.size());
- for (auto it = processNames_.begin(); it != processNames_.end();) {
+ HIVIEW_LOGI("start to clear process cache, size=%{public}zu", processInfos_.size());
+ for (auto it = processInfos_.begin(); it != processInfos_.end();) {
if (!IsValidProcessId(it->first)) {
- processNames_.erase(it++);
+ processInfos_.erase(it++);
} else {
it++;
}
}
- HIVIEW_LOGI("end to clear process name, size=%{public}zu", processNames_.size());
+ HIVIEW_LOGI("end to clear process cache, size=%{public}zu", processInfos_.size());
+}
+
+bool ProcessStatus::UpdateProcessName(int32_t pid, const std::string& procName)
+{
+ if (procName.empty()) {
+ return false;
+ }
+
+ if (processInfos_.find(pid) != processInfos_.end()) {
+ processInfos_[pid].name = procName;
+ return true;
+ }
+ processInfos_[pid] = {
+ .name = procName,
+ .state = BACKGROUND,
+ .lastForegroundTime = INVALID_LAST_FOREGROUND_TIME,
+ };
+ return true;
+}
+
+ProcessState ProcessStatus::GetProcessState(int32_t pid)
+{
+ std::unique_lock lock(mutex_);
+ return (processInfos_.find(pid) != processInfos_.end())
+ ? processInfos_[pid].state
+ : BACKGROUND;
+}
+
+uint64_t ProcessStatus::GetProcessLastForegroundTime(int32_t pid)
+{
+ std::unique_lock lock(mutex_);
+ return (processInfos_.find(pid) != processInfos_.end())
+ ? processInfos_[pid].lastForegroundTime
+ : INVALID_LAST_FOREGROUND_TIME;
+}
+
+void ProcessStatus::NotifyProcessState(int32_t pid, ProcessState procState)
+{
+ std::unique_lock lock(mutex_);
+ UpdateProcessState(pid, procState);
+}
+
+void ProcessStatus::UpdateProcessState(int32_t pid, ProcessState procState)
+{
+ HIVIEW_LOGI("update process=%{public}d state=%{public}d", pid, procState);
+ switch (procState) {
+ case FOREGROUND:
+ UpdateProcessForegroundState(pid);
+ break;
+ case BACKGROUND:
+ UpdateProcessBackgroundState(pid);
+ break;
+ default:
+ HIVIEW_LOGW("invalid process=%{public}d state=%{public}d", pid, procState);
+ }
+}
+
+void ProcessStatus::UpdateProcessForegroundState(int32_t pid)
+{
+ uint64_t nowTime = TimeUtil::GetMilliseconds();
+ if (processInfos_.find(pid) != processInfos_.end()) {
+ processInfos_[pid].state = FOREGROUND;
+ processInfos_[pid].lastForegroundTime = nowTime;
+ return;
+ }
+ processInfos_[pid] = {
+ .name = "",
+ .state = FOREGROUND,
+ .lastForegroundTime = nowTime,
+ };
+}
+
+void ProcessStatus::UpdateProcessBackgroundState(int32_t pid)
+{
+ if (processInfos_.find(pid) != processInfos_.end()) {
+ // last foreground time needs to be updated when the foreground status is switched to the background
+ if (processInfos_[pid].state == FOREGROUND) {
+ processInfos_[pid].lastForegroundTime = TimeUtil::GetMilliseconds();
+ }
+ processInfos_[pid].state = BACKGROUND;
+ return;
+ }
+ processInfos_[pid] = {
+ .name = "",
+ .state = BACKGROUND,
+ .lastForegroundTime = INVALID_LAST_FOREGROUND_TIME,
+ };
}
} // UCollectUtil
} // namespace HiviewDFX
diff --git a/plugins/unified_collector/BUILD.gn b/plugins/unified_collector/BUILD.gn
index f5e149fefa06e04af2d006e7bd5aca772d20c3bb..970f28c51b424fc17a5d5e24e451ed849c0d8b52 100644
--- a/plugins/unified_collector/BUILD.gn
+++ b/plugins/unified_collector/BUILD.gn
@@ -19,6 +19,7 @@ config("unified_collector_config") {
"include",
"storage/include",
"task/include",
+ "$hiview_framework/native/unified_collection/process/include",
]
}
@@ -34,6 +35,7 @@ ohos_source_set("unified_collector") {
deps = [
"$hiview_base:hiviewbase",
"$hiview_interfaces/inner_api/unified_collection/utility:libucollection_utility",
+ "config:UnifiedCollector_event",
]
external_deps = [
diff --git a/plugins/unified_collector/config/BUILD.gn b/plugins/unified_collector/config/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..5248d6f5dcd58538a3534bf8dbe5dcabe5c31efb
--- /dev/null
+++ b/plugins/unified_collector/config/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright (c) 2023 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.
+import("//build/ohos.gni")
+
+ohos_prebuilt_etc("UnifiedCollector_event") {
+ source = "UnifiedCollector"
+ relative_install_dir = "hiview/listener_rule"
+ part_name = "hiview"
+ subsystem_name = "hiviewdfx"
+}
diff --git a/plugins/unified_collector/config/UnifiedCollector b/plugins/unified_collector/config/UnifiedCollector
new file mode 100644
index 0000000000000000000000000000000000000000..4efb8a0e0d3df6e8f654e95794c8cfce2b003e8a
--- /dev/null
+++ b/plugins/unified_collector/config/UnifiedCollector
@@ -0,0 +1,8 @@
+{
+ "domains": [
+ {
+ "domain": "AAFWK",
+ "include": ["APP_FOREGROUND", "APP_BACKGROUND"]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/plugins/unified_collector/include/unified_collector.h b/plugins/unified_collector/include/unified_collector.h
index 96af9232ae3cb675e9450da92de64021938594ee..b0db43048242febe010f8bcee70fa2e8bdf1b5c2 100644
--- a/plugins/unified_collector/include/unified_collector.h
+++ b/plugins/unified_collector/include/unified_collector.h
@@ -26,6 +26,7 @@ class UnifiedCollector : public Plugin {
public:
void OnLoad() override;
void OnUnload() override;
+ void OnEventListeningCallback(const Event& event) override;
private:
void Init();
diff --git a/plugins/unified_collector/storage/cpu_storage.cpp b/plugins/unified_collector/storage/cpu_storage.cpp
index 94e00d1e20e782df1f779861d09edc9e394e70a8..c7b0053adac0c5a45858c22a61b600cf6fc0373e 100644
--- a/plugins/unified_collector/storage/cpu_storage.cpp
+++ b/plugins/unified_collector/storage/cpu_storage.cpp
@@ -20,6 +20,7 @@
#include "file_util.h"
#include "hisysevent.h"
#include "logger.h"
+#include "process_status.h"
#include "rdb_helper.h"
#include "sql_util.h"
#include "string_util.h"
@@ -28,6 +29,7 @@
namespace OHOS {
namespace HiviewDFX {
DEFINE_LOG_TAG("HiView-CpuStorage");
+using namespace OHOS::HiviewDFX::UCollectUtil;
namespace {
constexpr int32_t DB_VERSION = 1;
const std::string TABLE_NAME = "unified_collection_cpu";
@@ -35,6 +37,7 @@ const std::string COLUMN_START_TIME = "start_time";
const std::string COLUMN_END_TIME = "end_time";
const std::string COLUMN_PID = "pid";
const std::string COLUMN_PROC_NAME = "proc_name";
+const std::string COLUMN_PROC_STATE = "proc_state";
const std::string COLUMN_CPU_LOAD = "cpu_load";
const std::string COLUMN_CPU_USAGE = "cpu_usage";
constexpr uint32_t MAX_NUM_OF_DB_FILES = 7; // save files for one week
@@ -99,6 +102,24 @@ double TruncateDecimalWithNBitPrecision(double decimal, uint32_t precision = DEF
auto truncateCoefficient = std::pow(10, precision);
return std::floor(decimal * truncateCoefficient) / truncateCoefficient;
}
+
+bool IsForegroundStateInCollectionPeriod(const ProcessCpuStatInfo& cpuCollectionInfo)
+{
+ int32_t pid = cpuCollectionInfo.pid;
+ ProcessState procState = ProcessStatus::GetInstance().GetProcessState(pid);
+ if (procState == FOREGROUND) {
+ return true;
+ }
+ uint64_t procForegroundTime = ProcessStatus::GetInstance().GetProcessLastForegroundTime(pid);
+ return (procForegroundTime >= cpuCollectionInfo.startTime && procForegroundTime < cpuCollectionInfo.endTime);
+}
+
+int32_t GetProcessStateInCollectionPeriod(const ProcessCpuStatInfo& cpuCollectionInfo)
+{
+ return IsForegroundStateInCollectionPeriod(cpuCollectionInfo)
+ ? static_cast(FOREGROUND)
+ : static_cast(ProcessStatus::GetInstance().GetProcessState(cpuCollectionInfo.pid));
+}
}
class CpuDbStoreCallback : public NativeRdb::RdbOpenCallback {
@@ -181,6 +202,7 @@ void CpuStorage::InsertTable(const ProcessCpuStatInfo& cpuCollectionInfo)
bucket.PutLong(COLUMN_START_TIME, static_cast(cpuCollectionInfo.startTime));
bucket.PutLong(COLUMN_END_TIME, static_cast(cpuCollectionInfo.endTime));
bucket.PutInt(COLUMN_PID, cpuCollectionInfo.pid);
+ bucket.PutInt(COLUMN_PROC_STATE, GetProcessStateInCollectionPeriod(cpuCollectionInfo));
bucket.PutString(COLUMN_PROC_NAME, cpuCollectionInfo.procName);
bucket.PutDouble(COLUMN_CPU_LOAD, TruncateDecimalWithNBitPrecision(cpuCollectionInfo.cpuLoad));
bucket.PutDouble(COLUMN_CPU_USAGE, TruncateDecimalWithNBitPrecision(cpuCollectionInfo.cpuUsage));
@@ -195,16 +217,17 @@ int32_t CpuStorage::CreateTable()
/**
* table: unified_collection_cpu
*
- * |-----|------------|----------|-----|-----------|----------|-----------|
- * | id | start_time | end_time | pid | proc_name | cpu_load | cpu_usage |
- * |-----|------------|----------|-----|-----------|----------|-----------|
- * | INT | INT64 | INT64 | INT | VARCHAR | DOUBLE | DOUBLE |
- * |-----|------------|----------|-----|-----------|----------|-----------|
+ * |-----|------------|----------|-----|------------|-----------|----------|-----------|
+ * | id | start_time | end_time | pid | proc_state | proc_name | cpu_load | cpu_usage |
+ * |-----|------------|----------|-----|------------|-----------|----------|-----------|
+ * | INT | INT64 | INT64 | INT | INT | VARCHAR | DOUBLE | DOUBLE |
+ * |-----|------------|----------|-----|------------|-----------|----------|-----------|
*/
const std::vector> fields = {
{COLUMN_START_TIME, SqlUtil::COLUMN_TYPE_INT},
{COLUMN_END_TIME, SqlUtil::COLUMN_TYPE_INT},
{COLUMN_PID, SqlUtil::COLUMN_TYPE_INT},
+ {COLUMN_PROC_STATE, SqlUtil::COLUMN_TYPE_INT},
{COLUMN_PROC_NAME, SqlUtil::COLUMN_TYPE_STR},
{COLUMN_CPU_LOAD, SqlUtil::COLUMN_TYPE_DOU},
{COLUMN_CPU_USAGE, SqlUtil::COLUMN_TYPE_DOU},
diff --git a/plugins/unified_collector/unified_collector.cpp b/plugins/unified_collector/unified_collector.cpp
index a0cab73fb6a49069b44ebccb1e28861b0b202f2d..4551737c5ad64033d1828b18aa5de9583186f987 100644
--- a/plugins/unified_collector/unified_collector.cpp
+++ b/plugins/unified_collector/unified_collector.cpp
@@ -17,11 +17,30 @@
#include "file_util.h"
#include "logger.h"
#include "plugin_factory.h"
+#include "process_status.h"
+#include "sys_event.h"
namespace OHOS {
namespace HiviewDFX {
REGISTER(UnifiedCollector);
DEFINE_LOG_TAG("HiView-UnifiedCollector");
+using namespace OHOS::HiviewDFX::UCollectUtil;
+namespace {
+const std::unordered_map APP_STATES = {
+ {"APP_FOREGROUND", FOREGROUND},
+ {"APP_BACKGROUND", BACKGROUND},
+};
+
+ProcessState GetProcessStateByEvent(const SysEvent& sysEvent)
+{
+ std::string eventName = sysEvent.GetEventName();
+ if (APP_STATES.find(eventName) != APP_STATES.end()) {
+ return APP_STATES.at(eventName);
+ }
+ HIVIEW_LOGW("invalid event name=%{public}s", eventName.c_str());
+ return INVALID;
+}
+}
void UnifiedCollector::OnLoad()
{
@@ -34,6 +53,22 @@ void UnifiedCollector::OnUnload()
HIVIEW_LOGI("start to unload UnifiedCollector plugin");
}
+void UnifiedCollector::OnEventListeningCallback(const Event& event)
+{
+ SysEvent& sysEvent = static_cast(const_cast(event));
+ int32_t procId = sysEvent.GetEventIntValue("APP_PID");
+ if (procId <= 0) {
+ HIVIEW_LOGW("invalid process id=%{public}d", procId);
+ return;
+ }
+ ProcessState procState = GetProcessStateByEvent(sysEvent);
+ if (procState == INVALID) {
+ HIVIEW_LOGW("invalid process state=%{public}d", procState);
+ return;
+ }
+ ProcessStatus::GetInstance().NotifyProcessState(procId, procState);
+}
+
void UnifiedCollector::Init()
{
if (GetHiviewContext() == nullptr) {